fune/browser/base/content/test/tabs/browser_abandonment_telemetry.js
Jonathan Kingston 555f89c8d7 Bug 1485305 - browser/ tests Ensure loadURI always passes a triggeringPrincipal() r=Mossop
Differential Revision: https://phabricator.services.mozilla.com/D4552

--HG--
extra : source : 2cf17e4974823d09d0fdd1aef64e69e840b288a1
extra : intermediate-source : 4771e6948a78507aa95a56e5b324d87dc82e9009
2018-08-29 15:44:56 +01:00

305 lines
9.2 KiB
JavaScript

"use strict";
const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
// Keep this in sync with the order in Histograms.json for
// BUSY_TAB_ABANDONED
const CATEGORIES = [
"stop",
"back",
"forward",
"historyNavigation",
"reload",
"tabClosed",
"newURI",
];
const PAGE_2 = "data:text/html,<html>Page 2</html>";
/**
* This little framework helps to extract the unique things
* involved in testing each category of the BUSY_TAB_ABANDONED
* probe from all of the common things. The little framework
* in this test will take each item in PROBE_TEST, let it
* do some test preparation, then create a "busy" tab to be
* manipulated by the test. The "category" of the test will then
* be used to determine if the appropriate index in the
* histogram was bumped.
*
* Here's a more verbose breakdown of what each PROBE_TEST
* should supply:
*
* name (String):
* Human readable description of the test. This is dumped
* out via info().
*
* category (String):
* The string representation of the index that will get
* incremented in the BUSY_TAB_ABANDONED probe. This should
* be a value inside CATEGORIES.
*
* prepare (function*)
* A function that can yield Promises. This will be run once
* we have a brand new browser to deal with, and should be used by
* the PROBE_TEST to do any history preparation before the browser
* is made to appear "busy" and is tested.
*
* @param browser (<xul:browser>)
* The newly created browser that the test will use.
*
* doAction (function*)
* A function that can yield Promises. This will be run once
* the browser appears busy, and should cause the user action
* that will change the BUSY_TAB_ABANDONED probe.
*
* @param browser (<xul:browser>)
* The busy browser to perform the action on.
*/
const PROBE_TESTS = [
// Test stopping the tab
{
name: "Stopping the browser",
category: "stop",
prepare(browser) {},
doAction(browser) {
document.getElementById("Browser:Stop").doCommand();
},
},
// Test going back to a previous page
{
name: "Going back to a previous page",
category: "back",
async prepare(browser) {
BrowserTestUtils.loadURI(browser, PAGE_2);
await BrowserTestUtils.browserLoaded(browser);
},
async doAction(browser) {
let pageShow =
BrowserTestUtils.waitForContentEvent(browser, "pageshow");
document.getElementById("Browser:Back").doCommand();
await pageShow;
},
},
// Test going forward to a previous page
{
name: "Going forward to the next page",
category: "forward",
async prepare(browser) {
BrowserTestUtils.loadURI(browser, PAGE_2);
await BrowserTestUtils.browserLoaded(browser);
let pageShow =
BrowserTestUtils.waitForContentEvent(browser, "pageshow");
browser.goBack();
await pageShow;
},
async doAction(browser) {
let pageShow =
BrowserTestUtils.waitForContentEvent(browser, "pageshow");
document.getElementById("Browser:Forward").doCommand();
await pageShow;
},
},
// Test going backwards more than one page back via gotoIndex
{
name: "Going backward to a previous page via gotoIndex",
category: "historyNavigation",
async prepare(browser) {
BrowserTestUtils.loadURI(browser, PAGE_2);
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(browser, "http://example.com");
await BrowserTestUtils.browserLoaded(browser);
await TabStateFlusher.flush(browser);
},
async doAction(browser) {
let pageShow =
BrowserTestUtils.waitForContentEvent(browser, "pageshow");
synthesizeHistoryNavigationToIndex(0);
await pageShow;
},
},
// Test going forwards more than one page back via gotoIndex
{
name: "Going forward to a previous page via gotoIndex",
category: "historyNavigation",
async prepare(browser) {
BrowserTestUtils.loadURI(browser, PAGE_2);
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(browser, "http://example.com");
await BrowserTestUtils.browserLoaded(browser);
let pageShow =
BrowserTestUtils.waitForContentEvent(browser, "pageshow");
browser.gotoIndex(0);
await pageShow;
await TabStateFlusher.flush(browser);
},
async doAction(browser) {
let pageShow =
BrowserTestUtils.waitForContentEvent(browser, "pageshow");
synthesizeHistoryNavigationToIndex(2);
await pageShow;
},
},
// Test reloading the tab
{
name: "Reloading the browser",
category: "reload",
prepare(browser) {},
async doAction(browser) {
document.getElementById("Browser:Reload").doCommand();
await BrowserTestUtils.browserLoaded(browser);
},
},
// Testing closing the tab is done in its own test later on
// in this file.
// Test browsing to a new URL
{
name: "Browsing to a new URL",
category: "newURI",
prepare(browser) {},
async doAction(browser) {
openTrustedLinkIn(PAGE_2, "current");
await BrowserTestUtils.browserLoaded(browser);
},
},
];
/**
* Takes a Telemetry histogram snapshot and makes sure
* that the index for that value (as defined by CATEGORIES)
* has a count of 1, and that it's the only value that
* has been incremented.
*
* @param snapshot (Object)
* The Telemetry histogram snapshot to examine.
* @param category (String)
* The category in CATEGORIES whose index we expect to have
* been set to 1.
*/
function assertOnlyOneTypeSet(snapshot, category) {
let categoryIndex = CATEGORIES.indexOf(category);
Assert.equal(snapshot.counts[categoryIndex], 1,
`Should have seen the ${category} count increment.`);
// Use Array.prototype.reduce to sum up all of the
// snapshot.count entries
Assert.equal(snapshot.counts.reduce((a, b) => a + b), 1,
"Should only be 1 collected value.");
}
/**
* A helper function for simulating clicking on the history
* navigation popup menu that you get if you click and hold
* on the back or forward buttons when you have some browsing
* history.
*
* @param index (int)
* The index for the menuitem we want to simulate
* clicking on.
*/
function synthesizeHistoryNavigationToIndex(index) {
let popup = document.getElementById("backForwardMenu");
// I don't want to deal with popup listening - that's
// notoriously flake-y in automated tests. I'll just
// directly call the function that populates the menu.
FillHistoryMenu(popup);
Assert.ok(popup.childElementCount > 0,
"Should have some items in the back/forward menu");
let menuitem = popup.querySelector(`menuitem[index="${index}"]`);
Assert.ok(menuitem, `Should find a menuitem with index ${index}`);
// Now pretend we clicked on the right item.
let cmdEvent = new CustomEvent("command", {
bubbles: true,
cancelable: true,
});
menuitem.dispatchEvent(cmdEvent);
}
/**
* Goes through each of the categories for the BUSY_TAB_ABANDONED
* probe, and tests that they're properly changed.
*/
add_task(async function test_probes() {
let oldCanRecord = Services.telemetry.canRecordExtended;
Services.telemetry.canRecordExtended = true;
registerCleanupFunction(() => {
Services.telemetry.canRecordExtended = oldCanRecord;
});
let histogram = Services.telemetry
.getHistogramById("BUSY_TAB_ABANDONED");
// If you want to add new tests for probes that don't involve
// the tab or window hosting the tab closing, see the documentation
// above PROBE_TESTS for how to hook into this little framework.
for (let probeTest of PROBE_TESTS) {
await BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.com",
}, async function(browser) {
let tab = gBrowser.getTabForBrowser(browser);
info(`Test: "${probeTest.name}"`);
await probeTest.prepare(browser);
// Instead of trying to fiddle with network state or
// anything, we'll just set this attribute to fool our
// telemetry probes into thinking the browser is in the
// middle of loading some resources.
tab.setAttribute("busy", true);
histogram.clear();
await probeTest.doAction(browser);
let snapshot = histogram.snapshot();
assertOnlyOneTypeSet(snapshot, probeTest.category);
});
}
// The above tests used BrowserTestUtils.withNewTab, which is
// fine for almost all categories for this probe, except for
// "tabClosed", since withNewTab closes the tab automatically
// before resolving, which doesn't work well for a tabClosed
// test in the above framework. So the tabClosed tests are
// done separately below.
histogram.clear();
// Now test that we can close a busy tab and get the tabClosed
// measurement bumped.
let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
// As above, instead of trying to fiddle with network state
// or anything, we'll just set this attribute to fool our
// telemetry probes into thinking the browser is in the
// middle of loading some resources.
newTab.setAttribute("busy", true);
BrowserTestUtils.removeTab(newTab);
let snapshot = histogram.snapshot();
assertOnlyOneTypeSet(snapshot, "tabClosed");
});