diff options
Diffstat (limited to 'browser/components/uitour/test/browser_UITour_heartbeat.js')
-rw-r--r-- | browser/components/uitour/test/browser_UITour_heartbeat.js | 755 |
1 files changed, 0 insertions, 755 deletions
diff --git a/browser/components/uitour/test/browser_UITour_heartbeat.js b/browser/components/uitour/test/browser_UITour_heartbeat.js deleted file mode 100644 index 61be1d44b..000000000 --- a/browser/components/uitour/test/browser_UITour_heartbeat.js +++ /dev/null @@ -1,755 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -var gTestTab; -var gContentAPI; -var gContentWindow; - -function getHeartbeatNotification(aId, aChromeWindow = window) { - let notificationBox = aChromeWindow.document.getElementById("high-priority-global-notificationbox"); - // UITour.jsm prefixes the notification box ID with "heartbeat-" to prevent collisions. - return notificationBox.getNotificationWithValue("heartbeat-" + aId); -} - -/** - * Simulate a click on a rating element in the Heartbeat notification. - * - * @param aId - * The id of the notification box. - * @param aScore - * The score related to the rating element we want to click on. - */ -function simulateVote(aId, aScore) { - let notification = getHeartbeatNotification(aId); - - let ratingContainer = notification.childNodes[0]; - ok(ratingContainer, "The notification has a valid rating container."); - - let ratingElement = ratingContainer.getElementsByAttribute("data-score", aScore); - ok(ratingElement[0], "The rating container contains the requested rating element."); - - ratingElement[0].click(); -} - -/** - * Simulate a click on the learn-more link. - * - * @param aId - * The id of the notification box. - */ -function clickLearnMore(aId) { - let notification = getHeartbeatNotification(aId); - - let learnMoreLabel = notification.childNodes[2]; - ok(learnMoreLabel, "The notification has a valid learn more label."); - - learnMoreLabel.click(); -} - -/** - * Remove the notification box. - * - * @param aId - * The id of the notification box to remove. - * @param [aChromeWindow=window] - * The chrome window the notification box is in. - */ -function cleanUpNotification(aId, aChromeWindow = window) { - let notification = getHeartbeatNotification(aId, aChromeWindow); - notification.close(); -} - -/** - * Check telemetry payload for proper format and expected content. - * - * @param aPayload - * The Telemetry payload to verify - * @param aFlowId - * Expected value of the flowId field. - * @param aExpectedFields - * Array of expected fields. No other fields are allowed. - */ -function checkTelemetry(aPayload, aFlowId, aExpectedFields) { - // Basic payload format - is(aPayload.version, 1, "Telemetry ping must have heartbeat version=1"); - is(aPayload.flowId, aFlowId, "Flow ID in the Telemetry ping must match"); - - // Check for superfluous fields - let extraKeys = new Set(Object.keys(aPayload)); - extraKeys.delete("version"); - extraKeys.delete("flowId"); - - // Check for expected fields - for (let field of aExpectedFields) { - ok(field in aPayload, "The payload should have the field '" + field + "'"); - if (field.endsWith("TS")) { - let ts = aPayload[field]; - ok(Number.isInteger(ts) && ts > 0, "Timestamp '" + field + "' must be a natural number"); - } - extraKeys.delete(field); - } - - is(extraKeys.size, 0, "No unexpected fields in the Telemetry payload"); -} - -/** - * Waits for an UITour notification dispatched through |UITour.notify|. This should be - * done with |gContentAPI.observe|. Unfortunately, in e10s, |gContentAPI.observe| doesn't - * allow for multiple calls to the same callback, allowing to catch just the first - * notification. - * - * @param aEventName - * The notification name to wait for. - * @return {Promise} Resolved with the data that comes with the event. - */ -function promiseWaitHeartbeatNotification(aEventName) { - return ContentTask.spawn(gTestTab.linkedBrowser, { aEventName }, - function({ aEventName }) { - return new Promise(resolve => { - addEventListener("mozUITourNotification", function listener(event) { - if (event.detail.event !== aEventName) { - return; - } - removeEventListener("mozUITourNotification", listener, false); - resolve(event.detail.params); - }, false); - }); - }); -} - -/** - * Waits for UITour notifications dispatched through |UITour.notify|. This works like - * |promiseWaitHeartbeatNotification|, but waits for all the passed notifications to - * be received before resolving. If it receives an unaccounted notification, it rejects. - * - * @param events - * An array of expected notification names to wait for. - * @return {Promise} Resolved with the data that comes with the event. Rejects with the - * name of an undesired notification if received. - */ -function promiseWaitExpectedNotifications(events) { - return ContentTask.spawn(gTestTab.linkedBrowser, { events }, - function({ events }) { - let stillToReceive = events; - return new Promise((res, rej) => { - addEventListener("mozUITourNotification", function listener(event) { - if (stillToReceive.includes(event.detail.event)) { - // Filter out the received event. - stillToReceive = stillToReceive.filter(x => x !== event.detail.event); - } else { - removeEventListener("mozUITourNotification", listener, false); - rej(event.detail.event); - } - // We still need to catch some notifications. Don't do anything. - if (stillToReceive.length > 0) { - return; - } - // We don't need to listen for other notifications. Resolve the promise. - removeEventListener("mozUITourNotification", listener, false); - res(); - }, false); - }); - }); -} - -function validateTimestamp(eventName, timestamp) { - info("'" + eventName + "' notification received (timestamp " + timestamp.toString() + ")."); - ok(Number.isFinite(timestamp), "Timestamp must be a number."); -} - -add_task(function* test_setup() { - yield setup_UITourTest(); - requestLongerTimeout(2); - registerCleanupFunction(() => { - Services.prefs.clearUserPref("browser.uitour.surveyDuration"); - }); -}); - -/** - * Check that the "stars" heartbeat UI correctly shows and closes. - */ -add_UITour_task(function* test_heartbeat_stars_show() { - let flowId = "ui-ratefirefox-" + Math.random(); - let engagementURL = "http://example.com"; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications( - ["Heartbeat:NotificationOffered", "Heartbeat:NotificationClosed", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, engagementURL); - - // Validate the returned timestamp. - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Close the heartbeat notification. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - cleanUpNotification(flowId); - - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received"); - checkTelemetry(data, flowId, ["offeredTS", "closedTS"]); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Check that the heartbeat UI correctly takes optional icon URL. - */ -add_UITour_task(function* test_heartbeat_take_optional_icon_URL() { - let flowId = "ui-ratefirefox-" + Math.random(); - let engagementURL = "http://example.com"; - let iconURL = "chrome://branding/content/icon48.png"; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications( - ["Heartbeat:NotificationOffered", "Heartbeat:NotificationClosed", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, engagementURL, null, null, { - iconURL: iconURL - }); - - // Validate the returned timestamp. - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Check the icon URL - let notification = getHeartbeatNotification(flowId); - is(notification.image, iconURL, "The optional icon URL is not taken correctly"); - - // Close the heartbeat notification. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - cleanUpNotification(flowId); - - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received"); - checkTelemetry(data, flowId, ["offeredTS", "closedTS"]); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Test that the heartbeat UI correctly works with null engagement URL. - */ -add_UITour_task(function* test_heartbeat_null_engagementURL() { - let flowId = "ui-ratefirefox-" + Math.random(); - let originalTabCount = gBrowser.tabs.length; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications(["Heartbeat:NotificationOffered", - "Heartbeat:NotificationClosed", "Heartbeat:Voted", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, null); - - // Validate the returned timestamp. - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Wait an the Voted, Closed and Telemetry Sent events. They are fired together, so - // wait for them here. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let votedPromise = promiseWaitHeartbeatNotification("Heartbeat:Voted"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - - // The UI was just shown. We can simulate a click on a rating element (i.e., "star"). - simulateVote(flowId, 2); - data = yield votedPromise; - validateTimestamp('Heartbeat:Voted', data.timestamp); - - // Validate the closing timestamp. - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - is(gBrowser.tabs.length, originalTabCount, "No engagement tab should be opened."); - - // Validate the data we send out. - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received."); - checkTelemetry(data, flowId, ["offeredTS", "votedTS", "closedTS", "score"]); - is(data.score, 2, "Checking Telemetry payload.score"); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Test that the heartbeat UI correctly works with an invalid, but non null, engagement URL. - */ -add_UITour_task(function* test_heartbeat_invalid_engagement_URL() { - let flowId = "ui-ratefirefox-" + Math.random(); - let originalTabCount = gBrowser.tabs.length; - let invalidEngagementURL = "invalidEngagement"; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications(["Heartbeat:NotificationOffered", - "Heartbeat:NotificationClosed", "Heartbeat:Voted", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, invalidEngagementURL); - - // Validate the returned timestamp. - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Wait an the Voted, Closed and Telemetry Sent events. They are fired together, so - // wait for them here. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let votedPromise = promiseWaitHeartbeatNotification("Heartbeat:Voted"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - - // The UI was just shown. We can simulate a click on a rating element (i.e., "star"). - simulateVote(flowId, 2); - data = yield votedPromise; - validateTimestamp('Heartbeat:Voted', data.timestamp); - - // Validate the closing timestamp. - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - is(gBrowser.tabs.length, originalTabCount, "No engagement tab should be opened."); - - // Validate the data we send out. - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received."); - checkTelemetry(data, flowId, ["offeredTS", "votedTS", "closedTS", "score"]); - is(data.score, 2, "Checking Telemetry payload.score"); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Test that the score is correctly reported. - */ -add_UITour_task(function* test_heartbeat_stars_vote() { - const expectedScore = 4; - let originalTabCount = gBrowser.tabs.length; - let flowId = "ui-ratefirefox-" + Math.random(); - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications(["Heartbeat:NotificationOffered", - "Heartbeat:NotificationClosed", "Heartbeat:Voted", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, null); - - // Validate the returned timestamp. - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Wait an the Voted, Closed and Telemetry Sent events. They are fired together, so - // wait for them here. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let votedPromise = promiseWaitHeartbeatNotification("Heartbeat:Voted"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - - // The UI was just shown. We can simulate a click on a rating element (i.e., "star"). - simulateVote(flowId, expectedScore); - data = yield votedPromise; - validateTimestamp('Heartbeat:Voted', data.timestamp); - is(data.score, expectedScore, "Should report a score of " + expectedScore); - - // Validate the closing timestamp and vote. - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - is(gBrowser.tabs.length, originalTabCount, "No engagement tab should be opened."); - - // Validate the data we send out. - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received."); - checkTelemetry(data, flowId, ["offeredTS", "votedTS", "closedTS", "score"]); - is(data.score, expectedScore, "Checking Telemetry payload.score"); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Test that the engagement page is correctly opened when voting. - */ -add_UITour_task(function* test_heartbeat_engagement_tab() { - let engagementURL = "http://example.com"; - let flowId = "ui-ratefirefox-" + Math.random(); - let originalTabCount = gBrowser.tabs.length; - const expectedTabCount = originalTabCount + 1; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications(["Heartbeat:NotificationOffered", - "Heartbeat:NotificationClosed", "Heartbeat:Voted", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, engagementURL); - - // Validate the returned timestamp. - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Wait an the Voted, Closed and Telemetry Sent events. They are fired together, so - // wait for them here. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let votedPromise = promiseWaitHeartbeatNotification("Heartbeat:Voted"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - - // The UI was just shown. We can simulate a click on a rating element (i.e., "star"). - simulateVote(flowId, 1); - data = yield votedPromise; - validateTimestamp('Heartbeat:Voted', data.timestamp); - - // Validate the closing timestamp, vote and make sure the engagement page was opened. - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - is(gBrowser.tabs.length, expectedTabCount, "Engagement URL should open in a new tab."); - gBrowser.removeCurrentTab(); - - // Validate the data we send out. - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received."); - checkTelemetry(data, flowId, ["offeredTS", "votedTS", "closedTS", "score"]); - is(data.score, 1, "Checking Telemetry payload.score"); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Test that the engagement button opens the engagement URL. - */ -add_UITour_task(function* test_heartbeat_engagement_button() { - let engagementURL = "http://example.com"; - let flowId = "ui-engagewithfirefox-" + Math.random(); - let originalTabCount = gBrowser.tabs.length; - const expectedTabCount = originalTabCount + 1; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications(["Heartbeat:NotificationOffered", - "Heartbeat:NotificationClosed", "Heartbeat:Engaged", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("Do you want to engage with us?", "Thank you!", flowId, engagementURL, null, null, { - engagementButtonLabel: "Engage Me", - }); - - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Wait an the Engaged, Closed and Telemetry Sent events. They are fired together, so - // wait for them here. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let engagedPromise = promiseWaitHeartbeatNotification("Heartbeat:Engaged"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - - // Simulate user engagement. - let notification = getHeartbeatNotification(flowId); - is(notification.querySelectorAll(".star-x").length, 0, "No stars should be present"); - // The UI was just shown. We can simulate a click on the engagement button. - let engagementButton = notification.querySelector(".notification-button"); - is(engagementButton.label, "Engage Me", "Check engagement button text"); - engagementButton.doCommand(); - - data = yield engagedPromise; - validateTimestamp('Heartbeat:Engaged', data.timestamp); - - // Validate the closing timestamp, vote and make sure the engagement page was opened. - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - is(gBrowser.tabs.length, expectedTabCount, "Engagement URL should open in a new tab."); - gBrowser.removeCurrentTab(); - - // Validate the data we send out. - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received."); - checkTelemetry(data, flowId, ["offeredTS", "engagedTS", "closedTS"]); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Test that the learn more link is displayed and that the page is correctly opened when - * clicking on it. - */ -add_UITour_task(function* test_heartbeat_learnmore() { - let dummyURL = "http://example.com"; - let flowId = "ui-ratefirefox-" + Math.random(); - let originalTabCount = gBrowser.tabs.length; - const expectedTabCount = originalTabCount + 1; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications(["Heartbeat:NotificationOffered", - "Heartbeat:NotificationClosed", "Heartbeat:LearnMore", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, dummyURL, - "What is this?", dummyURL); - - let data = yield shownPromise; - validateTimestamp('Heartbeat:Offered', data.timestamp); - - // Wait an the LearnMore, Closed and Telemetry Sent events. They are fired together, so - // wait for them here. - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let learnMorePromise = promiseWaitHeartbeatNotification("Heartbeat:LearnMore"); - let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - - // The UI was just shown. Simulate a click on the learn more link. - clickLearnMore(flowId); - - data = yield learnMorePromise; - validateTimestamp('Heartbeat:LearnMore', data.timestamp); - cleanUpNotification(flowId); - - // The notification was closed. - data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - is(gBrowser.tabs.length, expectedTabCount, "Learn more URL should open in a new tab."); - gBrowser.removeCurrentTab(); - - // Validate the data we send out. - data = yield pingSentPromise; - info("'Heartbeat:TelemetrySent' notification received."); - checkTelemetry(data, flowId, ["offeredTS", "learnMoreTS", "closedTS"]); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -add_UITour_task(function* test_invalidEngagementButtonLabel() { - let engagementURL = "http://example.com"; - let flowId = "invalidEngagementButtonLabel-" + Math.random(); - - let eventPromise = promisePageEvent(); - - gContentAPI.showHeartbeat("Do you want to engage with us?", "Thank you!", flowId, engagementURL, - null, null, { - engagementButtonLabel: 42, - }); - - yield eventPromise; - ok(!isTourBrowser(gBrowser.selectedBrowser), - "Invalid engagementButtonLabel should prevent init"); - -}) - -add_UITour_task(function* test_privateWindowsOnly_noneOpen() { - let engagementURL = "http://example.com"; - let flowId = "privateWindowsOnly_noneOpen-" + Math.random(); - - let eventPromise = promisePageEvent(); - - gContentAPI.showHeartbeat("Do you want to engage with us?", "Thank you!", flowId, engagementURL, - null, null, { - engagementButtonLabel: "Yes!", - privateWindowsOnly: true, - }); - - yield eventPromise; - ok(!isTourBrowser(gBrowser.selectedBrowser), - "If there are no private windows opened, tour init should be prevented"); -}) - -add_UITour_task(function* test_privateWindowsOnly_notMostRecent() { - let engagementURL = "http://example.com"; - let flowId = "notMostRecent-" + Math.random(); - - let privateWin = yield BrowserTestUtils.openNewBrowserWindow({ private: true }); - let mostRecentWin = yield BrowserTestUtils.openNewBrowserWindow(); - - let eventPromise = promisePageEvent(); - - gContentAPI.showHeartbeat("Do you want to engage with us?", "Thank you!", flowId, engagementURL, - null, null, { - engagementButtonLabel: "Yes!", - privateWindowsOnly: true, - }); - - yield eventPromise; - is(getHeartbeatNotification(flowId, window), null, - "Heartbeat shouldn't appear in the default window"); - is(!!getHeartbeatNotification(flowId, privateWin), true, - "Heartbeat should appear in the most recent private window"); - is(getHeartbeatNotification(flowId, mostRecentWin), null, - "Heartbeat shouldn't appear in the most recent non-private window"); - - yield BrowserTestUtils.closeWindow(mostRecentWin); - yield BrowserTestUtils.closeWindow(privateWin); -}) - -add_UITour_task(function* test_privateWindowsOnly() { - let engagementURL = "http://example.com"; - let learnMoreURL = "http://example.org/learnmore/"; - let flowId = "ui-privateWindowsOnly-" + Math.random(); - - let privateWin = yield BrowserTestUtils.openNewBrowserWindow({ private: true }); - - yield new Promise((resolve) => { - gContentAPI.observe(function(aEventName, aData) { - info(aEventName + " notification received: " + JSON.stringify(aData, null, 2)); - ok(false, "No heartbeat notifications should arrive for privateWindowsOnly"); - }, resolve); - }); - - gContentAPI.showHeartbeat("Do you want to engage with us?", "Thank you!", flowId, engagementURL, - "Learn More", learnMoreURL, { - engagementButtonLabel: "Yes!", - privateWindowsOnly: true, - }); - - yield promisePageEvent(); - - ok(isTourBrowser(gBrowser.selectedBrowser), "UITour should have been init for the browser"); - - let notification = getHeartbeatNotification(flowId, privateWin); - - is(notification.querySelectorAll(".star-x").length, 0, "No stars should be present"); - - info("Test the learn more link."); - let learnMoreLink = notification.querySelector(".text-link"); - is(learnMoreLink.value, "Learn More", "Check learn more label"); - let learnMoreTabPromise = BrowserTestUtils.waitForNewTab(privateWin.gBrowser, null); - learnMoreLink.click(); - let learnMoreTab = yield learnMoreTabPromise; - is(learnMoreTab.linkedBrowser.currentURI.host, "example.org", "Check learn more site opened"); - ok(PrivateBrowsingUtils.isBrowserPrivate(learnMoreTab.linkedBrowser), "Ensure the learn more tab is private"); - yield BrowserTestUtils.removeTab(learnMoreTab); - - info("Test the engagement button's new tab."); - let engagementButton = notification.querySelector(".notification-button"); - is(engagementButton.label, "Yes!", "Check engagement button text"); - let engagementTabPromise = BrowserTestUtils.waitForNewTab(privateWin.gBrowser, null); - engagementButton.doCommand(); - let engagementTab = yield engagementTabPromise; - is(engagementTab.linkedBrowser.currentURI.host, "example.com", "Check enagement site opened"); - ok(PrivateBrowsingUtils.isBrowserPrivate(engagementTab.linkedBrowser), "Ensure the engagement tab is private"); - yield BrowserTestUtils.removeTab(engagementTab); - - yield BrowserTestUtils.closeWindow(privateWin); -}) - -/** - * Test that the survey closes itself after a while and submits Telemetry - */ -add_UITour_task(function* test_telemetry_surveyExpired() { - let flowId = "survey-expired-" + Math.random(); - let engagementURL = "http://example.com"; - let surveyDuration = 1; // 1 second (pref is in seconds) - Services.prefs.setIntPref("browser.uitour.surveyDuration", surveyDuration); - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications(["Heartbeat:NotificationOffered", - "Heartbeat:NotificationClosed", "Heartbeat:SurveyExpired", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, engagementURL); - - let expiredPromise = promiseWaitHeartbeatNotification("Heartbeat:SurveyExpired"); - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let pingPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - - yield Promise.all([shownPromise, expiredPromise, closedPromise]); - // Validate the ping data. - let data = yield pingPromise; - checkTelemetry(data, flowId, ["offeredTS", "expiredTS", "closedTS"]); - - Services.prefs.clearUserPref("browser.uitour.surveyDuration"); - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) - -/** - * Check that certain whitelisted experiment parameters get reflected in the - * Telemetry ping - */ -add_UITour_task(function* test_telemetry_params() { - let flowId = "telemetry-params-" + Math.random(); - let engagementURL = "http://example.com"; - let extraParams = { - "surveyId": "foo", - "surveyVersion": 1.5, - "testing": true, - "notWhitelisted": 123, - }; - let expectedFields = ["surveyId", "surveyVersion", "testing"]; - - // We need to call |gContentAPI.observe| at least once to set a valid |notificationListener| - // in UITour-lib.js, otherwise no message will get propagated. - gContentAPI.observe(() => {}); - - let receivedExpectedPromise = promiseWaitExpectedNotifications( - ["Heartbeat:NotificationOffered", "Heartbeat:NotificationClosed", "Heartbeat:TelemetrySent"]); - - // Show the Heartbeat notification and wait for it to be displayed. - let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered"); - gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", - flowId, engagementURL, null, null, extraParams); - yield shownPromise; - - let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed"); - let pingPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent"); - cleanUpNotification(flowId); - - // The notification was closed. - let data = yield closedPromise; - validateTimestamp('Heartbeat:NotificationClosed', data.timestamp); - - // Validate the data we send out. - data = yield pingPromise; - info("'Heartbeat:TelemetrySent' notification received."); - checkTelemetry(data, flowId, ["offeredTS", "closedTS"].concat(expectedFields)); - for (let param of expectedFields) { - is(data[param], extraParams[param], - "Whitelisted experiment configs should be copied into Telemetry pings"); - } - - // This rejects whenever an unexpected notification is received. - yield receivedExpectedPromise; -}) |