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
const { PromiseTestUtils } = ChromeUtils.importESModule(
);
const { RemoteFolder } = ChromeUtils.importESModule(
);
const { ServerTestUtils } = ChromeUtils.importESModule(
);
const { TestUtils } = ChromeUtils.importESModule(
);
add_task(async function testLocal() {
const localAccount = MailServices.accounts.createLocalMailAccount();
const localRoot = localAccount.incomingServer.rootFolder;
localRoot.createSubfolder("exists", null);
await checkSucceeds(localRoot, "test Ϟ");
await checkFails(localRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
await checkFails(localRoot, "exists", /NS_MSG_FOLDER_EXISTS/);
// Check the deprecated sync function.
await checkSucceedsSync(localRoot, "test ϰ");
await checkThrowsSync(localRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
await checkThrowsSync(localRoot, "exists", /NS_MSG_FOLDER_EXISTS/);
Assert.deepEqual(
localRoot.subFolders.map(f => f.name).toSorted(),
["Trash", "Unsent Messages", "exists", "test Ϟ", "test ϰ"],
"these folders should exist on the local account after the test"
);
});
add_task(async function testIMAP() {
const mockServer = await ServerTestUtils.createServer({ type: "imap" });
const imapAccount = MailServices.accounts.createAccount();
const imapServer = (imapAccount.incomingServer =
MailServices.accounts.createIncomingServer("user", "localhost", "imap"));
imapServer.port = mockServer.port;
imapServer.password = "password";
const imapRoot = imapServer.rootFolder;
const testFolder = await checkSucceeds(imapRoot, "test Ϟ", "test &A94-");
await checkFails(imapRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
mockServer.daemon.createMailbox("exists");
await checkFails(imapRoot, "exists", /NS_MSG_ERROR_IMAP_COMMAND_FAILED/);
// IMAP-only checks.
// These return early instead of going to the server.
await checkFails(imapRoot, "inBOx", /NS_MSG_FOLDER_EXISTS/); // Case-insensitive.
await checkFails(imapRoot, "Trash", /NS_MSG_FOLDER_EXISTS/); // Case-sensitive.
// These are the same but not on the root, so they should succeed.
await checkSucceeds(testFolder, "INBOX");
// await checkSucceeds(testFolder, "Trash");
// Check we get an error while offline.
imapServer.closeCachedConnections();
Services.io.offline = true;
await checkFails(imapRoot, "offline", /NS_MSG_ERROR_OFFLINE/);
Services.io.offline = false;
// Check the deprecated sync function.
await checkSucceedsSync(imapRoot, "test ϰ", "test &A,A-");
await checkThrowsSync(imapRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
await checkFailsSync(imapRoot, "exists");
Assert.deepEqual(
mockServer.daemon.root.allChildren.map(m => m.fullName).toSorted(),
[
"INBOX",
"Trash",
"exists",
"test Ϟ",
"test Ϟ/INBOX",
// "test Ϟ/Trash",
"test ϰ",
],
"these mailboxes should exist on the IMAP server after the test"
);
});
add_task(async function testEWS() {
const mockServer = await ServerTestUtils.createServer({ type: "ews" });
mockServer.setRemoteFolders(mockServer.getWellKnownFolders());
const ewsAccount = MailServices.accounts.createAccount();
const ewsServer = (ewsAccount.incomingServer =
MailServices.accounts.createIncomingServer("user", "localhost", "ews"));
ewsServer.port = mockServer.port;
ewsServer.password = "password";
ewsServer.setStringValue(
"ews_url",
);
ewsServer.performExpand(null);
await TestUtils.waitForCondition(
() => ewsServer.rootFolder.getChildNamed("Drafts"),
"waiting for folder sync to finish"
);
const ewsRoot = ewsServer.rootFolder;
await checkSucceeds(ewsRoot, "test Ϟ");
await checkFails(ewsRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
mockServer.appendRemoteFolder(new RemoteFolder("exists", "root"));
await checkFails(ewsRoot, "exists", /NS_ERROR_UNEXPECTED/);
// Check we get an error while offline.
ewsServer.closeCachedConnections();
Services.io.offline = true;
await checkFails(ewsRoot, "offline", /NS_MSG_ERROR_OFFLINE/);
Services.io.offline = false;
// Check the deprecated sync function.
await checkSucceedsSync(ewsRoot, "test ϰ");
await checkThrowsSync(ewsRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
// await checkFailsSync(ewsRoot, "exists");
Assert.deepEqual(
mockServer.folders.map(f => f.displayName).toSorted(),
[
"Archives",
"Deleted Items",
"Drafts",
"Inbox",
"Junk",
"Outbox",
"Root",
"Sent",
"exists",
"test Ϟ",
"test ϰ",
],
"these folders should exist on the EWS server after the test"
);
});
add_task(async function testGraph() {
const mockServer = await ServerTestUtils.createServer({ type: "graph" });
mockServer.setRemoteFolders(mockServer.getWellKnownFolders());
const graphAccount = MailServices.accounts.createAccount();
const graphServer = (graphAccount.incomingServer =
MailServices.accounts.createIncomingServer("user", "localhost", "graph"));
graphServer.port = mockServer.port;
graphServer.password = "password";
graphServer.performExpand(null);
await TestUtils.waitForCondition(
() => graphServer.rootFolder.getChildNamed("Drafts"),
"waiting for folder sync to finish"
);
const graphRoot = graphServer.rootFolder;
await checkSucceeds(graphRoot, "test Ϟ");
await checkFails(graphRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
// FIXME: There should be no alert here! It comes from the HTTP error response.
mockServer.appendRemoteFolder(new RemoteFolder("exists", "root"));
Services.prefs.setBoolPref("mail.suppressAlertsForTests", true);
await checkFails(graphRoot, "exists", /NS_ERROR_NET_ERROR_RESPONSE/);
Services.prefs.clearUserPref("mail.suppressAlertsForTests");
// Check we get an error while offline.
graphServer.closeCachedConnections();
Services.io.offline = true;
await checkFails(graphRoot, "offline", /NS_MSG_ERROR_OFFLINE/);
Services.io.offline = false;
// Check the deprecated sync function.
await checkSucceedsSync(graphRoot, "test ϰ");
await checkThrowsSync(graphRoot, "", /NS_MSG_ERROR_INVALID_FOLDER_NAME/);
// await checkFailsSync(graphRoot, "exists");
Assert.deepEqual(
mockServer.folders.map(f => f.displayName).toSorted(),
[
"Archives",
"Deleted Items",
"Drafts",
"Inbox",
"Junk",
"Outbox",
"Root",
"Sent",
"exists",
"test Ϟ",
"test ϰ",
],
"these folders should exist on the Graph server after the test"
);
});
/**
* Check createSubfolderAsync succeeds and resolves with the created folder.
*
* @param {nsIMsgFolder} parent
* @param {string} name
* @param {string} [uriFrag]
* @returns {nsIMsgFolder}
*/
async function checkSucceeds(parent, name, uriFrag = encodeURIComponent(name)) {
info(`asynchronously creating "${name}" as a child of ${parent.URI}`);
const folderAddedPromise = PromiseTestUtils.promiseFolderAdded(name);
const testFolder = await parent.createSubfolderAsync(name);
Assert.ok(testFolder, "the call should return the created folder");
Assert.equal(
testFolder.parent,
parent,
"the created folder should have the right parent"
);
Assert.equal(
testFolder.URI,
`${parent.URI}/${uriFrag}`,
"the created folder should have the right URI"
);
await folderAddedPromise;
return testFolder;
}
/**
* Check createSubfolderAsync fails and rejects with the expected status.
*
* @param {nsIMsgFolder} parent
* @param {string} name
* @param {RegExp} errorRegExp
*/
async function checkFails(parent, name, errorRegExp) {
info(`asynchronously creating "${name}" as a child of ${parent.URI}`);
await Assert.rejects(
parent.createSubfolderAsync(name),
errorRegExp,
errorRegExp.source
);
}
/**
* Check createSubfolder succeeds.
*
* @param {nsIMsgFolder} parent
* @param {string} name
* @param {string} [uriFrag]
* @returns {nsIMsgFolder}
*/
async function checkSucceedsSync(
parent,
name,
uriFrag = encodeURIComponent(name)
) {
info(`synchronously creating "${name}" as a child of ${parent.URI}`);
const folderAddedPromise = PromiseTestUtils.promiseFolderAdded(name);
parent.createSubfolder(name, null);
const testFolder = await folderAddedPromise;
Assert.ok(testFolder, "the call should return the created folder");
Assert.equal(
testFolder.parent,
parent,
"the created folder should have the right parent"
);
Assert.equal(
testFolder.URI,
`${parent.URI}/${uriFrag}`,
"the created folder should have the right URI"
);
return testFolder;
}
/**
* Check createSubfolder throws the expected status.
*
* @param {nsIMsgFolder} parent
* @param {string} name
* @param {RegExp} errorRegExp
*/
async function checkThrowsSync(parent, name, errorRegExp) {
info(`synchronously creating "${name}" as a child of ${parent.URI}`);
Assert.throws(
() => parent.createSubfolder(name, null),
errorRegExp,
errorRegExp.source
);
}
/**
* Check createSubfolder fails and emits the "FolderCreateFailed" event.
*
* @param {nsIMsgFolder} parent
* @param {string} name
*/
async function checkFailsSync(parent, name) {
info(`synchronously creating "${name}" as a child of ${parent.URI}`);
const folderEventPromise = PromiseTestUtils.promiseFolderEvent(
parent,
"FolderCreateFailed"
);
parent.createSubfolder(name, null);
await folderEventPromise;
}