Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const fxaDevices = [
{
id: 1,
name: "Device 1",
availableCommands: { "https://identity.mozilla.com/cmd/open-uri": "baz" },
lastAccessTime: Date.now(),
},
{
id: 2,
name: "Device 2",
availableCommands: { "https://identity.mozilla.com/cmd/open-uri": "boo" },
lastAccessTime: Date.now() + 60000,
},
];
let gSandbox;
add_setup(async function () {
await promiseSyncReady();
gSync.init();
gSandbox = sinon.createSandbox();
gSandbox
.stub(Weave.Service.clientsEngine, "getClientByFxaDeviceId")
.callsFake(fxaDeviceId => {
let target = fxaDevices.find(c => c.id == fxaDeviceId);
return target ? target.clientRecord : null;
});
gSandbox
.stub(Weave.Service.clientsEngine, "getClientType")
.returns("desktop");
registerCleanupFunction(() => {
gSandbox.restore();
});
});
async function openFxaPanel() {
let promiseViewShown = BrowserTestUtils.waitForEvent(
PanelMultiView.getViewNode(document, "PanelUI-fxa"),
"ViewShown"
);
await gSync.toggleAccountPanel(
document.getElementById("fxa-toolbar-menu-button"),
new MouseEvent("mousedown")
);
await promiseViewShown;
}
async function closeFxaPanel() {
let widgetPanel = document.getElementById("customizationui-widget-panel");
if (widgetPanel) {
let panelHidden = BrowserTestUtils.waitForEvent(widgetPanel, "popuphidden");
widgetPanel.hidePopup();
await panelHidden;
}
}
async function openFxaPanelFromAppMenu() {
let mainViewShown = BrowserTestUtils.waitForEvent(PanelUI.panel, "ViewShown");
PanelUI.show();
await mainViewShown;
let fxaViewShown = BrowserTestUtils.waitForEvent(
PanelMultiView.getViewNode(document, "PanelUI-fxa"),
"ViewShown"
);
document.getElementById("appMenu-fxa-label2").click();
await fxaViewShown;
}
async function closeAppMenu() {
if (PanelUI.panel.state == "closed") {
return;
}
let panelHidden = BrowserTestUtils.waitForEvent(PanelUI.panel, "popuphidden");
PanelUI.hide();
await panelHidden;
}
// A synced client with a single tab, used to render a device's inline section
// in the app menu (where the "Send Current Page to This Device" option lives).
const appMenuSendTabClient = {
id: "client1",
name: "Device 1",
lastModified: Date.now(),
tabs: [
{
title: "Tab 1",
icon: "",
lastUsed: Date.now(),
inactive: false,
},
],
};
// Opens the FxA panel from the app menu and renders a device's inline section.
// In the app menu, each device is rendered as its own section (rather than a
// button opening a subpanel), so the section is built into the app-menu devices
// list and its send tab telemetry is attributed to fxa_app_menu.
async function renderDeviceSectionFromAppMenu() {
gSync.updateAllUI({
status: UIState.STATUS_SIGNED_IN,
syncEnabled: true,
email: "foo@bar.com",
});
await openFxaPanelFromAppMenu();
let panelview = PanelMultiView.getViewNode(document, "PanelUI-fxa");
panelview.syncedTabsPanelList._appendDeviceSection(
appMenuSendTabClient,
fxaDevices[0]
);
}
add_task(async function test_sendtab_exposed_app_menu() {
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
);
const sandbox = setupSendTabMocks({ fxaDevices });
sandbox
.stub(fxAccounts.commands.closeTab, "isDeviceCompatible")
.returns(false);
await Services.fog.testFlushAllChildren();
Services.fog.testResetFOG();
await renderDeviceSectionFromAppMenu();
await Services.fog.testFlushAllChildren();
let appMenuExposed = Glean.fxaAppMenu.sendTabExposed.testGetValue();
let avatarExposed = Glean.fxaAvatarMenu.sendTabExposed.testGetValue();
Assert.ok(
appMenuExposed && appMenuExposed.length,
"send_tab_exposed recorded under fxa_app_menu when opened via hamburger"
);
Assert.ok(
!avatarExposed || !avatarExposed.length,
"send_tab_exposed not misattributed to fxa_avatar_menu"
);
await closeAppMenu();
BrowserTestUtils.removeTab(tab);
sandbox.restore();
});
add_task(async function test_sendtab_opened_app_menu() {
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
);
const sandbox = setupSendTabMocks({ fxaDevices });
sandbox
.stub(fxAccounts.commands.closeTab, "isDeviceCompatible")
.returns(false);
await Services.fog.testFlushAllChildren();
Services.fog.testResetFOG();
await renderDeviceSectionFromAppMenu();
await Services.fog.testFlushAllChildren();
let appMenuOpened = Glean.fxaAppMenu.sendTabOpened.testGetValue();
let avatarOpened = Glean.fxaAvatarMenu.sendTabOpened.testGetValue();
Assert.ok(
appMenuOpened && appMenuOpened.length,
"send_tab_opened recorded under fxa_app_menu when opened via hamburger"
);
Assert.ok(
!avatarOpened || !avatarOpened.length,
"send_tab_opened not misattributed to fxa_avatar_menu"
);
await closeAppMenu();
BrowserTestUtils.removeTab(tab);
sandbox.restore();
});
add_task(async function test_sendtab_click_device_app_menu() {
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
);
const sandbox = setupSendTabMocks({ fxaDevices });
sandbox
.stub(fxAccounts.commands.closeTab, "isDeviceCompatible")
.returns(false);
sandbox.stub(fxAccounts, "flushLogFile").resolves();
await Services.fog.testFlushAllChildren();
Services.fog.testResetFOG();
await renderDeviceSectionFromAppMenu();
let devicesList = PanelMultiView.getViewNode(
document,
"PanelUI-fxa-menu-devices-list"
);
let sendPageBtn = devicesList.querySelector(
'[data-l10n-id="fxa-menu-device-send-current-page"]'
);
ok(sendPageBtn, "Send Current Page button rendered in the device section");
sendPageBtn.click();
await TestUtils.waitForCondition(async () => {
await Services.fog.testFlushAllChildren();
return !!Glean.fxaAppMenu.clickSendTab.testGetValue()?.length;
}, "Waiting for click_send_tab telemetry under fxa_app_menu");
let appMenuClicks = Glean.fxaAppMenu.clickSendTab.testGetValue();
let avatarClicks = Glean.fxaAvatarMenu.clickSendTab.testGetValue();
Assert.ok(
appMenuClicks && appMenuClicks.length,
"click_send_tab recorded under fxa_app_menu when clicked via hamburger"
);
Assert.equal(
appMenuClicks[0].extra.action,
"device",
"Correct action for device click"
);
Assert.ok(
!avatarClicks || !avatarClicks.length,
"click_send_tab not misattributed to fxa_avatar_menu"
);
await closeAppMenu();
BrowserTestUtils.removeTab(tab);
sandbox.restore();
});
/**
* Basic sanity test: send_tab_exposed is no longer fired on FxA panel open.
* It is now fired per-device when opening the "Recent tabs" subpanel and
* the "Send Current Page to This Device" button is shown.
*/
add_task(async function test_sendtab_exposed_not_on_panel_open() {
const sandbox = setupSendTabMocks({ fxaDevices });
await Services.fog.testFlushAllChildren();
Services.fog.testResetFOG();
await openFxaPanel();
await Services.fog.testFlushAllChildren();
let exposedEvents = Glean.fxaAvatarMenu.sendTabExposed.testGetValue();
Assert.ok(
!exposedEvents || !exposedEvents.length,
"send_tab_exposed is not fired on FxA panel open (now fires per-device)"
);
await closeFxaPanel();
sandbox.restore();
});
/**
* Test that telemetry is recorded for tab context menu.
*/
add_task(async function test_sendtab_tab_context_menu() {
const sandbox = setupSendTabMocks({ fxaDevices });
await Services.fog.testFlushAllChildren();
Services.fog.testResetFOG();
// Open a new tab
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:blank"
);
// Open tab context menu
let contextMenu = document.getElementById("tabContextMenu");
let popupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
// Initialize TabContextMenu
let evt = new Event("");
tab.dispatchEvent(evt);
gBrowser.selectedTab.focus();
contextMenu.openPopup(tab, "end_after", 0, 0, true, false, evt);
await popupShown;
await Services.fog.testFlushAllChildren();
let exposedEvents = Glean.tabContextMenu.sendTabExposed.testGetValue();
Assert.ok(
exposedEvents && exposedEvents.length,
"send_tab_exposed event was recorded for tab context menu"
);
Assert.equal(
exposedEvents[0].extra.device_count,
"2",
"Correct device count for tab context menu"
);
// Close the context menu
let popupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
contextMenu.hidePopup();
await popupHidden;
BrowserTestUtils.removeTab(tab);
sandbox.restore();
info("Tab context menu telemetry test passed!");
});
/**
* Test that click_send_tab is recorded when the user clicks "Send Current Page
* to This Device" in the per-device recent tabs subpanel.
*/
add_task(async function test_click_send_tab_telemetry_recent_tabs_panel() {
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
);
const sandbox = setupSendTabMocks({ fxaDevices });
sandbox
.stub(fxAccounts.commands.closeTab, "isDeviceCompatible")
.returns(false);
sandbox.stub(fxAccounts, "flushLogFile").resolves();
await Services.fog.testFlushAllChildren();
Services.fog.testResetFOG();
gSync.updateAllUI({
status: UIState.STATUS_SIGNED_IN,
syncEnabled: true,
email: "foo@bar.com",
});
await openFxaPanel();
let panelview = PanelMultiView.getViewNode(document, "PanelUI-fxa");
let devicesListContainer = PanelMultiView.getViewNode(
document,
"PanelUI-fxa-menu-devices-list"
);
let mockDevice = fxaDevices[0];
let mockClient = {
id: "client1",
name: "Device 1",
lastModified: Date.now(),
tabs: [
{
title: "Tab 1",
icon: "",
lastUsed: Date.now(),
inactive: false,
},
],
};
let subviewShown = BrowserTestUtils.waitForEvent(
PanelMultiView.getViewNode(document, "PanelUI-fxa-device-recent-tabs"),
"ViewShown"
);
panelview.syncedTabsPanelList._showDeviceRecentTabs(
mockClient,
mockDevice,
devicesListContainer,
new PointerEvent("click")
);
await subviewShown;
let sendPageBtn = PanelMultiView.getViewNode(
document,
"PanelUI-fxa-device-send-current-page"
);
ok(!sendPageBtn.hidden, "Send Current Page button is visible");
sendPageBtn.click();
await TestUtils.waitForCondition(async () => {
await Services.fog.testFlushAllChildren();
return !!Glean.fxaAvatarMenu.clickSendTab.testGetValue()?.length;
}, "Waiting for clickSendTab telemetry to be recorded");
let clickEvents = Glean.fxaAvatarMenu.clickSendTab.testGetValue();
Assert.equal(clickEvents[0].extra.action, "device", "action is 'device'");
Assert.equal(
clickEvents[0].extra.device_count,
"2",
"device_count matches number of send tab targets"
);
BrowserTestUtils.removeTab(tab);
sandbox.restore();
});
/**
* elements inside the Send Tab subviews
* (PanelUI-fxa-menu-sendtab-{connect-phone,enable-sync,no-devices,
* not-configured}) should resolve to "fxa_avatar_menu", so URL parameters and
* telemetry are attributed correctly when the user is in those flows from
* the avatar menu. These subviews are NOT nested inside PanelUI-fxa-menu
* (they are siblings), so a contains() check would miss them. See
*/
add_task(async function test_get_entry_point_for_sendtab_subviews() {
for (const id of [
"PanelUI-fxa-menu-sendtab-connect-phone-button",
"PanelUI-fxa-menu-sendtab-enable-sync-button",
]) {
const button = PanelMultiView.getViewNode(document, id);
Assert.ok(button, `${id} exists in the view cache`);
Assert.equal(
gSync._getEntryPointForElement(button),
"fxa_avatar_menu",
`${id} resolves to fxa_avatar_menu`
);
}
});