Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

const { ChromeMigrationUtils } = ChromeUtils.importESModule(
"resource:///modules/ChromeMigrationUtils.sys.mjs"
);
const { ExperimentAPI } = ChromeUtils.importESModule(
"resource://nimbus/ExperimentAPI.sys.mjs"
);
const { ExperimentFakes } = ChromeUtils.importESModule(
);
const { sinon } = ChromeUtils.importESModule(
);
// 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(() => {
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 wizardTab;
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);
EventUtils.synthesizeMouseAtCenter(importableItem, {});
wizardTab = await wizardPromise;
Assert.ok(wizardTab, "Wizard opened");
Assert.equal(
gTestMigrator.migrate.callCount,
0,
"Direct migrate not used"
);
await closePopup(popup);
}
);
// Close the wizard tab 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.removeTab(wizardTab);
});
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);
}
);
});