Bug 1837367 - Allow file migrators to show an error message if migration failed for some reason. r=kpatenio,desktop-theme-reviewers
The spec calls for a special-case in the event that file migration ever fails - the wizard should be sent back to the selection page, have the associated file migrator still set in the dropdown, and show an error message. A later patch in this series will add such an error message for the bookmarks file migrator. Depends on D180458 Differential Revision: https://phabricator.services.mozilla.com/D180490
This commit is contained in:
@@ -62,6 +62,18 @@ class DummyFileMigrator extends FileMigratorBase {
|
||||
}
|
||||
}
|
||||
|
||||
const { MockFilePicker } = SpecialPowers;
|
||||
|
||||
add_setup(async () => {
|
||||
// We use MockFilePicker to simulate a native file picker, and prepare it
|
||||
// to return a dummy file pointed at TEST_FILE_PATH. The file at
|
||||
// TEST_FILE_PATH is not required (nor expected) to exist.
|
||||
MockFilePicker.init(window);
|
||||
registerCleanupFunction(() => {
|
||||
MockFilePicker.cleanup();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests the flow of selecting a file migrator (in this case,
|
||||
* the DummyFileMigrator), getting the file picker opened for it,
|
||||
@@ -97,15 +109,6 @@ add_task(async function test_file_migration() {
|
||||
return SUCCESS_STATE;
|
||||
});
|
||||
|
||||
// We use MockFilePicker to simulate a native file picker, and prepare it
|
||||
// to return a dummy file pointed at TEST_FILE_PATH. The file at
|
||||
// TEST_FILE_PATH is not required (nor expected) to exist.
|
||||
const { MockFilePicker } = SpecialPowers;
|
||||
MockFilePicker.init(window);
|
||||
registerCleanupFunction(() => {
|
||||
MockFilePicker.cleanup();
|
||||
});
|
||||
|
||||
let dummyFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
dummyFile.initWithPath(TEST_FILE_PATH);
|
||||
let filePickerShownPromise = new Promise(resolve => {
|
||||
@@ -182,4 +185,121 @@ add_task(async function test_file_migration() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the migration wizard will go back to the selection page and
|
||||
* show an error message if the migration for a FileMigrator throws an
|
||||
* exception.
|
||||
*/
|
||||
add_task(async function test_file_migration_error() {
|
||||
let migrator = new DummyFileMigrator();
|
||||
let sandbox = sinon.createSandbox();
|
||||
registerCleanupFunction(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
// First, use Sinon to insert our DummyFileMigrator as the only available
|
||||
// file migrator.
|
||||
sandbox.stub(MigrationUtils, "getFileMigrator").callsFake(() => {
|
||||
return migrator;
|
||||
});
|
||||
sandbox.stub(MigrationUtils, "availableFileMigrators").get(() => {
|
||||
return [migrator];
|
||||
});
|
||||
|
||||
const ERROR_MESSAGE = "This is my error message";
|
||||
|
||||
let migrateStub = sandbox.stub(migrator, "migrate").callsFake(() => {
|
||||
throw new Error(ERROR_MESSAGE);
|
||||
});
|
||||
|
||||
let dummyFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
dummyFile.initWithPath(TEST_FILE_PATH);
|
||||
let filePickerShownPromise = new Promise(resolve => {
|
||||
MockFilePicker.showCallback = () => {
|
||||
Assert.ok(true, "Filepicker shown.");
|
||||
MockFilePicker.setFiles([dummyFile]);
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
|
||||
await withMigrationWizardDialog(async prefsWin => {
|
||||
let dialogBody = prefsWin.document.body;
|
||||
let wizard = dialogBody.querySelector("migration-wizard");
|
||||
let shadow = wizard.openOrClosedShadowRoot;
|
||||
|
||||
let wizardDone = BrowserTestUtils.waitForEvent(
|
||||
wizard,
|
||||
"MigrationWizard:DoneMigration"
|
||||
);
|
||||
|
||||
// Now select our DummyFileMigrator from the list.
|
||||
let selector = shadow.querySelector("#browser-profile-selector");
|
||||
selector.click();
|
||||
|
||||
info("Waiting for panel-list shown");
|
||||
await new Promise(resolve => {
|
||||
wizard
|
||||
.querySelector("panel-list")
|
||||
.addEventListener("shown", resolve, { once: true });
|
||||
});
|
||||
|
||||
info("Panel list shown. Clicking on panel-item");
|
||||
let panelItem = wizard.querySelector(
|
||||
`panel-item[key="${DUMMY_FILEMIGRATOR_KEY}"]`
|
||||
);
|
||||
panelItem.click();
|
||||
|
||||
// Selecting a file migrator from the selector should automatically
|
||||
// open the file picker, so we await it here. Once the file is
|
||||
// selected, migration should begin immediately.
|
||||
|
||||
info("Waiting for file picker");
|
||||
await filePickerShownPromise;
|
||||
await wizardDone;
|
||||
Assert.ok(migrateStub.called, "Migrate on DummyFileMigrator was called.");
|
||||
|
||||
// At this point, with migration having completed, we should be showing
|
||||
// the SELECTION page again with the ERROR_MESSAGE displayed.
|
||||
let deck = shadow.querySelector("#wizard-deck");
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
deck,
|
||||
{ attributeFilter: ["selected-view"] },
|
||||
() => {
|
||||
return (
|
||||
deck.getAttribute("selected-view") ==
|
||||
"page-" + MigrationWizardConstants.PAGES.SELECTION
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
selector.selectedPanelItem.getAttribute("key"),
|
||||
DUMMY_FILEMIGRATOR_KEY,
|
||||
"Should have the file migrator selected."
|
||||
);
|
||||
|
||||
let errorMessageContainer = shadow.querySelector(".file-import-error");
|
||||
|
||||
// Using BrowserTestUtils.is_visible to check for the visibility of the
|
||||
// message seems to throw as it works its way up the ancestry and hits
|
||||
// the shadowRoot. We'll work around this by making sure that the
|
||||
// boundingClientRect has a width and height.
|
||||
let errorRect = errorMessageContainer.getBoundingClientRect();
|
||||
Assert.ok(
|
||||
errorRect.width && errorRect.height,
|
||||
"Should be showing the error message container"
|
||||
);
|
||||
|
||||
let fileImportErrorMessage = shadow.querySelector(
|
||||
"#file-import-error-message"
|
||||
).textContent;
|
||||
Assert.equal(fileImportErrorMessage, ERROR_MESSAGE);
|
||||
});
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
@@ -1139,6 +1139,60 @@
|
||||
""
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that the migration wizard can be put into the selection page after
|
||||
* a file migrator error and show an error message.
|
||||
*/
|
||||
add_task(async function test_file_migrator_error() {
|
||||
const FILE_MIGRATOR_KEY = "some-file-migrator";
|
||||
const FILE_IMPORT_ERROR_MESSAGE = "This is an error message";
|
||||
const MIGRATORS = [
|
||||
{
|
||||
key: "some-browser-0",
|
||||
type: MigrationWizardConstants.MIGRATOR_TYPES.BROWSER,
|
||||
displayName: "Some Browser 0",
|
||||
resourceTypes: ["HISTORY", "FORMDATA", "PASSWORDS", "BOOKMARKS"],
|
||||
profile: { id: "person-2", name: "Person 2" },
|
||||
},
|
||||
{
|
||||
key: "some-browser-1",
|
||||
type: MigrationWizardConstants.MIGRATOR_TYPES.BROWSER,
|
||||
displayName: "Some Browser 1",
|
||||
resourceTypes: ["HISTORY", "BOOKMARKS"],
|
||||
profile: null,
|
||||
},
|
||||
{
|
||||
key: FILE_MIGRATOR_KEY,
|
||||
type: MigrationWizardConstants.MIGRATOR_TYPES.FILE,
|
||||
displayName: "Some File Migrator",
|
||||
resourceTypes: [],
|
||||
},
|
||||
];
|
||||
|
||||
gWiz.setState({
|
||||
page: MigrationWizardConstants.PAGES.SELECTION,
|
||||
migrators: MIGRATORS,
|
||||
showImportAll: true,
|
||||
migratorKey: "some-file-migrator",
|
||||
fileImportErrorMessage: FILE_IMPORT_ERROR_MESSAGE,
|
||||
});
|
||||
|
||||
let errorMessageContainer = gShadowRoot.querySelector(".file-import-error");
|
||||
ok(!isHidden(errorMessageContainer), "Error message should be shown.");
|
||||
let errorText = gShadowRoot.querySelector("#file-import-error-message").textContent;
|
||||
is(errorText, FILE_IMPORT_ERROR_MESSAGE);
|
||||
|
||||
gWiz.setState({
|
||||
page: MigrationWizardConstants.PAGES.SELECTION,
|
||||
migrators: MIGRATORS,
|
||||
showImportAll: true,
|
||||
});
|
||||
|
||||
ok(isHidden(errorMessageContainer), "Error message should be hidden.");
|
||||
errorText = gShadowRoot.querySelector("#file-import-error-message").textContent;
|
||||
is(errorText, "");
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user