From 4a61d97608eac88e7886b169db8b51176da2b718 Mon Sep 17 00:00:00 2001 From: Marian-Vasile Laza Date: Tue, 14 Feb 2023 00:19:16 +0200 Subject: [PATCH] Backed out changeset 2ca3d042a78d (bug 1801204) for causing multiple bc failures. --- .../components/firefoxview/firefoxview.css | 45 ++- .../components/firefoxview/firefoxview.html | 11 +- browser/components/firefoxview/helpers.mjs | 6 +- .../firefoxview/recently-closed-tabs.mjs | 366 ++++++++++-------- .../firefoxview/tab-pickup-list.mjs | 2 +- .../browser/browser_recently_closed_tabs.js | 131 ++++--- .../browser_recently_closed_tabs_keyboard.js | 19 +- 7 files changed, 326 insertions(+), 254 deletions(-) diff --git a/browser/components/firefoxview/firefoxview.css b/browser/components/firefoxview/firefoxview.css index 641f24d297b5..0d3e6a4ed828 100644 --- a/browser/components/firefoxview/firefoxview.css +++ b/browser/components/firefoxview/firefoxview.css @@ -628,20 +628,18 @@ details[open] > .page-section-header > .twisty { } @media (prefers-contrast) { - .closed-tab-li-main, - .closed-tab-li-dismiss { + span.closed-tab-li-main, + button.closed-tab-li-dismiss { color: ButtonText; border-radius: 4px; border: 1px solid ButtonText; } } -@media not (prefers-contrast) { - .closed-tab-li-main:hover { - background-color: var(--fxview-element-background-hover); - color: var(--fxview-text-color-hover); - } - } +.closed-tab-li-main:hover { + background-color: var(--fxview-element-background-hover); + color: var(--fxview-text-color-hover); +} .closed-tab-li-main:hover .closed-tab-li-title { text-decoration-line: underline; @@ -696,26 +694,32 @@ details[open] > .page-section-header > .twisty { fill: var(--in-content-button-text-color-hover); } -.tab-link, -.tab-link:hover, -.tab-link:active, -.tab-link:hover:active, -.tab-link:visited { +.synced-tab-a, +.synced-tab-a:hover, +.synced-tab-a:active, +.synced-tab-a:hover:active, +.synced-tab-a:visited { color: inherit; text-decoration: none; + height: 100%; } @media (prefers-contrast) { - .tab-link { + .synced-tab-a { border-color: FieldText; } - .tab-link, - .tab-link:hover, - .tab-link:active, - .tab-link:hover:active, - .tab-link:visited { + .synced-tab-a, + .synced-tab-a:hover, + .synced-tab-a:active, + .synced-tab-a:hover:active, + .synced-tab-a:visited { color: LinkText; } + .synced-tab-a:focus-visible { + box-shadow: none; + outline: var(--in-content-focus-outline); + outline-offset: var(--in-content-focus-outline-offset); + } } .closed-tab-li-url, @@ -792,8 +796,7 @@ details[open] > .page-section-header > .twisty { grid-template-areas: "favicon title title title" "favicon domain domain domain" - "favicon device device time"; - height: 100%; + "favicon device device time" } .synced-tab-a:hover { diff --git a/browser/components/firefoxview/firefoxview.html b/browser/components/firefoxview/firefoxview.html index aa334025eeec..d8b473ea1342 100644 --- a/browser/components/firefoxview/firefoxview.html +++ b/browser/components/firefoxview/firefoxview.html @@ -159,7 +159,16 @@

- + + + +
diff --git a/browser/components/firefoxview/helpers.mjs b/browser/components/firefoxview/helpers.mjs index e733bd799607..4cd95c794801 100644 --- a/browser/components/firefoxview/helpers.mjs +++ b/browser/components/firefoxview/helpers.mjs @@ -46,8 +46,12 @@ export function convertTimestamp( } export function createFaviconElement(image, targetURI = "") { + const imageUrl = image + ? lazy.PlacesUIUtils.getImageURL(image) + : `page-icon:${targetURI}`; let favicon = document.createElement("div"); - favicon.style.backgroundImage = `url('${getImageUrl(image, targetURI)}')`; + + favicon.style.backgroundImage = `url('${imageUrl}')`; favicon.classList.add("favicon"); return favicon; } diff --git a/browser/components/firefoxview/recently-closed-tabs.mjs b/browser/components/firefoxview/recently-closed-tabs.mjs index 30fdebd1a852..e3a207fc5dcc 100644 --- a/browser/components/firefoxview/recently-closed-tabs.mjs +++ b/browser/components/firefoxview/recently-closed-tabs.mjs @@ -10,18 +10,11 @@ ChromeUtils.defineESModuleGetters(lazy, { import { formatURIForDisplay, convertTimestamp, - getImageUrl, + createFaviconElement, onToggleContainer, NOW_THRESHOLD_MS, } from "./helpers.mjs"; -import { - html, - ifDefined, - styleMap, -} from "chrome://global/content/vendor/lit.all.mjs"; -import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; - const { XPCOMUtils } = ChromeUtils.importESModule( "resource://gre/modules/XPCOMUtils.sys.mjs" ); @@ -35,12 +28,11 @@ function getWindow() { return window.browsingContext.embedderWindowGlobal.browsingContext.window; } -class RecentlyClosedTabsList extends MozLitElement { +class RecentlyClosedTabsList extends HTMLElement { constructor() { super(); this.maxTabsLength = 25; - this.recentlyClosedTabs = []; - this.lastFocusedIndex = -1; + this.closedTabsData = new Map(); // The recency timestamp update period is stored in a pref to allow tests to easily change it XPCOMUtils.defineLazyPreferenceGetter( @@ -52,15 +44,10 @@ class RecentlyClosedTabsList extends MozLitElement { ); } - createRenderRoot() { - return this; + get tabsList() { + return this.querySelector("ol"); } - static queries = { - tabsList: "ol", - timeElements: { all: "span.closed-tab-li-time" }, - }; - get fluentStrings() { if (!this._fluentStrings) { this._fluentStrings = new Localization(["browser/firefoxView.ftl"], true); @@ -68,8 +55,13 @@ class RecentlyClosedTabsList extends MozLitElement { return this._fluentStrings; } + get timeElements() { + return this.querySelectorAll("span.closed-tab-li-time"); + } + connectedCallback() { - super.connectedCallback(); + this.addEventListener("click", this); + this.addEventListener("keydown", this); this.intervalID = setInterval(() => this.updateTime(), lazy.timeMsPref); } @@ -77,6 +69,20 @@ class RecentlyClosedTabsList extends MozLitElement { clearInterval(this.intervalID); } + handleEvent(event) { + if ( + (event.type == "click" && !event.altKey) || + (event.type == "keydown" && event.keyCode == KeyEvent.DOM_VK_RETURN) || + (event.type == "keydown" && event.keyCode == KeyEvent.DOM_VK_SPACE) + ) { + if (!event.target.classList.contains("closed-tab-li-dismiss")) { + this.openTabAndUpdate(event); + } else { + this.dismissTabAndUpdate(event); + } + } + } + updateTime() { for (let timeEl of this.timeElements) { timeEl.textContent = convertTimestamp( @@ -99,17 +105,44 @@ class RecentlyClosedTabsList extends MozLitElement { return value; } + focusFirstItemOrHeader(dismissedIndex) { + // When a tab is removed from the list, the focus should + // remain on the list or the list header. This prevents context + // switching when navigating back to Firefox View. + let recentlyClosedList = [...this.tabsList.children]; + if (recentlyClosedList.length) { + recentlyClosedList.forEach(element => + element.setAttribute("tabindex", "-1") + ); + let mainContent; + if (dismissedIndex) { + // Select the item above the one that was just dismissed + mainContent = recentlyClosedList[dismissedIndex - 1].querySelector( + ".closed-tab-li-main" + ); + } else { + mainContent = recentlyClosedList[0].querySelector( + ".closed-tab-li-main" + ); + } + mainContent.setAttribute("tabindex", "0"); + mainContent.focus(); + } else { + document.getElementById("recently-closed-tabs-header-section").focus(); + } + } + openTabAndUpdate(event) { event.preventDefault(); - if (event.type == "click" && event.altKey) { - return; - } const item = event.target.closest(".closed-tab-li"); // only used for telemetry const position = [...this.tabsList.children].indexOf(item) + 1; const closedId = item.dataset.tabid; lazy.SessionStore.undoCloseById(closedId); + this.tabsList.removeChild(item); + + this.focusFirstItemOrHeader(); // record telemetry let tabClosedAt = parseInt( @@ -141,8 +174,11 @@ class RecentlyClosedTabsList extends MozLitElement { // Tab not found in recently closed list return; } + this.tabsList.removeChild(item); lazy.SessionStore.forgetClosedTab(getWindow(), closedTabIndex); + this.focusFirstItemOrHeader(closedTabIndex); + // record telemetry let tabClosedAt = parseInt( item.querySelector(".closed-tab-li-time").dataset.timestamp @@ -161,145 +197,138 @@ class RecentlyClosedTabsList extends MozLitElement { ); } - updateRecentlyClosedTabs() { - let recentlyClosedTabsData = lazy.SessionStore.getClosedTabData( - getWindow() - ); - this.recentlyClosedTabs = recentlyClosedTabsData.slice( - 0, - this.maxTabsLength - ); - this.requestUpdate(); - } + updateTabsList() { + let newClosedTabs = lazy.SessionStore.getClosedTabData(getWindow()); + newClosedTabs = newClosedTabs.slice(0, this.maxTabsLength); - render() { - let { recentlyClosedTabs } = this; - let closedTabsContainer = document.getElementById( - "recently-closed-tabs-container" - ); - - if (!recentlyClosedTabs.length) { - // Show empty message if no recently closed tabs - closedTabsContainer.toggleContainerStyleForEmptyMsg(true); - return html` - ${this.emptyMessageTemplate()} - `; - } - - closedTabsContainer.toggleContainerStyleForEmptyMsg(false); - - return html` -
    - ${recentlyClosedTabs.map((tab, i) => - this.recentlyClosedTabTemplate(tab, !i) - )} -
- `; - } - - willUpdate() { - if (this.tabsList && this.tabsList.contains(document.activeElement)) { - let activeLi = document.activeElement.closest(".closed-tab-li"); - this.lastFocusedIndex = [...this.tabsList.children].indexOf(activeLi); - } else { - this.lastFocusedIndex = -1; - } - } - - updated() { - let focusRestored = false; - if (this.lastFocusedIndex >= 0) { - if (this.tabsList && this.tabsList.children.length) { - let items = [...this.tabsList.children]; - let newFocusIndex = Math.max( - Math.min(items.length - 1, this.lastFocusedIndex - 1), - 0 - ); - let newFocus = items[newFocusIndex]; - if (newFocus) { - focusRestored = true; - newFocus.querySelector(".closed-tab-li-main").focus(); - } + if (this.closedTabsData.size && !newClosedTabs.length) { + // if a user purges history, clear the list + while (this.tabsList.lastElementChild) { + this.tabsList.lastElementChild.remove(); } - if (!focusRestored) { - document.getElementById("recently-closed-tabs-header-section").focus(); + document + .getElementById("recently-closed-tabs-container") + .togglePlaceholderVisibility(true); + this.tabsList.hidden = true; + this.closedTabsData = new Map(); + return; + } + + // First purge obsolete items out of the map so we don't leak them forever: + for (let id of this.closedTabsData.keys()) { + if (!newClosedTabs.some(t => t.closedId == id)) { + this.closedTabsData.delete(id); } } - this.lastFocusedIndex = -1; + + // Then work out which of the new closed tabs are additions and which update + // existing items: + let tabsToAdd = []; + let tabsToUpdate = []; + for (let newTab of newClosedTabs) { + let oldTab = this.closedTabsData.get(newTab.closedId); + this.closedTabsData.set(newTab.closedId, newTab); + if (!oldTab) { + tabsToAdd.push(newTab); + } else if ( + this.getTabStateValue(oldTab, "url") != + this.getTabStateValue(newTab, "url") + ) { + tabsToUpdate.push(newTab); + } + } + + // Remove existing tabs from tabsList if not in latest closedTabsData + // which is necessary when using "Reopen Closed Tab" from the toolbar + // or when selecting "Forget this site" in History + [...this.tabsList.children].forEach(existingTab => { + if (!this.closedTabsData.get(parseInt(existingTab.dataset.tabid, 10))) { + this.tabsList.removeChild(existingTab); + } + }); + + // If there's nothing to add/update, return. + if (!tabsToAdd.length && !tabsToUpdate.length) { + return; + } + + // Add new tabs. + for (let tab of tabsToAdd.reverse()) { + if (this.tabsList.children.length == this.maxTabsLength) { + this.tabsList.lastChild.remove(); + } + let li = this.generateListItem(tab); + let mainContent = li.querySelector(".closed-tab-li-main"); + // Only the first item in the list should be focusable + if (!this.tabsList.children.length) { + mainContent.setAttribute("tabindex", "0"); + } else if (this.tabsList.children.length) { + mainContent.setAttribute("tabindex", "0"); + this.tabsList.children[0].setAttribute("tabindex", "-1"); + } + this.tabsList.prepend(li); + } + + // Update any recently closed tabs that now have different URLs: + for (let tab of tabsToUpdate) { + let tabElement = this.querySelector( + `.closed-tab-li[data-tabid="${tab.closedId}"]` + ); + let url = this.getTabStateValue(tab, "url"); + this.updateURLForListItem(tabElement, url); + } + + // Now unhide the list if necessary: + if (this.tabsList.hidden) { + this.tabsList.hidden = false; + document + .getElementById("recently-closed-tabs-container") + .togglePlaceholderVisibility(false); + } } - emptyMessageTemplate() { - return html` - - `; - } + generateListItem(tab) { + const li = document.createElement("li"); + li.classList.add("closed-tab-li"); + li.dataset.tabid = tab.closedId; + + const title = document.createElement("span"); + title.textContent = `${tab.title}`; + title.classList.add("closed-tab-li-title"); - recentlyClosedTabTemplate(tab, primary) { const targetURI = this.getTabStateValue(tab, "url"); + const image = tab.image; + const favicon = createFaviconElement(image, targetURI); + + const urlElement = document.createElement("span"); + urlElement.classList.add("closed-tab-li-url"); + + const time = document.createElement("span"); const convertedTime = convertTimestamp(tab.closedAt, this.fluentStrings); - return html` -
  • - this.openTabAndUpdate(e)} - > -
    - - ${tab.title} - - - ${formatURIForDisplay(targetURI)} - - - ${convertedTime} - -
    - -
  • - `; + time.textContent = convertedTime; + time.setAttribute("data-timestamp", tab.closedAt); + time.classList.add("closed-tab-li-time"); + + const mainContent = document.createElement("span"); + mainContent.classList.add("closed-tab-li-main"); + mainContent.setAttribute("role", "link"); + mainContent.setAttribute("tabindex", 0); + mainContent.append(favicon, title, urlElement, time); + + const dismissButton = document.createElement("button"); + let tabTitle = tab.title ?? ""; + document.l10n.setAttributes( + dismissButton, + "firefoxview-closed-tabs-dismiss-tab", + { + tabTitle, + } + ); + dismissButton.classList.add("closed-tab-li-dismiss"); + + li.append(mainContent, dismissButton); + this.updateURLForListItem(li, targetURI); + return li; } // Update the URL for a new or previously-populated list item. @@ -384,7 +413,8 @@ class RecentlyClosedTabsContainer extends HTMLDetailsElement { handleObservers(contentDocument) { if (contentDocument?.URL == "about:firefoxview") { this.addObserversIfNeeded(); - this.list.updateRecentlyClosedTabs(); + this.list.updateTabsList(); + this.maybeUpdateFocus(); } else { this.removeObserversIfNeeded(); } @@ -396,12 +426,16 @@ class RecentlyClosedTabsContainer extends HTMLDetailsElement { (topic == SS_NOTIFY_BROWSER_SHUTDOWN_FLUSH && subject.ownerGlobal == getWindow()) ) { - this.list.updateRecentlyClosedTabs(); + this.list.updateTabsList(); } } onLoad() { - this.list.updateRecentlyClosedTabs(); + if (this.getClosedTabCount() == 0) { + this.togglePlaceholderVisibility(true); + } else { + this.list.updateTabsList(); + } this.addObserversIfNeeded(); } @@ -413,7 +447,27 @@ class RecentlyClosedTabsContainer extends HTMLDetailsElement { } } - toggleContainerStyleForEmptyMsg(visible) { + /** + * Manages focus when returning to the Firefox View tab + * + * @memberof RecentlyClosedTabsContainer + */ + maybeUpdateFocus() { + // Check if focus is in the container element + if (this.contains(document.activeElement)) { + let listItems = this.list.querySelectorAll("li"); + // More tabs may have been added to the list, so we'll refocus + // the first item in the list. + if (listItems.length) { + listItems[0].querySelector(".closed-tab-li-main").focus(); + } else { + this.querySelector("summary").focus(); + } + } + } + + togglePlaceholderVisibility(visible) { + this.noTabsElement.toggleAttribute("hidden", !visible); this.collapsibleContainer.classList.toggle("empty-container", visible); } diff --git a/browser/components/firefoxview/tab-pickup-list.mjs b/browser/components/firefoxview/tab-pickup-list.mjs index d12126f454bc..0acf328a6854 100644 --- a/browser/components/firefoxview/tab-pickup-list.mjs +++ b/browser/components/firefoxview/tab-pickup-list.mjs @@ -352,7 +352,7 @@ class TabPickupList extends HTMLElement { li.classList.add("synced-tab-li"); const a = document.createElement("a"); - a.classList.add("synced-tab-a", "tab-link"); + a.classList.add("synced-tab-a"); a.target = "_blank"; if (index != 0) { a.setAttribute("tabindex", "-1"); diff --git a/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs.js b/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs.js index b66262465ba2..ecb5680c50b1 100644 --- a/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs.js +++ b/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs.js @@ -44,7 +44,7 @@ async function close_tab(tab) { } async function dismiss_tab(tab, content) { - info(`Dismissing tab ${tab.dataset.targeturi}`); + info(`Dismissing tab ${tab.dataset.targetURI}`); const closedObjectsChanged = () => TestUtils.topicObserved("sessionstore-closed-objects-changed"); let dismissButton = tab.querySelector(".closed-tab-li-dismiss"); @@ -63,15 +63,12 @@ add_task(async function test_empty_list() { "collapsible container should have correct styling when the list is empty" ); - Assert.ok( - document.getElementById("recently-closed-tabs-placeholder"), - "The empty message is displayed." - ); - - Assert.ok( - !document.querySelector("ol.closed-tabs-list"), - "The recently closed tabs list is not displayed." - ); + testVisibility(browser, { + expectedVisible: { + "#recently-closed-tabs-placeholder": true, + "ol.closed-tabs-list": false, + }, + }); const tab1 = await add_new_tab(URLs[0]); @@ -88,15 +85,12 @@ add_task(async function test_empty_list() { "collapsible container should have correct styling when the list is not empty" ); - Assert.ok( - !document.getElementById("recently-closed-tabs-placeholder"), - "The empty message is not displayed." - ); - - Assert.ok( - document.querySelector("ol.closed-tabs-list"), - "The recently closed tabs list is displayed." - ); + testVisibility(browser, { + expectedVisible: { + "#recently-closed-tabs-placeholder": false, + "ol.closed-tabs-list": true, + }, + }); is( document.querySelector("ol.closed-tabs-list").children.length, @@ -152,7 +146,7 @@ add_task(async function test_list_ordering() { ok( document .querySelector("ol.closed-tabs-list") - .children[0].textContent.includes("mochi.test"), + .firstChild.textContent.includes("mochi.test"), "first list item in recently-closed-tabs-list is in the correct order" ); @@ -164,9 +158,9 @@ add_task(async function test_list_ordering() { ); let ele = document.querySelector("ol.closed-tabs-list").firstElementChild; - let uri = ele.getAttribute("data-targeturi"); + let uri = ele.getAttribute("data-target-u-r-i"); let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, uri); - ele.querySelector(".closed-tab-li-main").click(); + ele.click(); await newTabPromise; await TestUtils.waitForCondition( @@ -251,18 +245,15 @@ add_task(async function test_max_list_items() { "collapsible container should have correct styling when the list is not empty" ); - Assert.ok( - !document.getElementById("recently-closed-tabs-placeholder"), - "The empty message is not displayed." - ); - - Assert.ok( - document.querySelector("ol.closed-tabs-list"), - "The recently closed tabs list is displayed." - ); + testVisibility(browser, { + expectedVisible: { + "#recently-closed-tabs-placeholder": false, + "ol.closed-tabs-list": true, + }, + }); is( - document.querySelector("ol.closed-tabs-list").children.length, + document.querySelector("ol.closed-tabs-list").childNodes.length, mockMaxTabsLength, `recently-closed-tabs-list should have ${mockMaxTabsLength} list items` ); @@ -274,8 +265,9 @@ add_task(async function test_max_list_items() { const tab = await add_new_tab(URLs[3]); await close_tab(tab); await closedObjectsChanged; + let firstListItem = document.querySelector("ol.closed-tabs-list") - .children[0]; + .firstChild; await BrowserTestUtils.waitForMutationCondition( firstListItem, { characterData: true, childList: true, subtree: true }, @@ -287,7 +279,7 @@ add_task(async function test_max_list_items() { ); is( - document.querySelector("ol.closed-tabs-list").children.length, + document.querySelector("ol.closed-tabs-list").childNodes.length, mockMaxTabsLength, `recently-closed-tabs-list should still have ${mockMaxTabsLength} list items` ); @@ -318,7 +310,6 @@ add_task(async function test_time_updates_correctly() { closedId: 0, closedAt: Date.now() - TAB_CLOSED_AGO_MS, image: null, - title: "Example", }, ], }, @@ -338,10 +329,9 @@ add_task(async function test_time_updates_correctly() { }, async browser => { const { document } = browser.contentWindow; - const numOfListItems = document.querySelector("ol.closed-tabs-list") - .children.length; + const lastListItem = document.querySelector("ol.closed-tabs-list") - .children[numOfListItems - 1]; + .lastChild; const timeLabel = lastListItem.querySelector("span.closed-tab-li-time"); let initialTimeText = timeLabel.textContent; Assert.stringContains( @@ -397,12 +387,14 @@ add_task(async function test_list_maintains_focus_when_restoring_tab() { let gBrowser = browser.getTabBrowser(); const { document } = browser.contentWindow; const list = document.querySelectorAll(".closed-tab-li"); + let expectedFocusedElement = list[1].querySelector(".closed-tab-li-main"); list[0].querySelector(".closed-tab-li-main").focus(); EventUtils.synthesizeKey("KEY_Enter"); let firefoxViewTab = gBrowser.tabs.find(tab => tab.label == "Firefox View"); await BrowserTestUtils.switchTab(gBrowser, firefoxViewTab); - Assert.ok( - document.activeElement.textContent.includes("mochitest index"), + is( + document.activeElement, + expectedFocusedElement, "Focus should be on the first item in the recently closed list" ); }); @@ -422,6 +414,7 @@ add_task(async function test_list_maintains_focus_when_restoring_tab() { ); const list = document.querySelectorAll(".closed-tab-li"); list[0].querySelector(".closed-tab-li-main").focus(); + EventUtils.synthesizeKey("KEY_Enter"); let firefoxViewTab = gBrowser.tabs.find(tab => tab.label == "Firefox View"); await BrowserTestUtils.switchTab(gBrowser, firefoxViewTab); @@ -462,25 +455,27 @@ add_task(async function test_switch_before_closing() { ); BrowserTestUtils.loadURIString(newTab.linkedBrowser, FINAL_URL); await loadPromise; + // Close the added tab BrowserTestUtils.removeTab(newTab); const { document } = browser.contentWindow; - await BrowserTestUtils.waitForMutationCondition( - document.querySelector("recently-closed-tabs-list"), - { childList: true, subtree: true }, - () => document.querySelector("ol.closed-tabs-list") - ); const tabsList = document.querySelector("ol.closed-tabs-list"); + await BrowserTestUtils.waitForMutationCondition( + tabsList, + { childList: true }, + () => !!tabsList.children.length + ); info("A tab appeared in the list, ensure it has the right URL."); - let urlBit = tabsList.children[0].querySelector(".closed-tab-li-url"); + let urlBit = tabsList.firstElementChild.querySelector(".closed-tab-li-url"); await BrowserTestUtils.waitForMutationCondition( urlBit, { characterData: true, attributeFilter: ["title"] }, () => urlBit.textContent.includes(".com") ); - Assert.ok( - urlBit.textContent.includes("example.com"), + is( + urlBit.textContent, + "example.com", "Item should end up with the correct URL." ); }); @@ -500,7 +495,7 @@ add_task(async function test_alt_click_no_launch() { let gBrowser = browser.getTabBrowser(); let originalTabsLength = gBrowser.tabs.length; await BrowserTestUtils.synthesizeMouseAtCenter( - ".closed-tab-li .closed-tab-li-main", + ".closed-tab-li", { altKey: true }, browser ); @@ -559,6 +554,19 @@ add_task(async function test_restore_recently_closed_tabs() { await tabRestored; ok(true, "Tab was restored by using the Enter key"); + await EventUtils.synthesizeMouseAtCenter( + gBrowser.ownerDocument.getElementById("firefox-view-button"), + { type: "mousedown" }, + window + ); + + tabRestored = BrowserTestUtils.waitForNewTab(gBrowser, URLs[0]); + document.querySelector(".closed-tab-li .closed-tab-li-main").focus(); + EventUtils.synthesizeKey(" ", {}, gBrowser.contentWindow); + + await tabRestored; + ok(true, "Tab was restored by using the Space bar"); + // clean up extra tabs while (gBrowser.tabs.length > 1) { BrowserTestUtils.removeTab(gBrowser.tabs.at(-1)); @@ -610,7 +618,7 @@ add_task(async function test_reopen_recently_closed_tabs() { ); Assert.equal( - tabsList.children[0].dataset.targeturi, + tabsList.children[0].dataset.targetURI, URLs[1], `First recently closed item should be ${URLs[1]}` ); @@ -624,7 +632,7 @@ add_task(async function test_reopen_recently_closed_tabs() { ); Assert.equal( - tabsList.children[0].dataset.targeturi, + tabsList.children[0].dataset.targetURI, URLs[2], `First recently closed item should be ${URLs[2]}` ); @@ -638,7 +646,7 @@ add_task(async function test_reopen_recently_closed_tabs() { ); Assert.equal( - tabsList.children[0].dataset.targeturi, + tabsList.children[0].dataset.targetURI, URLs[1], `First recently closed item should be ${URLs[1]}` ); @@ -707,7 +715,7 @@ add_task(async function test_dismiss_tab() { ); Assert.equal( - tabsList.children[0].dataset.targeturi, + tabsList.children[0].dataset.targetURI, URLs[1], `First recently closed item should be ${URLs[1]}` ); @@ -742,7 +750,7 @@ add_task(async function test_dismiss_tab() { ); Assert.equal( - tabsList.children[0].dataset.targeturi, + tabsList.children[0].dataset.targetURI, URLs[2], `First recently closed item should be ${URLs[2]}` ); @@ -776,14 +784,11 @@ add_task(async function test_dismiss_tab() { { clear: true, process: "parent" } ); - Assert.ok( - document.getElementById("recently-closed-tabs-placeholder"), - "The empty message is displayed." - ); - - Assert.ok( - !document.querySelector("ol.closed-tabs-list"), - "The recently closed tabs list is not displayed." - ); + testVisibility(browser, { + expectedVisible: { + "#recently-closed-tabs-placeholder": true, + "ol.closed-tabs-list": false, + }, + }); }); }); diff --git a/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs_keyboard.js b/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs_keyboard.js index 21ecaa334ed9..2d495934dfb4 100644 --- a/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs_keyboard.js +++ b/browser/components/firefoxview/tests/browser/browser_recently_closed_tabs_keyboard.js @@ -218,7 +218,7 @@ add_task(async function test_dismiss_tab_keyboard() { await dismiss_tab_keyboard(tabsList.children[0], document); Assert.equal( - tabsList.children[0].dataset.targeturi, + tabsList.children[0].dataset.targetURI, URLs[1], `First recently closed item should be ${URLs[1]}` ); @@ -232,7 +232,7 @@ add_task(async function test_dismiss_tab_keyboard() { await dismiss_tab_keyboard(tabsList.children[0], document); Assert.equal( - tabsList.children[0].dataset.targeturi, + tabsList.children[0].dataset.targetURI, URLs[0], `First recently closed item should be ${URLs[0]}` ); @@ -245,14 +245,11 @@ add_task(async function test_dismiss_tab_keyboard() { await dismiss_tab_keyboard(tabsList.children[0], document); - Assert.ok( - document.getElementById("recently-closed-tabs-placeholder"), - "The empty message is displayed." - ); - - Assert.ok( - !document.querySelector("ol.closed-tabs-list"), - "The recently clsoed tabs list is not displayed." - ); + testVisibility(browser, { + expectedVisible: { + "#recently-closed-tabs-placeholder": true, + "ol.closed-tabs-list": false, + }, + }); }); });