describe 'up.form', -> u = up.util describe 'Javascript functions', -> describe 'up.observe', -> changeEvents = if up.browser.canInputEvent() # Actually we only need `input`, but we want to notice # if another script manually triggers `change` on the element. ['input', 'change'] else # Actually we won't ever get `input` from the user in this browser, # but we want to notice if another script manually triggers `input` # on the element. ['input', 'change', 'keypress', 'paste', 'cut', 'click', 'propertychange'] u.each changeEvents, (eventName) -> describe 'when the first argument is a form field', -> it "runs the callback when the input receives a '#{eventName}' event and the value changed", (done) -> $input = affix('input[value="old-value"]') callback = jasmine.createSpy('change callback') up.observe($input, callback) $input.val('new-value') u.times 2, -> $input.trigger(eventName) u.nextFrame -> expect(callback).toHaveBeenCalledWith('new-value', $input) expect(callback.calls.count()).toEqual(1) done() it "does not run the callback when the input receives a '#{eventName}' event, but the value didn't change", (done) -> $input = affix('input[value="old-value"]') callback = jasmine.createSpy('change callback') up.observe($input, callback) $input.trigger(eventName) u.nextFrame -> expect(callback).not.toHaveBeenCalled() done() it "runs a callback in the same frame if the delay is 0 and it receives a '#{eventName}' event", -> $input = affix('input[value="old-value"]') callback = jasmine.createSpy('change callback') up.observe($input, { delay: 0 }, callback) $input.val('new-value') $input.trigger(eventName) expect(callback.calls.count()).toEqual(1) it "runs multiple callbacks in the same frame if the delay is 0 and it receives a '#{eventName}' event", -> $input = affix('input[value="old-value"]') callback = jasmine.createSpy('change callback') up.observe($input, { delay: 0 }, callback) $input.val('new-value') $input.trigger(eventName) $input.val('yet-another-value') $input.trigger(eventName) expect(callback.calls.count()).toEqual(2) describe 'when the first argument is a form', -> it "runs the callback when any of the form's inputs receives a '#{eventName}' event and the value changed", (done) -> $form = affix('form') $input = $form.affix('input[value="old-value"]') callback = jasmine.createSpy('change callback') up.observe($form, callback) $input.val('new-value') u.times 2, -> $input.trigger(eventName) u.nextFrame -> expect(callback).toHaveBeenCalledWith('new-value', $input) expect(callback.calls.count()).toEqual(1) done() it "does not run the callback when any of the form's inputs receives a '#{eventName}' event, but the value didn't change", (done) -> $form = affix('form') $input = $form.affix('input[value="old-value"]') callback = jasmine.createSpy('change callback') up.observe($form, callback) $input.trigger(eventName) u.nextFrame -> expect(callback).not.toHaveBeenCalled() done() describe 'up.submit', -> if up.browser.canPushState() beforeEach -> $form = affix('form[action="/path/to"][method="put"][up-target=".response"]') $form.append('') $form.append('') affix('.response').text('old-text') @promise = up.submit($form) @request = @lastRequest() expect(@request.url).toMatch /\/path\/to$/ expect(@request.method).toBe 'PUT' expect(@request.data()).toEqual field1: ['value1'] field2: ['value2'] it 'submits the given form and replaces the target with the response', (done) -> @respondWith """ text-before
new-text
text-after """ @promise.then -> expect($('.response')).toHaveText('new-text') expect($('body')).not.toHaveText('text-before') expect($('body')).not.toHaveText('text-after') done() it 'places the response into the form if the submission returns a 5xx status code', (done) -> @request.respondWith status: 500 contentType: 'text/html' responseText: """ text-before
error-messages
text-after """ @promise.always -> expect($('.response')).toHaveText('old-text') expect($('form')).toHaveText('error-messages') expect($('body')).not.toHaveText('text-before') expect($('body')).not.toHaveText('text-after') done() it 'respects a X-Up-Location header that the server sends in case of a redirect', (done) -> @request.respondWith status: 200 contentType: 'text/html' responseHeaders: { 'X-Up-Location': '/other/path' } responseText: """
new-text
""" @promise.then -> expect(up.browser.url()).toMatch(/\/other\/path$/) done() else it 'submits the given form', -> $form = affix('form[action="/path/to"][method="put"][up-target=".response"]') form = $form.get(0) spyOn(form, 'submit') up.submit($form) expect(form.submit).toHaveBeenCalled() describe 'unobtrusive behavior', -> describe 'form[up-target]', -> it 'rigs the form to use up.submit instead of a standard submit' describe 'input[up-autosubmit]', -> it 'submits the form when a change is observed in the given form field', (done) -> $form = affix('form') $field = $form.affix('input[up-autosubmit][val="old-value"]') up.hello($field) submitSpy = up.form.knife.mock('submit').and.returnValue(u.unresolvablePromise()) $field.val('new-value') $field.trigger('change') u.nextFrame -> expect(submitSpy).toHaveBeenCalled() done() describe 'form[up-autosubmit]', -> it 'submits the form when a change is observed in any of its fields', (done) -> $form = affix('form[up-autosubmit]') $field = $form.affix('input[val="old-value"]') up.hello($form) submitSpy = up.form.knife.mock('submit').and.returnValue(u.unresolvablePromise()) $field.val('new-value') $field.trigger('change') u.nextFrame -> expect(submitSpy).toHaveBeenCalled() done() describe '[up-observe]', -> it 'should have tests' describe 'input[up-validate]', -> describe 'when a selector is given', -> it "submits the input's form with an 'X-Up-Validate' header and replaces the selector with the response", -> $form = affix('form[action="/path/to"]') $group = $("""
""").appendTo($form) $group.find('input').trigger('change') request = @lastRequest() expect(request.requestHeaders['X-Up-Validate']).toEqual('user') expect(request.requestHeaders['X-Up-Selector']).toEqual(".field-group:has([name='user'])") @respondWith """
Username has already been taken
""" $group = $('.field-group') expect($group.length).toBe(1) expect($group).toHaveClass('has-error') expect($group).toHaveText('Username has already been taken') describe 'when no selector is given', -> it 'automatically finds a form group around the input field and only updates that', -> @appendFixture """
""" $('#registration input[name=password]').trigger('change') @respondWith """
""" $labels = $('#registration label') expect($labels[0]).not.toHaveText('Validation message') expect($labels[1]).toHaveText('Validation message')