diff --git a/src/autofill-event.js b/src/autofill-event.js index acf9914..fba6ed1 100644 --- a/src/autofill-event.js +++ b/src/autofill-event.js @@ -21,6 +21,7 @@ // form fields a little later... window.setTimeout(function() { findParentForm(target).find('input').checkAndTriggerAutoFillEvent(); + findParentForm(target).find('select').checkAndTriggerAutoFillEvent(); }, 20); }); @@ -66,6 +67,18 @@ // ... // Note: it's important to not use the value property here! el.$$currentValue = el.getAttribute('value'); + + // This handles select elements, which have option tags as children + // If an option tag has the selected attribute, then it is the default + // value of the select element. Input elements don't have children, + // so it is safe to have this code run after the above statement. + if (el.children.length > 0) { + forEach(el.children, function(child) { + if (child.getAttribute("selected")) { + el.$$currentValue = child.getAttribute("value"); + } + }); + } } var val = el.value, diff --git a/test/manual/web-form.html b/test/manual/web-form.html index b981d43..66a95a8 100644 --- a/test/manual/web-form.html +++ b/test/manual/web-form.html @@ -23,7 +23,7 @@

Prepare

  • Click on "Manage Autofill settings"
  • Add a new street address with: - First Name="Some" / Last Name="User" / Address line 1="1234 Some Street" / City="Some City" + First Name="Some" / Last Name="User" / Address line 1="1234 Some Street" / City="Some City" / State="Oblivion"
  • @@ -36,7 +36,7 @@

    Prepare

    Close preferences.
  • - Enter name="Some User" / address="1234 Some Street" / City="Some City" and hit submit + Enter name="Some User" / address="1234 Some Street" / City="Some City" / State="Oblivion" and hit submit
  • The next page should show the values in json format @@ -49,7 +49,7 @@

    Prepare

    Other browsers
    1. - Enter name="Some User" / address="1234 Some Street" / City="Some City" and hit submit + Enter name="Some User" / address="1234 Some Street" / City="Some City" / State="Oblivion" and hit submit
    2. The next page should show the values in json format @@ -73,6 +73,7 @@

      Form

      Name:
      Address:
      City:
      + State:
      @@ -81,6 +82,7 @@

      Form

      Name:
      Address:
      City:
      + State:
      diff --git a/test/manual/web-formSpec.js b/test/manual/web-formSpec.js index fa75323..2772b38 100644 --- a/test/manual/web-formSpec.js +++ b/test/manual/web-formSpec.js @@ -1,27 +1,33 @@ describe('normal forms', function() { - var name, address, city, ngName, ngAddress, ngCity, + var name, address, city, state, ngName, ngAddress, ngCity, ngState, mt = window.manualTest; - + var nameValue = 'Some User', addressValue = '1234 Some Street', - cityValue = 'Some City'; - + cityValue = 'Some City', + stateValue = 'Oblivion'; + beforeEach(function () { name = document.querySelector('.name'); address = document.querySelector('.address'); city = document.querySelector('.city'); + state = document.querySelector('.state'); + ngName = document.querySelector('.ng-name'); ngAddress = document.querySelector('.ng-address'); ngCity = document.querySelector('.ng-city'); + ngState = document.querySelector('.ng-state'); }); beforeEach(function() { mt.askForInput(name, '', 'user field'); mt.askForInput(address, '', 'address field'); mt.askForInput(city, '', 'city field'); + mt.askForInput(state, '', 'state field'); mt.askToBlur(name, 'name field'); mt.askToBlur(address, 'address field'); mt.askToBlur(city, 'city field'); + mt.askToBlur(state, 'state field'); waitForAutoFill(); }); @@ -50,9 +56,12 @@ describe('normal forms', function() { expect(name.value).toBe(nameValue); expect(address.value).toBe(addressValue); expect(city.value).toBe(cityValue); + expect(state.value).toBe(stateValue); + expect(ngName.textContent).toBe(nameValue); expect(ngAddress.textContent).toBe(addressValue); expect(ngCity.textContent).toBe(cityValue); + expect(ngState.textContent).toBe(stateValue); }); }); diff --git a/test/unit/autofill-eventSpec.js b/test/unit/autofill-eventSpec.js index a628c63..e6a52f0 100644 --- a/test/unit/autofill-eventSpec.js +++ b/test/unit/autofill-eventSpec.js @@ -14,7 +14,7 @@ describe('check other inputs when one input fires a blur event', function() { container.remove() }); - it('should check elements in the same form and not in other forms after 20ms when an element is blurred', function() { + it('should check input elements in the same form and not in other forms after 20ms when an element is blurred', function() { jasmine.Clock.useMock(); var spy = spyOn(testutils.$.prototype, 'checkAndTriggerAutoFillEvent'); @@ -28,9 +28,33 @@ describe('check other inputs when one input fires a blur event', function() { jasmine.Clock.tick(20); expect(spy).toHaveBeenCalled(); - expect(spy.mostRecentCall.object.length).toBe(2); - expect(spy.mostRecentCall.object[0]).toBe(inputs[0]); - expect(spy.mostRecentCall.object[1]).toBe(inputs[1]); + expect(spy.calls[0].object.length).toBe(2); + expect(spy.calls[0].object[0]).toBe(inputs[0]); + expect(spy.calls[0].object[1]).toBe(inputs[1]); + }); + + it('should check select elements in the same form and not in other forms after 20ms when an element is blurred', function() { + jasmine.Clock.useMock(); + + var spy = spyOn(testutils.$.prototype, 'checkAndTriggerAutoFillEvent'); + + container.append("
      " + + "" + + "" + + "
      " + + "" + + "
      "); + var selects = container.find('select'); + + testutils.triggerBlurEvent(selects[0]); + expect(spy).not.toHaveBeenCalled(); + + jasmine.Clock.tick(20); + + expect(spy).toHaveBeenCalled(); + expect(spy.calls[1].object.length).toBe(2); + expect(spy.calls[1].object[0]).toBe(selects[0]); + expect(spy.calls[1].object[1]).toBe(selects[1]); }); describe('checkAndTriggerAutoFillEvent', function() { @@ -120,4 +144,88 @@ describe('check other inputs when one input fires a blur event', function() { }); + + describe('checkAndTriggerAutoFillEvent with selects', function() { + var select; + + beforeEach(function() { + container.append(''); + select = container.children().eq(0); + }); + + + describe('changes by user via change event', function() { + it('should not fire an extra change event when there was a change event for the element', function() { + // Don't use .val as we intercept this! + select[0].value = 'someValue'; + + testutils.triggerChangeEvent(select[0]); + expect(select[0].changeEventCount).toBe(1); + + select.checkAndTriggerAutoFillEvent(); + + expect(select[0].changeEventCount).toBe(1); + }); + + it('should not fire an extra change event when the value did not change', function() { + // Don't use .val as we intercept this! + select[0].value = 'someValue'; + + testutils.triggerChangeEvent(select[0]); + select.checkAndTriggerAutoFillEvent(); + + testutils.triggerChangeEvent(select[0]); + select.checkAndTriggerAutoFillEvent(); + + expect(select[0].changeEventCount).toBe(2); + }); + }); + + describe('changes by js code via $.fn.val', function() { + it('should not fire a change event when js code changes the element', function() { + select.val('someValue'); + expect(select[0].changeEventCount).toBeUndefined(); + + select.checkAndTriggerAutoFillEvent(); + + expect(select[0].changeEventCount).toBeUndefined(); + }); + + it('should not fire an extra change event when the value did not change', function() { + select.val('someValue'); + select.checkAndTriggerAutoFillEvent(); + + select.val('someValue'); + select.checkAndTriggerAutoFillEvent(); + + expect(select[0].changeEventCount).toBeUndefined(); + }); + }); + + describe('misc', function() { + it('should not fire for untouched select with empty value', function() { + select.checkAndTriggerAutoFillEvent(); + expect(select[0].changeEventCount).toBeUndefined(); + }); + + it('should not fire if select boxes are added with predefined value', function() { + container.append(''); + var newSelect = container.children().eq(1); + newSelect.checkAndTriggerAutoFillEvent(); + expect(newSelect[0].changeEventCount).toBeUndefined(); + }); + }); + + it('should fire a change event if the value was changed by another way', function() { + // Don't use .val as we intercept this! + select[0].value = 'someValue'; + + select.checkAndTriggerAutoFillEvent(); + + expect(select[0].changeEventCount).toBe(1); + }); + + }); + + });