/* * Test for form auto fill content helper collectFormFields functions. */ "use strict"; var FormAutofillHandler; add_task(async function setup() { ({ FormAutofillHandler } = ChromeUtils.import( "resource://formautofill/FormAutofillHandler.jsm" )); }); const TESTCASES = [ { description: "Form without autocomplete property", document: `
`, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "given-name", }, { section: "", addressType: "", contactType: "", fieldName: "family-name", }, { section: "", addressType: "", contactType: "", fieldName: "address-line1", }, { section: "", addressType: "", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "", contactType: "", fieldName: "country" }, { section: "", addressType: "", contactType: "", fieldName: "email" }, { section: "", addressType: "", contactType: "", fieldName: "tel" }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "given-name", }, { section: "", addressType: "", contactType: "", fieldName: "family-name", }, { section: "", addressType: "", contactType: "", fieldName: "address-line1", }, { section: "", addressType: "", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "", contactType: "", fieldName: "country" }, { section: "", addressType: "", contactType: "", fieldName: "email" }, { section: "", addressType: "", contactType: "", fieldName: "tel" }, ], ids: [ "given-name", "family-name", "street-addr", "city", "country", "email", "phone", ], }, { description: "An address and credit card form with autocomplete properties and 1 token", document: ``, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "given-name", }, { section: "", addressType: "", contactType: "", fieldName: "family-name", }, { section: "", addressType: "", contactType: "", fieldName: "street-address", }, { section: "", addressType: "", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "", contactType: "", fieldName: "country" }, { section: "", addressType: "", contactType: "", fieldName: "email" }, { section: "", addressType: "", contactType: "", fieldName: "tel" }, ], [ { section: "", addressType: "", contactType: "", fieldName: "cc-number", }, { section: "", addressType: "", contactType: "", fieldName: "cc-name" }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-month", }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-year", }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "given-name", }, { section: "", addressType: "", contactType: "", fieldName: "family-name", }, { section: "", addressType: "", contactType: "", fieldName: "street-address", }, { section: "", addressType: "", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "", contactType: "", fieldName: "country" }, { section: "", addressType: "", contactType: "", fieldName: "email" }, { section: "", addressType: "", contactType: "", fieldName: "tel" }, { section: "", addressType: "", contactType: "", fieldName: "cc-number" }, { section: "", addressType: "", contactType: "", fieldName: "cc-name" }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-month", }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-year", }, ], }, { description: "An address form with autocomplete properties and 2 tokens", document: ``, sections: [ [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, { section: "", addressType: "shipping", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "shipping", contactType: "", fieldName: "country", }, { section: "", addressType: "shipping", contactType: "", fieldName: "email", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, ], ], validFieldDetails: [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, { section: "", addressType: "shipping", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "shipping", contactType: "", fieldName: "country", }, { section: "", addressType: "shipping", contactType: "", fieldName: "email", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, ], }, { description: "Form with autocomplete properties and profile is partly matched", document: ``, sections: [ [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, { section: "", addressType: "shipping", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "shipping", contactType: "", fieldName: "country", }, { section: "", addressType: "shipping", contactType: "", fieldName: "email", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, ], ], validFieldDetails: [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, { section: "", addressType: "shipping", contactType: "", fieldName: "address-level2", }, { section: "", addressType: "shipping", contactType: "", fieldName: "country", }, { section: "", addressType: "shipping", contactType: "", fieldName: "email", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, ], }, { description: "It's a valid address and credit card form.", document: ``, sections: [ [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, ], [ { section: "", addressType: "shipping", contactType: "", fieldName: "cc-number", }, ], ], validFieldDetails: [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, { section: "", addressType: "shipping", contactType: "", fieldName: "cc-number", }, ], }, { description: "An invalid address form due to less than 3 fields.", document: ``, sections: [[]], validFieldDetails: [], }, { description: "An invalid credit card form due to non-autocomplete-attr cc-number only", document: ``, sections: [[]], validFieldDetails: [], }, { description: "An invalid credit card form due to omitted cc-number.", document: ``, sections: [[]], validFieldDetails: [], }, { description: "A valid credit card form with non-autocomplete-attr cc-number and cc-name.", document: ``, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "cc-name" }, { section: "", addressType: "", contactType: "", fieldName: "cc-number", }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "cc-name" }, { section: "", addressType: "", contactType: "", fieldName: "cc-number" }, ], ids: ["cc-name", "cc-number"], }, { description: "A valid credit card form with autocomplete-attr cc-number only.", document: ``, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "cc-number", }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "cc-number" }, ], }, { description: "A valid credit card form with non-autocomplete-attr cc-number and cc-exp.", document: ``, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "cc-number", }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp" }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "cc-number" }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp" }, ], ids: ["cc-number", "cc-exp"], }, { description: "A valid credit card form with non-autocomplete-attr cc-number and cc-exp-month/cc-exp-year.", document: ``, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "cc-number", }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-month", }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-year", }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "cc-number" }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-month", }, { section: "", addressType: "", contactType: "", fieldName: "cc-exp-year", }, ], ids: ["cc-number", "cc-exp-month", "cc-exp-year"], }, { description: "Three sets of adjacent phone number fields", document: ``, allowDuplicates: true, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-suffix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-extension", }, ], [ { section: "", addressType: "", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-suffix", }, // TODO Bug 1421181 - "tel-country-code" field should belong to the next // section. There should be a way to group the related fields during the // parsing stage. { section: "", addressType: "", contactType: "", fieldName: "tel-country-code", }, ], [ { section: "", addressType: "", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-suffix", }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-suffix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-extension", }, { section: "", addressType: "", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-suffix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-country-code", }, { section: "", addressType: "", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "", contactType: "", fieldName: "tel-local-suffix", }, ], ids: [ "shippingAC", "shippingPrefix", "shippingSuffix", "shippingTelExt", "billingAC", "billingPrefix", "billingSuffix", "otherCC", "otherAC", "otherPrefix", "otherSuffix", ], }, { description: "Dedup the same field names of the different telephone fields.", document: ``, sections: [ [ { section: "", addressType: "", contactType: "", fieldName: "given-name", }, { section: "", addressType: "", contactType: "", fieldName: "family-name", }, { section: "", addressType: "", contactType: "", fieldName: "street-address", }, { section: "", addressType: "", contactType: "", fieldName: "email" }, { section: "", addressType: "", contactType: "", fieldName: "tel" }, ], ], validFieldDetails: [ { section: "", addressType: "", contactType: "", fieldName: "given-name", }, { section: "", addressType: "", contactType: "", fieldName: "family-name", }, { section: "", addressType: "", contactType: "", fieldName: "street-address", }, { section: "", addressType: "", contactType: "", fieldName: "email" }, { section: "", addressType: "", contactType: "", fieldName: "tel" }, ], ids: ["i1", "i2", "i3", "i4", "homePhone"], }, { description: "The duplicated phones of a single one and a set with ac, prefix, suffix.", document: ``, sections: [ [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, { section: "", addressType: "shipping", contactType: "", fieldName: "email", }, // NOTES: Ideally, there is only one full telephone field(s) in a form for // this case. We can see if there is any better solution later. { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel-local-suffix", }, ], ], validFieldDetails: [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "street-address", }, { section: "", addressType: "shipping", contactType: "", fieldName: "email", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel-area-code", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel-local-prefix", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel-local-suffix", }, ], ids: [ "i1", "i2", "i3", "i4", "singlePhone", "shippingAreaCode", "shippingPrefix", "shippingSuffix", ], }, { description: "Always adopt the info from autocomplete attribute.", document: ``, sections: [ [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, ], ], validFieldDetails: [ { section: "", addressType: "shipping", contactType: "", fieldName: "given-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "family-name", }, { section: "", addressType: "shipping", contactType: "", fieldName: "tel", }, ], ids: ["given-name", "family-name", "dummyAreaCode"], }, ]; for (let tc of TESTCASES) { (function() { let testcase = tc; add_task(async function() { info("Starting testcase: " + testcase.description); let doc = MockDocument.createTestDocument( "http://localhost:8080/test/", testcase.document ); let form = doc.querySelector("form"); let formLike = FormLikeFactory.createFromForm(form); function setElementWeakRef(details) { if (!details) { return; } details.forEach((detail, index) => { let elementRef; if (testcase.ids && testcase.ids[index]) { elementRef = doc.getElementById(testcase.ids[index]); } else { elementRef = doc.querySelector( "*[autocomplete*='" + detail.fieldName + "']" ); } detail.elementWeakRef = Cu.getWeakReference(elementRef); }); } function verifyDetails(handlerDetails, testCaseDetails) { if (handlerDetails === null) { Assert.equal(handlerDetails, testCaseDetails); return; } Assert.equal( handlerDetails.length, testCaseDetails.length, "field count" ); handlerDetails.forEach((detail, index) => { Assert.equal( detail.fieldName, testCaseDetails[index].fieldName, "fieldName" ); Assert.equal( detail.section, testCaseDetails[index].section, "section" ); Assert.equal( detail.addressType, testCaseDetails[index].addressType, "addressType" ); Assert.equal( detail.contactType, testCaseDetails[index].contactType, "contactType" ); Assert.equal( detail.elementWeakRef.get(), testCaseDetails[index].elementWeakRef.get(), "DOM reference" ); }); } setElementWeakRef( testcase.sections.reduce((fieldDetails, section) => { fieldDetails.push(...section); return fieldDetails; }, []) ); setElementWeakRef(testcase.validFieldDetails); let handler = new FormAutofillHandler(formLike); let validFieldDetails = handler.collectFormFields( testcase.allowDuplicates ); Assert.equal( handler.sections.length, testcase.sections.length, "section count" ); for (let i = 0; i < handler.sections.length; i++) { let section = handler.sections[i]; verifyDetails(section.fieldDetails, testcase.sections[i]); } verifyDetails(validFieldDetails, testcase.validFieldDetails); }); })(); }