From e7896fecc47b489acd565316627e5b28f27379dc Mon Sep 17 00:00:00 2001 From: Yuchen Shi Date: Fri, 19 Mar 2021 14:52:31 -0700 Subject: [PATCH 1/5] Add tests for cross-tab sync. --- .../integration/webdriver/persistence.test.ts | 31 +++++++++++++++++++ .../webdriver/static/persistence.js | 2 +- .../integration/webdriver/util/auth_driver.ts | 28 ++++++++++++----- .../integration/webdriver/util/test_runner.ts | 1 + 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts index 2570ff38099..8063a34ec72 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts @@ -410,4 +410,35 @@ browserDescribe('WebDriver persistence test', driver => { } }); }); + + context.only('persistence sync across windows and tabs', () => { + it('sync current user across windows', async () => { + const cred: UserCredential = await driver.call( + AnonFunction.SIGN_IN_ANONYMOUSLY + ); + const uid = cred.user.uid; + await driver.webDriver.executeScript('window.open(".");'); + await driver.selectPopupWindow(); + await driver.injectConfigAndInitAuth(); + await driver.waitForAuthInit(); + const userInPopup = await driver.getUserSnapshot(); + expect(userInPopup).not.to.be.null; + expect(userInPopup.uid).to.equal(uid); + + await driver.call(CoreFunction.SIGN_OUT); + expect(await driver.getUserSnapshot()).to.be.null; + await driver.selectMainWindow({ noWait: true }); + await new Promise(resolve => setTimeout(resolve, 500)); + expect(await driver.getUserSnapshot()).to.be.null; + + const cred2: UserCredential = await driver.call( + AnonFunction.SIGN_IN_ANONYMOUSLY + ); + const uid2 = cred2.user.uid; + + await driver.selectPopupWindow(); + await new Promise(resolve => setTimeout(resolve, 500)); + expect(await driver.getUserSnapshot()).to.contain({ uid: uid2 }); + }); + }); }); diff --git a/packages-exp/auth-exp/test/integration/webdriver/static/persistence.js b/packages-exp/auth-exp/test/integration/webdriver/static/persistence.js index 9f185b4c387..d2bb4fb89b5 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/static/persistence.js +++ b/packages-exp/auth-exp/test/integration/webdriver/static/persistence.js @@ -134,7 +134,7 @@ function dbPromise(dbRequest) { reject(dbRequest.error); }); dbRequest.addEventListener('blocked', () => { - reject(dbRequest.error || 'blocked'); + reject('blocked'); }); }); } diff --git a/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts b/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts index d2caae45c14..ce5a0bd1936 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts @@ -200,14 +200,16 @@ export class AuthDriver { .window(handles.find(h => h !== currentWindowHandle)!); } - async selectMainWindow(): Promise { - const condition = new Condition( - 'Waiting for popup to close', - async driver => { - return (await driver.getAllWindowHandles()).length === 1; - } - ); - await this.webDriver.wait(condition); + async selectMainWindow(options: { noWait?: boolean } = {}): Promise { + if (!options.noWait) { + const condition = new Condition( + 'Waiting for popup to close', + async driver => { + return (await driver.getAllWindowHandles()).length === 1; + } + ); + await this.webDriver.wait(condition); + } const handles = await this.webDriver.getAllWindowHandles(); return this.webDriver.switchTo().window(handles[0]); } @@ -217,4 +219,14 @@ export class AuthDriver { await this.webDriver.close(); return this.selectMainWindow(); } + + async closeExtraWindows(): Promise { + const handles = await this.webDriver.getAllWindowHandles(); + await this.webDriver.switchTo().window(handles[handles.length - 1]); + while (handles.length > 1) { + await this.webDriver.close(); + handles.pop(); + await this.webDriver.switchTo().window(handles[handles.length - 1]); + } + } } diff --git a/packages-exp/auth-exp/test/integration/webdriver/util/test_runner.ts b/packages-exp/auth-exp/test/integration/webdriver/util/test_runner.ts index ed688a3ed4d..e84b248acc4 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/util/test_runner.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/util/test_runner.ts @@ -69,6 +69,7 @@ setTimeout(() => { // It's assumed that the tests will start with a clean slate (i.e. // no storage). beforeEach(async () => { + await DRIVER.closeExtraWindows(); await DRIVER.reset(); await DRIVER.injectConfigAndInitAuth(); }); From 4e2e216446f5e3ea917a7d5c64c3b4a60b0e4da0 Mon Sep 17 00:00:00 2001 From: Yuchen Shi Date: Mon, 22 Mar 2021 18:12:12 -0700 Subject: [PATCH 2/5] Add legacy test. --- .../integration/webdriver/persistence.test.ts | 38 ++++++++++++++++++- .../integration/webdriver/static/index.js | 29 +++++++------- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts index 8063a34ec72..57e42773a84 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts @@ -411,7 +411,43 @@ browserDescribe('WebDriver persistence test', driver => { }); }); - context.only('persistence sync across windows and tabs', () => { + context('persistence sync across windows and tabs', () => { + it('sync current user across windows in legacy SDK', async () => { + await driver.webDriver.navigate().refresh(); + await driver.injectConfigAndInitLegacySDK(); + await driver.waitForLegacyAuthInit(); + + const result = await driver.call<{ user: { uid: string } }>( + 'legacyAuth.signInAnonymously' + ); + const uid = result.user.uid; + await driver.webDriver.executeScript('window.open(".");'); + await driver.selectPopupWindow(); + await driver.injectConfigAndInitLegacySDK(); + await driver.waitForLegacyAuthInit(); + + const userInPopup = await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT); + expect(userInPopup).not.to.be.null; + expect(userInPopup).to.contain({ uid }); + + await driver.call('legacyAuth.signOut'); + expect(await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT)).to.be.null; + await driver.selectMainWindow({ noWait: true }); + await driver.pause(500); + expect(await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT)).to.be.null; + + const result2 = await driver.call<{ user: { uid: string } }>( + 'legacyAuth.signInAnonymously' + ); + const uid2 = result2.user.uid; + + await driver.selectPopupWindow(); + await new Promise(resolve => setTimeout(resolve, 500)); + expect(await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT)).to.contain({ + uid: uid2 + }); + }); + it('sync current user across windows', async () => { const cred: UserCredential = await driver.call( AnonFunction.SIGN_IN_ANONYMOUSLY diff --git a/packages-exp/auth-exp/test/integration/webdriver/static/index.js b/packages-exp/auth-exp/test/integration/webdriver/static/index.js index 91ad74edb8a..ec69288acc2 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/static/index.js +++ b/packages-exp/auth-exp/test/integration/webdriver/static/index.js @@ -49,20 +49,21 @@ window.startLegacySDK = async persistence => { // TODO: Find some way to make the tests work without Internet. appScript.src = 'https://www.gstatic.com/firebasejs/8.3.0/firebase-app.js'; appScript.onerror = reject; - document.head.appendChild(appScript); - - const authScript = document.createElement('script'); - authScript.src = - 'https://www.gstatic.com/firebasejs/8.3.0/firebase-auth.js'; - authScript.onerror = reject; - authScript.onload = function () { - firebase.initializeApp(firebaseConfig); - const legacyAuth = firebase.auth(); - legacyAuth.useEmulator(emulatorUrl); - legacyAuth.setPersistence(persistence.toLowerCase()); - window.legacyAuth = legacyAuth; - resolve(); + appScript.onload = () => { + const authScript = document.createElement('script'); + authScript.src = + 'https://www.gstatic.com/firebasejs/8.3.0/firebase-auth.js'; + authScript.onerror = reject; + authScript.onload = () => { + firebase.initializeApp(firebaseConfig); + const legacyAuth = firebase.auth(); + legacyAuth.useEmulator(emulatorUrl); + legacyAuth.setPersistence(persistence.toLowerCase()); + window.legacyAuth = legacyAuth; + resolve(); + }; + document.head.appendChild(authScript); }; - document.head.appendChild(authScript); + document.head.appendChild(appScript); }); }; From e72e25ebf72e398f7269d84a65036db2cec7888f Mon Sep 17 00:00:00 2001 From: Yuchen Shi Date: Wed, 24 Mar 2021 14:46:26 -0700 Subject: [PATCH 3/5] Fix tab sync and add tests. --- .../persistence/indexed_db.test.ts | 13 +++++ .../persistence/indexed_db.ts | 15 ++++-- .../persistence/local_storage.test.ts | 16 ++++++ .../persistence/local_storage.ts | 19 +++++++ .../integration/webdriver/persistence.test.ts | 54 ++++++++++--------- .../integration/webdriver/util/auth_driver.ts | 2 +- 6 files changed, 90 insertions(+), 29 deletions(-) diff --git a/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.test.ts b/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.test.ts index 93ecbc89086..24d13b88d49 100644 --- a/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.test.ts +++ b/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.test.ts @@ -34,6 +34,7 @@ import { Receiver } from '../messagechannel/receiver'; import { Sender } from '../messagechannel/sender'; import * as workerUtil from '../util/worker'; import { + _deleteObject, indexedDBLocalPersistence, _clearDatabase, _openDatabase, @@ -135,6 +136,18 @@ describe('platform_browser/persistence/indexed_db', () => { expect(callback).to.have.been.calledWith(newValue); }); + it('should trigger the listener when the key is removed', async () => { + await _putObject(db, key, newValue); + await waitUntilPoll(clock); + callback.resetHistory(); + + await _deleteObject(db, key); + + await waitUntilPoll(clock); + + expect(callback).to.have.been.calledOnceWith(null); + }); + it('should not trigger the listener when a different key changes', async () => { await _putObject(db, 'other-key', newValue); diff --git a/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.ts b/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.ts index 3a060b58e0d..2f4cf31b16d 100644 --- a/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/platform_browser/persistence/indexed_db.ts @@ -152,7 +152,7 @@ async function getObject( return data === undefined ? null : data.value; } -function deleteObject(db: IDBDatabase, key: string): Promise { +export function _deleteObject(db: IDBDatabase, key: string): Promise { const request = getObjectStore(db, true).delete(key); return new DBPromise(request).toPromise(); } @@ -317,7 +317,7 @@ class IndexedDBLocalPersistence implements InternalPersistence { } const db = await _openDatabase(); await _putObject(db, STORAGE_AVAILABLE_KEY, '1'); - await deleteObject(db, STORAGE_AVAILABLE_KEY); + await _deleteObject(db, STORAGE_AVAILABLE_KEY); return true; } catch {} return false; @@ -350,7 +350,7 @@ class IndexedDBLocalPersistence implements InternalPersistence { async _remove(key: string): Promise { return this._withPendingWrite(async () => { - await this._withRetries((db: IDBDatabase) => deleteObject(db, key)); + await this._withRetries((db: IDBDatabase) => _deleteObject(db, key)); delete this.localCache[key]; return this.notifyServiceWorker(key); }); @@ -373,12 +373,21 @@ class IndexedDBLocalPersistence implements InternalPersistence { } const keys = []; + const keysInResult = new Set(); for (const { fbase_key: key, value } of result) { + keysInResult.add(key); if (JSON.stringify(this.localCache[key]) !== JSON.stringify(value)) { this.notifyListeners(key, value as PersistenceValue); keys.push(key); } } + for (const localKey of Object.keys(this.localCache)) { + if (!keysInResult.has(localKey)) { + // Deleted + this.notifyListeners(localKey, null); + keys.push(localKey); + } + } return keys; } diff --git a/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts b/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts index dd5b713eded..89233503512 100644 --- a/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts +++ b/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts @@ -143,6 +143,22 @@ describe('platform_browser/persistence/local_storage', () => { expect(callback).to.have.been.calledWith(newValue); }); + it('should trigger on storage event for the same key after local change', async () => { + await persistence._set(key, newValue); + await new Promise(resolve => setTimeout(resolve, 100)); // wait after the event trigger + callback.resetHistory(); + + window.dispatchEvent( + new StorageEvent('storage', { + key, + oldValue: JSON.stringify(newValue), + newValue: null + }) + ); + + expect(callback).to.have.been.calledOnceWith(null); + }); + it('should not trigger after unsubscribe', () => { persistence._removeListener(key, callback); window.dispatchEvent( diff --git a/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.ts b/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.ts index 4e47cfe6c81..cadbe0aa478 100644 --- a/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.ts +++ b/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.ts @@ -28,6 +28,7 @@ import { import { PersistenceInternal as InternalPersistence, PersistenceType, + PersistenceValue, StorageEventListener } from '../../core/persistence'; import { BrowserPersistenceClass } from './browser'; @@ -239,6 +240,24 @@ class BrowserLocalPersistence this.stopPolling(); } } + + // Update local cache on base operations: + + async _set(key: string, value: PersistenceValue): Promise { + await super._set(key, value); + this.localCache[key] = JSON.stringify(value); + } + + async _get(key: string): Promise { + const value = await super._get(key); + this.localCache[key] = JSON.stringify(value); + return value; + } + + async _remove(key: string): Promise { + await super._remove(key); + delete this.localCache[key]; + } } /** diff --git a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts index 57e42773a84..2f138eb5d25 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts @@ -20,11 +20,13 @@ import { UserCredential } from '@firebase/auth-exp'; import { expect } from 'chai'; import { createAnonAccount } from '../../helpers/integration/emulator_rest_helpers'; import { API_KEY } from '../../helpers/integration/settings'; +import { START_FUNCTION } from './util/auth_driver'; import { AnonFunction, CoreFunction, PersistenceFunction } from './util/functions'; +import { JsLoadCondition } from './util/js_load_condition'; import { browserDescribe } from './util/test_runner'; // eslint-disable-next-line @typescript-eslint/explicit-function-return-type @@ -411,50 +413,52 @@ browserDescribe('WebDriver persistence test', driver => { }); }); - context('persistence sync across windows and tabs', () => { - it('sync current user across windows in legacy SDK', async () => { - await driver.webDriver.navigate().refresh(); - await driver.injectConfigAndInitLegacySDK(); - await driver.waitForLegacyAuthInit(); - - const result = await driver.call<{ user: { uid: string } }>( - 'legacyAuth.signInAnonymously' + context.only('persistence sync across windows and tabs', () => { + it('sync current user across windows with indexedDB', async () => { + const cred: UserCredential = await driver.call( + AnonFunction.SIGN_IN_ANONYMOUSLY ); - const uid = result.user.uid; + const uid = cred.user.uid; await driver.webDriver.executeScript('window.open(".");'); await driver.selectPopupWindow(); - await driver.injectConfigAndInitLegacySDK(); - await driver.waitForLegacyAuthInit(); - - const userInPopup = await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT); + await driver.webDriver.wait(new JsLoadCondition(START_FUNCTION)); + await driver.injectConfigAndInitAuth(); + await driver.waitForAuthInit(); + const userInPopup = await driver.getUserSnapshot(); expect(userInPopup).not.to.be.null; - expect(userInPopup).to.contain({ uid }); + expect(userInPopup.uid).to.equal(uid); - await driver.call('legacyAuth.signOut'); - expect(await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT)).to.be.null; + await driver.call(CoreFunction.SIGN_OUT); + expect(await driver.getUserSnapshot()).to.be.null; await driver.selectMainWindow({ noWait: true }); - await driver.pause(500); - expect(await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT)).to.be.null; + await new Promise(resolve => setTimeout(resolve, 500)); + expect(await driver.getUserSnapshot()).to.be.null; - const result2 = await driver.call<{ user: { uid: string } }>( - 'legacyAuth.signInAnonymously' + const cred2: UserCredential = await driver.call( + AnonFunction.SIGN_IN_ANONYMOUSLY ); - const uid2 = result2.user.uid; + const uid2 = cred2.user.uid; await driver.selectPopupWindow(); await new Promise(resolve => setTimeout(resolve, 500)); - expect(await driver.call(CoreFunction.LEGACY_USER_SNAPSHOT)).to.contain({ - uid: uid2 - }); + expect(await driver.getUserSnapshot()).to.contain({ uid: uid2 }); }); - it('sync current user across windows', async () => { + it('sync current user across windows with localStorage', async () => { + await driver.webDriver.navigate().refresh(); + // Simulate browsers that do not support indexedDB. + await driver.webDriver.executeScript('delete window.indexedDB'); + await driver.injectConfigAndInitAuth(); + await driver.waitForAuthInit(); const cred: UserCredential = await driver.call( AnonFunction.SIGN_IN_ANONYMOUSLY ); const uid = cred.user.uid; await driver.webDriver.executeScript('window.open(".");'); await driver.selectPopupWindow(); + await driver.webDriver.wait(new JsLoadCondition(START_FUNCTION)); + // Simulate browsers that do not support indexedDB. + await driver.webDriver.executeScript('delete window.indexedDB'); await driver.injectConfigAndInitAuth(); await driver.waitForAuthInit(); const userInPopup = await driver.getUserSnapshot(); diff --git a/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts b/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts index ce5a0bd1936..624f83c0f99 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/util/auth_driver.ts @@ -28,7 +28,7 @@ import { CoreFunction } from './functions'; import { JsLoadCondition } from './js_load_condition'; import { authTestServer } from './test_server'; -const START_FUNCTION = 'startAuth'; +export const START_FUNCTION = 'startAuth'; const START_LEGACY_SDK_FUNCTION = 'startLegacySDK'; const PASSED_ARGS = '...Array.prototype.slice.call(arguments, 0, -1)'; From 5a7f797ff79341e5f240496895683995d08ccde6 Mon Sep 17 00:00:00 2001 From: Yuchen Shi Date: Thu, 25 Mar 2021 14:45:27 -0700 Subject: [PATCH 4/5] Remove unit test for localStoage sync. --- .../persistence/local_storage.test.ts | 16 ---------------- .../integration/webdriver/persistence.test.ts | 2 +- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts b/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts index 89233503512..dd5b713eded 100644 --- a/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts +++ b/packages-exp/auth-exp/src/platform_browser/persistence/local_storage.test.ts @@ -143,22 +143,6 @@ describe('platform_browser/persistence/local_storage', () => { expect(callback).to.have.been.calledWith(newValue); }); - it('should trigger on storage event for the same key after local change', async () => { - await persistence._set(key, newValue); - await new Promise(resolve => setTimeout(resolve, 100)); // wait after the event trigger - callback.resetHistory(); - - window.dispatchEvent( - new StorageEvent('storage', { - key, - oldValue: JSON.stringify(newValue), - newValue: null - }) - ); - - expect(callback).to.have.been.calledOnceWith(null); - }); - it('should not trigger after unsubscribe', () => { persistence._removeListener(key, callback); window.dispatchEvent( diff --git a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts index 2f138eb5d25..d8ae90ebfd3 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts @@ -413,7 +413,7 @@ browserDescribe('WebDriver persistence test', driver => { }); }); - context.only('persistence sync across windows and tabs', () => { + context('persistence sync across windows and tabs', () => { it('sync current user across windows with indexedDB', async () => { const cred: UserCredential = await driver.call( AnonFunction.SIGN_IN_ANONYMOUSLY From 9f4b5631640643c8729bc70123221f18df44323a Mon Sep 17 00:00:00 2001 From: Yuchen Shi Date: Thu, 25 Mar 2021 15:58:41 -0700 Subject: [PATCH 5/5] Use drivers.pause. --- .../test/integration/webdriver/persistence.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts index d8ae90ebfd3..ca9f7981714 100644 --- a/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts +++ b/packages-exp/auth-exp/test/integration/webdriver/persistence.test.ts @@ -431,7 +431,7 @@ browserDescribe('WebDriver persistence test', driver => { await driver.call(CoreFunction.SIGN_OUT); expect(await driver.getUserSnapshot()).to.be.null; await driver.selectMainWindow({ noWait: true }); - await new Promise(resolve => setTimeout(resolve, 500)); + await driver.pause(500); expect(await driver.getUserSnapshot()).to.be.null; const cred2: UserCredential = await driver.call( @@ -440,7 +440,7 @@ browserDescribe('WebDriver persistence test', driver => { const uid2 = cred2.user.uid; await driver.selectPopupWindow(); - await new Promise(resolve => setTimeout(resolve, 500)); + await driver.pause(500); expect(await driver.getUserSnapshot()).to.contain({ uid: uid2 }); }); @@ -468,7 +468,7 @@ browserDescribe('WebDriver persistence test', driver => { await driver.call(CoreFunction.SIGN_OUT); expect(await driver.getUserSnapshot()).to.be.null; await driver.selectMainWindow({ noWait: true }); - await new Promise(resolve => setTimeout(resolve, 500)); + await driver.pause(500); expect(await driver.getUserSnapshot()).to.be.null; const cred2: UserCredential = await driver.call( @@ -477,7 +477,7 @@ browserDescribe('WebDriver persistence test', driver => { const uid2 = cred2.user.uid; await driver.selectPopupWindow(); - await new Promise(resolve => setTimeout(resolve, 500)); + await driver.pause(500); expect(await driver.getUserSnapshot()).to.contain({ uid: uid2 }); }); });