From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../creditCard/browser_editCreditCardDialog.js | 422 +++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 browser/extensions/formautofill/test/browser/creditCard/browser_editCreditCardDialog.js (limited to 'browser/extensions/formautofill/test/browser/creditCard/browser_editCreditCardDialog.js') diff --git a/browser/extensions/formautofill/test/browser/creditCard/browser_editCreditCardDialog.js b/browser/extensions/formautofill/test/browser/creditCard/browser_editCreditCardDialog.js new file mode 100644 index 0000000000..f532ea5da9 --- /dev/null +++ b/browser/extensions/formautofill/test/browser/creditCard/browser_editCreditCardDialog.js @@ -0,0 +1,422 @@ +"use strict"; + +add_setup(async function () { + let { formAutofillStorage } = ChromeUtils.importESModule( + "resource://autofill/FormAutofillStorage.sys.mjs" + ); + await formAutofillStorage.initialize(); +}); + +add_task(async function test_cancelEditCreditCardDialog() { + await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, win => { + win.document.querySelector("#cancel").click(); + }); +}); + +add_task(async function test_cancelEditCreditCardDialogWithESC() { + await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, win => { + EventUtils.synthesizeKey("VK_ESCAPE", {}, win); + }); +}); + +add_task(async function test_saveCreditCard() { + await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, win => { + ok( + win.document.documentElement + .querySelector("title") + .textContent.includes("Add"), + "Add card dialog title is correct" + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-number"], {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey( + "0" + TEST_CREDIT_CARD_1["cc-exp-month"].toString(), + {}, + win + ); + is( + win.document.activeElement.selectedOptions[0].text, + "04 - April", + "Displayed month should match number and name" + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey( + TEST_CREDIT_CARD_1["cc-exp-year"].toString(), + {}, + win + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey(TEST_CREDIT_CARD_1["cc-name"], {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + info("saving credit card"); + EventUtils.synthesizeKey("VK_RETURN", {}, win); + }); + let creditCards = await getCreditCards(); + + is(creditCards.length, 1, "only one credit card is in storage"); + for (let [fieldName, fieldValue] of Object.entries(TEST_CREDIT_CARD_1)) { + if (fieldName === "cc-number") { + fieldValue = "*".repeat(fieldValue.length - 4) + fieldValue.substr(-4); + } + is(creditCards[0][fieldName], fieldValue, "check " + fieldName); + } + is(creditCards[0].billingAddressGUID, undefined, "check billingAddressGUID"); + ok(creditCards[0]["cc-number-encrypted"], "cc-number-encrypted exists"); +}); + +add_task(async function test_saveCreditCardWithMaxYear() { + await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, win => { + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey(TEST_CREDIT_CARD_2["cc-number"], {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey( + TEST_CREDIT_CARD_2["cc-exp-month"].toString(), + {}, + win + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey( + TEST_CREDIT_CARD_2["cc-exp-year"].toString(), + {}, + win + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey(TEST_CREDIT_CARD_2["cc-name"], {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + info("saving credit card"); + EventUtils.synthesizeKey("VK_RETURN", {}, win); + }); + let creditCards = await getCreditCards(); + + is(creditCards.length, 2, "Two credit cards are in storage"); + for (let [fieldName, fieldValue] of Object.entries(TEST_CREDIT_CARD_2)) { + if (fieldName === "cc-number") { + fieldValue = "*".repeat(fieldValue.length - 4) + fieldValue.substr(-4); + } + is(creditCards[1][fieldName], fieldValue, "check " + fieldName); + } + ok(creditCards[1]["cc-number-encrypted"], "cc-number-encrypted exists"); + await removeCreditCards([creditCards[1].guid]); +}); + +add_task(async function test_saveCreditCardWithBillingAddress() { + await setStorage(TEST_ADDRESS_4, TEST_ADDRESS_1); + let addresses = await getAddresses(); + let billingAddress = addresses[0]; + + const TEST_CREDIT_CARD = Object.assign({}, TEST_CREDIT_CARD_2, { + billingAddressGUID: undefined, + }); + + await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, win => { + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-number"], {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey( + TEST_CREDIT_CARD["cc-exp-month"].toString(), + {}, + win + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey( + TEST_CREDIT_CARD["cc-exp-year"].toString(), + {}, + win + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey(TEST_CREDIT_CARD["cc-name"], {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey(billingAddress["given-name"], {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + info("saving credit card"); + EventUtils.synthesizeKey("VK_RETURN", {}, win); + }); + let creditCards = await getCreditCards(); + + is(creditCards.length, 2, "Two credit cards are in storage"); + for (let [fieldName, fieldValue] of Object.entries(TEST_CREDIT_CARD)) { + if (fieldName === "cc-number") { + fieldValue = "*".repeat(fieldValue.length - 4) + fieldValue.substr(-4); + } + is(creditCards[1][fieldName], fieldValue, "check " + fieldName); + } + ok(creditCards[1]["cc-number-encrypted"], "cc-number-encrypted exists"); + await removeCreditCards([creditCards[1].guid]); + await removeAddresses([addresses[0].guid, addresses[1].guid]); +}); + +add_task(async function test_editCreditCard() { + let creditCards = await getCreditCards(); + is(creditCards.length, 1, "only one credit card is in storage"); + await testDialog( + EDIT_CREDIT_CARD_DIALOG_URL, + win => { + ok( + win.document.documentElement + .querySelector("title") + .textContent.includes("Edit"), + "Edit card dialog title is correct" + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_RIGHT", {}, win); + EventUtils.synthesizeKey("test", {}, win); + win.document.querySelector("#save").click(); + }, + { + record: creditCards[0], + } + ); + ok(true, "Edit credit card dialog is closed"); + creditCards = await getCreditCards(); + + is(creditCards.length, 1, "only one credit card is in storage"); + is( + creditCards[0]["cc-name"], + TEST_CREDIT_CARD_1["cc-name"] + "test", + "cc name changed" + ); + await removeCreditCards([creditCards[0].guid]); + + creditCards = await getCreditCards(); + is(creditCards.length, 0, "Credit card storage is empty"); +}); + +add_task(async function test_editCreditCardWithMissingBillingAddress() { + const TEST_CREDIT_CARD = Object.assign({}, TEST_CREDIT_CARD_2, { + billingAddressGUID: "unknown-guid", + }); + await setStorage(TEST_CREDIT_CARD); + + let creditCards = await getCreditCards(); + is(creditCards.length, 1, "one credit card in storage"); + is( + creditCards[0].billingAddressGUID, + TEST_CREDIT_CARD.billingAddressGUID, + "Check saved billingAddressGUID" + ); + await testDialog( + EDIT_CREDIT_CARD_DIALOG_URL, + win => { + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_RIGHT", {}, win); + EventUtils.synthesizeKey("test", {}, win); + win.document.querySelector("#save").click(); + }, + { + record: creditCards[0], + } + ); + ok(true, "Edit credit card dialog is closed"); + creditCards = await getCreditCards(); + + is(creditCards.length, 1, "only one credit card is in storage"); + is( + creditCards[0]["cc-name"], + TEST_CREDIT_CARD["cc-name"] + "test", + "cc name changed" + ); + is( + creditCards[0].billingAddressGUID, + undefined, + "unknown GUID removed upon manual save" + ); + await removeCreditCards([creditCards[0].guid]); + + creditCards = await getCreditCards(); + is(creditCards.length, 0, "Credit card storage is empty"); +}); + +add_task(async function test_addInvalidCreditCard() { + await testDialog(EDIT_CREDIT_CARD_DIALOG_URL, async win => { + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("test", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("test name", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeMouseAtCenter( + win.document.querySelector("#save"), + {}, + win + ); + + is( + win.document.querySelector("form").checkValidity(), + false, + "cc-number is invalid" + ); + await ensureCreditCardDialogNotClosed(win); + info("closing"); + win.close(); + }); + info("closed"); + let creditCards = await getCreditCards(); + + is(creditCards.length, 0, "Credit card storage is empty"); +}); + +add_task(async function test_editInvalidCreditCardNumber() { + await setStorage(TEST_ADDRESS_4); + let addresses = await getAddresses(); + let billingAddress = addresses[0]; + + const INVALID_CREDIT_CARD_NUMBER = "123456789"; + const TEST_CREDIT_CARD = Object.assign({}, TEST_CREDIT_CARD_2, { + billingAddressGUID: billingAddress.guid, + guid: "invalid-number", + version: 2, + "cc-number": INVALID_CREDIT_CARD_NUMBER, + }); + + // Directly use FormAutofillStorage so we can set + // sourceSync: true, since saveCreditCard uses FormAutofillParent + // which doesn't expose this option. + let { formAutofillStorage } = ChromeUtils.importESModule( + "resource://autofill/FormAutofillStorage.sys.mjs" + ); + await formAutofillStorage.initialize(); + // Use `sourceSync: true` to bypass field normalization which will + // fail due to the invalid credit card number. + await formAutofillStorage.creditCards.add(TEST_CREDIT_CARD, { + sourceSync: true, + }); + + let creditCards = await getCreditCards(); + is(creditCards.length, 1, "only one credit card is in storage"); + is( + creditCards[0]["cc-number"], + "*********", + "invalid credit card number stored" + ); + await testDialog( + EDIT_CREDIT_CARD_DIALOG_URL, + win => { + is( + win.document.querySelector("#cc-number").value, + INVALID_CREDIT_CARD_NUMBER, + "cc-number field should be showing invalid credit card number" + ); + is( + win.document.querySelector("#cc-number").checkValidity(), + false, + "cc-number is invalid" + ); + win.document.querySelector("#cancel").click(); + }, + { + record: creditCards[0], + skipDecryption: true, + } + ); + ok(true, "Edit credit card dialog is closed"); + creditCards = await getCreditCards(); + + is(creditCards.length, 1, "only one credit card is in storage"); + is( + creditCards[0]["cc-number"], + "*********", + "invalid cc number still in record" + ); + await removeCreditCards([creditCards[0].guid]); + await removeAddresses([addresses[0].guid]); + + creditCards = await getCreditCards(); + is(creditCards.length, 0, "Credit card storage is empty"); + addresses = await getAddresses(); + is(addresses.length, 0, "Address storage is empty"); +}); + +add_task(async function test_editCreditCardWithInvalidNumber() { + const TEST_CREDIT_CARD = Object.assign({}, TEST_CREDIT_CARD_1); + await setStorage(TEST_CREDIT_CARD); + + let creditCards = await getCreditCards(); + is(creditCards.length, 1, "only one credit card is in storage"); + await testDialog( + EDIT_CREDIT_CARD_DIALOG_URL, + win => { + ok( + win.document.documentElement + .querySelector("title") + .textContent.includes("Edit"), + "Edit card dialog title is correct" + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + is( + win.document.querySelector("#cc-number").validity.customError, + false, + "cc-number field should not have a custom error" + ); + EventUtils.synthesizeKey("4111111111111112", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + is( + win.document.querySelector("#cc-number").validity.customError, + true, + "cc-number field should have a custom error" + ); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + win.document.querySelector("#cancel").click(); + }, + { + record: creditCards[0], + } + ); + ok(true, "Edit credit card dialog is closed"); + creditCards = await getCreditCards(); + + is(creditCards.length, 1, "only one credit card is in storage"); + await removeCreditCards([creditCards[0].guid]); + + creditCards = await getCreditCards(); + is(creditCards.length, 0, "Credit card storage is empty"); +}); + +add_task(async function test_noAutocompletePopupOnSystemTab() { + await setStorage(TEST_CREDIT_CARD_1); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: PRIVACY_PREF_URL }, + async browser => { + // Open credit card manage dialog + await SpecialPowers.spawn(browser, [], async () => { + let button = content.document.querySelector( + "#creditCardAutofill button" + ); + button.click(); + }); + let dialog = await waitForSubDialogLoad( + content, + MANAGE_CREDIT_CARDS_DIALOG_URL + ); + + // Open edit credit card dialog + await SpecialPowers.spawn(dialog, [], async () => { + let button = content.document.querySelector("#add"); + button.click(); + }); + dialog = await waitForSubDialogLoad(content, EDIT_CREDIT_CARD_DIALOG_URL); + + // Focus on credit card number field + await SpecialPowers.spawn(dialog, [], async () => { + let number = content.document.querySelector("#cc-number"); + number.focus(); + }); + + // autocomplete popup should not appear + await ensureNoAutocompletePopup(browser); + } + ); + + await removeAllRecords(); +}); -- cgit v1.2.3