Skip to content

Commit

Permalink
Bug 1740070 - Reset <select> elements when autofilled form is cleared…
Browse files Browse the repository at this point in the history
…. r=sgalich,dimi

Differential Revision: https://phabricator.services.mozilla.com/D133213
  • Loading branch information
TGiles committed Jan 5, 2022
1 parent efdb8d4 commit 5c8c444
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 6 deletions.
116 changes: 116 additions & 0 deletions browser/extensions/formautofill/test/unit/test_clearPopulatedForm.js
Original file line number Diff line number Diff line change
@@ -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: `<form>
<input id="given-name">
<input id="family-name">
<input id="street-addr">
<input id="city">
</form>`,
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: `<form>
<input id="given-name">
<input id="family-name">
<input id="street-addr">
<select id="state">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="OH">Ohio</option>
</select>
</form>`,
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: `<form>
<input id="given-name">
<input id="family-name">
<input id="street-addr">
<select id="state">
<option value="AL">Alabama</option>
<option selected value="AK">Alaska</option>
<option value="OH">Ohio</option>
</select>
</form>`,
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`
);
});
}
});
1 change: 1 addition & 0 deletions browser/extensions/formautofill/test/unit/xpcshell.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
31 changes: 25 additions & 6 deletions toolkit/components/formautofill/FormAutofillHandler.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -722,6 +726,21 @@ class FormAutofillSection {
}
}
}
/**
* Resets a <select> element to its selected option or the first option if there is none selected.
*
* @param {HTMLElement} element
* @memberof FormAutofillSection
*/
_resetSelectElementValue(element) {
if (!element.options.length) {
return;
}
let selected = [...element.options].find(option =>
option.hasAttribute("selected")
);
element.value = selected ? selected.value : element.options[0].value;
}
}

class FormAutofillAddressSection extends FormAutofillSection {
Expand Down

0 comments on commit 5c8c444

Please sign in to comment.