tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_autofill_ios_library.js (6725B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 https://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { FormAutofillChild } = ChromeUtils.importESModule(
      7  "resource://autofill/FormAutofillChild.ios.sys.mjs"
      8 );
      9 
     10 const { AutofillTelemetry } = ChromeUtils.importESModule(
     11  "resource://gre/modules/shared/AutofillTelemetry.sys.mjs"
     12 );
     13 
     14 var { FormAutofillHandler } = ChromeUtils.importESModule(
     15  "resource://gre/modules/shared/FormAutofillHandler.sys.mjs"
     16 );
     17 
     18 const TEST_CASES = [
     19  {
     20    description: `basic credit card form`,
     21    document: `<form>
     22                 <input id="cc-number" autocomplete="cc-number">
     23                 <input id="cc-name" autocomplete="cc-name">
     24                 <input id="cc-exp-month" autocomplete="cc-exp-month">
     25                 <input id="cc-exp-year" autocomplete="cc-exp-year">
     26               </form>`,
     27    fillPayload: {
     28      "cc-number": "4111111111111111",
     29      "cc-name": "test name",
     30      "cc-exp-month": 6,
     31      "cc-exp-year": 25,
     32    },
     33 
     34    expectedDetectedFields: {
     35      "cc-number": "",
     36      "cc-name": "",
     37      "cc-exp-month": "",
     38      "cc-exp-year": "",
     39      "cc-type": "",
     40    },
     41 
     42    expectedFill: {
     43      "#cc-number": "4111111111111111",
     44      "#cc-name": "test name",
     45      "#cc-exp-month": 6,
     46      "#cc-exp-year": 25,
     47    },
     48 
     49    expectedSubmit: [
     50      {
     51        "cc-number": "4111111111111111",
     52        "cc-name": "test name",
     53        "cc-exp-month": 6,
     54        "cc-exp-year": 2025,
     55        "cc-type": "visa",
     56      },
     57    ],
     58  },
     59  {
     60    description: `basic address form`,
     61    document: `<form>
     62                 <input id="given-name" autocomplete="given-name">
     63                 <input id="family-name" autocomplete="family-name">
     64                 <input id="street-address" autocomplete="street-address">
     65                 <input id="address-level2" autocomplete="address-level2">
     66                 <select id="country" autocomplete="country">
     67                   <option/>
     68                   <option value="US">United States</option>
     69                 </select>
     70                 <input id="email" autocomplete="email">
     71                 <input id="tel" autocomplete="tel">
     72                <form>`,
     73    fillPayload: {
     74      "street-address": "2 Harrison St line2",
     75      "address-level2": "San Francisco",
     76      country: "US",
     77      email: "foo@mozilla.com",
     78      tel: "1234567",
     79    },
     80 
     81    expectedFill: {
     82      "#street-address": "2 Harrison St line2",
     83      "#address-level2": "San Francisco",
     84      "#country": "US",
     85      "#email": "foo@mozilla.com",
     86      "#tel": "1234567",
     87    },
     88 
     89    expectedDetectedFields: {
     90      "given-name": "",
     91      "family-name": "",
     92      "street-address": "",
     93      "address-level2": "",
     94      country: "",
     95      email: "",
     96      tel: "",
     97    },
     98 
     99    expectedSubmit: null,
    100  },
    101  {
    102    description: `Test correct street-address to address-line1`,
    103    document: `<form>
    104                 <input id="email" autocomplete="email">
    105                 <input id="tel" autocomplete="tel">
    106                 <input id="street-address" >
    107                 <input id="address-line2">
    108                <form>`,
    109    fillPayload: {
    110      "street-address": "2 Harrison St\nline2",
    111      email: "foo@mozilla.com",
    112      tel: "1234567",
    113    },
    114 
    115    expectedFill: {
    116      "#street-address": "2 Harrison St",
    117      "#address-line2": "line2",
    118      "#email": "foo@mozilla.com",
    119      "#tel": "1234567",
    120    },
    121 
    122    expectedDetectedFields: {
    123      email: "",
    124      tel: "",
    125      "address-line1": "",
    126      "address-line2": "",
    127    },
    128 
    129    expectedSubmit: null,
    130  },
    131  {
    132    description: `Test invalid address section`,
    133    document: `<form>
    134                 <input id="email">
    135                <form>`,
    136    fillPayload: {},
    137    expectedFill: false,
    138    expectedDetectedFields: {},
    139 
    140    expectedSubmit: null,
    141  },
    142 ];
    143 
    144 const recordFormInteractionEventStub = sinon.stub(
    145  AutofillTelemetry,
    146  "recordFormInteractionEvent"
    147 );
    148 
    149 add_setup(() => {
    150  registerCleanupFunction(() => sinon.restore());
    151 });
    152 
    153 add_task(async function test_ios_api() {
    154  for (const TEST of TEST_CASES) {
    155    info(`Test ${TEST.description}`);
    156    const doc = MockDocument.createTestDocument(
    157      "http://localhost:8080/test/",
    158      TEST.document
    159    );
    160 
    161    const autofillSpy = sinon.spy();
    162    const submitSpy = sinon.spy();
    163 
    164    const fac = new FormAutofillChild({
    165      address: {
    166        autofill: autofillSpy,
    167        submit: submitSpy,
    168      },
    169      creditCard: {
    170        autofill: autofillSpy,
    171        submit: submitSpy,
    172      },
    173    });
    174 
    175    // Test `onFocusIn` API
    176    fac.onFocusIn({ target: doc.querySelector("input") });
    177 
    178    if (TEST.expectedFill) {
    179      Assert.ok(
    180        autofillSpy.calledOnce,
    181        "autofill callback should be called once"
    182      );
    183      Assert.ok(
    184        autofillSpy.calledWithExactly(TEST.expectedDetectedFields),
    185        "autofill callback should be called with correct payload"
    186      );
    187      Assert.ok(
    188        recordFormInteractionEventStub.calledWithMatch("detected"),
    189        "detect telemetry event should be recorded"
    190      );
    191 
    192      // Test `fillFormFields` API
    193      fac.fillFormFields(TEST.fillPayload);
    194      Object.entries(TEST.expectedFill).forEach(([selector, expectedValue]) => {
    195        const element = doc.querySelector(selector);
    196        Assert.equal(
    197          element.value,
    198          expectedValue,
    199          `Should fill ${element.id} field correctly`
    200        );
    201      });
    202      Assert.ok(
    203        recordFormInteractionEventStub.calledWithMatch("filled"),
    204        "filled telemetry event should be recorded"
    205      );
    206 
    207      // Test `onFilledModified` API
    208      Object.entries(TEST.expectedFill).forEach(([selector, expectedValue]) => {
    209        const element = doc.querySelector(selector);
    210        // Simulate input change (e.g. adding a char)
    211        FormAutofillHandler.fillFieldValue(element, expectedValue + "a");
    212        Assert.ok(
    213          recordFormInteractionEventStub.calledWithMatch("filled_modified"),
    214          "filled_modified telemetry event should be recorded"
    215        );
    216        FormAutofillHandler.fillFieldValue(element, expectedValue);
    217      });
    218    } else {
    219      Assert.ok(
    220        autofillSpy.notCalled,
    221        "autofill callback should not be called when section is invalid"
    222      );
    223    }
    224 
    225    // Test `onSubmit` API
    226    if (TEST.expectedSubmit) {
    227      fac.onSubmit();
    228      Assert.ok(submitSpy.calledOnce, "submit callback should be called once");
    229      Assert.ok(
    230        submitSpy.calledWithExactly(TEST.expectedSubmit),
    231        "submit callback should be called with correct payload"
    232      );
    233      Assert.ok(
    234        recordFormInteractionEventStub.calledWithMatch("submitted"),
    235        "submitted telemetry event should be recorded"
    236      );
    237    }
    238  }
    239 });