diff --git a/README.md b/README.md index 85832e6046..ca08892a1c 100644 --- a/README.md +++ b/README.md @@ -903,11 +903,15 @@ This is accomplished by selecting a single tab to handle the network requests to ### `start()` +> :hourglass: async + Starts the `OktaAuth` service. See [running as a service](#running-as-a-service) for more details. ### `stop()` -Starts the `OktaAuth` service. See [running as a service](#running-as-a-service) for more details. +> :hourglass: async + +Stops the `OktaAuth` service. See [running as a service](#running-as-a-service) for more details. ### `signIn(options)` diff --git a/lib/OktaAuth.ts b/lib/OktaAuth.ts index 5bc047ec29..23eb0b530c 100644 --- a/lib/OktaAuth.ts +++ b/lib/OktaAuth.ts @@ -376,8 +376,8 @@ class OktaAuth implements OktaAuthInterface, SigninAPI, SignoutAPI { this.serviceManager = new ServiceManager(this, args.services); } - start() { - this.serviceManager.start(); + async start() { + await this.serviceManager.start(); // TODO: review tokenManager.start this.tokenManager.start(); if (!this.token.isLoginRedirect()) { diff --git a/lib/ServiceManager.ts b/lib/ServiceManager.ts index 7dbdb9b3bd..aeece01dc7 100644 --- a/lib/ServiceManager.ts +++ b/lib/ServiceManager.ts @@ -66,10 +66,10 @@ export class ServiceManager implements ServiceManagerInterface { }); } - private onLeader() { + private async onLeader() { if (this.started) { // Start services that requires leadership - this.startServices(); + await this.startServices(); } } @@ -85,12 +85,12 @@ export class ServiceManager implements ServiceManagerInterface { if (this.started) { return; // noop if services have already started } - this.startServices(); + await this.startServices(); this.started = true; } - stop() { - this.stopServices(); + async stop() { + await this.stopServices(); this.started = false; } @@ -98,17 +98,17 @@ export class ServiceManager implements ServiceManagerInterface { return this.services.get(name); } - private startServices() { + private async startServices() { for (const [name, srv] of this.services.entries()) { if (this.canStartService(name, srv)) { - srv.start(); + await srv.start(); } } } - private stopServices() { + private async stopServices() { for (const srv of this.services.values()) { - srv.stop(); + await srv.stop(); } } diff --git a/lib/services/AutoRenewService.ts b/lib/services/AutoRenewService.ts index eb838f8623..351167d3b8 100644 --- a/lib/services/AutoRenewService.ts +++ b/lib/services/AutoRenewService.ts @@ -63,15 +63,15 @@ export class AutoRenewService implements ServiceInterface { return (!!this.options.autoRenew || !!this.options.autoRemove); } - start() { + async start() { if (this.canStart()) { - this.stop(); + await this.stop(); this.tokenManager.on(EVENT_EXPIRED, this.onTokenExpiredHandler); this.started = true; } } - stop() { + async stop() { if (this.started) { this.tokenManager.off(EVENT_EXPIRED, this.onTokenExpiredHandler); this.renewTimeQueue = []; diff --git a/lib/services/LeaderElectionService.ts b/lib/services/LeaderElectionService.ts index 5ecaa2cc6d..f7f8bd8caa 100644 --- a/lib/services/LeaderElectionService.ts +++ b/lib/services/LeaderElectionService.ts @@ -19,7 +19,7 @@ import { } from 'broadcast-channel'; import { isBrowser } from '../features'; -declare type OnLeaderHandler = (() => void); +declare type OnLeaderHandler = (() => Promise<void>); declare type ServiceOptions = ServiceManagerOptions & { onLeader?: OnLeaderHandler; }; @@ -39,8 +39,8 @@ export class LeaderElectionService implements ServiceInterface { private onLeaderDuplicate() { } - private onLeader() { - this.options.onLeader?.(); + private async onLeader() { + await this.options.onLeader?.(); } isLeader() { @@ -51,8 +51,8 @@ export class LeaderElectionService implements ServiceInterface { return !!this.elector?.hasLeader; } - start() { - this.stop(); + async start() { + await this.stop(); if (this.canStart()) { const { electionChannelName } = this.options; this.channel = new BroadcastChannel(electionChannelName as string); @@ -63,14 +63,18 @@ export class LeaderElectionService implements ServiceInterface { } } - stop() { + async stop() { if (this.started) { - this.elector?.die(); - this.elector = undefined; - this.channel?.close(); - // Workaround to fix error `Failed to execute 'postMessage' on 'BroadcastChannel': Channel is closed` - (this.channel as any).postInternal = () => Promise.resolve(); - this.channel = undefined; + if (this.elector) { + await this.elector.die(); + this.elector = undefined; + } + if (this.channel) { + // Workaround to fix error `Failed to execute 'postMessage' on 'BroadcastChannel': Channel is closed` + (this.channel as any).postInternal = () => Promise.resolve(); + await this.channel.close(); + this.channel = undefined; + } this.started = false; } } diff --git a/lib/services/SyncStorageService.ts b/lib/services/SyncStorageService.ts index b0fe730d46..10007fa36e 100644 --- a/lib/services/SyncStorageService.ts +++ b/lib/services/SyncStorageService.ts @@ -54,9 +54,9 @@ export class SyncStorageService implements ServiceInterface { return !!this.options.syncStorage && isBrowser(); } - start() { + async start() { if (this.canStart()) { - this.stop(); + await this.stop(); const { syncChannelName } = this.options; this.channel = new BroadcastChannel(syncChannelName as string); this.tokenManager.on(EVENT_ADDED, this.onTokenAddedHandler); @@ -68,14 +68,14 @@ export class SyncStorageService implements ServiceInterface { } } - stop() { + async stop() { if (this.started) { this.tokenManager.off(EVENT_ADDED, this.onTokenAddedHandler); this.tokenManager.off(EVENT_REMOVED, this.onTokenRemovedHandler); this.tokenManager.off(EVENT_RENEWED, this.onTokenRenewedHandler); this.tokenManager.off(EVENT_SET_STORAGE, this.onSetStorageHandler); this.channel?.removeEventListener('message', this.onSyncMessageHandler); - this.channel?.close(); + await this.channel?.close(); this.channel = undefined; this.started = false; } diff --git a/lib/types/Service.ts b/lib/types/Service.ts index 94bcfe3005..a58245d357 100644 --- a/lib/types/Service.ts +++ b/lib/types/Service.ts @@ -1,7 +1,7 @@ // only add methods needed internally export interface ServiceInterface { - start(): void; - stop(): void; + start(): Promise<void>; + stop(): Promise<void>; isStarted(): boolean; canStart(): boolean; requiresLeadership(): boolean; diff --git a/test/spec/AuthStateManager.js b/test/spec/AuthStateManager.js index 88c3b34464..ecc2cde3f5 100644 --- a/test/spec/AuthStateManager.js +++ b/test/spec/AuthStateManager.js @@ -137,7 +137,7 @@ describe('AuthStateManager', () => { const auth = createAuth(); auth.authStateManager.updateAuthState = jest.fn(); auth.tokenManager.start(); // uses TokenService / crossTabs - auth.serviceManager.start(); + await auth.serviceManager.start(); // simulate change from other dom context const channel = new BroadcastChannel('syncChannel'); await channel.postMessage({ diff --git a/test/spec/OktaAuth/api.ts b/test/spec/OktaAuth/api.ts index 7872cd03ec..71fd4e8f88 100644 --- a/test/spec/OktaAuth/api.ts +++ b/test/spec/OktaAuth/api.ts @@ -47,20 +47,20 @@ describe('OktaAuth (api)', function() { }); describe('start', () => { - it('starts the token service', () => { + it('starts the token service', async () => { jest.spyOn(auth.tokenManager, 'start'); - auth.start(); + await auth.start(); expect(auth.tokenManager.start).toHaveBeenCalled(); }); - it('updates auth state', () => { + it('updates auth state', async () => { jest.spyOn(auth.authStateManager, 'updateAuthState'); - auth.start(); + await auth.start(); expect(auth.authStateManager.updateAuthState).toHaveBeenCalled(); }); - it('should not update auth state during login redirect', () => { + it('should not update auth state during login redirect', async () => { jest.spyOn(auth.authStateManager, 'updateAuthState'); jest.spyOn(auth.token, 'isLoginRedirect').mockReturnValue(true); - auth.start(); + await auth.start(); expect(auth.authStateManager.updateAuthState).not.toHaveBeenCalled(); }); }); diff --git a/test/spec/ServiceManager.ts b/test/spec/ServiceManager.ts index 8c0450c071..ccd43fc62c 100644 --- a/test/spec/ServiceManager.ts +++ b/test/spec/ServiceManager.ts @@ -26,12 +26,12 @@ jest.mock('../../lib/services/LeaderElectionService', () => { canStart() { return true; } requiresLeadership() { return false; } isStarted() { return this.started; } - start() { this.started = true; } - stop() { this.started = false; } + async start() { this.started = true; } + async stop() { this.started = false; } isLeader() { return this._isLeader; } _setLeader() { this._isLeader = true; } - public onLeader() { - (this.options as any).onLeader?.(); + async onLeader() { + await (this.options as any).onLeader?.(); } } return { @@ -67,128 +67,128 @@ describe('ServiceManager', () => { }); describe('syncStorage', () => { - it('allows syncStorage for storage type "cookie"', () => { + it('allows syncStorage for storage type "cookie"', async () => { const options = { tokenManager: { syncStorage: true, storage: 'cookie' } }; util.disableLeaderElection(); const client = createAuth(options); - client.serviceManager.start(); + await client.serviceManager.start(); expect(client.serviceManager.getService('syncStorage')?.isStarted()).toBeTruthy(); - client.serviceManager.stop(); + await client.serviceManager.stop(); }); - it('allows syncStorage for storage type "localStorage"', () => { + it('allows syncStorage for storage type "localStorage"', async () => { const options = { tokenManager: { syncStorage: true, storage: 'localStorage' } }; util.disableLeaderElection(); const client = createAuth(options); - client.serviceManager.start(); + await client.serviceManager.start(); expect(client.serviceManager.getService('syncStorage')?.isStarted()).toBeTruthy(); - client.serviceManager.stop(); + await client.serviceManager.stop(); }); - it('NOT allows syncStorage for storage type "sessionStorage"', () => { + it('NOT allows syncStorage for storage type "sessionStorage"', async () => { const options = { tokenManager: { syncStorage: true, storage: 'sessionStorage' } }; util.disableLeaderElection(); const client = createAuth(options); - client.serviceManager.start(); + await client.serviceManager.start(); expect(client.serviceManager.getService('syncStorage')?.isStarted()).toBeFalsy(); - client.serviceManager.stop(); + await client.serviceManager.stop(); }); - it('NOT allows syncStorage for storage type "memory"', () => { + it('NOT allows syncStorage for storage type "memory"', async () => { const options = { tokenManager: { syncStorage: true, storage: 'memory' } }; util.disableLeaderElection(); const client = createAuth(options); - client.serviceManager.start(); + await client.serviceManager.start(); expect(client.serviceManager.getService('syncStorage')?.isStarted()).toBeFalsy(); - client.serviceManager.stop(); + await client.serviceManager.stop(); }); }); describe('leaderElection', () => { - it('doesn\'t start leaderElection service if other services don\'t require leadership', () => { + it('doesn\'t start leaderElection service if other services don\'t require leadership', async () => { const options = { tokenManager: { syncStorage: false, autoRenew: true } }; const client = createAuth(options); - client.serviceManager.start(); + await client.serviceManager.start(); expect(client.serviceManager.isLeaderRequired()).toBeFalsy(); expect(client.serviceManager.getService('leaderElection')?.isStarted()).toBeFalsy(); - client.serviceManager.stop(); + await client.serviceManager.stop(); }); - it('starts leaderElection service if any service (autoRenew) requires leadership', () => { + it('starts leaderElection service if any service (autoRenew) requires leadership', async () => { const options = { tokenManager: { syncStorage: true, autoRenew: true } }; const client = createAuth(options); - client.serviceManager.start(); + await client.serviceManager.start(); expect(client.serviceManager.isLeaderRequired()).toBeTruthy(); expect(client.serviceManager.getService('leaderElection')?.isStarted()).toBeTruthy(); - client.serviceManager.stop(); + await client.serviceManager.stop(); }); }); describe('autoRenew', () => { - it('starts syncStorage service for every tab, autoRenew service for leader tab (for syncStorage == true)', () => { + it('starts syncStorage service for every tab, autoRenew service for leader tab (for syncStorage == true)', async () => { const options = { tokenManager: { syncStorage: true, autoRenew: true } }; const client1 = createAuth(options); const client2 = createAuth(options); util.disableLeaderElection(); jest.spyOn(client1.serviceManager, 'isLeader').mockReturnValue(true); jest.spyOn(client2.serviceManager, 'isLeader').mockReturnValue(false); - client1.serviceManager.start(); - client2.serviceManager.start(); + await client1.serviceManager.start(); + await client2.serviceManager.start(); expect(client1.serviceManager.getService('autoRenew')?.isStarted()).toBeTruthy(); expect(client2.serviceManager.getService('autoRenew')?.isStarted()).toBeFalsy(); expect(client1.serviceManager.getService('syncStorage')?.isStarted()).toBeTruthy(); expect(client2.serviceManager.getService('syncStorage')?.isStarted()).toBeTruthy(); - client1.serviceManager.stop(); - client2.serviceManager.stop(); + await client1.serviceManager.stop(); + await client2.serviceManager.stop(); }); - it('starts autoRenew service for every tab (for syncStorage == false)', () => { + it('starts autoRenew service for every tab (for syncStorage == false)', async () => { const options = { tokenManager: { syncStorage: false, autoRenew: true } }; const client1 = createAuth(options); const client2 = createAuth(options); util.disableLeaderElection(); jest.spyOn(client1.serviceManager, 'isLeader').mockReturnValue(true); jest.spyOn(client2.serviceManager, 'isLeader').mockReturnValue(false); - client1.serviceManager.start(); - client2.serviceManager.start(); + await client1.serviceManager.start(); + await client2.serviceManager.start(); expect(client1.serviceManager.getService('autoRenew')?.isStarted()).toBeTruthy(); expect(client2.serviceManager.getService('autoRenew')?.isStarted()).toBeTruthy(); expect(client1.serviceManager.getService('syncStorage')?.isStarted()).toBeFalsy(); expect(client2.serviceManager.getService('syncStorage')?.isStarted()).toBeFalsy(); - client1.serviceManager.stop(); - client2.serviceManager.stop(); + await client1.serviceManager.stop(); + await client2.serviceManager.stop(); }); - it('starts no services for syncStorage == false and autoRenew == false', () => { + it('starts no services for syncStorage == false and autoRenew == false', async () => { const options = { tokenManager: { syncStorage: false, autoRenew: false } }; const client1 = createAuth(options); const client2 = createAuth(options); util.disableLeaderElection(); jest.spyOn(client1.serviceManager, 'isLeader').mockReturnValue(true); jest.spyOn(client2.serviceManager, 'isLeader').mockReturnValue(false); - client1.serviceManager.start(); - client2.serviceManager.start(); + await client1.serviceManager.start(); + await client2.serviceManager.start(); expect(client1.serviceManager.getService('autoRenew')?.isStarted()).toBeFalsy(); expect(client2.serviceManager.getService('autoRenew')?.isStarted()).toBeFalsy(); expect(client1.serviceManager.getService('syncStorage')?.isStarted()).toBeFalsy(); expect(client2.serviceManager.getService('syncStorage')?.isStarted()).toBeFalsy(); - client1.serviceManager.stop(); - client2.serviceManager.stop(); + await client1.serviceManager.stop(); + await client2.serviceManager.stop(); }); it('starts autoRenew service after becoming leader (for syncStorage == true)', async () => { const options = { tokenManager: { syncStorage: true, autoRenew: true } }; const client = createAuth(options); - client.serviceManager.start(); + await client.serviceManager.start(); expect(client.serviceManager.isLeader()).toBeFalsy(); expect(client.serviceManager.getService('autoRenew')?.isStarted()).toBeFalsy(); expect(client.serviceManager.getService('syncStorage')?.isStarted()).toBeTruthy(); expect(client.serviceManager.getService('leaderElection')?.isStarted()).toBeTruthy(); (client.serviceManager.getService('leaderElection') as any)?._setLeader(); - (client.serviceManager.getService('leaderElection') as any)?.onLeader(); + await (client.serviceManager.getService('leaderElection') as any)?.onLeader(); expect(client.serviceManager.isLeader()).toBeTruthy(); expect(client.serviceManager.getService('autoRenew')?.isStarted()).toBeTruthy(); - client.serviceManager.stop(); + await client.serviceManager.stop(); }); }); diff --git a/test/spec/services/LeaderElectionService.ts b/test/spec/services/LeaderElectionService.ts index c349725482..9d2800662a 100644 --- a/test/spec/services/LeaderElectionService.ts +++ b/test/spec/services/LeaderElectionService.ts @@ -16,7 +16,7 @@ import { LeaderElectionService } from '../../../lib/services/LeaderElectionServi jest.mock('broadcast-channel', () => { const actual = jest.requireActual('broadcast-channel'); class FakeBroadcastChannel { - close() {} + async close() {} } return { createLeaderElection: actual.createLeaderElection, @@ -29,7 +29,7 @@ const mocked = { }; describe('LeaderElectionService', () => { - let service; + let service: LeaderElectionService | null; beforeEach(function() { jest.useFakeTimers(); service = null; @@ -67,18 +67,18 @@ describe('LeaderElectionService', () => { resolve(); }, 100); }) as Promise<void>, - die: () => {}, + die: () => Promise.resolve(undefined), }; return mockedElector; } describe('start', () => { - it('creates elector and awaits leadership', () => { + it('creates elector and awaits leadership', async () => { const elector = createElectorWithLeadership(); jest.spyOn(mocked.broadcastChannel, 'createLeaderElection').mockReturnValue(elector); const service = createService(); - service.start(); + await service.start(); expect(service.isStarted()).toBeTruthy(); expect((service as any).elector).toStrictEqual(elector); expect(elector.awaitLeadership).toHaveBeenCalledTimes(1); @@ -88,20 +88,20 @@ describe('LeaderElectionService', () => { const elector = createElectorWithLeadership(); jest.spyOn(mocked.broadcastChannel, 'createLeaderElection').mockReturnValue(elector); const service = createService(); - service.start(); - service.start(); + await service.start(); + await service.start(); expect(service.isStarted()).toBeTruthy(); expect(elector.die).toHaveBeenCalledTimes(1); }); }); describe('stop', () => { - it('should kill elector', () => { + it('should kill elector', async () => { const elector = createElectorWithLeadership(); jest.spyOn(mocked.broadcastChannel, 'createLeaderElection').mockReturnValue(elector); const service = createService(); - service.start(); - service.stop(); + await service.start(); + await service.stop(); expect(service.isStarted()).toBeFalsy(); expect(elector.die).toHaveBeenCalledTimes(1); }); @@ -110,24 +110,23 @@ describe('LeaderElectionService', () => { const elector = createElectorWithLeadership(); jest.spyOn(mocked.broadcastChannel, 'createLeaderElection').mockReturnValue(elector); const service = createService(); - service.start(); + await service.start(); expect(service.isStarted()).toBeTruthy(); await Promise.race([ service.stop(), service.stop() ]); expect(service.isStarted()).toBeFalsy(); - expect(elector.die).toHaveBeenCalledTimes(1); }); }); describe('isLeader', () => { - it('returns true if current tab is elected as leader', () => { + it('returns true if current tab is elected as leader', async () => { const elector = createElectorWithLeadership(); jest.spyOn(mocked.broadcastChannel, 'createLeaderElection').mockReturnValue(elector); const service = createService(); expect(service.isLeader()).toBeFalsy(); - service.start(); + await service.start(); expect(service.isLeader()).toBeTruthy(); }); }); @@ -138,7 +137,7 @@ describe('LeaderElectionService', () => { const elector = createElectorWithDelayedLeadership(); jest.spyOn(mocked.broadcastChannel, 'createLeaderElection').mockReturnValue(elector); const service = createService({ onLeader }); - service.start(); + await service.start(); await Promise.resolve(); expect(onLeader).toHaveBeenCalledTimes(0); expect(service.isLeader()).toBeFalsy(); diff --git a/test/spec/services/SyncStorageService.ts b/test/spec/services/SyncStorageService.ts index 183e48c2c8..5653e28d01 100644 --- a/test/spec/services/SyncStorageService.ts +++ b/test/spec/services/SyncStorageService.ts @@ -67,14 +67,14 @@ describe('SyncStorageService', () => { } }); - function createInstance(options?) { + async function createInstance(options?) { tokenManager = new TokenManager(sdkMock, options); tokenManager.start(); service = new SyncStorageService(tokenManager, { ...tokenManager.getOptions(), syncChannelName: 'syncChannel' }); - service.start(); + await service.start(); // Create another channel with same name for communication channel = new BroadcastChannel('syncChannel'); return tokenManager; @@ -82,10 +82,10 @@ describe('SyncStorageService', () => { describe('start', () => { it('stops service if already started, closes and recreates channel', async () => { - createInstance(); + await createInstance(); const oldChannel = (service as any).channel; jest.spyOn(oldChannel, 'close'); - service.start(); // restart + await service.start(); // restart const newChannel = (service as any).channel; expect(service.isStarted()).toBeTruthy(); expect(oldChannel.close).toHaveBeenCalledTimes(1); @@ -95,22 +95,19 @@ describe('SyncStorageService', () => { describe('stop', () => { it('can be called twice without error', async () => { - createInstance(); - const serviceChannel = (service as any).channel; - jest.spyOn(serviceChannel, 'close'); + await createInstance(); await Promise.race([ service.stop(), service.stop() ]); expect(service.isStarted()).toBeFalsy(); - expect(serviceChannel.close).toHaveBeenCalledTimes(1); expect((service as any).channel).not.toBeDefined(); }); }); describe('handling sync messages', () => { it('should emit "added" event if new token is added from another tab', async () => { - createInstance(); + await createInstance(); jest.spyOn(sdkMock.emitter, 'emit'); await channel.postMessage({ type: 'added', @@ -121,7 +118,7 @@ describe('SyncStorageService', () => { }); it('should emit "removed" event if token is removed from another tab', async () => { - createInstance(); + await createInstance(); jest.spyOn(sdkMock.emitter, 'emit'); await channel.postMessage({ type: 'removed', @@ -132,7 +129,7 @@ describe('SyncStorageService', () => { }); it('should emit "renewed" event if token is chnaged from another tab', async () => { - createInstance(); + await createInstance(); jest.spyOn(sdkMock.emitter, 'emit'); await channel.postMessage({ type: 'renewed', @@ -144,7 +141,7 @@ describe('SyncStorageService', () => { }); it('should not post sync message to other tabs', async () => { - createInstance(); + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); await channel.postMessage({ @@ -157,8 +154,8 @@ describe('SyncStorageService', () => { }); describe('posting sync messages', () => { - it('should post "added" sync message when new token is added', () => { - createInstance(); + it('should post "added" sync message when new token is added', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.add('idToken', tokens.standardIdToken2Parsed); @@ -169,8 +166,8 @@ describe('SyncStorageService', () => { }); }); - it('should post "removed" sync message when token is removed', () => { - createInstance(); + it('should post "removed" sync message when token is removed', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.remove('idToken'); @@ -181,8 +178,8 @@ describe('SyncStorageService', () => { }); }); - it('should post "removed", "added", "renewed" sync messages when token is changed', () => { - createInstance(); + it('should post "removed", "added", "renewed" sync messages when token is changed', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.setTokens({ @@ -206,8 +203,8 @@ describe('SyncStorageService', () => { }); }); - it('should post "remove" events when token storage is cleared', () => { - createInstance(); + it('should post "remove" events when token storage is cleared', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.clear(); @@ -219,8 +216,8 @@ describe('SyncStorageService', () => { }); }); - it('should not post "set_storage" event on storage change (for non-IE)', () => { - createInstance(); + it('should not post "set_storage" event on storage change (for non-IE)', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.add('idToken', tokens.standardIdTokenParsed); @@ -233,8 +230,8 @@ describe('SyncStorageService', () => { jest.spyOn(features, 'isIE11OrLess').mockReturnValue(true); }); - it('should post "set_storage" event when new token is added', () => { - createInstance(); + it('should post "set_storage" event when new token is added', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.add('idToken', tokens.standardIdToken2Parsed); @@ -252,8 +249,8 @@ describe('SyncStorageService', () => { }); }); - it('should post "set_storage" event when token is removed', () => { - createInstance(); + it('should post "set_storage" event when token is removed', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.remove('idToken'); @@ -270,8 +267,8 @@ describe('SyncStorageService', () => { }); }); - it('should post "set_storage" event when token storage is cleared', () => { - createInstance(); + it('should post "set_storage" event when token storage is cleared', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.clear(); @@ -288,8 +285,8 @@ describe('SyncStorageService', () => { }); }); - it('should post "set_storage" event when token is chnaged', () => { - createInstance(); + it('should post "set_storage" event when token is chnaged', async () => { + await createInstance(); const serviceChannel = (service as any).channel; jest.spyOn(serviceChannel, 'postMessage'); tokenManager.setTokens({ @@ -321,7 +318,7 @@ describe('SyncStorageService', () => { }); it('should update storage excplicitly on "set_storage" event', async () => { - createInstance(); + await createInstance(); const newStorage = { idToken: tokens.standardIdToken2Parsed };