Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const TIMING_HISTOGRAM = "WEBEXT_BROWSERACTION_POPUP_OPEN_MS";
const TIMING_HISTOGRAM_KEYED = "WEBEXT_BROWSERACTION_POPUP_OPEN_MS_BY_ADDONID";
const RESULT_HISTOGRAM = "WEBEXT_BROWSERACTION_POPUP_PRELOAD_RESULT_COUNT";
const RESULT_HISTOGRAM_KEYED =
"WEBEXT_BROWSERACTION_POPUP_PRELOAD_RESULT_COUNT_BY_ADDONID";
const EXTENSION_ID1 = "@test-extension1";
const EXTENSION_ID2 = "@test-extension2";
// Keep this in sync with the order in Histograms.json for
// WEBEXT_BROWSERACTION_POPUP_PRELOAD_RESULT_COUNT
const CATEGORIES = ["popupShown", "clearAfterHover", "clearAfterMousedown"];
const GLEAN_RESULT_LABELS = [...CATEGORIES, "__other__"];
function assertGleanPreloadResultLabelCounter(expectedLabelsValue) {
for (const label of GLEAN_RESULT_LABELS) {
const expectedLabelValue = expectedLabelsValue[label];
Assert.deepEqual(
Glean.extensionsCounters.browserActionPreloadResult[label].testGetValue(),
expectedLabelValue,
`Expect Glean browserActionPreloadResult metric label ${label} to be ${
expectedLabelValue > 0 ? expectedLabelValue : "empty"
}`
);
}
}
function assertGleanPreloadResultLabelCounterEmpty() {
// All empty labels passed to the other helpers to make it
// assert that all labels are empty.
assertGleanPreloadResultLabelCounter({});
}
/**
* 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 {object} snapshot
* The Telemetry histogram snapshot to examine.
* @param {string} category
* 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.values[categoryIndex],
1,
`Should have seen the ${category} count increment.`
);
// Use Array.prototype.reduce to sum up all of the
// snapshot.count entries
Assert.equal(
Object.values(snapshot.values).reduce((a, b) => a + b, 0),
1,
"Should only be 1 collected value."
);
}
add_task(async function testBrowserActionTelemetryTiming() {
let extensionOptions = {
manifest: {
browser_action: {
default_popup: "popup.html",
default_area: "navbar",
browser_style: true,
},
},
files: {
"popup.html": `<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><div></div></body></html>`,
},
};
let extension1 = ExtensionTestUtils.loadExtension({
...extensionOptions,
manifest: {
...extensionOptions.manifest,
browser_specific_settings: {
gecko: { id: EXTENSION_ID1 },
},
},
});
let extension2 = ExtensionTestUtils.loadExtension({
...extensionOptions,
manifest: {
...extensionOptions.manifest,
browser_specific_settings: {
gecko: { id: EXTENSION_ID2 },
},
},
});
let histogram = Services.telemetry.getHistogramById(TIMING_HISTOGRAM);
let histogramKeyed = Services.telemetry.getKeyedHistogramById(
TIMING_HISTOGRAM_KEYED
);
histogram.clear();
histogramKeyed.clear();
Services.fog.testResetFOG();
is(
histogram.snapshot().sum,
0,
`No data recorded for histogram: ${TIMING_HISTOGRAM}.`
);
is(
Object.keys(histogramKeyed).length,
0,
`No data recorded for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
Assert.deepEqual(
Glean.extensionsTiming.browserActionPopupOpen.testGetValue(),
undefined,
"No data recorded for glean metric extensionsTiming.browserActionPopupOpen"
);
await extension1.startup();
await extension2.startup();
is(
histogram.snapshot().sum,
0,
`No data recorded for histogram after startup: ${TIMING_HISTOGRAM}.`
);
is(
Object.keys(histogramKeyed).length,
0,
`No data recorded for histogram after startup: ${TIMING_HISTOGRAM_KEYED}.`
);
Assert.deepEqual(
Glean.extensionsTiming.browserActionPopupOpen.testGetValue(),
undefined,
"No data recorded for glean metric extensionsTiming.browserActionPopupOpen"
);
clickBrowserAction(extension1);
await awaitExtensionPanel(extension1);
let sumOld = histogram.snapshot().sum;
Assert.greater(
sumOld,
0,
`Data recorded for first extension for histogram: ${TIMING_HISTOGRAM}.`
);
let oldKeyedSnapshot = histogramKeyed.snapshot();
Assert.deepEqual(
Object.keys(oldKeyedSnapshot),
[EXTENSION_ID1],
`Data recorded for first extension for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
Assert.greater(
oldKeyedSnapshot[EXTENSION_ID1].sum,
0,
`Data recorded for first extension for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
let gleanSumOld =
Glean.extensionsTiming.browserActionPopupOpen.testGetValue()?.sum;
Assert.greater(
gleanSumOld,
0,
"Data recorded for first extension on glean metric extensionsTiming.browserActionPopupOpen"
);
await closeBrowserAction(extension1);
clickBrowserAction(extension2);
await awaitExtensionPanel(extension2);
let sumNew = histogram.snapshot().sum;
Assert.greater(
sumNew,
sumOld,
`Data recorded for second extension for histogram: ${TIMING_HISTOGRAM}.`
);
sumOld = sumNew;
let gleanSumNew =
Glean.extensionsTiming.browserActionPopupOpen.testGetValue()?.sum;
Assert.greater(
gleanSumNew,
gleanSumOld,
"Data recorded for second extension on glean metric extensionsTiming.browserActionPopupOpen"
);
gleanSumOld = gleanSumNew;
let newKeyedSnapshot = histogramKeyed.snapshot();
Assert.deepEqual(
Object.keys(newKeyedSnapshot).sort(),
[EXTENSION_ID1, EXTENSION_ID2],
`Data recorded for second extension for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
Assert.greater(
newKeyedSnapshot[EXTENSION_ID2].sum,
0,
`Data recorded for second extension for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
is(
newKeyedSnapshot[EXTENSION_ID1].sum,
oldKeyedSnapshot[EXTENSION_ID1].sum,
`Data recorded for first extension should not change for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
oldKeyedSnapshot = newKeyedSnapshot;
await closeBrowserAction(extension2);
clickBrowserAction(extension2);
await awaitExtensionPanel(extension2);
sumNew = histogram.snapshot().sum;
Assert.greater(
sumNew,
sumOld,
`Data recorded for second opening of popup for histogram: ${TIMING_HISTOGRAM}.`
);
sumOld = sumNew;
gleanSumNew =
Glean.extensionsTiming.browserActionPopupOpen.testGetValue()?.sum;
Assert.greater(
gleanSumNew,
gleanSumOld,
"Data recorded for second popup opening on glean metric extensionsTiming.browserActionPopupOpen"
);
gleanSumOld = gleanSumNew;
newKeyedSnapshot = histogramKeyed.snapshot();
Assert.greater(
newKeyedSnapshot[EXTENSION_ID2].sum,
oldKeyedSnapshot[EXTENSION_ID2].sum,
`Data recorded for second opening of popup for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
is(
newKeyedSnapshot[EXTENSION_ID1].sum,
oldKeyedSnapshot[EXTENSION_ID1].sum,
`Data recorded for first extension should not change for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
oldKeyedSnapshot = newKeyedSnapshot;
await closeBrowserAction(extension2);
clickBrowserAction(extension1);
await awaitExtensionPanel(extension1);
sumNew = histogram.snapshot().sum;
Assert.greater(
sumNew,
sumOld,
`Data recorded for third opening of popup for histogram: ${TIMING_HISTOGRAM}.`
);
gleanSumNew =
Glean.extensionsTiming.browserActionPopupOpen.testGetValue()?.sum;
Assert.greater(
gleanSumNew,
gleanSumOld,
"Data recorded for third popup opening on glean metric extensionsTiming.browserActionPopupOpen"
);
newKeyedSnapshot = histogramKeyed.snapshot();
Assert.greater(
newKeyedSnapshot[EXTENSION_ID1].sum,
oldKeyedSnapshot[EXTENSION_ID1].sum,
`Data recorded for second opening of popup for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
is(
newKeyedSnapshot[EXTENSION_ID2].sum,
oldKeyedSnapshot[EXTENSION_ID2].sum,
`Data recorded for second extension should not change for histogram: ${TIMING_HISTOGRAM_KEYED}.`
);
await closeBrowserAction(extension1);
await extension1.unload();
await extension2.unload();
});
add_task(async function testBrowserActionTelemetryResults() {
let extensionOptions = {
manifest: {
browser_specific_settings: {
gecko: { id: EXTENSION_ID1 },
},
browser_action: {
default_popup: "popup.html",
default_area: "navbar",
browser_style: true,
},
},
files: {
"popup.html": `<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><div></div></body></html>`,
},
};
let extension = ExtensionTestUtils.loadExtension(extensionOptions);
let histogram = Services.telemetry.getHistogramById(RESULT_HISTOGRAM);
let histogramKeyed = Services.telemetry.getKeyedHistogramById(
RESULT_HISTOGRAM_KEYED
);
histogram.clear();
histogramKeyed.clear();
Services.fog.testResetFOG();
is(
histogram.snapshot().sum,
0,
`No data recorded for histogram: ${RESULT_HISTOGRAM}.`
);
is(
Object.keys(histogramKeyed).length,
0,
`No data recorded for histogram: ${RESULT_HISTOGRAM_KEYED}.`
);
assertGleanPreloadResultLabelCounterEmpty();
await extension.startup();
// Make sure the mouse isn't hovering over the browserAction widget to start.
EventUtils.synthesizeMouseAtCenter(
gURLBar.textbox,
{ type: "mouseover" },
window
);
let widget = getBrowserActionWidget(extension).forWindow(window);
// Hover the mouse over the browserAction widget and then move it away.
EventUtils.synthesizeMouseAtCenter(
widget.node,
{ type: "mouseover", button: 0 },
window
);
EventUtils.synthesizeMouseAtCenter(
widget.node,
{ type: "mouseout", button: 0 },
window
);
EventUtils.synthesizeMouseAtCenter(
document.documentElement,
{ type: "mousemove" },
window
);
assertOnlyOneTypeSet(histogram.snapshot(), "clearAfterHover");
assertGleanPreloadResultLabelCounter({ clearAfterHover: 1 });
let keyedSnapshot = histogramKeyed.snapshot();
Assert.deepEqual(
Object.keys(keyedSnapshot),
[EXTENSION_ID1],
`Data recorded for histogram: ${RESULT_HISTOGRAM_KEYED}.`
);
assertOnlyOneTypeSet(keyedSnapshot[EXTENSION_ID1], "clearAfterHover");
histogram.clear();
histogramKeyed.clear();
Services.fog.testResetFOG();
// TODO: Create a test for cancel after mousedown.
// This is tricky because calling mouseout after mousedown causes a
// "Hover" event to be added to the queue in ext-browserAction.js.
clickBrowserAction(extension);
await awaitExtensionPanel(extension);
assertOnlyOneTypeSet(histogram.snapshot(), "popupShown");
assertGleanPreloadResultLabelCounter({ popupShown: 1 });
keyedSnapshot = histogramKeyed.snapshot();
Assert.deepEqual(
Object.keys(keyedSnapshot),
[EXTENSION_ID1],
`Data recorded for histogram: ${RESULT_HISTOGRAM_KEYED}.`
);
assertOnlyOneTypeSet(keyedSnapshot[EXTENSION_ID1], "popupShown");
await closeBrowserAction(extension);
await extension.unload();
});