forked from mirrors/gecko-dev
* We make some changes to heuristicsRegexp.js to improve accuracy. (Nothing else uses these regexps, so they're safe to change.) The commenting out of some languages in the expiration fields are because they caused a lot of false positives, according to Daniel Hertenstein's recollection. In any case, we've never preffed CC autofill on for those languages.
* Delete a few tests from test_known_strings.js and one from test_getInfo.js, which were testing for the presence of regexes we removed.
* Delete tests of CC autofill against third-party sites. These tests no longer work as xpcshell tests, since Fathom expects full layout and style information. The spirit of these tests is maintained by adding these pages to Fathom's training, validation, and testing corpora at 2bfcdf23dc. A few don't make it due to iframes which confound Fathom's capture tools, but the rest all succeed--and now improve the ML model as well as acting as tests. The training results after said integration reflect this improvement, which boosts testing precision and recall for every type.
* Add a mochitest to ensure the Fathom integration code can surface a decision that a field should not be autofilled. Decisions that go the other way are taken care of by the existing autofill tests.
Differential Revision: https://phabricator.services.mozilla.com/D100141
328 lines
8.7 KiB
JavaScript
328 lines
8.7 KiB
JavaScript
"use strict";
|
|
|
|
var FormAutofillHeuristics, LabelUtils;
|
|
add_task(async function() {
|
|
({ FormAutofillHeuristics } = ChromeUtils.import(
|
|
"resource://formautofill/FormAutofillHeuristics.jsm"
|
|
));
|
|
({ LabelUtils } = ChromeUtils.import(
|
|
"resource://formautofill/FormAutofillUtils.jsm"
|
|
));
|
|
});
|
|
|
|
const TESTCASES = [
|
|
{
|
|
description: "Input element in a label element",
|
|
document: `<form>
|
|
<label> E-Mail
|
|
<input id="targetElement" type="text">
|
|
</label>
|
|
</form>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "email",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description:
|
|
"A label element is out of the form contains the related input",
|
|
document: `<label for="targetElement"> E-Mail</label>
|
|
<form>
|
|
<input id="targetElement" type="text">
|
|
</form>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "email",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "A label element contains span element",
|
|
document: `<label for="targetElement">FOO<span>E-Mail</span>BAR</label>
|
|
<form>
|
|
<input id="targetElement" type="text">
|
|
</form>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "email",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "The signature in 'name' attr of an input",
|
|
document: `<input id="targetElement" name="email" type="text">`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "email",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "The signature in 'id' attr of an input",
|
|
document: `<input id="targetElement_email" name="tel" type="text">`,
|
|
elementId: "targetElement_email",
|
|
expectedReturnValue: {
|
|
fieldName: "email",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "Select element in a label element",
|
|
document: `<form>
|
|
<label> State
|
|
<select id="targetElement"></select>
|
|
</label>
|
|
</form>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "address-level1",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "A select element without a form wrapped",
|
|
document: `<label for="targetElement">State</label>
|
|
<select id="targetElement"></select>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "address-level1",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "address line input",
|
|
document: `<label for="targetElement">street</label>
|
|
<input id="targetElement" type="text">`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "street-address",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "CJK character - Traditional Chinese",
|
|
document: `<label> 郵遞區號
|
|
<input id="targetElement" />
|
|
</label>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "postal-code",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "CJK character - Japanese",
|
|
document: `<label> 郵便番号
|
|
<input id="targetElement" />
|
|
</label>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "postal-code",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "CJK character - Korean",
|
|
document: `<label> 우편 번호
|
|
<input id="targetElement" />
|
|
</label>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "postal-code",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "",
|
|
document: `<input id="targetElement" name="fullname">`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "name",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: 'input element with "submit" type',
|
|
document: `<input id="targetElement" type="submit" />`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: null,
|
|
},
|
|
{
|
|
description: "The signature in 'name' attr of an email input",
|
|
document: `<input id="targetElement" name="email" type="number">`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "email",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: 'input element with "email" type',
|
|
document: `<input id="targetElement" type="email" />`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "email",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "Exclude United State string",
|
|
document: `<label>United State
|
|
<input id="targetElement" />
|
|
</label>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: null,
|
|
},
|
|
{
|
|
description: '"County" field with "United State" string',
|
|
document: `<label>United State County
|
|
<input id="targetElement" />
|
|
</label>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "address-level1",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: '"city" field with double "United State" string',
|
|
document: `<label>United State united sTATE city
|
|
<input id="targetElement" />
|
|
</label>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "address-level2",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "Verify credit card number",
|
|
document: `<form>
|
|
<label for="targetElement"> Card Number</label>
|
|
<input id="targetElement" type="text">
|
|
</form>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "cc-number",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
{
|
|
description: "Identify credit card type field",
|
|
document: `<form>
|
|
<label for="targetElement">Card Type</label>
|
|
<input id="targetElement" type="text">
|
|
</form>`,
|
|
elementId: "targetElement",
|
|
expectedReturnValue: {
|
|
fieldName: "cc-type",
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
},
|
|
},
|
|
];
|
|
|
|
TESTCASES.forEach(testcase => {
|
|
add_task(async function() {
|
|
info("Starting testcase: " + testcase.description);
|
|
|
|
let doc = MockDocument.createTestDocument(
|
|
"http://localhost:8080/test/",
|
|
testcase.document
|
|
);
|
|
|
|
let element = doc.getElementById(testcase.elementId);
|
|
let value = FormAutofillHeuristics.getInfo(element);
|
|
|
|
Assert.deepEqual(value, testcase.expectedReturnValue);
|
|
LabelUtils.clearLabelMap();
|
|
});
|
|
});
|
|
|
|
add_task(async function test_regexp_list() {
|
|
info("Verify the fieldName support for select element.");
|
|
let SUPPORT_LIST = {
|
|
email: null, // email
|
|
"tel-extension": null, // tel-extension
|
|
phone: null, // tel
|
|
organization: null, // organization
|
|
"street-address": null, // street-address
|
|
address1: null, // address-line1
|
|
address2: null, // address-line2
|
|
address3: null, // address-line3
|
|
city: "address-level2",
|
|
region: "address-level1",
|
|
"postal-code": null, // postal-code
|
|
country: "country",
|
|
fullname: null, // name
|
|
fname: null, // given-name
|
|
mname: null, // additional-name
|
|
lname: null, // family-name
|
|
"cc-number": null, // cc-number
|
|
addmonth: "cc-exp-month",
|
|
addyear: "cc-exp-year",
|
|
};
|
|
for (let label of Object.keys(SUPPORT_LIST)) {
|
|
let testcase = {
|
|
description: `A select element supports ${label} or not`,
|
|
document: `<select id="${label}"></select>`,
|
|
elementId: label,
|
|
expectedReturnValue: SUPPORT_LIST[label]
|
|
? {
|
|
fieldName: SUPPORT_LIST[label],
|
|
section: "",
|
|
addressType: "",
|
|
contactType: "",
|
|
}
|
|
: null,
|
|
};
|
|
info(testcase.description);
|
|
info(testcase.document);
|
|
let doc = MockDocument.createTestDocument(
|
|
"http://localhost:8080/test/",
|
|
testcase.document
|
|
);
|
|
|
|
let element = doc.getElementById(testcase.elementId);
|
|
let value = FormAutofillHeuristics.getInfo(element);
|
|
|
|
Assert.deepEqual(value, testcase.expectedReturnValue, label);
|
|
}
|
|
LabelUtils.clearLabelMap();
|
|
});
|