From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../tests/browser/browser_toolbar_overflow.js | 436 +++++++++++++++++++++ 1 file changed, 436 insertions(+) create mode 100644 browser/components/places/tests/browser/browser_toolbar_overflow.js (limited to 'browser/components/places/tests/browser/browser_toolbar_overflow.js') diff --git a/browser/components/places/tests/browser/browser_toolbar_overflow.js b/browser/components/places/tests/browser/browser_toolbar_overflow.js new file mode 100644 index 0000000000..03d340b799 --- /dev/null +++ b/browser/components/places/tests/browser/browser_toolbar_overflow.js @@ -0,0 +1,436 @@ +/* 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 toolbar overflow. + */ + +var gToolbar = document.getElementById("PersonalToolbar"); +var gChevron = document.getElementById("PlacesChevron"); + +const BOOKMARKS_COUNT = 250; + +add_setup(async function () { + let wasCollapsed = gToolbar.collapsed; + await PlacesUtils.bookmarks.eraseEverything(); + + // Add bookmarks. + await PlacesUtils.bookmarks.insertTree({ + guid: PlacesUtils.bookmarks.toolbarGuid, + children: Array(BOOKMARKS_COUNT) + .fill("") + .map((_, i) => ({ url: `http://test.places.${i}/` })), + }); + + // Toggle the bookmarks toolbar so that we start from a stable situation and + // are not affected by all bookmarks removal. + await toggleToolbar(false); + await toggleToolbar(true); + + registerCleanupFunction(async () => { + if (wasCollapsed) { + await toggleToolbar(false); + } + await PlacesUtils.bookmarks.eraseEverything(); + await PlacesUtils.history.clear(); + }); +}); + +add_task(async function test_overflow() { + // Check that the overflow chevron is visible. + Assert.ok(!gChevron.collapsed, "The overflow chevron should be visible"); + let children = getPlacesChildren(); + Assert.ok( + children.length < BOOKMARKS_COUNT, + "Not all the nodes should be built by default" + ); + let visibleNodes = []; + for (let node of children) { + if (getComputedStyle(node).visibility == "visible") { + visibleNodes.push(node); + } + } + Assert.ok( + visibleNodes.length < children.length, + `The number of visible nodes (${visibleNodes.length}) should be smaller than the number of built nodes (${children.length})` + ); + + await test_index( + "Node at the last visible index", + visibleNodes.length - 1, + "visible" + ); + await test_index( + "Node at the first invisible index", + visibleNodes.length, + "hidden" + ); + await test_index("First non-built node", children.length, undefined); + await test_index("Later non-built node", children.length + 1, undefined); + + await test_move_index( + "Move node from last visible to first hidden", + visibleNodes.length - 1, + visibleNodes.length, + "visible", + "hidden" + ); + await test_move_index( + "Move node from fist visible to last built", + 0, + children.length - 1, + "visible", + "hidden" + ); + await test_move_index( + "Move node from fist visible to first non built", + 0, + children.length, + "visible", + undefined + ); +}); + +add_task(async function test_separator_first() { + await toggleToolbar(false); + // Check that if a separator is the first node, we still calculate overflow + // properly. + let bm = await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + type: PlacesUtils.bookmarks.TYPE_SEPARATOR, + index: 0, + }); + await toggleToolbar(true, 2); + + let children = getPlacesChildren(); + Assert.greater(children.length, 2, "Multiple elements are visible"); + Assert.equal( + children[1]._placesNode.uri, + "http://test.places.0/", + "Found the first bookmark" + ); + Assert.equal( + getComputedStyle(children[1]).visibility, + "visible", + "The first bookmark is visible" + ); + + await PlacesUtils.bookmarks.remove(bm); +}); + +add_task(async function test_newWindow_noOverflow() { + info( + "Check toolbar in a new widow when it was already visible and not overflowed" + ); + Assert.ok(!gToolbar.collapsed, "Toolbar is not collapsed in original window"); + await PlacesUtils.bookmarks.eraseEverything(); + // Add a single bookmark. + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + url: "http://toolbar.overflow/", + title: "Example", + }); + // Add a favicon for the bookmark. + let favicon = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAA" + + "AAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg=="; + await PlacesTestUtils.addFavicons( + new Map([["http://toolbar.overflow/", favicon]]) + ); + + let win = await BrowserTestUtils.openNewBrowserWindow(); + try { + let toolbar = win.document.getElementById("PersonalToolbar"); + Assert.ok(!toolbar.collapsed, "The toolbar is not collapsed"); + let content = win.document.getElementById("PlacesToolbarItems"); + await TestUtils.waitForCondition(() => { + return ( + content.children.length == 1 && + content.children[0].hasAttribute("image") + ); + }); + let chevron = win.document.getElementById("PlacesChevron"); + Assert.ok(chevron.collapsed, "The chevron should be collapsed"); + } finally { + await BrowserTestUtils.closeWindow(win); + } +}); + +async function test_index(desc, index, expected) { + info(desc); + let children = getPlacesChildren(); + let originalLen = children.length; + let nodeExisted = children.length > index; + let previousNodeIsVisible = + nodeExisted && + getComputedStyle(children[index - 1]).visibility == "visible"; + let promise = promiseUpdateVisibility( + expected == "visible" || previousNodeIsVisible + ); + + let bm = await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + url: "http://test.places.added/", + index, + }); + Assert.equal(bm.index, index, "Sanity check the bookmark index"); + await promise; + children = getPlacesChildren(); + + if (!expected) { + Assert.ok( + children.length <= index, + "The new node should not have been added" + ); + } else { + Assert.equal( + children[index]._placesNode.bookmarkGuid, + bm.guid, + "Found the added bookmark at the expected position" + ); + Assert.equal( + getComputedStyle(children[index]).visibility, + expected, + `The bookmark node should be ${expected}` + ); + } + Assert.equal( + children.length, + originalLen, + "Number of built nodes should stay the same" + ); + + info("Remove the node"); + promise = promiseUpdateVisibility(expected == "visible"); + + await PlacesUtils.bookmarks.remove(bm); + await promise; + children = getPlacesChildren(); + + if (expected && nodeExisted) { + Assert.equal( + children[index]._placesNode.uri, + `http://test.places.${index}/`, + "Found the previous bookmark at the expected position" + ); + Assert.equal( + getComputedStyle(children[index]).visibility, + expected, + `The bookmark node should be ${expected}` + ); + } + Assert.equal( + children.length, + originalLen, + "Number of built nodes should stay the same" + ); +} + +async function test_move_index(desc, fromIndex, toIndex, original, expected) { + info(desc); + let children = getPlacesChildren(); + let originalLen = children.length; + let movedGuid = children[fromIndex]._placesNode.bookmarkGuid; + let existingGuid = children[toIndex] + ? children[toIndex]._placesNode.bookmarkGuid + : null; + let existingIndex = fromIndex < toIndex ? toIndex - 1 : toIndex + 1; + + Assert.equal( + getComputedStyle(children[fromIndex]).visibility, + original, + `The bookmark node should be ${original}` + ); + let promise = promiseUpdateVisibility( + original == "visible" || expected == "visible" + ); + + await PlacesUtils.bookmarks.update({ + guid: movedGuid, + index: toIndex, + }); + await promise; + children = getPlacesChildren(); + + if (!expected) { + Assert.ok( + children.length <= toIndex, + "Node in the new position is not expected" + ); + Assert.ok( + children[originalLen - 1], + "We should keep number of built nodes consistent" + ); + } else { + Assert.equal( + children[toIndex]._placesNode.bookmarkGuid, + movedGuid, + "Found the moved bookmark at the expected position" + ); + Assert.equal( + getComputedStyle(children[toIndex]).visibility, + expected, + `The destination bookmark node should be ${expected}` + ); + } + Assert.equal( + getComputedStyle(children[fromIndex]).visibility, + original, + `The origin bookmark node should be ${original}` + ); + if (existingGuid) { + Assert.equal( + children[existingIndex]._placesNode.bookmarkGuid, + existingGuid, + "Found the pushed away bookmark at the expected position" + ); + } + Assert.equal( + children.length, + originalLen, + "Number of built nodes should stay the same" + ); + + info("Moving back the node"); + promise = promiseUpdateVisibility( + original == "visible" || expected == "visible" + ); + + await PlacesUtils.bookmarks.update({ + guid: movedGuid, + index: fromIndex, + }); + await promise; + children = getPlacesChildren(); + + Assert.equal( + children[fromIndex]._placesNode.bookmarkGuid, + movedGuid, + "Found the moved bookmark at the expected position" + ); + if (expected) { + Assert.equal( + getComputedStyle(children[toIndex]).visibility, + expected, + `The bookmark node should be ${expected}` + ); + } + Assert.equal( + getComputedStyle(children[fromIndex]).visibility, + original, + `The bookmark node should be ${original}` + ); + if (existingGuid) { + Assert.equal( + children[toIndex]._placesNode.bookmarkGuid, + existingGuid, + "Found the pushed away bookmark at the expected position" + ); + } + Assert.equal( + children.length, + originalLen, + "Number of built nodes should stay the same" + ); +} + +add_task(async function test_separator_first() { + // Check that if there are only separators, we still show nodes properly. + await toggleToolbar(false); + await PlacesUtils.bookmarks.eraseEverything(); + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + type: PlacesUtils.bookmarks.TYPE_SEPARATOR, + index: 0, + }); + await PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + type: PlacesUtils.bookmarks.TYPE_SEPARATOR, + index: 0, + }); + await toggleToolbar(true, 2); + + let children = getPlacesChildren(); + Assert.equal(children.length, 2, "The expected elements are visible"); + Assert.equal( + getComputedStyle(children[0]).visibility, + "visible", + "The first bookmark is visible" + ); + Assert.equal( + getComputedStyle(children[1]).visibility, + "visible", + "The second bookmark is visible" + ); + + await toggleToolbar(false); + await PlacesUtils.bookmarks.eraseEverything(); +}); + +/** + * If the passed-in condition is fulfilled, awaits for the toolbar nodes + * visibility to have been updated. + * + * @param {boolean} [condition] Awaits for visibility only if this condition is true. + * @returns {Promise} resolved when the condition is not fulfilled or the + * visilibily update happened. + */ +function promiseUpdateVisibility(condition = true) { + if (condition) { + return BrowserTestUtils.waitForEvent( + gToolbar, + "BookmarksToolbarVisibilityUpdated" + ); + } + return Promise.resolve(); +} + +/** + * Returns an array of toolbar children that are Places nodes, ignoring things + * like the chevron or other additional buttons. + * + * @returns {Array} An array of Places element nodes. + */ +function getPlacesChildren() { + return Array.prototype.filter.call( + document.getElementById("PlacesToolbarItems").children, + c => c._placesNode?.itemId + ); +} + +/** + * Toggles the toolbar on or off. + * + * @param {boolean} show Whether to show or hide the toolbar. + * @param {number} [expectedMinChildCount] Optional number of Places nodes that + * should be visible on the toolbar. + */ +async function toggleToolbar(show, expectedMinChildCount = 0) { + let promiseReady = Promise.resolve(); + if (show) { + promiseReady = promiseUpdateVisibility(); + } + + await promiseSetToolbarVisibility(gToolbar, show); + await promiseReady; + + if (show) { + if (getPlacesChildren().length < expectedMinChildCount) { + await new Promise(resolve => { + info("Waiting for bookmark elements to appear"); + let mut = new MutationObserver(mutations => { + let children = getPlacesChildren(); + info(`${children.length} bookmark elements appeared`); + if (children.length >= expectedMinChildCount) { + resolve(); + mut.disconnect(); + } + }); + mut.observe(document.getElementById("PlacesToolbarItems"), { + childList: true, + }); + }); + } + } +} -- cgit v1.2.3