browser_avatar_menu_signin_cta_variants.js (5148B)
1 /* Any copyright is dedicated to the Public Domain. 2 https://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { NimbusTestUtils } = ChromeUtils.importESModule( 7 "resource://testing-common/NimbusTestUtils.sys.mjs" 8 ); 9 10 /** 11 * Tests that we can change the CTA for the FxA sign-in button in the avatar 12 * menu using Nimbus. 13 */ 14 15 const DEFAULT_HEADER = gSync.fluentStrings.formatValueSync( 16 "synced-tabs-fxa-sign-in" 17 ); 18 const DEFAULT_DESCRIPTION = gSync.fluentStrings.formatValueSync( 19 "fxa-menu-sync-description" 20 ); 21 22 add_setup(async () => { 23 gSync.init(); 24 }); 25 26 /** 27 * Closes and re-opens the avatar menu for the current browser window, and 28 * returns a Promise once the main view fires the "ViewShown" event. The Promise 29 * resolves to the object with properties pointing at the header and the 30 * description text of the sign-in button. 31 * 32 * If the panel is not already open, this just opens it. 33 * 34 * @returns {Promise<object>} 35 */ 36 async function reopenAvatarMenu() { 37 let widgetPanel = document.getElementById("customizationui-widget-panel"); 38 // The customizationui-widget-panel is created lazily, and destroyed upon 39 // closing, meaning that if we didn't find it, it's not open. 40 if (widgetPanel) { 41 let panelHidden = BrowserTestUtils.waitForEvent(widgetPanel, "popuphidden"); 42 widgetPanel.hidePopup(); 43 await panelHidden; 44 } 45 let promiseViewShown = BrowserTestUtils.waitForEvent( 46 PanelMultiView.getViewNode(document, "PanelUI-fxa"), 47 "ViewShown" 48 ); 49 await gSync.toggleAccountPanel( 50 document.getElementById("fxa-toolbar-menu-button"), 51 new MouseEvent("mousedown") 52 ); 53 await promiseViewShown; 54 let headerEl = PanelMultiView.getViewNode(document, "fxa-menu-header-title"); 55 let descriptionEl = PanelMultiView.getViewNode( 56 document, 57 "fxa-menu-header-description" 58 ); 59 60 return { 61 header: headerEl.value, 62 description: descriptionEl.value, 63 }; 64 } 65 66 /** 67 * Tests that we use the default CTA when not enrolled in an experiment. 68 */ 69 add_task(async function test_default() { 70 Assert.equal( 71 NimbusFeatures.fxaAvatarMenuItem.getVariable("ctaCopyVariant"), 72 undefined, 73 "Should not start with a NimbusFeature set for the CTA copy." 74 ); 75 let sandbox = sinon.createSandbox(); 76 sandbox.spy(NimbusFeatures.fxaAvatarMenuItem, "recordExposureEvent"); 77 let { header, description } = await reopenAvatarMenu(); 78 Assert.equal(header, DEFAULT_HEADER, "Should have the default header."); 79 Assert.equal( 80 description, 81 DEFAULT_DESCRIPTION, 82 "Should have the default description." 83 ); 84 Assert.ok( 85 NimbusFeatures.fxaAvatarMenuItem.recordExposureEvent.notCalled, 86 "Did not record any exposure." 87 ); 88 sandbox.restore(); 89 }); 90 91 /** 92 * Tests that the control variant uses the default CTA, but also records an 93 * impression. 94 */ 95 add_task(async function test_control() { 96 let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( 97 { 98 featureId: NimbusFeatures.fxaAvatarMenuItem.featureId, 99 value: { 100 ctaCopyVariant: "control", 101 }, 102 }, 103 { isRollout: true } 104 ); 105 let sandbox = sinon.createSandbox(); 106 sandbox.spy(NimbusFeatures.fxaAvatarMenuItem, "recordExposureEvent"); 107 let { header, description } = await reopenAvatarMenu(); 108 Assert.equal(header, DEFAULT_HEADER, "Should have the default header."); 109 Assert.equal( 110 description, 111 DEFAULT_DESCRIPTION, 112 "Should have the default description." 113 ); 114 Assert.ok( 115 NimbusFeatures.fxaAvatarMenuItem.recordExposureEvent.calledOnce, 116 "Recorded exposure." 117 ); 118 await doCleanup(); 119 sandbox.restore(); 120 }); 121 122 /** 123 * Tests all variants , and that when we stop experimenting with that variant, 124 * we revert back to the default CTA. 125 */ 126 add_task(async function test_variants() { 127 let variants = ["sync-devices", "backup-data", "backup-sync", "mobile"]; 128 129 for (let variant of variants) { 130 let sandbox = sinon.createSandbox(); 131 sandbox.spy(NimbusFeatures.fxaAvatarMenuItem, "recordExposureEvent"); 132 133 let expectedHeader = gSync.fluentStrings.formatValueSync( 134 `fxa-menu-message-${variant}-primary-text` 135 ); 136 let expectedDescription = gSync.fluentStrings.formatValueSync( 137 `fxa-menu-message-${variant}-secondary-text` 138 ); 139 let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( 140 { 141 featureId: NimbusFeatures.fxaAvatarMenuItem.featureId, 142 value: { 143 ctaCopyVariant: variant, 144 }, 145 }, 146 { isRollout: true } 147 ); 148 149 let { header, description } = await reopenAvatarMenu(); 150 Assert.equal(header, expectedHeader, "Should have the expected header."); 151 Assert.equal( 152 description, 153 expectedDescription, 154 "Should have the expected description." 155 ); 156 await doCleanup(); 157 158 ({ header, description } = await reopenAvatarMenu()); 159 Assert.equal(header, DEFAULT_HEADER, "Should have the default header."); 160 Assert.equal( 161 description, 162 DEFAULT_DESCRIPTION, 163 "Should have the default description." 164 ); 165 Assert.ok( 166 NimbusFeatures.fxaAvatarMenuItem.recordExposureEvent.calledOnce, 167 "Recorded exposure." 168 ); 169 sandbox.restore(); 170 } 171 });