gecko-dev/toolkit/components/reader/test/browser_readerMode.js
Kris Maglione e930b89c34 Bug 1514594: Part 3 - Change ChromeUtils.import API.
***
Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8

This changes the behavior of ChromeUtils.import() to return an exports object,
rather than a module global, in all cases except when `null` is passed as a
second argument, and changes the default behavior not to pollute the global
scope with the module's exports. Thus, the following code written for the old
model:

  ChromeUtils.import("resource://gre/modules/Services.jsm");

is approximately the same as the following, in the new model:

  var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");

Since the two behaviors are mutually incompatible, this patch will land with a
scripted rewrite to update all existing callers to use the new model rather
than the old.
***
Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs

This was done using the followng script:

https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm
***
Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8

Differential Revision: https://phabricator.services.mozilla.com/D16747
***
Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D16748
***
Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D16749
***
Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs
***
Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D16750

--HG--
extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895
extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
2019-01-17 10:18:31 -08:00

245 lines
9.6 KiB
JavaScript

/* 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/. */
/**
* Test that the reader mode button appears and works properly on
* reader-able content.
*/
const TEST_PREFS = [
["reader.parse-on-load.enabled", true],
];
const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
var readerButton = document.getElementById("reader-mode-button");
ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
add_task(async function test_reader_button() {
registerCleanupFunction(function() {
// Reset test prefs.
TEST_PREFS.forEach(([name, value]) => {
Services.prefs.clearUserPref(name);
});
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
// Set required test prefs.
TEST_PREFS.forEach(([name, value]) => {
Services.prefs.setBoolPref(name, value);
});
let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
is_element_hidden(readerButton, "Reader mode button is not present on a new tab");
ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"),
"Info panel shouldn't appear without the reader mode button");
// Point tab to a test page that is reader-able.
let url = TEST_PATH + "readerModeArticle.html";
// Set up favicon for testing.
let favicon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAA" +
"AAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==";
info("Adding visit so we can add favicon");
await PlacesTestUtils.addVisits(new URL(url));
info("Adding favicon");
await PlacesTestUtils.addFavicons(new Map([[url, favicon]]));
info("Opening tab and waiting for reader mode button to show up");
await promiseTabLoadEvent(tab, url);
await TestUtils.waitForCondition(() => !readerButton.hidden);
is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
// Switch page into reader mode.
let promiseTabLoad = promiseTabLoadEvent(tab);
readerButton.click();
await promiseTabLoad;
let readerUrl = gBrowser.selectedBrowser.currentURI.spec;
ok(readerUrl.startsWith("about:reader"), "about:reader loaded after clicking reader mode button");
is_element_visible(readerButton, "Reader mode button is present on about:reader");
let iconEl = document.getAnonymousElementByAttribute(tab, "anonid", "tab-icon-image");
await TestUtils.waitForCondition(() => iconEl.getBoundingClientRect().width != 0);
is_element_visible(iconEl, "Favicon should be visible");
is(iconEl.src, favicon, "Correct favicon should be loaded");
is(gURLBar.value, readerUrl, "gURLBar value is about:reader URL");
is(gURLBar.textValue, url.substring("http://".length), "gURLBar is displaying original article URL");
// Check selected value for URL bar
await new Promise((resolve, reject) => {
waitForClipboard(url, function() {
gURLBar.focus();
gURLBar.select();
goDoCommand("cmd_copy");
}, resolve, reject);
});
info("Got correct URL when copying");
// Switch page back out of reader mode.
let promisePageShow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
readerButton.click();
await promisePageShow;
is(gBrowser.selectedBrowser.currentURI.spec, url,
"Back to the original page after clicking active reader mode button");
ok(gBrowser.selectedBrowser.canGoForward,
"Moved one step back in the session history.");
let nonReadableUrl = TEST_PATH + "readerModeNonArticle.html";
// Load a new tab that is NOT reader-able.
let newTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
await promiseTabLoadEvent(newTab, nonReadableUrl);
await TestUtils.waitForCondition(() => readerButton.hidden);
is_element_hidden(readerButton, "Reader mode button is not present on a non-reader-able page");
// Switch back to the original tab to make sure reader mode button is still visible.
gBrowser.removeCurrentTab();
await TestUtils.waitForCondition(() => !readerButton.hidden);
is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
// Load a new tab in reader mode that is NOT reader-able in the reader mode.
newTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
let promiseAboutReaderError = BrowserTestUtils.waitForContentEvent(newTab.linkedBrowser, "AboutReaderContentError");
await promiseTabLoadEvent(newTab, "about:reader?url=" + nonReadableUrl);
await promiseAboutReaderError;
await TestUtils.waitForCondition(() => !readerButton.hidden);
is_element_visible(readerButton, "Reader mode button is present on about:reader even in error state");
// Switch page back out of reader mode.
promisePageShow = BrowserTestUtils.waitForContentEvent(newTab.linkedBrowser, "pageshow");
readerButton.click();
await promisePageShow;
is(gBrowser.selectedBrowser.currentURI.spec, nonReadableUrl,
"Back to the original non-reader-able page after clicking active reader mode button");
await TestUtils.waitForCondition(() => readerButton.hidden);
is_element_hidden(readerButton, "Reader mode button is not present on a non-reader-able page");
});
add_task(async function test_getOriginalUrl() {
let { ReaderMode } = ChromeUtils.import("resource://gre/modules/ReaderMode.jsm");
let url = "http://foo.com/article.html";
is(ReaderMode.getOriginalUrl("about:reader?url=" + encodeURIComponent(url)), url, "Found original URL from encoded URL");
is(ReaderMode.getOriginalUrl("about:reader?foobar"), null, "Did not find original URL from malformed reader URL");
is(ReaderMode.getOriginalUrl(url), null, "Did not find original URL from non-reader URL");
let badUrl = "http://foo.com/?;$%^^";
is(ReaderMode.getOriginalUrl("about:reader?url=" + encodeURIComponent(badUrl)), badUrl, "Found original URL from encoded malformed URL");
is(ReaderMode.getOriginalUrl("about:reader?url=" + badUrl), badUrl, "Found original URL from non-encoded malformed URL");
});
add_task(async function test_reader_view_element_attribute_transform() {
registerCleanupFunction(function() {
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
function observeAttribute(element, attribute, triggerFn, checkFn) {
return new Promise(resolve => {
let observer = new MutationObserver((mutations) => {
mutations.forEach( mu => {
if (element.getAttribute(attribute) !== mu.oldValue) {
checkFn();
resolve();
observer.disconnect();
}
});
});
observer.observe(element, {
attributes: true,
attributeOldValue: true,
attributeFilter: [attribute],
});
triggerFn();
});
}
let menuitem = document.getElementById("menu_readerModeItem");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
is(menuitem.hidden, true, "menuitem element should have the hidden attribute");
info("Navigate a reader-able page");
let waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
await observeAttribute(menuitem, "hidden",
() => {
let url = TEST_PATH + "readerModeArticle.html";
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
},
() => {
is(menuitem.hidden, false, "menuitem's hidden attribute should be false on a reader-able page");
}
);
await waitForPageshow;
info("Navigate a non-reader-able page");
waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
await observeAttribute(menuitem, "hidden",
() => {
let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
},
() => {
is(menuitem.hidden, true, "menuitem's hidden attribute should be true on a non-reader-able page");
}
);
await waitForPageshow;
info("Navigate a reader-able page");
waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
await observeAttribute(menuitem, "hidden",
() => {
let url = TEST_PATH + "readerModeArticle.html";
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
},
() => {
is(menuitem.hidden, false, "menuitem's hidden attribute should be false on a reader-able page");
}
);
await waitForPageshow;
info("Enter Reader Mode");
waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
await observeAttribute(readerButton, "readeractive",
() => {
readerButton.click();
},
() => {
is(readerButton.getAttribute("readeractive"), "true", "readerButton's readeractive attribute should be true when entering reader mode");
}
);
await waitForPageshow;
info("Exit Reader Mode");
waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
await observeAttribute(readerButton, "readeractive",
() => {
readerButton.click();
},
() => {
is(readerButton.getAttribute("readeractive"), "", "readerButton's readeractive attribute should be empty when reader mode is exited");
}
);
await waitForPageshow;
info("Navigate a non-reader-able page");
waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
await observeAttribute(menuitem, "hidden",
() => {
let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
},
() => {
is(menuitem.hidden, true, "menuitem's hidden attribute should be true on a non-reader-able page");
}
);
await waitForPageshow;
});