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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let gAccount, gMessages, gAbout3Pane, gAboutMessage;
// Mock the prompt service. We're going to be asked if we're sure
// we want to remove a contact, so let's say yes.
/** @implements {nsIPromptService} */
const mockPromptService = {
confirm() {
return true;
},
QueryInterface: ChromeUtils.generateQI(["nsIPromptService"]),
};
add_setup(async () => {
gAccount = createAccount();
const rootFolder = gAccount.incomingServer.rootFolder;
const subFolders = rootFolder.subFolders;
await createMessages(subFolders[0], 10);
gMessages = subFolders[0].messages;
gAbout3Pane = document.getElementById("tabmail").currentAbout3Pane;
gAbout3Pane.restoreState({
folderPaneVisible: true,
folderURI: subFolders[0],
messagePaneVisible: true,
});
gAbout3Pane.threadTree.selectedIndex = 0;
await awaitBrowserLoaded(
gAbout3Pane.messageBrowser.contentWindow.getMessagePaneBrowser()
);
// Disable animations on the panel, so that we don't have to deal with
// async openings. The panel is lazy-loaded, so it needs to be referenced
// this way rather than finding it in the DOM.
gAboutMessage = document.getElementById("tabmail").currentAboutMessage;
gAboutMessage.editContactInlineUI.panel.setAttribute("animate", false);
// Mock prompt service.
const originalPromptService = Services.prompt;
Services.prompt = mockPromptService;
registerCleanupFunction(async () => {
// Restore prompt service.
Services.prompt = originalPromptService;
// Restore animation to the contact panel.
gAboutMessage.document
.getElementById("editContactPanel")
.removeAttribute("animate");
});
});
add_task(async function test_moving_contact_bug_1742904() {
const files = {
"background.js": async () => {
// Create a new test address book.
const testAbId = await browser.addressBooks.create({ name: "testAB" });
// Keep track of UIDs (they should all be unique).
const UUIDS = new Set();
// Select a message.
const { messages } = await browser.messages.query();
browser.test.assertEq(
10,
messages.length,
"Should have found the correct number of messages"
);
const display_promise = new Promise(resolve => {
const onDisplayed = (tab, list) => {
if (list.messages.some(m => m.id == messages[0].id)) {
browser.messageDisplay.onMessagesDisplayed.removeListener(
onDisplayed
);
resolve();
}
};
browser.messageDisplay.onMessagesDisplayed.addListener(onDisplayed);
});
await browser.mailTabs.setSelectedMessages([messages[0].id]);
await display_promise;
// Repeat the STR from Bug 1742904 multiple times.
const STR_RUNS = 4;
for (let i = 0; i < STR_RUNS; i++) {
// Wait for the widget being used to create a new contact from the recipient
// of the selected message.
const create_promise = new Promise(resolve => {
const onCreated = node => {
browser.addressBooks.contacts.onCreated.removeListener(onCreated);
resolve(node);
};
browser.addressBooks.contacts.onCreated.addListener(onCreated);
});
await window.sendMessage("create");
const node1 = await create_promise;
browser.test.assertFalse(
UUIDS.has(node1.id),
"Created node should have a unique UUID"
);
UUIDS.add(node1.id);
browser.test.assertTrue(
node1.vCard.includes("FN:Bob Bell"),
"Should have seen the correct contact"
);
// Try to access the created contact with browser.addressBooks.contacts.get().
const node2 = await browser.addressBooks.contacts.get(node1.id);
window.assertDeepEqual(
node1,
node2,
"The created contact should have been returned by contacts.get()",
{ strict: true }
);
// Wait for the widget being used to move the contact to the test address
// book.
const move_promise = new Promise(resolve => {
let createdNode = null;
let deletedNode = null;
const onCreated = node => {
browser.test.assertEq(
testAbId,
node.parentId,
"Should have seen a contact created in the test AB"
);
browser.addressBooks.contacts.onCreated.removeListener(onCreated);
createdNode = node;
if (createdNode && deletedNode) {
resolve(createdNode);
}
};
const onDeleted = (parentId, nodeId) => {
browser.test.assertEq(
node1.id,
nodeId,
"Should have seen the correct contact being deleted"
);
browser.test.assertEq(
node1.parentId,
parentId,
"Should have seen the contact being deleted from the correct address book"
);
browser.addressBooks.contacts.onDeleted.removeListener(onDeleted);
deletedNode = nodeId;
if (createdNode && deletedNode) {
resolve(createdNode);
}
};
browser.addressBooks.contacts.onDeleted.addListener(onDeleted);
browser.addressBooks.contacts.onCreated.addListener(onCreated);
});
await window.sendMessage("move");
const node3 = await move_promise;
browser.test.assertFalse(
UUIDS.has(node3.id),
"Created node should have a unique UUID"
);
UUIDS.add(node3.id);
browser.test.assertTrue(
node3.vCard.includes("FN:Bob Bell"),
"Should have seen the correct contact"
);
// Try to access the moved contact with browser.addressBooks.contacts.get().
const node4 = await browser.addressBooks.contacts.get(node3.id);
window.assertDeepEqual(
node3,
node4,
"The moved contact should have been returned by contacts.get()",
{ strict: true }
);
// Wait for the widget being used to removed the contact from the testAB.
const delete_promise = new Promise(resolve => {
const onDeleted = (parentId, nodeId) => {
browser.test.assertEq(
node3.id,
nodeId,
"Should have seen the correct contact being deleted"
);
browser.test.assertEq(
testAbId,
parentId,
"Should have seen the contact being deleted from the test address book"
);
browser.addressBooks.contacts.onDeleted.removeListener(onDeleted);
resolve();
};
browser.addressBooks.contacts.onDeleted.addListener(onDeleted);
});
await window.sendMessage("delete");
await delete_promise;
}
browser.test.assertEq(
STR_RUNS * 2,
UUIDS.size,
"Number of found unique contact ids should be correct"
);
browser.test.notifyPass("finished");
},
"utils.js": await getUtilsJS(),
};
const extension = ExtensionTestUtils.loadExtension({
files,
manifest: {
manifest_version: 3,
background: { scripts: ["utils.js", "background.js"] },
permissions: ["addressBooks", "messagesRead", "accountsRead"],
},
});
extension.onMessage("create", () => {
const doc = gAboutMessage.document;
doc.querySelector("#expandedtoRow .recipient-address-book-button").click();
extension.sendMessage();
});
extension.onMessage("move", async () => {
// Ensure that the inline contact editing panel is not open.
const doc = gAboutMessage.document;
const contactPanel = doc.getElementById("editContactPanel");
Assert.notEqual(contactPanel.state, "open");
// Click the ab indicator and wait for the panel to open.
const panelOpened = TestUtils.waitForCondition(
() => contactPanel.state == "open",
"The contactPanel was opened"
);
doc.querySelector("#expandedtoRow .recipient-address-book-button").click();
await panelOpened;
// Change the ab selection, click the done button and wait for the panel to
// close.
doc.querySelector("#editContactAddressBookList").selectedIndex = 1;
doc.querySelector("#editContactPanelDoneButton").click();
await TestUtils.waitForCondition(
() => contactPanel.state == "closed",
"The contactPanel was closed"
);
extension.sendMessage();
});
extension.onMessage("delete", async () => {
// Ensure that the inline contact editing panel is not open
const doc = gAboutMessage.document;
const contactPanel = doc.getElementById("editContactPanel");
Assert.notEqual(contactPanel.state, "open");
// Click the ab indicator and wait for the panel to open.
const panelOpened = TestUtils.waitForCondition(
() => contactPanel.state == "open",
"The contactPanel was opened"
);
doc.querySelector("#expandedtoRow .recipient-address-book-button").click();
await panelOpened;
// Click the delete button and wait for the panel to close.
doc.querySelector("#editContactPanelDeleteContactButton").click();
await TestUtils.waitForCondition(
() => contactPanel.state == "closed",
"The contactPanel was closed"
);
extension.sendMessage();
});
await extension.startup();
await extension.awaitFinish("finished");
await extension.unload();
});