Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
"use strict";
var { ExtensionTestUtils } = ChromeUtils.importESModule(
);
var { AddonTestUtils } = ChromeUtils.importESModule(
);
ExtensionTestUtils.mockAppInfo();
AddonTestUtils.maybeInit(this);
registerCleanupFunction(async () => {
// Remove the temporary MozillaMailnews folder, which is not deleted in time when
// the cleanupFunction registered by AddonTestUtils.maybeInit() checks for left over
// files in the temp folder.
// Note: PathUtils.tempDir points to the system temp folder, which is different.
const path = PathUtils.join(
Services.dirsvc.get("TmpD", Ci.nsIFile).path,
"MozillaMailnews"
);
await IOUtils.remove(path, { recursive: true });
});
// Test events and persistent events for Manifest V3 for onCreated, onRenamed,
// onMoved, onCopied and onDeleted.
add_task(
{
skip_if: () => IS_NNTP,
},
async function test_folders_MV3_event_pages() {
await AddonTestUtils.promiseStartupManager();
const account = createAccount();
const rootFolder = account.incomingServer.rootFolder;
addIdentity(account, "id1@invalid");
const files = {
"background.js": () => {
for (const eventName of [
"onCreated",
"onDeleted",
"onCopied",
"onRenamed",
"onMoved",
]) {
browser.folders[eventName].addListener(async (...args) => {
browser.test.log(`${eventName} received: ${JSON.stringify(args)}`);
browser.test.sendMessage(`${eventName} received`, args);
});
}
browser.test.sendMessage("background started");
},
"utils.js": await getUtilsJS(),
};
const extension = ExtensionTestUtils.loadExtension({
files,
manifest: {
manifest_version: 3,
background: { scripts: ["utils.js", "background.js"] },
permissions: ["accountsRead"],
},
});
// Function to start an event page extension (MV3), which can be called whenever
// the main test is about to trigger an event. The extension terminates its
// background and listens for that single event, verifying it is waking up correctly.
async function event_page_extension(eventName, actionCallback) {
const ext = ExtensionTestUtils.loadExtension({
files: {
"background.js": async () => {
// Whenever the extension starts or wakes up, hasFired is set to false. In
// case of a wake-up, the first fired event is the one that woke up the background.
let hasFired = false;
const _eventName = browser.runtime.getManifest().description;
browser.folders[_eventName].addListener(async (...args) => {
// Only send the first event after background wake-up, this should
// be the only one expected.
if (!hasFired) {
hasFired = true;
browser.test.sendMessage(`${_eventName} received`, args);
}
});
browser.test.sendMessage("background started");
},
},
manifest: {
manifest_version: 3,
description: eventName,
background: { scripts: ["background.js"] },
permissions: ["accountsRead"],
},
});
await ext.startup();
await ext.awaitMessage("background started");
// The listener should be persistent, but not primed.
assertPersistentListeners(ext, "folders", eventName, { primed: false });
await ext.terminateBackground({ disableResetIdleForTest: true });
// Verify the primed persistent listener.
assertPersistentListeners(ext, "folders", eventName, { primed: true });
await actionCallback();
const rv = await ext.awaitMessage(`${eventName} received`);
await ext.awaitMessage("background started");
// The listener should be persistent, but not primed.
assertPersistentListeners(ext, "folders", eventName, { primed: false });
await ext.unload();
return rv;
}
await extension.startup();
await extension.awaitMessage("background started");
// Create a test folder before terminating the background script, to make sure
// everything is sane.
rootFolder.createSubfolder("TestFolder", null);
await extension.awaitMessage("onCreated received");
if (IS_IMAP) {
// IMAP creates a default Trash folder on the fly.
await extension.awaitMessage("onCreated received");
}
// Create SubFolder1.
{
rootFolder.createSubfolder("SubFolder1", null);
const createData = await extension.awaitMessage("onCreated received");
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder1`,
accountId: account.key,
name: "SubFolder1",
path: "/SubFolder1",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
createData,
"The onCreated event should return the correct values"
);
}
// Create SubFolder2 (used for primed onFolderInfoChanged).
{
const primedChangeData = await event_page_extension(
"onFolderInfoChanged",
() => {
rootFolder.createSubfolder("SubFolder3", null);
}
);
const createData = await extension.awaitMessage("onCreated received");
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
createData,
"The onCreated event should return the correct values"
);
// Testing for onFolderInfoChanged is difficult, because it may not be for
// the last created folder, but for one of the folders created earlier. We
// therefore do not check the folder, but only the value.
Assert.deepEqual(
{ totalMessageCount: 0, unreadMessageCount: 0 },
primedChangeData[1],
"The primed onFolderInfoChanged event should return the correct values"
);
}
// Copy.
{
const primedCopyData = await event_page_extension("onCopied", () => {
MailServices.copy.copyFolder(
rootFolder.getChildNamed("SubFolder3"),
rootFolder.getChildNamed("SubFolder1"),
false,
null,
null
);
});
const copyData = await extension.awaitMessage("onCopied received");
Assert.deepEqual(
primedCopyData,
copyData,
"The primed onCopied event should return the correct values"
);
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
{
id: `${account.key}://SubFolder1/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder1/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
copyData,
"The onCopied event should return the correct values"
);
if (IS_IMAP) {
// IMAP fires an additional create event.
const createData = await extension.awaitMessage("onCreated received");
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder1/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder1/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
createData,
"The onCreated event should return the correct MailFolder values."
);
}
}
// Move.
{
const primedMoveData = await event_page_extension("onMoved", () => {
MailServices.copy.copyFolder(
rootFolder.getChildNamed("SubFolder1").getChildNamed("SubFolder3"),
rootFolder.getChildNamed("SubFolder3"),
true,
null,
null
);
});
const moveData = await extension.awaitMessage("onMoved received");
Assert.deepEqual(
primedMoveData,
moveData,
"The primed onMoved event should return the correct values"
);
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder1/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder1/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
{
id: `${account.key}://SubFolder3/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder3/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
moveData,
"The onMoved event should return the correct values"
);
if (IS_IMAP) {
// IMAP fires additional rename and delete events.
const renameData = await extension.awaitMessage("onRenamed received");
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder1/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder1/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
{
id: `${account.key}://SubFolder3/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder3/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
renameData,
"The onRenamed event should return the correct MailFolder values."
);
const deleteData = await extension.awaitMessage("onDeleted received");
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder1/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder1/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
deleteData,
"The onDeleted event should return the correct MailFolder values."
);
}
}
// Delete.
{
const primedDeleteData = await event_page_extension("onDeleted", () => {
const subFolder1 = rootFolder.getChildNamed("SubFolder3");
subFolder1.propagateDelete(
subFolder1.getChildNamed("SubFolder3"),
true
);
});
const deleteData = await extension.awaitMessage("onDeleted received");
Assert.deepEqual(
primedDeleteData,
deleteData,
"The primed onDeleted event should return the correct values"
);
Assert.deepEqual(
[
{
id: `${account.key}://SubFolder3/SubFolder3`,
accountId: account.key,
name: "SubFolder3",
path: "/SubFolder3/SubFolder3",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
deleteData,
"The onDeleted event should return the correct values"
);
}
// Rename.
{
const primedRenameData = await event_page_extension("onRenamed", () => {
rootFolder.getChildNamed("TestFolder").rename("TestFolder2", null);
});
const renameData = await extension.awaitMessage("onRenamed received");
Assert.deepEqual(
primedRenameData,
renameData,
"The primed onRenamed event should return the correct values"
);
if (IS_IMAP) {
// IMAP server sends an additional onDeleted and onCreated.
await extension.awaitMessage("onDeleted received");
await extension.awaitMessage("onCreated received");
}
Assert.deepEqual(
[
{
id: `${account.key}://TestFolder`,
accountId: account.key,
name: "TestFolder",
path: "/TestFolder",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
{
id: `${account.key}://TestFolder2`,
accountId: account.key,
name: "TestFolder2",
path: "/TestFolder2",
specialUse: [],
isFavorite: false,
isRoot: false,
isTag: false,
isUnified: false,
isVirtual: false,
},
],
renameData,
"The onRenamed event should return the correct values"
);
}
await extension.unload();
cleanUpAccount(account);
await AddonTestUtils.promiseShutdownManager();
}
);