diff --git a/src/zen/tests/run.sh b/src/zen/tests/run.sh index c431f5b78..0046ab1ca 100644 --- a/src/zen/tests/run.sh +++ b/src/zen/tests/run.sh @@ -8,11 +8,22 @@ if [ ! -f "package.json" ]; then exit 1 fi +path="$1" +other_args="" +for arg in "$@"; do + if [ "$arg" != "$path" ]; then + other_args="$other_args $arg" + fi +done cd ./engine -./mach mochitest $@ \ - zen/tests/workspaces \ - zen/tests/container_essentials \ - zen/tests/urlbar \ - zen/tests/pinned \ - zen/tests/compact_mode +if [ "$path" = "all" ] || [ "$path" = "" ]; then + all_tests=$(find zen/tests -type d) + all_paths="" + for test in $all_tests; do + all_paths="$all_paths zen/tests/$(basename $test)" + done + ./mach mochitest $other_args $all_paths +else + ./mach mochitest $other_args zen/tests/$path +fi cd .. diff --git a/src/zen/tests/workspaces/browser.toml b/src/zen/tests/workspaces/browser.toml index a5ff90e60..d67eb2bd3 100644 --- a/src/zen/tests/workspaces/browser.toml +++ b/src/zen/tests/workspaces/browser.toml @@ -4,3 +4,4 @@ support-files = [ ] ["browser_basic_workspaces.js"] +["browser_workspace_bookmarks.js"] diff --git a/src/zen/tests/workspaces/browser_workspace_bookmarks.js b/src/zen/tests/workspaces/browser_workspace_bookmarks.js new file mode 100644 index 000000000..3b20fbff7 --- /dev/null +++ b/src/zen/tests/workspaces/browser_workspace_bookmarks.js @@ -0,0 +1,151 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +'use strict'; + +function getToolbarNodeForItemGuid(aItemGuid) { + var children = document.getElementById('PlacesToolbarItems').children; + for (let child of children) { + if (aItemGuid == child._placesNode.bookmarkGuid) { + return child; + } + } + return null; +} + +function isToolbarVisible(aToolbar) { + let hidingAttribute = aToolbar.getAttribute('type') == 'menubar' ? 'autohide' : 'collapsed'; + let hidingValue = aToolbar.getAttribute(hidingAttribute)?.toLowerCase(); + // Check for both collapsed="true" and collapsed="collapsed" + return hidingValue !== 'true' && hidingValue !== hidingAttribute; +} + +function promiseSetToolbarVisibility(aToolbar, aVisible) { + if (isToolbarVisible(aToolbar) != aVisible) { + let visibilityChanged = TestUtils.waitForCondition(() => aToolbar.collapsed != aVisible); + setToolbarVisibility(aToolbar, aVisible, undefined, false); + return visibilityChanged; + } + return Promise.resolve(); +} + +async function changeWorkspaceForBookmark(aBookmark, aWorkspace) { + const toolbarNode = getToolbarNodeForItemGuid(aBookmark.guid); + await withBookmarksDialog( + false, + async function openPropertiesDialog() { + let placesContext = document.getElementById('placesContext'); + let promisePopup = BrowserTestUtils.waitForEvent(placesContext, 'popupshown'); + EventUtils.synthesizeMouseAtCenter(toolbarNode, { + button: 2, + type: 'contextmenu', + }); + await promisePopup; + + let properties = document.getElementById('placesContext_show_bookmark:info'); + placesContext.activateItem(properties, {}); + }, + async function test(dialogWin) { + // Ensure the dialog has initialized. + await TestUtils.waitForCondition(() => dialogWin.document.title); + + let openWorkspaceSelectorButton = dialogWin.document.getElementById( + 'editBMPanel_workspacesSelectorExpander' + ); + + // Open the workspace selector. + openWorkspaceSelectorButton.click(); + + await setTimeout(() => {}, 100); + const checkbox = dialogWin.document.querySelector(`input[value="${aWorkspace.uuid}"]`); + + // Check the checkbox for the workspace. + checkbox.click(); + await setTimeout(() => {}, 100); + + // Confirm and close the dialog. + EventUtils.synthesizeKey('VK_RETURN', {}, dialogWin); + await setTimeout(() => {}, 100); + } + ); +} + +async function withBookmarksShowing(aCallback) { + await SpecialPowers.pushPrefEnv({ + set: [['zen.view.hide-window-controls', false]], + }); + await setTimeout(() => {}, 1000); + await aCallback(); + await SpecialPowers.popPrefEnv(); +} + +add_setup(async function () { + let toolbar = document.getElementById('PersonalToolbar'); + let wasCollapsed = toolbar.collapsed; + + // Uncollapse the personal toolbar if needed. + if (wasCollapsed) { + await promiseSetToolbarVisibility(toolbar, true); + } + + registerCleanupFunction(async () => { + // Collapse the personal toolbar if needed. + if (wasCollapsed) { + await promiseSetToolbarVisibility(toolbar, false); + } + await PlacesUtils.bookmarks.eraseEverything(); + }); +}); + +add_task(async function test_workspace_bookmark() { + todo(false, 'Properly implement this function'); + return; + + await withBookmarksShowing(async () => { + await ZenWorkspaces.createAndSaveWorkspace('Test Workspace 2'); + const workspaces = await ZenWorkspaces._workspaces(); + ok(workspaces.workspaces.length === 2, 'Two workspaces should exist.'); + const firstWorkspace = workspaces.workspaces[0]; + const secondWorkspace = workspaces.workspaces[1]; + ok( + firstWorkspace.uuid !== secondWorkspace.uuid, + 'The new workspace should be different from the current one.' + ); + + const bookmark1 = await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + title: 'workspace1', + url: Services.io.newURI('https://example.com/'), + workspaces: [firstWorkspace.uuid], + }); + + await changeWorkspaceForBookmark(bookmark1, firstWorkspace); + + const bookmark2 = await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + title: 'workspace2', + url: Services.io.newURI('https://example.com/'), + workspaces: [secondWorkspace.uuid], + }); + + await changeWorkspaceForBookmark(bookmark2, secondWorkspace); + + await ZenWorkspaces.changeWorkspace(secondWorkspace); + const toolbarNode1 = getToolbarNodeForItemGuid(bookmark1.guid); + const toolbarNode2 = getToolbarNodeForItemGuid(bookmark2.guid); + ok(toolbarNode1, 'Bookmark1 should be in the toolbar'); + ok(!toolbarNode2, 'Bookmark2 should be in the toolbar'); + + await ZenWorkspaces.changeWorkspace(firstWorkspace); + + const toolbarNode3 = getToolbarNodeForItemGuid(bookmark1.guid); + const toolbarNode4 = getToolbarNodeForItemGuid(bookmark2.guid); + ok(!toolbarNode3, 'Bookmark1 should be in the toolbar'); + ok(toolbarNode4, 'Bookmark2 should be in the toolbar'); + + await PlacesUtils.bookmarks.remove(bookmark1); + await PlacesUtils.bookmarks.remove(bookmark2); + + await ZenWorkspaces.removeWorkspace(secondWorkspace.uuid); + }); +}); diff --git a/src/zen/tests/workspaces/head.js b/src/zen/tests/workspaces/head.js index f1a074220..9443d7683 100644 --- a/src/zen/tests/workspaces/head.js +++ b/src/zen/tests/workspaces/head.js @@ -649,3 +649,89 @@ async function openTabMenuFor(tab) { return tabMenu; } + +var withBookmarksDialog = async function (autoCancel, openFn, taskFn, closeFn) { + let dialogUrl = 'chrome://browser/content/places/bookmarkProperties.xhtml'; + let closed = false; + // We can't show the in-window prompt for windows which don't have + // gDialogBox, like the library (Places:Organizer) window. + let hasDialogBox = !!Services.wm.getMostRecentWindow('').gDialogBox; + let dialogPromise; + if (hasDialogBox) { + dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(null, dialogUrl, { + isSubDialog: true, + }); + } else { + dialogPromise = BrowserTestUtils.domWindowOpenedAndLoaded(null, (win) => { + return win.document.documentURI.startsWith(dialogUrl); + }).then((win) => { + ok( + win.location.href.startsWith(dialogUrl), + 'The bookmark properties dialog is open: ' + win.location.href + ); + // This is needed for the overlay. + return SimpleTest.promiseFocus(win).then(() => win); + }); + } + let dialogClosePromise = dialogPromise.then((win) => { + if (!hasDialogBox) { + return BrowserTestUtils.domWindowClosed(win); + } + let container = win.top.document.getElementById('window-modal-dialog'); + return BrowserTestUtils.waitForEvent(container, 'close').then(() => { + return BrowserTestUtils.waitForMutationCondition( + container, + { childList: true, attributes: true }, + () => !container.hasChildNodes() && !container.open + ); + }); + }); + dialogClosePromise.then(() => { + closed = true; + }); + + info('withBookmarksDialog: opening the dialog'); + // The dialog might be modal and could block our events loop, so executeSoon. + executeSoon(openFn); + + info('withBookmarksDialog: waiting for the dialog'); + let dialogWin = await dialogPromise; + + // Ensure overlay is loaded + info('waiting for the overlay to be loaded'); + await dialogWin.document.mozSubdialogReady; + + // Check the first input is focused. + let doc = dialogWin.document; + let elt = doc.querySelector('input:not([hidden="true"])'); + ok(elt, 'There should be an input to focus.'); + + if (elt) { + info('waiting for focus on the first textfield'); + await TestUtils.waitForCondition( + () => doc.activeElement == elt, + 'The first non collapsed input should have been focused' + ); + } + + info('withBookmarksDialog: executing the task'); + + let closePromise = () => Promise.resolve(); + if (closeFn) { + closePromise = closeFn(dialogWin); + } + let guid; + try { + await taskFn(dialogWin); + } finally { + if (!closed && autoCancel) { + info('withBookmarksDialog: canceling the dialog'); + doc.getElementById('bookmarkpropertiesdialog').cancelDialog(); + await closePromise; + } + guid = await PlacesUIUtils.lastBookmarkDialogDeferred.promise; + // Give the dialog a little time to close itself. + await dialogClosePromise; + } + return guid; +};