diff --git a/browser/extensions/formautofill/test/unit/test_clearPopulatedForm.js b/browser/extensions/formautofill/test/unit/test_clearPopulatedForm.js new file mode 100644 index 0000000000000..4b14b1e54cfa4 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/test_clearPopulatedForm.js @@ -0,0 +1,116 @@ +/* Any copyright is dedicated to the Public Domain. +http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TESTCASES = [ + { + description: "Clear populated address form with text inputs", + document: `
+ + + + +
`, + focusedInputId: "given-name", + profileData: { + "given-name": "John", + "family-name": "Doe", + "street-addr": "1000 Main Street", + city: "Nowhere", + }, + expectedResult: { + "given-name": "", + "family-name": "", + "street-addr": "", + city: "", + }, + }, + { + description: "Clear populated address form with select and text inputs", + document: `
+ + + + +
`, + focusedInputId: "given-name", + profileData: { + "given-name": "John", + "family-name": "Doe", + "street-addr": "1000 Main Street", + state: "OH", + }, + expectedResult: { + "given-name": "", + "family-name": "", + "street-addr": "", + state: "AL", + }, + }, + { + description: + "Clear populated address form with select element with selected attribute and text inputs", + document: `
+ + + + +
`, + focusedInputId: "given-name", + profileData: { + "given-name": "John", + "family-name": "Doe", + "street-addr": "1000 Main Street", + state: "OH", + }, + expectedResult: { + "given-name": "", + "family-name": "", + "street-addr": "", + state: "AK", + }, + }, +]; + +add_task(async function do_test() { + let { FormAutofillHandler } = ChromeUtils.import( + "resource://autofill/FormAutofillHandler.jsm" + ); + for (let test of TESTCASES) { + info("Test case: " + test.description); + let testDoc = MockDocument.createTestDocument( + "http://localhost:8080/test", + test.document + ); + let form = testDoc.querySelector("form"); + let formLike = FormLikeFactory.createFromForm(form); + let handler = new FormAutofillHandler(formLike); + handler.collectFormFields(); + let focusedInput = testDoc.getElementById(test.focusedInputId); + handler.focusedInput = focusedInput; + let [adaptedProfile] = handler.activeSection.getAdaptedProfiles([ + test.profileData, + ]); + await handler.autofillFormFields(adaptedProfile, focusedInput); + + handler.activeSection.clearPopulatedForm(); + handler.activeSection.fieldDetails.forEach(detail => { + let element = detail.elementWeakRef.get(); + let id = element.id; + Assert.equal( + element.value, + test.expectedResult[id], + `Check the ${id} field was restored to the correct value` + ); + }); + } +}); diff --git a/browser/extensions/formautofill/test/unit/xpcshell.ini b/browser/extensions/formautofill/test/unit/xpcshell.ini index c38156a06755d..83b6c28c76cce 100644 --- a/browser/extensions/formautofill/test/unit/xpcshell.ini +++ b/browser/extensions/formautofill/test/unit/xpcshell.ini @@ -14,6 +14,7 @@ skip-if = skip-if = tsan # Times out, bug 1612707 apple_silicon # bug 1729554 +[test_clearPopulatedForm.js] [test_collectFormFields.js] [test_createRecords.js] [test_creditCardRecords.js] diff --git a/toolkit/components/formautofill/FormAutofillHandler.jsm b/toolkit/components/formautofill/FormAutofillHandler.jsm index 7778e9df8dbd1..fb08511a9fd95 100644 --- a/toolkit/components/formautofill/FormAutofillHandler.jsm +++ b/toolkit/components/formautofill/FormAutofillHandler.jsm @@ -497,12 +497,13 @@ class FormAutofillSection { continue; } - // Only reset value for input element. - if ( - fieldDetail.state == FIELD_STATES.AUTO_FILLED && - ChromeUtils.getClassName(element) === "HTMLInputElement" - ) { - element.setUserInput(""); + if (fieldDetail.state == FIELD_STATES.AUTO_FILLED) { + if (ChromeUtils.getClassName(element) === "HTMLInputElement") { + element.setUserInput(""); + } else if (ChromeUtils.getClassName(element) === "HTMLSelectElement") { + // If we can't find a selected option, then we should just reset to the first option's value + this._resetSelectElementValue(element); + } } } } @@ -714,6 +715,9 @@ class FormAutofillSection { // Restore the dim fields to initial state as well once we knew // that user had intention to clear the filled form manually. for (const fieldDetail of dimFieldDetails) { + // If we can't find a selected option, then we should just reset to the first option's value + let element = fieldDetail.elementWeakRef.get(); + this._resetSelectElementValue(element); this._changeFieldState(fieldDetail, FIELD_STATES.NORMAL); } this.filledRecordGUID = null; @@ -722,6 +726,21 @@ class FormAutofillSection { } } } + /** + * Resets a