summaryrefslogtreecommitdiffstats
path: root/toolkit/components/reader/test
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /toolkit/components/reader/test
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'toolkit/components/reader/test')
-rw-r--r--toolkit/components/reader/test/browser.ini15
-rw-r--r--toolkit/components/reader/test/browser_bug1124271_readerModePinnedTab.js47
-rw-r--r--toolkit/components/reader/test/browser_readerMode.js220
-rw-r--r--toolkit/components/reader/test/browser_readerMode_hidden_nodes.js53
-rw-r--r--toolkit/components/reader/test/browser_readerMode_with_anchor.js21
-rw-r--r--toolkit/components/reader/test/head.js126
-rw-r--r--toolkit/components/reader/test/readerModeArticle.html25
-rw-r--r--toolkit/components/reader/test/readerModeArticleHiddenNodes.html22
8 files changed, 529 insertions, 0 deletions
diff --git a/toolkit/components/reader/test/browser.ini b/toolkit/components/reader/test/browser.ini
new file mode 100644
index 000000000..4f9df23b3
--- /dev/null
+++ b/toolkit/components/reader/test/browser.ini
@@ -0,0 +1,15 @@
+[DEFAULT]
+support-files = head.js
+[browser_readerMode.js]
+support-files =
+ readerModeArticle.html
+ readerModeArticleHiddenNodes.html
+[browser_readerMode_hidden_nodes.js]
+support-files =
+ readerModeArticleHiddenNodes.html
+[browser_readerMode_with_anchor.js]
+support-files =
+ readerModeArticle.html
+[browser_bug1124271_readerModePinnedTab.js]
+support-files =
+ readerModeArticle.html
diff --git a/toolkit/components/reader/test/browser_bug1124271_readerModePinnedTab.js b/toolkit/components/reader/test/browser_bug1124271_readerModePinnedTab.js
new file mode 100644
index 000000000..39913aa3e
--- /dev/null
+++ b/toolkit/components/reader/test/browser_bug1124271_readerModePinnedTab.js
@@ -0,0 +1,47 @@
+/* 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 won't open in a new tab when clicked from a pinned tab
+
+const PREF = "reader.parse-on-load.enabled";
+
+const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
+
+var readerButton = document.getElementById("reader-mode-button");
+
+add_task(function* () {
+ registerCleanupFunction(function() {
+ Services.prefs.clearUserPref(PREF);
+ while (gBrowser.tabs.length > 1) {
+ gBrowser.removeCurrentTab();
+ }
+ });
+
+ // Enable the reader mode button.
+ Services.prefs.setBoolPref(PREF, true);
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.pinTab(tab);
+
+ let initialTabsCount = gBrowser.tabs.length;
+
+ // Point tab to a test page that is reader-able.
+ let url = TEST_PATH + "readerModeArticle.html";
+ yield promiseTabLoadEvent(tab, url);
+ yield promiseWaitForCondition(() => !readerButton.hidden);
+
+ readerButton.click();
+ yield promiseTabLoadEvent(tab);
+
+ // Ensure no new tabs are opened when exiting reader mode in a pinned tab
+ is(gBrowser.tabs.length, initialTabsCount, "No additional tabs were opened.");
+
+ let pageShownPromise = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+ readerButton.click();
+ yield pageShownPromise;
+ // Ensure no new tabs are opened when exiting reader mode in a pinned tab
+ is(gBrowser.tabs.length, initialTabsCount, "No additional tabs were opened.");
+
+ gBrowser.removeCurrentTab();
+});
diff --git a/toolkit/components/reader/test/browser_readerMode.js b/toolkit/components/reader/test/browser_readerMode.js
new file mode 100644
index 000000000..70290c3b5
--- /dev/null
+++ b/toolkit/components/reader/test/browser_readerMode.js
@@ -0,0 +1,220 @@
+/* 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");
+
+add_task(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);
+ });
+ Services.prefs.setBoolPref("browser.reader.detectedFirstArticle", false);
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab();
+ 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");
+ ok(!Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
+ "Shouldn't have detected the first article");
+
+ // We're going to show the reader mode intro popup, make sure we wait for it:
+ let tourPopupShownPromise =
+ BrowserTestUtils.waitForEvent(document.getElementById("UITourTooltip"), "popupshown");
+ // Point tab to a test page that is reader-able.
+ let url = TEST_PATH + "readerModeArticle.html";
+ yield promiseTabLoadEvent(tab, url);
+ yield promiseWaitForCondition(() => !readerButton.hidden);
+ yield tourPopupShownPromise;
+ is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
+ ok(UITour.isInfoOnTarget(window, "readerMode-urlBar"),
+ "Info panel should be anchored at the reader mode button");
+ ok(Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
+ "Should have detected the first article");
+
+ // Switch page into reader mode.
+ readerButton.click();
+ yield promiseTabLoadEvent(tab);
+ ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"), "Info panel should have closed");
+
+ 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");
+
+ 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
+ yield 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();
+ yield 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.");
+
+ // Load a new tab that is NOT reader-able.
+ let newTab = gBrowser.selectedTab = gBrowser.addTab();
+ yield promiseTabLoadEvent(newTab, "about:robots");
+ yield promiseWaitForCondition(() => 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();
+ yield promiseWaitForCondition(() => !readerButton.hidden);
+ is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
+});
+
+add_task(function* test_getOriginalUrl() {
+ let { ReaderMode } = Cu.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(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 command = document.getElementById("View:ReaderView");
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
+ is(command.hidden, true, "Command element should have the hidden attribute");
+
+ info("Navigate a reader-able page");
+ let waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+ yield observeAttribute(command, "hidden",
+ () => {
+ let url = TEST_PATH + "readerModeArticle.html";
+ tab.linkedBrowser.loadURI(url);
+ },
+ () => {
+ is(command.hidden, false, "Command's hidden attribute should be false on a reader-able page");
+ }
+ );
+ yield waitForPageshow;
+
+ info("Navigate a non-reader-able page");
+ waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+ yield observeAttribute(command, "hidden",
+ () => {
+ let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
+ tab.linkedBrowser.loadURI(url);
+ },
+ () => {
+ is(command.hidden, true, "Command's hidden attribute should be true on a non-reader-able page");
+ }
+ );
+ yield waitForPageshow;
+
+ info("Navigate a reader-able page");
+ waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+ yield observeAttribute(command, "hidden",
+ () => {
+ let url = TEST_PATH + "readerModeArticle.html";
+ tab.linkedBrowser.loadURI(url);
+ },
+ () => {
+ is(command.hidden, false, "Command's hidden attribute should be false on a reader-able page");
+ }
+ );
+ yield waitForPageshow;
+
+ info("Enter Reader Mode");
+ waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+ yield observeAttribute(readerButton, "readeractive",
+ () => {
+ readerButton.click();
+ },
+ () => {
+ is(readerButton.getAttribute("readeractive"), "true", "readerButton's readeractive attribute should be true when entering reader mode");
+ }
+ );
+ yield waitForPageshow;
+
+ info("Exit Reader Mode");
+ waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+ yield observeAttribute(readerButton, "readeractive",
+ () => {
+ readerButton.click();
+ },
+ () => {
+ is(readerButton.getAttribute("readeractive"), "", "readerButton's readeractive attribute should be empty when reader mode is exited");
+ }
+ );
+ yield waitForPageshow;
+
+ info("Navigate a non-reader-able page");
+ waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+ yield observeAttribute(command, "hidden",
+ () => {
+ let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
+ tab.linkedBrowser.loadURI(url);
+ },
+ () => {
+ is(command.hidden, true, "Command's hidden attribute should be true on a non-reader-able page");
+ }
+ );
+ yield waitForPageshow;
+});
diff --git a/toolkit/components/reader/test/browser_readerMode_hidden_nodes.js b/toolkit/components/reader/test/browser_readerMode_hidden_nodes.js
new file mode 100644
index 000000000..b73eab58d
--- /dev/null
+++ b/toolkit/components/reader/test/browser_readerMode_hidden_nodes.js
@@ -0,0 +1,53 @@
+/* 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],
+ ["browser.reader.detectedFirstArticle", false],
+];
+
+const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
+
+var readerButton = document.getElementById("reader-mode-button");
+
+add_task(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 = gBrowser.addTab();
+ is_element_hidden(readerButton, "Reader mode button is not present on a new tab");
+ // Point tab to a test page that is not reader-able due to hidden nodes.
+ let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
+ let paintPromise = ContentTask.spawn(tab.linkedBrowser, "", function() {
+ return new Promise(resolve => {
+ addEventListener("DOMContentLoaded", function onDCL() {
+ removeEventListener("DOMContentLoaded", onDCL);
+ addEventListener("MozAfterPaint", function onPaint() {
+ removeEventListener("MozAfterPaint", onPaint);
+ resolve();
+ });
+ });
+ });
+ });
+ tab.linkedBrowser.loadURI(url);
+ yield paintPromise;
+
+ is_element_hidden(readerButton, "Reader mode button is still not present on tab with unreadable content.");
+});
diff --git a/toolkit/components/reader/test/browser_readerMode_with_anchor.js b/toolkit/components/reader/test/browser_readerMode_with_anchor.js
new file mode 100644
index 000000000..24c23c49f
--- /dev/null
+++ b/toolkit/components/reader/test/browser_readerMode_with_anchor.js
@@ -0,0 +1,21 @@
+/* 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/. */
+
+"use strict";
+
+const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
+
+add_task(function* () {
+ yield BrowserTestUtils.withNewTab(TEST_PATH + "readerModeArticle.html#foo", function* (browser) {
+ let pageShownPromise = BrowserTestUtils.waitForContentEvent(browser, "AboutReaderContentReady");
+ let readerButton = document.getElementById("reader-mode-button");
+ readerButton.click();
+ yield pageShownPromise;
+ yield ContentTask.spawn(browser, null, function* () {
+ // Check if offset != 0
+ ok(content.document.getElementById("foo") !== null, "foo element should be in document");
+ ok(content.pageYOffset != 0, "pageYOffset should be > 0");
+ });
+ });
+});
diff --git a/toolkit/components/reader/test/head.js b/toolkit/components/reader/test/head.js
new file mode 100644
index 000000000..3d8d989bc
--- /dev/null
+++ b/toolkit/components/reader/test/head.js
@@ -0,0 +1,126 @@
+XPCOMUtils.defineLazyModuleGetter(this, "Promise",
+ "resource://gre/modules/Promise.jsm");
+
+/* exported promiseTabLoadEvent, promiseWaitForCondition, is_element_visible, is_element_hidden */
+
+/**
+ * Waits for a load (or custom) event to finish in a given tab. If provided
+ * load an uri into the tab.
+ *
+ * @param tab
+ * The tab to load into.
+ * @param [optional] url
+ * The url to load, or the current url.
+ * @return {Promise} resolved when the event is handled.
+ * @resolves to the received event
+ * @rejects if a valid load event is not received within a meaningful interval
+ */
+function promiseTabLoadEvent(tab, url) {
+ let deferred = Promise.defer();
+ info("Wait tab event: load");
+
+ function handle(loadedUrl) {
+ if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) {
+ info(`Skipping spurious load event for ${loadedUrl}`);
+ return false;
+ }
+
+ info("Tab event received: load");
+ return true;
+ }
+
+ // Create two promises: one resolved from the content process when the page
+ // loads and one that is rejected if we take too long to load the url.
+ let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle);
+
+ let timeout = setTimeout(() => {
+ deferred.reject(new Error("Timed out while waiting for a 'load' event"));
+ }, 30000);
+
+ loaded.then(() => {
+ clearTimeout(timeout);
+ deferred.resolve();
+ });
+
+ if (url)
+ BrowserTestUtils.loadURI(tab.linkedBrowser, url);
+
+ // Promise.all rejects if either promise rejects (i.e. if we time out) and
+ // if our loaded promise resolves before the timeout, then we resolve the
+ // timeout promise as well, causing the all promise to resolve.
+ return Promise.all([deferred.promise, loaded]);
+}
+
+function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
+ retryTimes = typeof retryTimes !== 'undefined' ? retryTimes : 30;
+ var tries = 0;
+ var interval = setInterval(function() {
+ if (tries >= retryTimes) {
+ ok(false, errorMsg);
+ moveOn();
+ }
+ var conditionPassed;
+ try {
+ conditionPassed = condition();
+ } catch (e) {
+ ok(false, e + "\n" + e.stack);
+ conditionPassed = false;
+ }
+ if (conditionPassed) {
+ moveOn();
+ }
+ tries++;
+ }, 100);
+ var moveOn = function() {
+ clearInterval(interval);
+ nextTest();
+ };
+}
+
+function promiseWaitForCondition(aConditionFn) {
+ let deferred = Promise.defer();
+ waitForCondition(aConditionFn, deferred.resolve, "Condition didn't pass.");
+ return deferred.promise;
+}
+
+function is_element_visible(element, msg) {
+ isnot(element, null, "Element should not be null, when checking visibility");
+ ok(is_visible(element), msg || "Element should be visible");
+
+}
+function is_element_hidden(element, msg) {
+ isnot(element, null, "Element should not be null, when checking visibility");
+ ok(is_hidden(element), msg || "Element should be hidden");
+}
+
+function is_visible(element) {
+ var style = element.ownerGlobal.getComputedStyle(element);
+ if (style.display == "none")
+ return false;
+ if (style.visibility != "visible")
+ return false;
+ if (style.display == "-moz-popup" && element.state != "open")
+ return false;
+
+ // Hiding a parent element will hide all its children
+ if (element.parentNode != element.ownerDocument)
+ return is_visible(element.parentNode);
+
+ return true;
+}
+
+function is_hidden(element) {
+ var style = element.ownerGlobal.getComputedStyle(element);
+ if (style.display == "none")
+ return true;
+ if (style.visibility != "visible")
+ return true;
+ if (style.display == "-moz-popup")
+ return ["hiding", "closed"].indexOf(element.state) != -1;
+
+ // Hiding a parent element will hide all its children
+ if (element.parentNode != element.ownerDocument)
+ return is_hidden(element.parentNode);
+
+ return false;
+}
diff --git a/toolkit/components/reader/test/readerModeArticle.html b/toolkit/components/reader/test/readerModeArticle.html
new file mode 100644
index 000000000..7c5033d5b
--- /dev/null
+++ b/toolkit/components/reader/test/readerModeArticle.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Article title</title>
+<meta name="description" content="This is the article description." />
+</head>
+<body>
+<header>Site header</header>
+<div>
+<h1>Article title</h1>
+<h2 class="author">by Jane Doe</h2>
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<div id="foo">by John Doe</div>
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+</div>
+</body>
+</html>
diff --git a/toolkit/components/reader/test/readerModeArticleHiddenNodes.html b/toolkit/components/reader/test/readerModeArticleHiddenNodes.html
new file mode 100644
index 000000000..92441b797
--- /dev/null
+++ b/toolkit/components/reader/test/readerModeArticleHiddenNodes.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Article title</title>
+<meta name="description" content="This is the article description." />
+</head>
+<body>
+<style>
+p { display: none }
+</style>
+<header>Site header</header>
+<div>
+<h1>Article title</h1>
+<h2 class="author">by Jane Doe</h2>
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+</div>
+</body>
+</html>