diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/components/passwordmgr/test/browser/browser_autocomplete_import.js | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/passwordmgr/test/browser/browser_autocomplete_import.js')
-rw-r--r-- | toolkit/components/passwordmgr/test/browser/browser_autocomplete_import.js | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/toolkit/components/passwordmgr/test/browser/browser_autocomplete_import.js b/toolkit/components/passwordmgr/test/browser/browser_autocomplete_import.js new file mode 100644 index 0000000000..0be137d88d --- /dev/null +++ b/toolkit/components/passwordmgr/test/browser/browser_autocomplete_import.js @@ -0,0 +1,259 @@ +const { ChromeMigrationUtils } = ChromeUtils.importESModule( + "resource:///modules/ChromeMigrationUtils.sys.mjs" +); +const { ExperimentAPI } = ChromeUtils.importESModule( + "resource://nimbus/ExperimentAPI.sys.mjs" +); +const { ExperimentFakes } = ChromeUtils.importESModule( + "resource://testing-common/NimbusTestUtils.sys.mjs" +); +const { sinon } = ChromeUtils.importESModule( + "resource://testing-common/Sinon.sys.mjs" +); + +// Dummy migrator to change and detect importable behavior. +const gTestMigrator = { + profiles: [], + + getSourceProfiles() { + return this.profiles; + }, + + migrate: sinon + .stub() + .callsFake(() => + LoginTestUtils.addLogin({ username: "import", password: "pass" }) + ), +}; + +// Showing importables updates counts delayed, so adjust and cleanup. +add_setup(async function setup() { + const debounce = sinon + .stub(LoginManagerParent, "SUGGEST_IMPORT_DEBOUNCE_MS") + .value(0); + const importable = sinon + .stub(ChromeMigrationUtils, "getImportableLogins") + .resolves(["chrome"]); + const migrator = sinon + .stub(MigrationUtils, "getMigrator") + .resolves(gTestMigrator); + + const doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({ + featureId: "password-autocomplete", + value: { directMigrateSingleProfile: true }, + }); + + // This makes the last autocomplete test *not* show import suggestions. + Services.prefs.setIntPref("signon.suggestImportCount", 3); + + registerCleanupFunction(async () => { + await doExperimentCleanup(); + debounce.restore(); + importable.restore(); + migrator.restore(); + Services.prefs.clearUserPref("signon.suggestImportCount"); + }); +}); + +add_task(async function check_fluent_ids() { + await document.l10n.ready; + MozXULElement.insertFTLIfNeeded("toolkit/main-window/autocomplete.ftl"); + + const host = "testhost.com"; + for (const browser of ChromeMigrationUtils.CONTEXTUAL_LOGIN_IMPORT_BROWSERS) { + const id = `autocomplete-import-logins-${browser}`; + const message = await document.l10n.formatValue(id, { host }); + Assert.ok( + message.includes(`data-l10n-name="line1"`), + `${id} included line1` + ); + Assert.ok( + message.includes(`data-l10n-name="line2"`), + `${id} included line2` + ); + Assert.ok(message.includes(host), `${id} replaced host`); + } +}); + +/** + * Tests that if the user selects the password import suggestion from + * the autocomplete popup, and there is more than one profile available + * to import from, that the migration wizard opens to guide the user + * through importing those logins. + */ +add_task(async function import_suggestion_wizard() { + let wizard; + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "https://example.com" + DIRECTORY_PATH + "form_basic.html", + }, + async function (browser) { + const popup = document.getElementById("PopupAutoComplete"); + Assert.ok(popup, "Got popup"); + await openACPopup(popup, browser, "#form-basic-username"); + + const importableItem = popup.querySelector( + `[originaltype="importableLogins"]` + ); + Assert.ok(importableItem, "Got importable suggestion richlistitem"); + + await BrowserTestUtils.waitForCondition( + () => !importableItem.collapsed, + "Wait for importable suggestion to show" + ); + + // Pretend there's 2+ profiles to trigger the wizard. + gTestMigrator.profiles.length = 2; + + info("Clicking on importable suggestion"); + const wizardPromise = BrowserTestUtils.waitForMigrationWizard(window); + + // The modal window blocks execution, so avoid calling directly. + executeSoon(() => EventUtils.synthesizeMouseAtCenter(importableItem, {})); + + wizard = await wizardPromise; + Assert.ok(wizard, "Wizard opened"); + Assert.equal( + gTestMigrator.migrate.callCount, + 0, + "Direct migrate not used" + ); + + await closePopup(popup); + } + ); + + // Close the wizard in the end of the test. If we close the wizard when the tab + // is still opened, the username field will be focused again, which triggers another + // importable suggestion. + await BrowserTestUtils.closeMigrationWizard(wizard); +}); + +add_task(async function import_suggestion_learn_more() { + let supportTab; + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "https://example.com" + DIRECTORY_PATH + "form_basic.html", + }, + async function (browser) { + const popup = document.getElementById("PopupAutoComplete"); + Assert.ok(popup, "Got popup"); + await openACPopup(popup, browser, "#form-basic-username"); + + const learnMoreItem = popup.querySelector(`[type="importableLearnMore"]`); + Assert.ok(learnMoreItem, "Got importable learn more richlistitem"); + + await BrowserTestUtils.waitForCondition( + () => !learnMoreItem.collapsed, + "Wait for importable learn more to show" + ); + + info("Clicking on importable learn more"); + const supportTabPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + Services.urlFormatter.formatURLPref("app.support.baseURL") + + "password-import" + ); + EventUtils.synthesizeMouseAtCenter(learnMoreItem, {}); + supportTab = await supportTabPromise; + Assert.ok(supportTab, "Support tab opened"); + + await closePopup(popup); + } + ); + + // Close the tab in the end of the test to avoid the username field being + // focused again. + await BrowserTestUtils.removeTab(supportTab); +}); + +add_task(async function import_suggestion_migrate() { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "https://example.com" + DIRECTORY_PATH + "form_basic.html", + }, + async function (browser) { + const popup = document.getElementById("PopupAutoComplete"); + Assert.ok(popup, "Got popup"); + await openACPopup(popup, browser, "#form-basic-username"); + + const importableItem = popup.querySelector( + `[originaltype="importableLogins"]` + ); + Assert.ok(importableItem, "Got importable suggestion richlistitem"); + + await BrowserTestUtils.waitForCondition( + () => !importableItem.collapsed, + "Wait for importable suggestion to show" + ); + + // Pretend there's 1 profile to trigger migrate. + gTestMigrator.profiles.length = 1; + + info("Clicking on importable suggestion"); + const migratePromise = BrowserTestUtils.waitForCondition( + () => gTestMigrator.migrate.callCount, + "Wait for direct migration attempt" + ); + EventUtils.synthesizeMouseAtCenter(importableItem, {}); + + const callCount = await migratePromise; + Assert.equal(callCount, 1, "Direct migrate used once"); + + const importedItem = await BrowserTestUtils.waitForCondition( + () => popup.querySelector(`[originaltype="loginWithOrigin"]`), + "Wait for imported login to show" + ); + EventUtils.synthesizeMouseAtCenter(importedItem, {}); + + const username = await SpecialPowers.spawn( + browser, + [], + () => content.document.getElementById("form-basic-username").value + ); + Assert.equal(username, "import", "username from import filled in"); + + LoginTestUtils.clearData(); + } + ); +}); + +add_task(async function import_suggestion_not_shown() { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "https://example.com" + DIRECTORY_PATH + "form_basic.html", + }, + async function (browser) { + const popup = document.getElementById("PopupAutoComplete"); + Assert.ok(popup, "Got popup"); + let opened = false; + openACPopup(popup, browser, "#form-basic-password").then( + () => (opened = true) + ); + + await TestUtils.waitForCondition(() => { + EventUtils.synthesizeKey("KEY_ArrowDown"); + return opened; + }); + + const footer = popup.querySelector(`[originaltype="loginsFooter"]`); + Assert.ok(footer, "Got footer richlistitem"); + + await TestUtils.waitForCondition(() => { + return !EventUtils.isHidden(footer); + }, "Waiting for footer to become visible"); + + Assert.ok( + !popup.querySelector(`[originaltype="importableLogins"]`), + "No importable suggestion shown" + ); + + await closePopup(popup); + } + ); +}); |