commit 2d981f7a96ab01ece0481b996cade7e2038d265c
parent 6d290e91d1a34a6d04172a5461a6beb838538329
Author: Maxx Crawford <mcrawford@mozilla.com>
Date: Fri, 3 Oct 2025 19:08:54 +0000
Bug 1990047 - Alphabetize custom ping names in ping selection dropdown on about:glean manual testing r=toolkit-telemetry-reviewers,fluent-reviewers,chutten,bolsson,chumphreys
Differential Revision: https://phabricator.services.mozilla.com/D265680
Diffstat:
4 files changed, 110 insertions(+), 12 deletions(-)
diff --git a/toolkit/content/aboutGlean.html b/toolkit/content/aboutGlean.html
@@ -75,7 +75,10 @@
<label for="tag-pings" data-l10n-id="about-glean-label-for-tag-pings-with-requirements"></label>
</li>
<li>
- <select name="ping-names" id="ping-names"></select>
+ <select name="ping-names" id="ping-names">
+ <optgroup id="builtin-pings" data-l10n-id="about-glean-ping-list-optgroup-built-in"></optgroup>
+ <optgroup id="custom-pings" data-l10n-id="about-glean-ping-list-optgroup-custom"></optgroup>
+ </select>
<label for="ping-names" data-l10n-id="about-glean-label-for-ping-names">
<a data-l10n-name="custom-ping-link" href="https://mozilla.github.io/glean/book/user/pings/custom.html"></a>
</label>
diff --git a/toolkit/content/aboutGlean.js b/toolkit/content/aboutGlean.js
@@ -104,19 +104,34 @@ function camelToKebab(str) {
// a use-case for sending it via about:glean.
const GLEAN_BUILTIN_PINGS = ["metrics", "events", "baseline"];
const NO_PING = "(don't submit any ping)";
-function refillPingNames() {
- let select = document.getElementById("ping-names");
- let pings = GLEAN_BUILTIN_PINGS.slice().concat(Object.keys(GleanPings));
- pings.forEach(ping => {
- let option = document.createElement("option");
- option.textContent = camelToKebab(ping);
- select.appendChild(option);
+function refillPingNames() {
+ const builtInGroup = document.getElementById("builtin-pings");
+ const customGroup = document.getElementById("custom-pings");
+
+ // Add built-in ping options to the dropdown.
+ GLEAN_BUILTIN_PINGS.forEach(id => {
+ const option = document.createElement("option");
+ option.value = id;
+ option.textContent = camelToKebab(id);
+ builtInGroup.appendChild(option);
});
- let option = document.createElement("option");
- document.l10n.setAttributes(option, "about-glean-no-ping-label");
- option.value = NO_PING;
- select.appendChild(option);
+
+ // Add "(don't submit any ping)" as last built-in option in the dropdown.
+ const noPingOption = document.createElement("option");
+ noPingOption.value = NO_PING;
+ document.l10n.setAttributes(noPingOption, "about-glean-no-ping-label");
+ builtInGroup.appendChild(noPingOption);
+
+ // Add alpha sorted custom ping options to the dropdown.
+ Object.keys(GleanPings)
+ .map(id => ({ id, label: camelToKebab(id) }))
+ .sort((a, b) => a.label.localeCompare(b.label))
+ .forEach(({ label }) => {
+ const option = document.createElement("option");
+ option.textContent = label;
+ customGroup.appendChild(option);
+ });
}
// If there's been a previous tag, use it.
diff --git a/toolkit/content/tests/browser/browser_about_glean.js b/toolkit/content/tests/browser/browser_about_glean.js
@@ -376,3 +376,74 @@ add_task(async function test_about_glean_event_timeline() {
});
});
});
+
+add_task(async function test_about_glean_ping_groups_and_none_label() {
+ await BrowserTestUtils.withNewTab("about:glean", async browser => {
+ await ContentTask.spawn(browser, null, async function () {
+ const { TestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TestUtils.sys.mjs"
+ );
+ const { Assert } = ChromeUtils.importESModule(
+ "resource://testing-common/Assert.sys.mjs"
+ );
+
+ // 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"
+ );
+ }
+ });
+ });
+});
diff --git a/toolkit/locales/en-US/toolkit/about/aboutGlean.ftl b/toolkit/locales/en-US/toolkit/about/aboutGlean.ftl
@@ -64,6 +64,15 @@ about-glean-manual-testing =
and in the <a data-l10n-name="glean-sdk-doc-link">{ glean-sdk-brand-name } documentation</a>,
but, in short, to manually test that your instrumentation works, you should:
+## These labels are displayed to organize the different ping types within the dropdown.
+
+about-glean-ping-list-optgroup-built-in =
+ .label = Built-in Pings
+about-glean-ping-list-optgroup-custom =
+ .label = Custom Pings
+
+##
+
# This message is an option in a dropdown filled with untranslated names of pings.
about-glean-no-ping-label = (don’t submit any ping)
# An in-line text input field precedes this string.