Bug 1920799 - Add tests for the new menu messaging surface for the FxA CTA message. r=pdahiya,omc-reviewers,home-newtab-reviewers,nbarrett

To manually test the message, make sure to set
`browser.newtabpage.activity-stream.asrouter.devtoolsEnabled` to `true`,
and then visit about:asrouter. Scroll down to the message with ID
FXA_ACCOUNTS_APPMENU_PROTECT_BROWSING_DATA, and click "Show".

This will default to opening the AppMenu with the message. You can open
it for the PXI menu by changing `testingTriggerContext` in the test
message definition from "app_menu" to "pxi_menu".

Differential Revision: https://phabricator.services.mozilla.com/D224790
This commit is contained in:
Mike Conley 2024-10-15 16:15:09 +00:00
parent a785d24daf
commit d99dcfb323
6 changed files with 823 additions and 0 deletions

View File

@ -42,6 +42,8 @@ EXTRA_JS_MODULES.asrouter += [
"modules/ToolbarBadgeHub.sys.mjs",
]
MOCHITEST_CHROME_MANIFESTS += ["tests/chrome/chrome.toml"]
BROWSER_CHROME_MANIFESTS += [
"tests/browser/browser.toml",
]

View File

@ -25,6 +25,8 @@ skip-if = ["os == 'linux' && bits == 64 && debug"] # Bug 1892548
["browser_asrouter_keyboard_cfr.js"]
https_first_disabled = true
["browser_asrouter_menu_messages.js"]
["browser_asrouter_milestone_message_cfr.js"]
["browser_asrouter_momentspagehub.js"]

View File

@ -0,0 +1,617 @@
/* Any copyright is dedicated to the Public Domain.
https://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { MenuMessage } = ChromeUtils.importESModule(
"resource:///modules/asrouter/MenuMessage.sys.mjs"
);
const { PanelTestProvider } = ChromeUtils.importESModule(
"resource:///modules/asrouter/PanelTestProvider.sys.mjs"
);
const { AboutWelcomeTelemetry } = ChromeUtils.importESModule(
"resource:///modules/aboutwelcome/AboutWelcomeTelemetry.sys.mjs"
);
const { SpecialMessageActions } = ChromeUtils.importESModule(
"resource://messaging-system/lib/SpecialMessageActions.sys.mjs"
);
const { AppMenuNotifications } = ChromeUtils.importESModule(
"resource://gre/modules/AppMenuNotifications.sys.mjs"
);
/**
* Hides all popups for all sources for a given window if any of them are
* open.
*
* @param {DOMWindow} win
* The window to close popups for.
* @returns {Promise<undefined>}
*/
async function hideAllPopups(win = window) {
if (win.PanelUI.panel.state === "open") {
let panelHidden = BrowserTestUtils.waitForEvent(
win.PanelUI.panel,
"popuphidden"
);
win.PanelUI.hide();
await panelHidden;
}
let widgetPanel = win.document.getElementById("customizationui-widget-panel");
// The customizationui-widget-panel is created lazily, and destroyed upon
// closing, meaning that if we didn't find it, it's not open.
if (widgetPanel) {
let panelHidden = BrowserTestUtils.waitForEvent(widgetPanel, "popuphidden");
widgetPanel.hidePopup();
await panelHidden;
}
}
/**
* Asserts that a given message is correctly rendered and visible in the
* opened menu source for `win`.
*
* This function checks if the `fxa-menu-message` element exists within the
* source panel and ensures that it contains the correct content and properties
* based on the provided message object.
*
* It validates that:
* - The element is present and visible.
* - The primary text, secondary text, image URL, and button text match the
* content of the message.
* - The element has a `navigableWithTabOnly` data attribute set to "true".
*
* For the MenuMessage.SOURCES.APP_MENU source, it also ensures that the default
* sign-in button as well as the default separator are hidden when the message
* is visible.
*
* For the MenuMessage.SOURCES.PXI_MENU source, it ensures that the default
* sign-in button is hidden when the message is visible.
*
* @param {string} source
* The menu message source panel to check. One of the string constants from
* MenuMessage.SOURCES (example: MenuMessage.SOURCES.APP_MENU).
* @param {object} message
* The message object containing the content to be checked.
* @param {DOMWindow} [win=window]
* The window object where the panel UI and the app menu message are located
* (defaults to the main window).
*/
async function assertMessageInMenuSource(source, message, win = window) {
let messageEl;
if (source === MenuMessage.SOURCES.APP_MENU) {
messageEl = win.PanelUI.mainView.querySelector("fxa-menu-message");
} else if (source === MenuMessage.SOURCES.PXI_MENU) {
messageEl = win.document.querySelector("#PanelUI-fxa fxa-menu-message");
}
await messageEl.updateComplete;
Assert.ok(messageEl, "Found the fxa-menu-message element.");
Assert.ok(
BrowserTestUtils.isVisible(messageEl, "fxa-menu-message is visible.")
);
Assert.equal(
messageEl.primaryText,
message.content.primaryText,
"The primary text was set."
);
Assert.equal(
messageEl.secondaryText,
message.content.secondaryText,
"The secondary text was set."
);
Assert.equal(
messageEl.imageURL,
message.content.imageURL,
"The imageURL property was set."
);
Assert.equal(
messageEl.buttonText,
message.content.primaryActionText,
"The buttonText property was set."
);
Assert.equal(
messageEl.dataset.navigableWithTabOnly,
"true",
"The element should be configured for tab navigation."
);
let messageElStyles = window.getComputedStyle(messageEl);
Assert.equal(
messageElStyles.getPropertyValue("--illustration-margin-block-offset"),
`${message.content.imageVerticalOffset}px`
);
if (source === MenuMessage.SOURCES.APP_MENU) {
// The zap gradient and the default sign-in button should be hidden.
Assert.ok(
BrowserTestUtils.isHidden(
win.PanelUI.mainView.querySelector("#appMenu-fxa-separator")
),
"Zap gradient separator is hidden in the AppMenu."
);
Assert.ok(
BrowserTestUtils.isHidden(
win.PanelUI.mainView.querySelector("#appMenu-fxa-status2")
),
"Default FxA sign-in button is hidden in the AppMenu."
);
} else if (source === MenuMessage.SOURCES.PXI_MENU) {
Assert.ok(
BrowserTestUtils.isHidden(
win.document.querySelector("#fxa-manage-account-button")
),
"Default FxA sign-in button in the PXI panel is hidden."
);
}
return messageEl;
}
/**
* Asserts that no fxa-menu-message is rendered in the opened menu source for
* `win`.
*
* For the MenuMessage.SOURCES.APP_MENU source, it also ensures that the default
* sign-in button as well as the default separator are visible.
*
* For the MenuMessage.SOURCES.PXI_MENU source, it ensures that the default
* sign-in button is visible.
*
* @param {string} source
* The menu message source panel to check. One of the string constants from
* MenuMessage.SOURCES (example: MenuMessage.SOURCES.APP_MENU).
* @param {DOMWindow} [win=window]
* The window object for the panel to check (defaults to the main window).
*/
function assertNoMessageInMenuSource(source, win = window) {
let messageEl;
if (source === MenuMessage.SOURCES.APP_MENU) {
messageEl = win.PanelUI.mainView.querySelector("fxa-menu-message");
} else if (source === MenuMessage.SOURCES.PXI_MENU) {
messageEl = win.document.querySelector("#PanelUI-fxa fxa-menu-message");
}
Assert.ok(!messageEl, "Should not have found an fxa-menu-message");
if (source === MenuMessage.SOURCES.APP_MENU) {
// The zap gradient and the default sign-in button should be visible.
Assert.ok(
BrowserTestUtils.isVisible(
win.PanelUI.mainView.querySelector("#appMenu-fxa-separator")
),
"Zap gradient separator is visible."
);
Assert.ok(
BrowserTestUtils.isVisible(
win.PanelUI.mainView.querySelector("#appMenu-fxa-status2")
),
"Default FxA sign-in button is visible."
);
} else if (source === MenuMessage.SOURCES.PXI_MENU) {
Assert.ok(
BrowserTestUtils.isVisible(
win.document.querySelector("#fxa-manage-account-button")
),
"Default FxA sign-in button in the PXI panel is visible."
);
}
}
/**
* Closes and re-opens one of the source menus for a browser window, and then
* checks to see if the expected message (or no message) is displayed within
* it. Afterwards, it closes the panel.
*
* @param {string} source
* The menu message source panel to open. One of the string constants from
* MenuMessage.SOURCES (example: MenuMessage.SOURCES.APP_MENU).
* @param {object|null} expectedMessage
* The message that is expected to be displayed in the menu source, or null
* if no message is expected.
* @param {DOMWindow} [win=window]
* The browser window to open the AppMenu for.
* @param {Function} taskFn
* An optional async function to call after the panel is opened and before
* it is closed again.
* @returns {Promise<undefined>}
*/
async function reopenMenuSource(source, expectedMessage, win = window, taskFn) {
await hideAllPopups(win);
let promiseViewShown;
if (source === MenuMessage.SOURCES.APP_MENU) {
promiseViewShown = BrowserTestUtils.waitForEvent(
win.PanelUI.panel,
"ViewShown"
);
win.PanelUI.show();
} else if (source === MenuMessage.SOURCES.PXI_MENU) {
promiseViewShown = BrowserTestUtils.waitForEvent(
PanelMultiView.getViewNode(win.document, "PanelUI-fxa"),
"ViewShown"
);
await win.gSync.toggleAccountPanel(
win.document.getElementById("fxa-toolbar-menu-button"),
new MouseEvent("mousedown")
);
}
info(`Waiting for menu source ${source} to open`);
await promiseViewShown;
info(`Menu source ${source} opened`);
let messageEl = null;
if (expectedMessage) {
messageEl = await assertMessageInMenuSource(source, expectedMessage, win);
} else {
assertNoMessageInMenuSource(source, win);
}
if (taskFn) {
await taskFn(messageEl);
}
await hideAllPopups(win);
// Now ensure that there are no fxa-menu-message's in the window anymore,
// now that all the panels are closed.
Assert.ok(
!win.document.querySelector("fxa-menu-message"),
"Should not find any fxa-menu-message elements"
);
}
/**
* Sets up stubs for ASRouter methods to simulate a scenario where a specific
* menu message is made available via the ASRouter system.
*
* This function stubs:
* - `ASRouter.handleMessageRequest` to resolve the provided message.
* - `ASRouter.messagesEnabledInAutomation` to consider the message enabled for automation.
* - `ASRouter.getMessageById` to return the provided message when queried by its ID.
*
* After the provided task function `taskFn` is executed, it restores all the stubs.
*
* @param {SinonSandbox} sandbox - The Sinon sandbox used to create the stubs and ensure cleanup.
* @param {object} message - The message object to be used in the stubs and passed for testing.
* @param {function} taskFn - The function to be executed with the stubs in place.
*/
async function withTestMessage(sandbox, message, taskFn) {
let handleMessageRequestStub = sandbox.stub(ASRouter, "handleMessageRequest");
handleMessageRequestStub.resolves([message]);
let messagesEnabledInAutomationStub = sandbox.stub(
ASRouter,
"messagesEnabledInAutomation"
);
messagesEnabledInAutomationStub.value([message.id]);
let getMessageByIdStub = sandbox.stub(ASRouter, "getMessageById");
getMessageByIdStub.withArgs(message.id).returns(message);
await taskFn(handleMessageRequestStub);
handleMessageRequestStub.restore();
messagesEnabledInAutomationStub.restore();
getMessageByIdStub.restore();
}
/**
* A utility function to iterate all of the current menu message sources and
* run some async function for each.
*
* @param {function} taskFn
* An async function that is passed the source string for each source.
* @returns {Promise<undefined>}
*/
async function withEachSource(taskFn) {
for (let source of [
MenuMessage.SOURCES.APP_MENU,
MenuMessage.SOURCES.PXI_MENU,
]) {
info(`Trying source ${source}`);
await taskFn(source);
}
}
let gTestFxAMessage;
add_setup(async function () {
Services.fog.testResetFOG();
gTestFxAMessage = await PanelTestProvider.getMessages().then(msgs =>
msgs.find(msg => msg.id === "FXA_ACCOUNTS_APPMENU_PROTECT_BROWSING_DATA")
);
Assert.ok(gTestFxAMessage, "Found a test AppMenu message to use.");
// The testing message defaults to displaying in the AppMenu via the
// testingTriggerContext property. That's only useful for manual testing,
// and will confuse things for automated testing, so we remove that property
// here.
delete gTestFxAMessage.testingTriggerContext;
await SpecialPowers.pushPrefEnv({
set: [["browser.newtabpage.activity-stream.telemetry", true]],
});
registerCleanupFunction(async () => {
Services.fog.testResetFOG();
});
// Ensure the current window has had gSync.init run so that the PXI panel
// works correctly.
gSync.init();
// Make sure that we always end the test with the panels closed.
registerCleanupFunction(async () => {
await hideAllPopups();
});
});
/**
* Tests that opening each menu source causes the menuOpened trigger to fire.
*/
add_task(async function test_trigger() {
let sandbox = sinon.createSandbox();
sandbox.spy(ASRouter, "sendTriggerMessage");
await reopenMenuSource(MenuMessage.SOURCES.APP_MENU);
Assert.ok(
ASRouter.sendTriggerMessage.calledWith({
browser: gBrowser.selectedBrowser,
id: "menuOpened",
context: {
source: MenuMessage.SOURCES.APP_MENU,
browserIsSelected: true,
},
}),
"sendTriggerMessage was called when opening the AppMenu panel."
);
ASRouter.sendTriggerMessage.resetHistory();
await reopenMenuSource(MenuMessage.SOURCES.PXI_MENU);
Assert.ok(
ASRouter.sendTriggerMessage.calledWith({
browser: gBrowser.selectedBrowser,
id: "menuOpened",
context: {
source: MenuMessage.SOURCES.PXI_MENU,
browserIsSelected: true,
},
}),
"sendTriggerMessage was called when opening the PXI panel."
);
sandbox.restore();
});
/**
* Tests that a registered MenuMessage of type fxa_cta will cause an
* fxa-menu-message element to appear in either menu source panel with the right
* attributes. This also tests that upon becoming visible, an impression is
* recorded.
*/
add_task(async function test_show_fxa_cta_message() {
let sandbox = sinon.createSandbox();
sandbox.spy(ASRouter, "addImpression");
sandbox.spy(AboutWelcomeTelemetry.prototype, "submitGleanPingForPing");
await withTestMessage(sandbox, gTestFxAMessage, async () => {
await withEachSource(async source => {
info(`Testing source ${source}`);
await reopenMenuSource(source, gTestFxAMessage);
Assert.ok(
ASRouter.addImpression.calledWith(gTestFxAMessage),
"The test message had an impression recorded for it."
);
Assert.ok(
AboutWelcomeTelemetry.prototype.submitGleanPingForPing.calledWithMatch(
sinon.match({
message_id: gTestFxAMessage.id,
event: "IMPRESSION",
pingType: "menu",
source,
})
),
"The test message had an impression recorded for it."
);
ASRouter.addImpression.resetHistory();
AboutWelcomeTelemetry.prototype.submitGleanPingForPing.resetHistory();
});
});
sandbox.restore();
});
/**
* Tests that a registered MenuMessage of type fxa_cta will cause an
* fxa-menu-message element to appear in the menu sources for all newly
* opened windows - and that, once blocked, will disappear from all menu
* sources.
*/
add_task(async function test_show_fxa_cta_message_multiple_windows() {
let sandbox = sinon.createSandbox();
let win1 = window;
let win2 = await BrowserTestUtils.openNewBrowserWindow();
let win3 = await BrowserTestUtils.openNewBrowserWindow();
// Ensure each new window has had gSync.init run so that the PXI panel works
// correctly.
win2.gSync.init();
win3.gSync.init();
await withTestMessage(
sandbox,
gTestFxAMessage,
async handleMessageRequestStub => {
let message = gTestFxAMessage;
for (let win of [win1, win2, win3]) {
await SimpleTest.promiseFocus(win);
await withEachSource(async source => {
await reopenMenuSource(source, message, win);
});
}
// Now simulate blocking the message. We're not fully exercising ASRouter's
// blocking mechanism here - we assume that if the action for blocking a
// message occurs that ASRouter will do the right thing and stop returning
// the blocked message with each `handleMessageRequest` call.
await reopenMenuSource(
MenuMessage.SOURCES.APP_MENU,
gTestFxAMessage,
win3,
async () => {
let win3Message =
win3.PanelUI.mainView.querySelector("fxa-menu-message");
await win3Message.updateComplete;
win3Message.closeButton.click();
Assert.ok(
!win3Message.isConnected,
"Closed message should have been immediately removed from the DOM."
);
}
);
// Fake out the blocking of the message.
handleMessageRequestStub.resolves([]);
for (let win of [win1, win2, win3]) {
await SimpleTest.promiseFocus(win);
await withEachSource(async source => {
await reopenMenuSource(source, null, win);
});
}
}
);
await BrowserTestUtils.closeWindow(win2);
await BrowserTestUtils.closeWindow(win3);
sandbox.restore();
});
/**
* Tests that a registered MenuMessage of type fxa_cta will cause the
* defined special message actions of the message to occur on both the
* sign-in action button, as well as the close action button. This should
* cause CLICK and DISMISS telemetry events, respectively.
*/
add_task(async function test_fxa_cta_actions() {
let sandbox = sinon.createSandbox();
sandbox.spy(AboutWelcomeTelemetry.prototype, "submitGleanPingForPing");
sandbox.stub(SpecialMessageActions, "handleAction");
await withTestMessage(sandbox, gTestFxAMessage, async () => {
await withEachSource(async source => {
AboutWelcomeTelemetry.prototype.submitGleanPingForPing.resetHistory();
SpecialMessageActions.handleAction.resetHistory();
await reopenMenuSource(
source,
gTestFxAMessage,
window,
async messageEl => {
messageEl.signUpButton.click();
}
);
// Depending on which source that has been opened, the entrypoint passed
// in the SpecialMessageAction will be different.
let clonedPrimaryAction = structuredClone(
gTestFxAMessage.content.primaryAction
);
if (source === MenuMessage.SOURCES.APP_MENU) {
clonedPrimaryAction.data.entrypoint = "fxa_app_menu";
} else if (source === MenuMessage.SOURCES.PXI_MENU) {
clonedPrimaryAction.data.entrypoint = "fxa_avatar_menu";
}
Assert.ok(
SpecialMessageActions.handleAction.calledWith(
clonedPrimaryAction,
gBrowser.selectedBrowser
),
"The message action for signing up for an account was passed."
);
// Wait a tick for the telemetry to go through.
await TestUtils.waitForTick();
Assert.ok(
AboutWelcomeTelemetry.prototype.submitGleanPingForPing.calledWithMatch(
sinon.match({
message_id: gTestFxAMessage.id,
event: "CLICK",
pingType: "menu",
source,
})
),
"A ping for clicking the message should have been passed."
);
AboutWelcomeTelemetry.prototype.submitGleanPingForPing.resetHistory();
SpecialMessageActions.handleAction.resetHistory();
await reopenMenuSource(
source,
gTestFxAMessage,
window,
async messageEl => {
messageEl.closeButton.click();
}
);
Assert.ok(
SpecialMessageActions.handleAction.calledWith(
gTestFxAMessage.content.closeAction,
gBrowser.selectedBrowser
),
"The message action for closing the message should have been passed."
);
// Wait a tick for the telemetry to go through.
await TestUtils.waitForTick();
Assert.ok(
AboutWelcomeTelemetry.prototype.submitGleanPingForPing.calledWithMatch(
sinon.match({
message_id: gTestFxAMessage.id,
event: "DISMISS",
pingType: "menu",
source,
})
),
"A ping for dismissing the message should have been passed."
);
});
});
sandbox.restore();
});
/**
* Tests that a registered AppMenuMessage will NOT be displayed if an
* AppMenuNotification exists. Once the AppMenuNotification exists, the
* message can display.
*/
add_task(async function test_fxa_cta_notification_precedence() {
let sandbox = sinon.createSandbox();
sandbox.spy(AboutWelcomeTelemetry.prototype, "submitGleanPingForPing");
await withTestMessage(sandbox, gTestFxAMessage, async () => {
const NOTIFICATION_ID = "update-restart";
AppMenuNotifications.showNotification(NOTIFICATION_ID);
await reopenMenuSource(MenuMessage.SOURCES.APP_MENU, null);
AppMenuNotifications.removeNotification(NOTIFICATION_ID);
await reopenMenuSource(MenuMessage.SOURCES.APP_MENU, gTestFxAMessage);
});
sandbox.restore();
});

View File

@ -0,0 +1,4 @@
[DEFAULT]
skip-if = ["os == 'android'"]
["test_fxa_menu_message.html"]

View File

@ -0,0 +1,184 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Tests for the FxA Menu Message component</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script
src="chrome://browser/content/asrouter/components/fxa-menu-message.mjs"
type="module"
></script>
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script>
const { BrowserTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/BrowserTestUtils.sys.mjs"
);
/**
* Tests that the exposed properties of the component are reflected
* as expected in the shadow DOM.
*/
add_task(async function test_properties() {
let message = document.createElement("fxa-menu-message");
const TEST_IMAGE_URL = "chrome://activity-stream/content/data/content/assets/fox-doodle-waving-static.png";
message.imageURL = TEST_IMAGE_URL;
const TEST_BUTTON_TEXT = "Howdy, partner! Sign up!";
message.buttonText = TEST_BUTTON_TEXT;
const PRIMARY_TEXT = "This is the primary text";
message.primaryText = PRIMARY_TEXT;
const SECONDARY_TEXT = "This is the secondary text";
message.secondaryText = SECONDARY_TEXT;
let content = document.getElementById("content");
content.appendChild(message);
await message.updateComplete;
let shadow = message.shadowRoot;
let image = shadow.querySelector("img");
is(image.src, TEST_IMAGE_URL, "The img element got the expected URL");
let button = shadow.querySelector("#sign-up-button");
is(button.textContent, TEST_BUTTON_TEXT, "The sign-up button got the right text.");
let primaryText = shadow.querySelector("#primary");
is(primaryText.textContent, PRIMARY_TEXT, "The primary text was correct.");
let secondaryText = shadow.querySelector("#secondary");
is(secondaryText.textContent, SECONDARY_TEXT, "The secondary text was correct.");
message.remove();
});
/**
* Tests that the buttons exposed by the component emit the expected
* events.
*/
add_task(async function test_properties() {
let message = document.createElement("fxa-menu-message");
const TEST_BUTTON_TEXT = "Howdy, partner! Sign up!";
message.buttonText = TEST_BUTTON_TEXT;
let content = document.getElementById("content");
content.appendChild(message);
await message.updateComplete;
let shadow = message.shadowRoot;
let signUpEventPromise = BrowserTestUtils.waitForEvent(message, "FxAMenuMessage:SignUp");
let signUpButton = shadow.querySelector("#sign-up-button");
signUpButton.click();
await signUpEventPromise;
ok(true, "Got the FxAMenuMessage:SignUp event");
let closeEventPromise = BrowserTestUtils.waitForEvent(message, "FxAMenuMessage:Close");
let closeButton = shadow.querySelector("#close-button");
closeButton.click();
await closeEventPromise;
ok(true, "Got the FxAMenuMessage:Close event");
message.remove();
});
/**
* Tests that the sign-up button is focused by default, and that focus
* can be changed via the keyboard.
*/
add_task(async function test_focus() {
let message = document.createElement("fxa-menu-message");
const TEST_BUTTON_TEXT = "Howdy, partner! Sign up!";
message.buttonText = TEST_BUTTON_TEXT;
let content = document.getElementById("content");
content.appendChild(message);
await message.updateComplete;
message.focus();
let shadow = message.shadowRoot;
let signUpButton = shadow.querySelector("#sign-up-button");
is(shadow.activeElement, signUpButton, "Sign-up button is focused by default.");
let closeButton = shadow.querySelector("#close-button");
const FOCUS_CHANGING_KEYS = [
"ArrowLeft",
"ArrowRight",
"ArrowUp",
"ArrowDown",
];
for (let keyName of FOCUS_CHANGING_KEYS) {
synthesizeKey(`KEY_${keyName}`);
// Now the close button should be focused.
is(shadow.activeElement, closeButton, "Close button is now focused.");
synthesizeKey(`KEY_${keyName}`);
// And pressing the same key should swap focus back to the sign-up
// button.
is(shadow.activeElement, signUpButton, "Sign-up button is now focused.");
}
message.remove();
});
/**
* Tests that setting no imageURL makes it so that the image element is
* not visible, and setting one makes it visible.
*/
add_task(async function test_focus() {
let message = document.createElement("fxa-menu-message");
const TEST_BUTTON_TEXT = "Howdy, partner! Sign up!";
message.buttonText = TEST_BUTTON_TEXT;
let content = document.getElementById("content");
content.appendChild(message);
await message.updateComplete;
let illustrationContainer = message.shadowRoot.querySelector("#illustration-container");
ok(isHidden(illustrationContainer), "Illustration container should be hidden.");
message.imageURL = "some-image.png";
await message.updateComplete;
ok(!isHidden(illustrationContainer), "Illustration container should be visible.");
message.remove();
});
/**
* Tests that setting the --illustration-margin-block-offset forwards that
* offset to the illustration container.
*/
add_task(async function test_focus() {
let message = document.createElement("fxa-menu-message");
const TEST_IMAGE_URL = "chrome://activity-stream/content/data/content/assets/fox-doodle-waving-static.png";
message.imageURL = TEST_IMAGE_URL;
let content = document.getElementById("content");
content.appendChild(message);
await message.updateComplete;
let illustrationContainer = message.shadowRoot.querySelector("#illustration-container");
ok(!isHidden(illustrationContainer), "Illustration container should not be hidden.");
let messageStyle = window.getComputedStyle(illustrationContainer);
is(messageStyle.marginBlockStart, "0px", "Illustration offset should default to 0px.");
const TEST_OFFSET = "123px";
message.style.setProperty("--illustration-margin-block-offset", TEST_OFFSET);
messageStyle = window.getComputedStyle(illustrationContainer);
is(
messageStyle.marginBlockStart,
TEST_OFFSET,
"Illustration offset should have been forwarded to the container."
);
message.remove();
});
</script>
</head>
<body>
<p id="display"></p>
<div id="content"></div>
<pre id="test"></pre>
</body>
</html>

View File

@ -1214,6 +1214,20 @@ add_task(
}
);
add_task(async function test_applyMenuMessagePolicy() {
info(
"TelemetryFeed.applyMenuMessagePolicy should set client_id and set pingType"
);
let instance = new TelemetryFeed();
let { ping, pingType } = await instance.applyMenuMessagePolicy({});
Assert.equal(
ping.client_id,
Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
);
Assert.equal(pingType, "menu");
});
add_task(async function test_applyUndesiredEventPolicy() {
info(
"TelemetryFeed.applyUndesiredEventPolicy should exclude client_id " +