describe 'up.flow', -> u = up.util describe 'Javascript functions', -> describe 'up.replace', -> if up.browser.canPushState() beforeEach -> @oldBefore = affix('.before').text('old-before') @oldMiddle = affix('.middle').text('old-middle') @oldAfter = affix('.after').text('old-after') @responseText = """
new-before
new-middle
new-after
""" @respond = -> @lastRequest().respondWith status: 200 contentType: 'text/html' responseText: @responseText it 'replaces the given selector with the same selector from a freshly fetched page', (done) -> @request = up.replace('.middle', '/path') @respond() @request.then -> expect($('.before')).toHaveText('old-before') expect($('.middle')).toHaveText('new-middle') expect($('.after')).toHaveText('old-after') done() it 'should set the browser location to the given URL', (done) -> @request = up.replace('.middle', '/path') @respond() @request.then -> expect(window.location.pathname).toBe('/path') done() it 'marks the element with the URL from which it was retrieved', (done) -> @request = up.replace('.middle', '/path') @respond() @request.then -> expect($('.middle').attr('up-source')).toMatch(/\/path$/) done() it 'replaces multiple selectors separated with a comma', (done) -> @request = up.replace('.middle, .after', '/path') @respond() @request.then -> expect($('.before')).toHaveText('old-before') expect($('.middle')).toHaveText('new-middle') expect($('.after')).toHaveText('new-after') done() it 'prepends instead of replacing when the target has a :before pseudo-selector', (done) -> @request = up.replace('.middle:before', '/path') @respond() @request.then -> expect($('.before')).toHaveText('old-before') console.log("foooo", $('.middle').text()) expect($('.middle')).toHaveText('new-middleold-middle') expect($('.after')).toHaveText('old-after') done() it 'appends instead of replacing when the target has a :after pseudo-selector', (done) -> @request = up.replace('.middle:after', '/path') @respond() @request.then -> expect($('.before')).toHaveText('old-before') expect($('.middle')).toHaveText('old-middlenew-middle') expect($('.after')).toHaveText('old-after') done() it "lets the developer choose between replacing/prepending/appending for each selector", (done) -> @request = up.replace('.before:before, .middle, .after:after', '/path') @respond() @request.then -> expect($('.before')).toHaveText('new-beforeold-before') expect($('.middle')).toHaveText('new-middle') expect($('.after')).toHaveText('old-afternew-after') done() it 'executes only those script-tags in the response that get inserted into the DOM', (done) -> window.scriptTagExecuted = jasmine.createSpy('scriptTagExecuted') @responseText = """
new-before
new-middle
""" @request = up.replace('.middle', '/path') @respond() @request.then -> expect(window.scriptTagExecuted).not.toHaveBeenCalledWith('before') expect(window.scriptTagExecuted).toHaveBeenCalledWith('middle') done() it 'restores the scroll positions of all viewports within the target with options.restoreScroll' describe 'with { reveal: true } option', -> beforeEach -> @revealedHTML = '' spyOn(up, 'reveal').and.callFake ($revealedElement) => @revealedHTML = $revealedElement.get(0).outerHTML u.resolvedPromise() it 'reveals an old element before it is being replaced', (done) -> @request = up.replace('.middle', '/path', reveal: true) @respond() @request.then => expect(up.reveal).toHaveBeenCalledWith(@oldMiddle) done() it 'reveals a new element that is being appended', (done) -> @request = up.replace('.middle:after', '/path', reveal: true) @respond() @request.then => expect(up.reveal).not.toHaveBeenCalledWith(@oldMiddle) # Text nodes are wrapped in a .up-insertion container so we can # animate them and measure their position/size for scrolling. # This is not possible for container-less text nodes. expect(@revealedHTML).toEqual('new-middle') # Show that the wrapper is done after the insertion. expect($('.up-insertion')).not.toExist() done() it 'reveals a new element that is being prepended', (done) -> @request = up.replace('.middle:before', '/path', reveal: true) @respond() @request.then => expect(up.reveal).not.toHaveBeenCalledWith(@oldMiddle) # Text nodes are wrapped in a .up-insertion container so we can # animate them and measure their position/size for scrolling. # This is not possible for container-less text nodes. expect(@revealedHTML).toEqual('new-middle') # Show that the wrapper is done after the insertion. expect($('.up-insertion')).not.toExist() done() else it 'makes a full page load', -> spyOn(up.browser, 'loadPage') up.replace('.selector', '/path') expect(up.browser.loadPage).toHaveBeenCalledWith('/path', jasmine.anything()) describe 'up.flow.implant', -> it 'Updates a selector on the current page with the same selector from the given HTML string', -> affix('.before').text('old-before') affix('.middle').text('old-middle') affix('.after').text('old-after') html = """
new-before
new-middle
new-after
""" up.flow.implant('.middle', html) expect($('.before')).toHaveText('old-before') expect($('.middle')).toHaveText('new-middle') expect($('.after')).toHaveText('old-after') it "throws an error if the selector can't be found on the current page", -> html = '
text
' implant = -> up.flow.implant('.foo-bar', html) expect(implant).toThrowError(/Could not find selector ".foo-bar" in current body/i) it "throws an error if the selector can't be found in the given HTML string", -> affix('.foo-bar') implant = -> up.flow.implant('.foo-bar', '') expect(implant).toThrowError(/Could not find selector ".foo-bar" in response/i) it "ignores an element that matches the selector but also matches .up-destroying", -> html = '
text
' affix('.foo-bar.up-destroying') implant = -> up.flow.implant('.foo-bar', html) expect(implant).toThrowError(/Could not find selector/i) it "ignores an element that matches the selector but also matches .up-ghost", -> html = '
text
' affix('.foo-bar.up-ghost') implant = -> up.flow.implant('.foo-bar', html) expect(implant).toThrowError(/Could not find selector/i) it "ignores an element that matches the selector but also has a parent matching .up-destroying", -> html = '
text
' $parent = affix('.up-destroying') $child = affix('.foo-bar').appendTo($parent) implant = -> up.flow.implant('.foo-bar', html) expect(implant).toThrowError(/Could not find selector/i) it "ignores an element that matches the selector but also has a parent matching .up-ghost", -> html = '
text
' $parent = affix('.up-ghost') $child = affix('.foo-bar').appendTo($parent) implant = -> up.flow.implant('.foo-bar', html) expect(implant).toThrowError(/Could not find selector/i) it 'only replaces the first element matching the selector', -> html = '
text
' affix('.foo-bar') affix('.foo-bar') up.flow.implant('.foo-bar', html) elements = $('.foo-bar') expect($(elements.get(0)).text()).toEqual('text') expect($(elements.get(1)).text()).toEqual('') describe 'up.destroy', -> it 'removes the element with the given selector', -> affix('.element') up.destroy('.element') expect($('.element')).not.toExist() it 'calls destructors for custom elements', -> up.compiler('.element', ($element) -> destructor) destructor = jasmine.createSpy('destructor') up.ready(affix('.element')) up.destroy('.element') expect(destructor).toHaveBeenCalled() describe 'up.reload', -> if up.browser.canPushState() it 'reloads the given selector from the closest known source URL', (done) -> affix('.container[up-source="/source"] .element').find('.element').text('old text') up.reload('.element').then -> expect($('.element')).toHaveText('new text') done() request = @lastRequest() expect(request.url).toMatch(/\/source$/) request.respondWith status: 200 contentType: '/text/html' responseText: """
new text
""" else it 'makes a page load from the closest known source URL', -> affix('.container[up-source="/source"] .element').find('.element').text('old text') spyOn(up.browser, 'loadPage') up.reload('.element') expect(up.browser.loadPage).toHaveBeenCalledWith('/source', jasmine.anything()) describe 'up.reset', -> it 'should have tests'