Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
/* Any copyright is dedicated to the Public Domain.
"use strict";
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [["test.wait300msAfterTabSwitch", true]],
});
});
add_task(async function test_about_glean_redesign_views_hidden_behind_pref() {
registerCleanupFunction(() => {
Services.prefs.clearUserPref("about.glean.redesign.enabled");
});
await BrowserTestUtils.withNewTab("about:glean", async function (browser) {
ok(!browser.isRemoteBrowser, "Browser should not be remote.");
await SpecialPowers.spawn(browser, [], async function () {
let metrics_table_category_button = content.document.getElementById(
"category-metrics-table"
);
is(metrics_table_category_button, null);
});
});
await BrowserTestUtils.withNewTab("about:glean", async function (browser) {
ok(!browser.isRemoteBrowser, "Browser should not be remote.");
await SpecialPowers.spawn(browser, [], async function () {
content.document.getElementById("enable-new-features").click();
let metrics_table_category_button = content.document.getElementById(
"category-metrics-table"
);
Assert.notEqual(
metrics_table_category_button,
null,
"Metrics table category button should not be null"
);
});
});
});
add_task(async function test_about_glean_metrics_table_loads_dynamically() {
registerCleanupFunction(() => {
Services.prefs.clearUserPref("about.glean.redesign.enabled");
});
Services.prefs.setBoolPref("about.glean.redesign.enabled", true);
await BrowserTestUtils.withNewTab("about:glean", async function (browser) {
ok(!browser.isRemoteBrowser, "Browser should not be remote.");
await SpecialPowers.spawn(browser, [], async function () {
const { TestUtils } = ChromeUtils.importESModule(
);
content.document.getElementById("category-metrics-table").click();
let tableContainer, tableBody;
const fetchTableBody = () => {
tableContainer = content.document.getElementById(
"metrics-table-instance"
);
tableBody = content.document.getElementById("metrics-table-body");
};
fetchTableBody();
let currentChildrenLength = tableBody.children.length;
const tableChildrenLengthChanged = () => {
fetchTableBody();
if (currentChildrenLength != tableBody.children.length) {
currentChildrenLength = tableBody.children.length;
return true;
}
return false;
};
let currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
const tableFirstChildChanged = () => {
fetchTableBody();
if (
currentFirstChild !=
tableBody.children[0].attributes["data-d3-row"].value
) {
currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
return true;
}
return false;
};
Assert.equal(
currentChildrenLength,
200,
"Table should start with 200 elements in it"
);
// Scroll and extend the count to 300
tableContainer.scrollTo({
top: tableContainer.scrollHeight - 1000,
behavior: "instant",
});
await TestUtils.waitForCondition(
tableChildrenLengthChanged,
"Wait for table children length to change",
200,
5
);
Assert.equal(
tableBody.children.length,
300,
"Table should now have 300 elements in it"
);
// Scroll and extend the count to 400
tableContainer.scrollTo({
top: tableContainer.scrollHeight - 1000,
behavior: "instant",
});
await TestUtils.waitForCondition(
tableChildrenLengthChanged,
"Wait for table children length to change",
200,
5
);
Assert.equal(
tableBody.children.length,
400,
"Table should now have 400 elements in it"
);
// Scroll and extend the count to 500
tableContainer.scrollTo({
top: tableContainer.scrollHeight - 1000,
behavior: "instant",
});
await TestUtils.waitForCondition(
tableChildrenLengthChanged,
"Wait for table children length to change",
200,
5
);
Assert.equal(
tableBody.children.length,
500,
"Table should now have 500 elements in it"
);
// Scroll offset the metrics by 100
tableContainer.scrollTo({
top: tableContainer.scrollHeight - 1000,
behavior: "instant",
});
await TestUtils.waitForCondition(
tableFirstChildChanged,
"Wait for the table's first child to change",
100,
3
);
Assert.equal(
tableBody.children.length,
500,
"Table should still have 500 elements in it"
);
});
});
});
add_task(async function test_about_glean_histogram() {
Services.fog.testResetFOG();
registerCleanupFunction(() => {
Services.prefs.clearUserPref("about.glean.redesign.enabled");
});
Services.prefs.setBoolPref("about.glean.redesign.enabled", true);
await BrowserTestUtils.withNewTab("about:glean", async function (browser) {
ok(!browser.isRemoteBrowser, "Browser should not be remote.");
await SpecialPowers.spawn(browser, [], async function () {
const { TestUtils } = ChromeUtils.importESModule(
);
content.document.getElementById("category-metrics-table").click();
let tableBody;
const fetchTableBody = () => {
tableBody = content.document.getElementById("metrics-table-body");
};
fetchTableBody();
let currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
const tableFirstChildChanged = () => {
fetchTableBody();
if (
currentFirstChild !=
tableBody.children[0].attributes["data-d3-row"].value
) {
currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
return true;
}
return false;
};
const input = content.document.getElementById("filter-metrics");
input.value = "aCustomDist";
input.dispatchEvent(new content.Event("input"));
await TestUtils.waitForCondition(
tableFirstChildChanged,
"Wait for the table's first child to change",
100,
3
);
});
Glean.testOnlyIpc.aCustomDist.accumulateSamples([0, 0, 1, 1, 1]);
await SpecialPowers.spawn(browser, [], async function () {
content.document
.querySelector(
"[data-d3-row='testOnlyIpc.aCustomDist'] button[data-l10n-id='about-glean-button-load-value']"
)
.click();
let valueCell;
const getValueCell = () => {
valueCell = content.document.querySelector(
"[data-d3-row='testOnlyIpc.aCustomDist'] [data-d3-cell='value']"
);
};
getValueCell();
Assert.equal(valueCell.childElementCount, 1);
Assert.equal(valueCell.firstChild.tagName, "svg");
// td svg g.boxes g*n >rect+text+text
const boxes = valueCell.firstChild.firstChild.children;
Assert.equal(boxes.length, 2, "Bar graphs for bucket 0 and 1 shown");
Assert.equal(boxes[0].children[1].textContent, "2");
Assert.equal(boxes[0].children[2].textContent, "0");
Assert.equal(boxes[1].children[1].textContent, "3");
Assert.equal(boxes[1].children[2].textContent, "1");
});
Services.fog.testResetFOG();
await SpecialPowers.spawn(browser, [], async function () {
content.document
.querySelector(
"[data-d3-row='testOnlyIpc.aCustomDist'] button[data-l10n-id='about-glean-button-load-value']"
)
.click();
const valueCell = content.document.querySelector(
"[data-d3-row='testOnlyIpc.aCustomDist'] [data-d3-cell='value']"
);
Assert.equal(valueCell.childElementCount, 1);
Assert.equal(valueCell.firstChild.tagName, "P");
Assert.equal(
valueCell.firstChild.getAttribute("data-l10n-id"),
"about-glean-no-data-to-display"
);
});
});
});
add_task(async function test_about_glean_event_timeline() {
Services.fog.testResetFOG();
registerCleanupFunction(() => {
Services.prefs.clearUserPref("about.glean.redesign.enabled");
});
Services.prefs.setBoolPref("about.glean.redesign.enabled", true);
await BrowserTestUtils.withNewTab("about:glean", async function (browser) {
ok(!browser.isRemoteBrowser, "Browser should not be remote.");
await SpecialPowers.spawn(browser, [], async function () {
const { TestUtils } = ChromeUtils.importESModule(
);
content.document.getElementById("category-metrics-table").click();
let tableBody;
const fetchTableBody = () => {
tableBody = content.document.getElementById("metrics-table-body");
};
fetchTableBody();
let currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
const tableFirstChildChanged = () => {
fetchTableBody();
if (
currentFirstChild !=
tableBody.children[0].attributes["data-d3-row"].value
) {
currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
return true;
}
return false;
};
const input = content.document.getElementById("filter-metrics");
input.value = "anEvent";
input.dispatchEvent(new content.Event("input"));
await TestUtils.waitForCondition(
tableFirstChildChanged,
"Wait for the table's first child to change",
100,
3
);
});
let extra = {
value: "a value for Telemetry",
extra1: "can set extras",
extra2: "passing more data",
};
Glean.testOnlyIpc.anEvent.record(extra);
Glean.testOnlyIpc.anEvent.record();
Glean.testOnlyIpc.anEvent.record();
await SpecialPowers.spawn(
browser,
[extra.value],
async function (extraValue) {
const { TestUtils } = ChromeUtils.importESModule(
);
content.document
.querySelector(
"[data-d3-row='testOnlyIpc.anEvent'] button[data-l10n-id='about-glean-button-load-value']"
)
.click();
let valueCell;
const getValueCell = () => {
valueCell = content.document.querySelector(
"[data-d3-row='testOnlyIpc.anEvent'] [data-d3-cell='value']"
);
};
getValueCell();
Assert.equal(valueCell.childElementCount, 2);
Assert.equal(valueCell.firstChild.tagName, "svg");
let code = content.document.querySelector(
`[data-d3-row='testOnlyIpc.anEvent'] pre>code`
).textContent;
const codeChanged = () => {
const newCode = content.document.querySelector(
`[data-d3-row='testOnlyIpc.anEvent'] pre>code`
).textContent;
if (newCode != code) {
code = newCode;
return true;
}
return false;
};
content.document
.querySelector(`[data-d3-row='testOnlyIpc.anEvent'] g.event`)
.focus();
await TestUtils.waitForCondition(
codeChanged,
"Wait for the table row's code textContent to change",
100,
3
);
getValueCell();
Assert.equal(valueCell.childElementCount, 2);
Assert.equal(valueCell.lastChild.tagName, "PRE");
Assert.equal(
valueCell.lastChild.firstChild.textContent.includes(extraValue),
true
);
}
);
});
});
add_task(async function test_about_glean_ping_groups_and_none_label() {
await BrowserTestUtils.withNewTab("about:glean", async browser => {
await SpecialPowers.spawn(browser, [], async function () {
const { TestUtils } = ChromeUtils.importESModule(
);
const { Assert } = ChromeUtils.importESModule(
);
// Wait for the select and optgroups to exist and be populated.
await TestUtils.waitForCondition(() => {
const doc = content.document;
const select = doc.getElementById("ping-names");
const builtin = doc.getElementById("builtin-pings");
const custom = doc.getElementById("custom-pings");
return select && builtin && custom && builtin.children.length >= 1;
}, "Wait for ping select to be populated");
const doc = content.document;
const builtin = doc.getElementById("builtin-pings");
const custom = doc.getElementById("custom-pings");
// Built-in group should contain metrics/events/baseline and end with the localized 'none' option.
const builtinOptions = Array.from(builtin.children);
Assert.strictEqual(
builtinOptions.length,
4,
"Built-in group has 4 options (incl. none)"
);
Assert.equal(
builtinOptions[0].textContent,
"metrics",
"Built-ins include 'metrics'"
);
Assert.equal(
builtinOptions[1].textContent,
"events",
"Built-ins include 'events'"
);
Assert.equal(
builtinOptions[2].textContent,
"baseline",
"Built-ins include 'baseline'"
);
// Note - We're checking the value instead of textContent
// for the last built in option, as textContent may be localized.
Assert.equal(
builtinOptions[3].value,
"(don't submit any ping)",
"Built-ins include '(don't submit any ping)'"
);
// Custom group should be alphabetically sorted by displayed label.
const customLabels = Array.from(custom.children).map(o => o.textContent);
if (customLabels.length >= 2) {
const sorted = customLabels.slice().sort((a, b) => a.localeCompare(b));
Assert.deepEqual(
customLabels,
sorted,
"Custom ping options are alphabetically sorted"
);
}
});
});
});
add_task(async function test_about_glean_metrics_table_settings() {
Services.fog.testResetFOG();
registerCleanupFunction(() => {
Services.prefs.clearUserPref("about.glean.redesign.enabled");
});
Services.prefs.setBoolPref("about.glean.redesign.enabled", true);
await BrowserTestUtils.withNewTab("about:glean", async browser => {
await SpecialPowers.spawn(browser, [], async function () {
const { TestUtils } = ChromeUtils.importESModule(
);
const { Assert } = ChromeUtils.importESModule(
);
content.document.getElementById("category-metrics-table").click();
let tableBody;
const fetchTableBody = () => {
tableBody = content.document.getElementById("metrics-table-body");
};
fetchTableBody();
let currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
const tableFirstChildChanged = () => {
fetchTableBody();
if (
currentFirstChild !=
tableBody.children[0].attributes["data-d3-row"].value
) {
currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
return true;
}
return false;
};
const input = content.document.getElementById("filter-metrics");
input.value = "aBool";
input.dispatchEvent(new content.Event("input"));
await TestUtils.waitForCondition(
tableFirstChildChanged,
"Wait for the table's first child to change",
100,
3
);
content.document
.querySelector(
"[data-d3-row='testOnlyIpc.aBool'] button[data-l10n-id='about-glean-button-load-value']"
)
.click();
content.document.getElementById("metrics-table-settings-button").click();
const checkbox = content.document.getElementById(
"settings-hide-empty-value-rows"
);
checkbox.checked = true;
checkbox.dispatchEvent(new content.Event("input"));
const tableNoChildren = () => {
fetchTableBody();
if (tableBody.children.length === 0) {
return true;
}
return false;
};
await TestUtils.waitForCondition(
tableNoChildren,
"Wait for the table's children to be empty",
100,
3
);
Assert.equal(
content.document.querySelector("[data-d3-row='testOnlyIpc.aBool']"),
null,
"Data row for `testOnlyIpc.aBool` should not exist"
);
});
});
});
add_task(
{
skip_if: () => true,
},
async function test_about_glean_export_button() {
Services.fog.testResetFOG();
registerCleanupFunction(() => {
Services.prefs.clearUserPref("about.glean.redesign.enabled");
});
Services.prefs.setBoolPref("about.glean.redesign.enabled", true);
await BrowserTestUtils.withNewTab("about:glean", async browser => {
await SpecialPowers.spawn(browser, [], async function () {
const { TestUtils } = ChromeUtils.importESModule(
);
content.document.getElementById("category-metrics-table").click();
let tableBody;
const fetchTableBody = () => {
tableBody = content.document.getElementById("metrics-table-body");
};
fetchTableBody();
let currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
const tableFirstChildChanged = () => {
fetchTableBody();
if (
currentFirstChild !=
tableBody.children[0].attributes["data-d3-row"].value
) {
currentFirstChild =
tableBody.children[0].attributes["data-d3-row"].value;
return true;
}
return false;
};
const input = content.document.getElementById("filter-metrics");
input.value = "anEvent";
input.dispatchEvent(new content.Event("input"));
await TestUtils.waitForCondition(
tableFirstChildChanged,
"Wait for the table's first child to change",
100,
3
);
});
const date = new Date();
const extra = {
value: "a value for Telemetry",
extra1: "can set extras",
extra2: "passing more data",
};
Glean.testOnlyIpc.anEvent.record(extra);
await SpecialPowers.spawn(
browser,
[date.getTime()],
async function (dateTime) {
const { TestUtils } = ChromeUtils.importESModule(
);
const { Assert } = ChromeUtils.importESModule(
);
content.document
.querySelector(
"[data-d3-row='testOnlyIpc.anEvent'] button[data-l10n-id='about-glean-button-load-value']"
)
.click();
content.document.getElementById("export-data").click();
const date = new Date(dateTime);
let downloads = undefined,
newDownloads = undefined;
const downloadDir = Services.dirsvc.get("DfltDwnld", Ci.nsIFile).path;
const downloadRegex = /about-glean-export-([\d-\.TZ_:]+)\.json/;
const downloadsContainsGleanData = () => {
IOUtils.getChildren(downloadDir).then(
v => {
downloads = v;
newDownloads = v
.filter(d => downloadRegex.test(d))
.map(d => [
d,
new Date(d.match(downloadRegex)[1].replaceAll("_", ":")),
])
.filter(([_, fileDate]) => fileDate - date >= 0);
},
reason => {
ok(false, reason + (reason.stack ? "\n" + reason.stack : ""));
}
);
return newDownloads !== undefined && !!newDownloads.length;
};
await TestUtils.waitForCondition(
downloadsContainsGleanData,
"Wait for the downloads to contain new Glean data",
100,
50
);
Assert.equal(
1,
newDownloads.length,
`New downloads has an unexpected value in list of downloads: ${JSON.stringify(downloads.filter(d => d.includes("glean")))}`
);
const data = await IOUtils.readJSON(newDownloads[0][0]);
// Clean up downloaded file
await IOUtils.remove(newDownloads[0][0]);
const index = data.findIndex(d => d.name === "testOnlyIpc.anEvent");
Assert.greaterOrEqual(index, 0);
Assert.notEqual(undefined, data[index].value);
}
);
});
DownloadsPanel.hidePanel();
}
);