browser_sync_pairing.js (4516B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { UIState } = ChromeUtils.importESModule( 7 "resource://services-sync/UIState.sys.mjs" 8 ); 9 const { FxAccountsPairingFlow } = ChromeUtils.importESModule( 10 "resource://gre/modules/FxAccountsPairing.sys.mjs" 11 ); 12 13 // Use sinon for mocking. 14 const { sinon } = ChromeUtils.importESModule( 15 "resource://testing-common/Sinon.sys.mjs" 16 ); 17 18 let flowCounter = 0; 19 20 add_setup(async function () { 21 Services.prefs.setBoolPref("identity.fxaccounts.pairing.enabled", true); 22 // Sync start-up might interfere with our tests, don't let UIState send UI updates. 23 const origNotifyStateUpdated = UIState._internal.notifyStateUpdated; 24 UIState._internal.notifyStateUpdated = () => {}; 25 26 const origGet = UIState.get; 27 UIState.get = () => { 28 return { status: UIState.STATUS_SIGNED_IN, email: "foo@bar.com" }; 29 }; 30 31 const origStart = FxAccountsPairingFlow.start; 32 FxAccountsPairingFlow.start = () => { 33 return `https://foo.bar/${flowCounter++}`; 34 }; 35 36 registerCleanupFunction(() => { 37 UIState._internal.notifyStateUpdated = origNotifyStateUpdated; 38 UIState.get = origGet; 39 FxAccountsPairingFlow.start = origStart; 40 }); 41 }); 42 43 add_task(async function testShowsQRCode() { 44 await runWithPairingDialog(async win => { 45 let doc = win.document; 46 let qrContainer = doc.getElementById("qrContainer"); 47 let qrWrapper = doc.getElementById("qrWrapper"); 48 49 await TestUtils.waitForCondition( 50 () => qrWrapper.getAttribute("pairing-status") == "ready" 51 ); 52 53 // Verify that a QRcode is being shown. 54 Assert.ok( 55 qrContainer.style.backgroundImage.startsWith( 56 `url("data:image/gif;base64,R0lGODdhOgA6AIAAAAAAAP///ywAAAAAOgA6AAAC/4yPqcvtD6OctNqLs968+w+G4gKU5nkiJYO2JuW6KsDGKEw3a7AbPZ+r4Ry7nzFIQkKKN6Avlzowo78` 57 ) 58 ); 59 60 // Close the dialog. 61 let promiseUnloaded = BrowserTestUtils.waitForEvent(win, "unload"); 62 gBrowser.contentDocument.querySelector(".dialogClose").click(); 63 64 info("waiting for dialog to unload"); 65 await promiseUnloaded; 66 }); 67 }); 68 69 add_task(async function testCantShowQrCode() { 70 const origStart = FxAccountsPairingFlow.start; 71 FxAccountsPairingFlow.start = async () => { 72 throw new Error("boom"); 73 }; 74 await runWithPairingDialog(async win => { 75 let doc = win.document; 76 let qrWrapper = doc.getElementById("qrWrapper"); 77 78 await TestUtils.waitForCondition( 79 () => qrWrapper.getAttribute("pairing-status") == "error" 80 ); 81 82 // Close the dialog. 83 let promiseUnloaded = BrowserTestUtils.waitForEvent(win, "unload"); 84 gBrowser.contentDocument.querySelector(".dialogClose").click(); 85 86 info("waiting for dialog to unload"); 87 await promiseUnloaded; 88 }); 89 FxAccountsPairingFlow.start = origStart; 90 }); 91 92 add_task(async function testSwitchToWebContent() { 93 await runWithPairingDialog(async win => { 94 let doc = win.document; 95 let qrWrapper = doc.getElementById("qrWrapper"); 96 97 await TestUtils.waitForCondition( 98 () => qrWrapper.getAttribute("pairing-status") == "ready" 99 ); 100 101 const spySwitchURL = sinon.spy(win.gFxaPairDeviceDialog, "_switchToUrl"); 102 const emitter = win.gFxaPairDeviceDialog._emitter; 103 emitter.emit("view:SwitchToWebContent", "about:robots"); 104 105 Assert.equal(spySwitchURL.callCount, 1); 106 }); 107 }); 108 109 add_task(async function testError() { 110 await runWithPairingDialog(async win => { 111 let doc = win.document; 112 let qrWrapper = doc.getElementById("qrWrapper"); 113 114 await TestUtils.waitForCondition( 115 () => qrWrapper.getAttribute("pairing-status") == "ready" 116 ); 117 118 const emitter = win.gFxaPairDeviceDialog._emitter; 119 emitter.emit("view:Error"); 120 121 await TestUtils.waitForCondition( 122 () => qrWrapper.getAttribute("pairing-status") == "error" 123 ); 124 125 // Close the dialog. 126 let promiseUnloaded = BrowserTestUtils.waitForEvent(win, "unload"); 127 gBrowser.contentDocument.querySelector(".dialogClose").click(); 128 129 info("waiting for dialog to unload"); 130 await promiseUnloaded; 131 }); 132 }); 133 134 async function runWithPairingDialog(test) { 135 await openPreferencesViaOpenPreferencesAPI("paneSync", { leaveOpen: true }); 136 137 let promiseSubDialogLoaded = promiseLoadSubDialog( 138 "chrome://browser/content/preferences/fxaPairDevice.xhtml" 139 ); 140 gBrowser.contentWindow.gSyncPane.pairAnotherDevice(); 141 142 let win = await promiseSubDialogLoaded; 143 144 await test(win); 145 146 sinon.restore(); 147 148 BrowserTestUtils.removeTab(gBrowser.selectedTab); 149 }