Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* 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/. */
/**
* Tests the bookmarks Properties dialog.
*/
// DOM ids of Places sidebar trees.
const SIDEBAR_HISTORY_TREE_ID = "historyTree";
const SIDEBAR_BOOKMARKS_TREE_ID = "bookmarks-view";
const SIDEBAR_HISTORY_ID = "viewHistorySidebar";
const SIDEBAR_BOOKMARKS_ID = "viewBookmarksSidebar";
// For history sidebar.
const SIDEBAR_HISTORY_BYLASTVISITED_VIEW = "bylastvisited";
const SIDEBAR_HISTORY_BYMOSTVISITED_VIEW = "byvisited";
const SIDEBAR_HISTORY_BYDATE_VIEW = "byday";
const SIDEBAR_HISTORY_BYSITE_VIEW = "bysite";
const SIDEBAR_HISTORY_BYDATEANDSITE_VIEW = "bydateandsite";
// Action to execute on the current node.
const ACTION_EDIT = 0;
const ACTION_ADD = 1;
// If action is ACTION_ADD, set type to one of those, to define what do you
// want to create.
const TYPE_FOLDER = 0;
const TYPE_BOOKMARK = 1;
const TEST_URL = "http://www.example.com/";
function add_bookmark(url) {
return PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url,
title: `bookmark/${url}`,
});
}
// Each test is an obj w/ a desc property and run method.
var gTests = [];
// ------------------------------------------------------------------------------
// Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog
gTests.push({
desc: "Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog",
sidebar: SIDEBAR_BOOKMARKS_ID,
action: ACTION_EDIT,
itemType: null,
window: null,
_bookmark: null,
_cleanShutdown: false,
async setup() {
// Add a bookmark in unsorted bookmarks folder.
this._bookmark = await add_bookmark(TEST_URL);
Assert.ok(this._bookmark, "Correctly added a bookmark");
// Add a tag to this bookmark.
PlacesUtils.tagging.tagURI(Services.io.newURI(TEST_URL), ["testTag"]);
var tags = PlacesUtils.tagging.getTagsForURI(Services.io.newURI(TEST_URL));
Assert.equal(tags[0], "testTag", "Correctly added a tag");
},
selectNode(tree) {
tree.selectItems([PlacesUtils.bookmarks.unfiledGuid]);
PlacesUtils.asContainer(tree.selectedNode).containerOpen = true;
tree.selectItems([this._bookmark.guid]);
Assert.equal(
tree.selectedNode.bookmarkGuid,
this._bookmark.guid,
"Bookmark has been selected"
);
},
async run() {
// open tags autocomplete and press enter
var tagsField = this.window.document.getElementById(
"editBMPanel_tagsField"
);
var self = this;
let unloadPromise = new Promise(resolve => {
this.window.addEventListener(
"unload",
function () {
tagsField.popup.removeEventListener(
"popuphidden",
popupListener,
true
);
Assert.ok(
self._cleanShutdown,
"Dialog window should not be closed by pressing Enter on the autocomplete popup"
);
executeSoon(function () {
resolve();
});
},
{ capture: true, once: true }
);
});
var popupListener = {
handleEvent(aEvent) {
switch (aEvent.type) {
case "popuphidden":
// Everything worked fine, we can stop observing the window.
self._cleanShutdown = true;
self.window.document
.getElementById("bookmarkpropertiesdialog")
.cancelDialog();
break;
case "popupshown":
tagsField.popup.removeEventListener("popupshown", this, true);
// In case this test fails the window will close, the test will fail
// since we didn't set _cleanShutdown.
let richlistbox = tagsField.popup.richlistbox;
// Focus and select first result.
Assert.equal(
richlistbox.itemCount,
1,
"We have 1 autocomplete result"
);
tagsField.popup.selectedIndex = 0;
Assert.equal(
richlistbox.selectedItems.length,
1,
"We have selected a tag from the autocomplete popup"
);
info("About to focus the autocomplete results");
richlistbox.focus();
EventUtils.synthesizeKey("VK_RETURN", {}, self.window);
break;
default:
Assert.ok(false, "unknown event: " + aEvent.type);
}
},
};
tagsField.popup.addEventListener("popupshown", popupListener, true);
tagsField.popup.addEventListener("popuphidden", popupListener, true);
// Open tags autocomplete popup.
info("About to focus the tagsField");
executeSoon(() => {
tagsField.focus();
tagsField.value = "";
EventUtils.synthesizeKey("t", {}, this.window);
});
await unloadPromise;
},
finish() {
SidebarController.hide();
},
async cleanup() {
// Check tags have not changed.
var tags = PlacesUtils.tagging.getTagsForURI(Services.io.newURI(TEST_URL));
Assert.equal(tags[0], "testTag", "Tag on node has not changed");
// Cleanup.
PlacesUtils.tagging.untagURI(Services.io.newURI(TEST_URL), ["testTag"]);
await PlacesUtils.bookmarks.remove(this._bookmark);
let bm = await PlacesUtils.bookmarks.fetch(this._bookmark.guid);
Assert.ok(!bm, "should have been removed");
},
});
// ------------------------------------------------------------------------------
// Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel
gTests.push({
desc: "Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel",
sidebar: SIDEBAR_BOOKMARKS_ID,
action: ACTION_EDIT,
itemType: null,
window: null,
_bookmark: null,
_cleanShutdown: false,
async setup() {
// Add a bookmark in unsorted bookmarks folder.
this._bookmark = await add_bookmark(TEST_URL);
Assert.ok(this._bookmark, "Correctly added a bookmark");
// Add a tag to this bookmark.
PlacesUtils.tagging.tagURI(Services.io.newURI(TEST_URL), ["testTag"]);
var tags = PlacesUtils.tagging.getTagsForURI(Services.io.newURI(TEST_URL));
Assert.equal(tags[0], "testTag", "Correctly added a tag");
},
selectNode(tree) {
tree.selectItems([PlacesUtils.bookmarks.unfiledGuid]);
PlacesUtils.asContainer(tree.selectedNode).containerOpen = true;
tree.selectItems([this._bookmark.guid]);
Assert.equal(
tree.selectedNode.bookmarkGuid,
this._bookmark.guid,
"Bookmark has been selected"
);
},
async run() {
// open tags autocomplete and press enter
var tagsField = this.window.document.getElementById(
"editBMPanel_tagsField"
);
var self = this;
let hiddenPromise = new Promise(resolve => {
this.window.addEventListener(
"unload",
function () {
tagsField.popup.removeEventListener(
"popuphidden",
popupListener,
true
);
Assert.ok(
self._cleanShutdown,
"Dialog window should not be closed by pressing Escape on the autocomplete popup"
);
executeSoon(function () {
resolve();
});
},
{ capture: true, once: true }
);
});
var popupListener = {
handleEvent(aEvent) {
switch (aEvent.type) {
case "popuphidden":
// Everything worked fine.
self._cleanShutdown = true;
self.window.document
.getElementById("bookmarkpropertiesdialog")
.cancelDialog();
break;
case "popupshown":
tagsField.popup.removeEventListener("popupshown", this, true);
// In case this test fails the window will close, the test will fail
// since we didn't set _cleanShutdown.
let richlistbox = tagsField.popup.richlistbox;
// Focus and select first result.
Assert.equal(
richlistbox.itemCount,
1,
"We have 1 autocomplete result"
);
tagsField.popup.selectedIndex = 0;
Assert.equal(
richlistbox.selectedItems.length,
1,
"We have selected a tag from the autocomplete popup"
);
info("About to focus the autocomplete results");
richlistbox.focus();
EventUtils.synthesizeKey("VK_ESCAPE", {}, self.window);
break;
default:
Assert.ok(false, "unknown event: " + aEvent.type);
}
},
};
tagsField.popup.addEventListener("popupshown", popupListener, true);
tagsField.popup.addEventListener("popuphidden", popupListener, true);
// Open tags autocomplete popup.
info("About to focus the tagsField");
tagsField.focus();
tagsField.value = "";
EventUtils.synthesizeKey("t", {}, this.window);
await hiddenPromise;
},
finish() {
SidebarController.hide();
},
async cleanup() {
// Check tags have not changed.
var tags = PlacesUtils.tagging.getTagsForURI(Services.io.newURI(TEST_URL));
Assert.equal(tags[0], "testTag", "Tag on node has not changed");
// Cleanup.
PlacesUtils.tagging.untagURI(Services.io.newURI(TEST_URL), ["testTag"]);
await PlacesUtils.bookmarks.remove(this._bookmark);
let bm = await PlacesUtils.bookmarks.fetch(this._bookmark.guid);
Assert.ok(!bm, "should have been removed");
},
});
// ------------------------------------------------------------------------------
// Bug 491269 - Test that editing folder name in bookmarks properties dialog does not accept the dialog
gTests.push({
desc: `Bug 491269 - Test that editing folder name in bookmarks properties dialog does not accept the dialog`,
sidebar: SIDEBAR_HISTORY_ID,
dialogUrl: DIALOG_URL,
action: ACTION_ADD,
historyView: SIDEBAR_HISTORY_BYLASTVISITED_VIEW,
window: null,
async setup() {
// Add a visit.
await PlacesTestUtils.addVisits(TEST_URL);
},
selectNode(tree) {
var visitNode = tree.view.nodeForTreeIndex(0);
tree.selectNode(visitNode);
Assert.equal(
tree.selectedNode.uri,
TEST_URL,
"The correct visit has been selected"
);
Assert.equal(
tree.selectedNode.itemId,
-1,
"The selected node is not bookmarked"
);
},
async run() {
// Open folder selector.
var foldersExpander = this.window.document.getElementById(
"editBMPanel_foldersExpander"
);
var folderTree = this.window.gEditItemOverlay._folderTree;
var self = this;
let unloadPromise = new Promise(resolve => {
this.window.addEventListener(
"unload",
() => {
Assert.ok(
self._cleanShutdown,
"Dialog window should not be closed by pressing ESC in folder name textbox"
);
executeSoon(() => {
resolve();
});
},
{ capture: true, once: true }
);
});
const observer = new this.window.MutationObserver(
(aMutationList, aObserver) => {
for (const mutation of aMutationList) {
if (
mutation.type != "attributes" ||
mutation.attributeName != "place"
) {
continue;
}
aObserver.disconnect();
executeSoon(async function () {
// Create a new folder.
var newFolderButton = self.window.document.getElementById(
"editBMPanel_newFolderButton"
);
newFolderButton.doCommand();
// Wait for the folder to be created and for editing to start.
await TestUtils.waitForCondition(
() => folderTree.hasAttribute("editing"),
"We are editing new folder name in folder tree"
);
// Press Escape to discard editing new folder name.
EventUtils.synthesizeKey("VK_ESCAPE", {}, self.window);
Assert.ok(
!folderTree.hasAttribute("editing"),
"We have finished editing folder name in folder tree"
);
self._cleanShutdown = true;
self.window.document
.getElementById("bookmarkpropertiesdialog")
.cancelDialog();
});
break;
}
}
);
observer.observe(folderTree, { attributes: true });
foldersExpander.doCommand();
await unloadPromise;
},
finish() {
SidebarController.hide();
},
async cleanup() {
await PlacesTestUtils.promiseAsyncUpdates();
await PlacesUtils.history.clear();
},
});
// ------------------------------------------------------------------------------
add_task(async function test_setup() {
// This test can take some time, if we timeout too early it could run
// in the middle of other tests, or hang them.
requestLongerTimeout(2);
});
add_task(async function test_run() {
for (let test of gTests) {
info(`Start of test: ${test.desc}`);
await test.setup();
await execute_test_in_sidebar(test);
await test.run();
await test.cleanup();
await test.finish();
info(`End of test: ${test.desc}`);
}
});
/**
* Global functions to run a test in Properties dialog context.
*/
function execute_test_in_sidebar(test) {
return new Promise(resolve => {
var sidebar = document.getElementById("sidebar");
sidebar.addEventListener(
"load",
function () {
// Need to executeSoon since the tree is initialized on sidebar load.
executeSoon(async () => {
await open_properties_dialog(test);
resolve();
});
},
{ capture: true, once: true }
);
SidebarController.show(test.sidebar);
});
}
async function promise_properties_window(dialogUrl = DIALOG_URL) {
let win = await BrowserTestUtils.promiseAlertDialogOpen(null, dialogUrl, {
isSubDialog: true,
});
await SimpleTest.promiseFocus(win);
await win.document.mozSubdialogReady;
return win;
}
async function open_properties_dialog(test) {
var sidebar = document.getElementById("sidebar");
// If this is history sidebar, set the required view.
if (test.sidebar == SIDEBAR_HISTORY_ID) {
sidebar.contentDocument.getElementById(test.historyView).doCommand();
}
// Get sidebar's Places tree.
var sidebarTreeID =
test.sidebar == SIDEBAR_BOOKMARKS_ID
? SIDEBAR_BOOKMARKS_TREE_ID
: SIDEBAR_HISTORY_TREE_ID;
var tree = sidebar.contentDocument.getElementById(sidebarTreeID);
// The sidebar may take a moment to open from the doCommand, therefore wait
// until it has opened before continuing.
await TestUtils.waitForCondition(() => tree, "Sidebar tree has been loaded");
// Ask current test to select the node to edit.
test.selectNode(tree);
Assert.ok(
tree.selectedNode,
"We have a places node selected: " + tree.selectedNode.title
);
return new Promise(resolve => {
var command = null;
switch (test.action) {
case ACTION_EDIT:
command = "placesCmd_show:info";
break;
case ACTION_ADD:
if (test.sidebar == SIDEBAR_BOOKMARKS_ID) {
if (test.itemType == TYPE_FOLDER) {
command = "placesCmd_new:folder";
} else if (test.itemType == TYPE_BOOKMARK) {
command = "placesCmd_new:bookmark";
} else {
Assert.ok(
false,
"You didn't set a valid itemType for adding an item"
);
}
} else {
command = "placesCmd_createBookmark";
}
break;
default:
Assert.ok(false, "You didn't set a valid action for this test");
}
// Ensure command is enabled for this node.
Assert.ok(
tree.controller.isCommandEnabled(command),
" command '" + command + "' on current selected node is enabled"
);
promise_properties_window(test.dialogUrl).then(win => {
test.window = win;
resolve();
});
// This will open the dialog. For some reason this needs to be executed
// later, as otherwise opening the dialog throws an exception.
executeSoon(() => {
tree.controller.doCommand(command);
});
});
}