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 --- .../test/browser/browser_ext_tabs_successors.js | 396 +++++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 browser/components/extensions/test/browser/browser_ext_tabs_successors.js (limited to 'browser/components/extensions/test/browser/browser_ext_tabs_successors.js') diff --git a/browser/components/extensions/test/browser/browser_ext_tabs_successors.js b/browser/components/extensions/test/browser/browser_ext_tabs_successors.js new file mode 100644 index 0000000000..77549c44d5 --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_tabs_successors.js @@ -0,0 +1,396 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +async function background(tabCount, testFn) { + try { + const { TAB_ID_NONE } = browser.tabs; + const tabIds = await Promise.all( + Array.from({ length: tabCount }, () => + browser.tabs.create({ url: "about:blank" }).then(t => t.id) + ) + ); + + const toTabIds = i => tabIds[i]; + + const setSuccessors = mapping => + Promise.all( + mapping.map((succ, i) => + browser.tabs.update(tabIds[i], { successorTabId: tabIds[succ] }) + ) + ); + + const verifySuccessors = async function (mapping, name) { + const promises = [], + expected = []; + for (let i = 0; i < mapping.length; i++) { + if (mapping[i] !== undefined) { + promises.push( + browser.tabs.get(tabIds[i]).then(t => t.successorTabId) + ); + expected.push( + mapping[i] === TAB_ID_NONE ? TAB_ID_NONE : tabIds[mapping[i]] + ); + } + } + const results = await Promise.all(promises); + for (let i = 0; i < results.length; i++) { + browser.test.assertEq( + expected[i], + results[i], + `${name}: successorTabId of tab ${i} in mapping should be ${expected[i]}` + ); + } + }; + + await testFn({ + TAB_ID_NONE, + tabIds, + toTabIds, + setSuccessors, + verifySuccessors, + }); + + browser.test.notifyPass("background-script"); + } catch (e) { + browser.test.fail(`${e} :: ${e.stack}`); + browser.test.notifyFail("background-script"); + } +} + +async function runTabTest(tabCount, testFn) { + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["tabs"], + }, + background: `(${background})(${tabCount}, ${testFn});`, + }); + + await extension.startup(); + await extension.awaitFinish("background-script"); + await extension.unload(); +} + +add_task(function testTabSuccessors() { + return runTabTest(3, async function ({ TAB_ID_NONE, tabIds }) { + const anotherWindow = await browser.windows.create({ url: "about:blank" }); + + browser.test.assertEq( + TAB_ID_NONE, + (await browser.tabs.get(tabIds[0])).successorTabId, + "Tabs default to an undefined successor" + ); + + // Basic getting and setting + + await browser.tabs.update(tabIds[0], { successorTabId: tabIds[1] }); + browser.test.assertEq( + tabIds[1], + (await browser.tabs.get(tabIds[0])).successorTabId, + "tabs.update assigned the correct successor" + ); + + await browser.tabs.update(tabIds[0], { + successorTabId: browser.tabs.TAB_ID_NONE, + }); + browser.test.assertEq( + TAB_ID_NONE, + (await browser.tabs.get(tabIds[0])).successorTabId, + "tabs.update cleared successor" + ); + + await browser.tabs.update(tabIds[0], { successorTabId: tabIds[1] }); + await browser.tabs.update(tabIds[0], { successorTabId: tabIds[0] }); + browser.test.assertEq( + TAB_ID_NONE, + (await browser.tabs.get(tabIds[0])).successorTabId, + "Setting a tab as its own successor clears the successor instead" + ); + + // Validation tests + + await browser.test.assertRejects( + browser.tabs.update(tabIds[0], { successorTabId: 1e8 }), + /Invalid successorTabId/, + "tabs.update should throw with an invalid successor tab ID" + ); + + await browser.test.assertRejects( + browser.tabs.update(tabIds[0], { + successorTabId: anotherWindow.tabs[0].id, + }), + /Successor tab must be in the same window as the tab being updated/, + "tabs.update should throw with a successor tab ID from another window" + ); + + // Make sure the successor is truly being assigned + + await browser.tabs.update(tabIds[0], { + successorTabId: tabIds[2], + active: true, + }); + await browser.tabs.remove(tabIds[0]); + browser.test.assertEq( + tabIds[2], + (await browser.tabs.query({ active: true }))[0].id + ); + + return browser.tabs.remove([ + tabIds[1], + tabIds[2], + anotherWindow.tabs[0].id, + ]); + }); +}); + +add_task(function testMoveInSuccession_appendFalse() { + return runTabTest( + 8, + async function ({ + TAB_ID_NONE, + tabIds, + toTabIds, + setSuccessors, + verifySuccessors, + }) { + await browser.tabs.moveInSuccession([1, 0].map(toTabIds), tabIds[0]); + await verifySuccessors([TAB_ID_NONE, 0], "scenario 1"); + + await browser.tabs.moveInSuccession( + [0, 1, 2, 3].map(toTabIds), + tabIds[0] + ); + await verifySuccessors([1, 2, 3, 0], "scenario 2"); + + await browser.tabs.moveInSuccession([1, 0].map(toTabIds), tabIds[0]); + await verifySuccessors( + [TAB_ID_NONE, 0], + "scenario 1 after tab 0 has a successor" + ); + + await browser.tabs.update(tabIds[7], { successorTabId: tabIds[0] }); + await browser.tabs.moveInSuccession([4, 5, 6, 7].map(toTabIds)); + await verifySuccessors( + new Array(4).concat([5, 6, 7, TAB_ID_NONE]), + "scenario 4" + ); + + await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]); + await browser.tabs.moveInSuccession( + [4, 6, 3, 2].map(toTabIds), + tabIds[7] + ); + await verifySuccessors([7, TAB_ID_NONE, 7, 2, 6, 7, 3, 5], "scenario 5"); + + await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]); + await browser.tabs.moveInSuccession( + [4, 6, 3, 2].map(toTabIds), + tabIds[7], + { + insert: true, + } + ); + await verifySuccessors( + [4, TAB_ID_NONE, 7, 2, 6, 4, 3, 5], + "insert = true" + ); + + await setSuccessors([1, 2, 3, 4, 0]); + await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[0], { + insert: true, + }); + await verifySuccessors([4, 2, 0, 1, 3], "insert = true, part 2"); + + await browser.tabs.moveInSuccession([ + tabIds[0], + tabIds[1], + 1e8, + tabIds[2], + ]); + await verifySuccessors([1, 2, TAB_ID_NONE], "unknown tab ID"); + + browser.test.assertTrue( + await browser.tabs.moveInSuccession([1e8]).then( + () => true, + () => false + ), + "When all tab IDs are unknown, tabs.moveInSuccession should not throw" + ); + + // Validation tests + + await browser.test.assertRejects( + browser.tabs.moveInSuccession([tabIds[0], tabIds[1], tabIds[0]]), + /IDs must not occur more than once in tabIds/, + "tabs.moveInSuccession should throw when a tab is referenced more than once in tabIds" + ); + + await browser.test.assertRejects( + browser.tabs.moveInSuccession([tabIds[0], tabIds[1]], tabIds[0], { + insert: true, + }), + /Value of tabId must not occur in tabIds if append or insert is true/, + "tabs.moveInSuccession should throw when tabId occurs in tabIds and insert is true" + ); + + return browser.tabs.remove(tabIds); + } + ); +}); + +add_task(function testMoveInSuccession_appendTrue() { + return runTabTest( + 8, + async function ({ + TAB_ID_NONE, + tabIds, + toTabIds, + setSuccessors, + verifySuccessors, + }) { + await browser.tabs.moveInSuccession([1].map(toTabIds), tabIds[0], { + append: true, + }); + await verifySuccessors([1, TAB_ID_NONE], "scenario 1"); + + await browser.tabs.update(tabIds[3], { successorTabId: tabIds[4] }); + await browser.tabs.moveInSuccession([1, 2, 3].map(toTabIds), tabIds[0], { + append: true, + }); + await verifySuccessors([1, 2, 3, TAB_ID_NONE], "scenario 2"); + + await browser.tabs.update(tabIds[0], { successorTabId: tabIds[1] }); + await browser.tabs.moveInSuccession([1e8], tabIds[0], { append: true }); + browser.test.assertEq( + TAB_ID_NONE, + (await browser.tabs.get(tabIds[0])).successorTabId, + "If no tabs get appended after the reference tab, it should lose its successor" + ); + + await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]); + await browser.tabs.moveInSuccession( + [4, 6, 3, 2].map(toTabIds), + tabIds[7], + { + append: true, + } + ); + await verifySuccessors( + [7, TAB_ID_NONE, TAB_ID_NONE, 2, 6, 7, 3, 4], + "scenario 3" + ); + + await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]); + await browser.tabs.moveInSuccession( + [4, 6, 3, 2].map(toTabIds), + tabIds[7], + { + append: true, + insert: true, + } + ); + await verifySuccessors( + [7, TAB_ID_NONE, 5, 2, 6, 7, 3, 4], + "insert = true" + ); + + await browser.tabs.moveInSuccession([0, 4].map(toTabIds), tabIds[7], { + append: true, + insert: true, + }); + await verifySuccessors( + [4, undefined, undefined, undefined, 6, undefined, undefined, 0], + "insert = true, part 2" + ); + + await setSuccessors([1, 2, 3, 4, 0]); + await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[0], { + append: true, + insert: true, + }); + await verifySuccessors([3, 2, 4, 1, 0], "insert = true, part 3"); + + await browser.tabs.update(tabIds[0], { successorTabId: tabIds[1] }); + await browser.tabs.moveInSuccession([1e8], tabIds[0], { + append: true, + insert: true, + }); + browser.test.assertEq( + tabIds[1], + (await browser.tabs.get(tabIds[0])).successorTabId, + "If no tabs get inserted after the reference tab, it should keep its successor" + ); + + // Validation tests + + await browser.test.assertRejects( + browser.tabs.moveInSuccession([tabIds[0], tabIds[1]], tabIds[0], { + append: true, + }), + /Value of tabId must not occur in tabIds if append or insert is true/, + "tabs.moveInSuccession should throw when tabId occurs in tabIds and insert is true" + ); + + return browser.tabs.remove(tabIds); + } + ); +}); + +add_task(function testMoveInSuccession_ignoreTabsInOtherWindows() { + return runTabTest( + 2, + async function ({ + TAB_ID_NONE, + tabIds, + toTabIds, + setSuccessors, + verifySuccessors, + }) { + const anotherWindow = await browser.windows.create({ + url: Array.from({ length: 3 }, () => "about:blank"), + }); + tabIds.push(...anotherWindow.tabs.map(t => t.id)); + + await setSuccessors([1, 0, 3, 4, 2]); + await browser.tabs.moveInSuccession([1, 3, 2].map(toTabIds), tabIds[4]); + await verifySuccessors( + [1, 0, 4, 2, TAB_ID_NONE], + "first tab in another window" + ); + + await setSuccessors([1, 0, 3, 4, 2]); + await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[4]); + await verifySuccessors( + [1, 0, 4, 2, TAB_ID_NONE], + "middle tab in another window" + ); + + await setSuccessors([1, 0, 3, 4, 2]); + await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds)); + await verifySuccessors( + [1, 0, TAB_ID_NONE, 2, TAB_ID_NONE], + "using the first tab to determine the window" + ); + + await setSuccessors([1, 0, 3, 4, 2]); + await browser.tabs.moveInSuccession([1, 3, 2].map(toTabIds), tabIds[4], { + append: true, + }); + await verifySuccessors( + [1, 0, TAB_ID_NONE, 2, 3], + "first tab in another window, appending" + ); + + await setSuccessors([1, 0, 3, 4, 2]); + await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[4], { + append: true, + }); + await verifySuccessors( + [1, 0, TAB_ID_NONE, 2, 3], + "middle tab in another window, appending" + ); + + return browser.tabs.remove(tabIds); + } + ); +}); -- cgit v1.2.3