import { AsyncTest, Expect, Setup, SetupFixture, SpyOn, Teardown, Test } from 'alsatian'; import type { AppManager } from '../../../src/server/AppManager'; import type { ProxiedApp } from '../../../src/server/ProxiedApp'; import type { AppBridges } from '../../../src/server/bridges'; import { VideoConfProviderAlreadyExistsError, VideoConfProviderNotRegisteredError } from '../../../src/server/errors'; import type { AppApiManager, AppExternalComponentManager, AppSchedulerManager, AppSlashCommandManager } from '../../../src/server/managers'; import { AppAccessorManager, AppVideoConfProviderManager } from '../../../src/server/managers'; import { AppVideoConfProvider } from '../../../src/server/managers/AppVideoConfProvider'; import type { UIActionButtonManager } from '../../../src/server/managers/UIActionButtonManager'; import type { AppLogStorage, IAppStorageItem } from '../../../src/server/storage'; import { TestsAppBridges } from '../../test-data/bridges/appBridges'; import { TestsAppLogStorage } from '../../test-data/storage/logStorage'; import { TestData } from '../../test-data/utilities'; export class AppVideoConfProviderManagerTestFixture { public static doThrow = false; private mockBridges: TestsAppBridges; private mockApp: ProxiedApp; private mockAccessors: AppAccessorManager; private mockManager: AppManager; @SetupFixture public setupFixture() { this.mockBridges = new TestsAppBridges(); this.mockApp = TestData.getMockApp({ info: { id: 'testing', name: 'testing' } } as IAppStorageItem, this.mockManager); const bri = this.mockBridges; const app = this.mockApp; this.mockManager = { getBridges(): AppBridges { return bri; }, getCommandManager() { return {} as AppSlashCommandManager; }, getExternalComponentManager(): AppExternalComponentManager { return {} as AppExternalComponentManager; }, getApiManager() { return {} as AppApiManager; }, getOneById(appId: string): ProxiedApp { return appId === 'failMePlease' ? undefined : app; }, getLogStorage(): AppLogStorage { return new TestsAppLogStorage(); }, getSchedulerManager() { return {} as AppSchedulerManager; }, getUIActionButtonManager() { return {} as UIActionButtonManager; }, getVideoConfProviderManager() { return {} as AppVideoConfProviderManager; }, } as AppManager; this.mockAccessors = new AppAccessorManager(this.mockManager); const ac = this.mockAccessors; this.mockManager.getAccessorManager = function _getAccessorManager(): AppAccessorManager { return ac; }; } @Setup public setup() {} @Teardown public teardown() {} @Test() public basicAppVideoConfProviderManager() { Expect(() => new AppVideoConfProviderManager({} as AppManager)).toThrow(); Expect(() => new AppVideoConfProviderManager(this.mockManager)).not.toThrow(); const manager = new AppVideoConfProviderManager(this.mockManager); Expect((manager as any).manager).toBe(this.mockManager); Expect((manager as any).accessors).toBe(this.mockManager.getAccessorManager()); Expect((manager as any).videoConfProviders).toBeDefined(); Expect((manager as any).videoConfProviders.size).toBe(0); } @Test() public addProvider() { const provider = TestData.getVideoConfProvider(); const manager = new AppVideoConfProviderManager(this.mockManager); Expect(() => manager.addProvider('testing', provider)).not.toThrow(); Expect((manager as any).videoConfProviders.size).toBe(1); Expect(() => manager.addProvider('failMePlease', provider)).toThrowError( Error, 'App must exist in order for a video conference provider to be added.', ); Expect((manager as any).videoConfProviders.size).toBe(1); } @Test() public ignoreAppsWithoutProviders() { const manager = new AppVideoConfProviderManager(this.mockManager); Expect(() => manager.registerProviders('non-existant')).not.toThrow(); } @Test() public registerProviders() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('firstApp', TestData.getVideoConfProvider()); const appInfo = (manager as any).videoConfProviders.get('firstApp') as Map; Expect(appInfo).toBeDefined(); const regInfo = appInfo.get('test'); Expect(regInfo).toBeDefined(); Expect(regInfo.isRegistered).toBe(false); Expect(() => manager.registerProviders('firstApp')).not.toThrow(); Expect(regInfo.isRegistered).toBe(true); } @Test() public registerTwoProviders() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('firstApp', TestData.getVideoConfProvider()); manager.addProvider('firstApp', TestData.getVideoConfProvider('another-test')); const firstApp = (manager as any).videoConfProviders.get('firstApp') as Map; Expect(firstApp).toBeDefined(); const firstRegInfo = firstApp.get('test'); Expect(firstRegInfo).toBeDefined(); const secondRegInfo = firstApp.get('another-test'); Expect(secondRegInfo).toBeDefined(); Expect(firstRegInfo.isRegistered).toBe(false); Expect(secondRegInfo.isRegistered).toBe(false); Expect(() => manager.registerProviders('firstApp')).not.toThrow(); Expect(firstRegInfo.isRegistered).toBe(true); Expect(secondRegInfo.isRegistered).toBe(true); } @Test() public registerProvidersFromMultipleApps() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('firstApp', TestData.getVideoConfProvider()); manager.addProvider('firstApp', TestData.getVideoConfProvider('another-test')); manager.addProvider('secondApp', TestData.getVideoConfProvider('test3')); const firstApp = (manager as any).videoConfProviders.get('firstApp') as Map; Expect(firstApp).toBeDefined(); const firstRegInfo = firstApp.get('test'); const secondRegInfo = firstApp.get('another-test'); Expect(firstRegInfo).toBeDefined(); Expect(secondRegInfo).toBeDefined(); const secondApp = (manager as any).videoConfProviders.get('secondApp') as Map; Expect(secondApp).toBeDefined(); const thirdRegInfo = secondApp.get('test3'); Expect(thirdRegInfo).toBeDefined(); Expect(firstRegInfo.isRegistered).toBe(false); Expect(secondRegInfo.isRegistered).toBe(false); Expect(() => manager.registerProviders('firstApp')).not.toThrow(); Expect(firstRegInfo.isRegistered).toBe(true); Expect(secondRegInfo.isRegistered).toBe(true); Expect(thirdRegInfo.isRegistered).toBe(false); Expect(() => manager.registerProviders('secondApp')).not.toThrow(); Expect(thirdRegInfo.isRegistered).toBe(true); } @Test() public failToRegisterSameProvider() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('firstApp', TestData.getVideoConfProvider()); Expect(() => manager.addProvider('secondApp', TestData.getVideoConfProvider('test'))).toThrowError( VideoConfProviderAlreadyExistsError, `The video conference provider "test" was already registered by another App.`, ); } @Test() public unregisterProviders() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('testing', TestData.getVideoConfProvider()); const regInfo = (manager as any).videoConfProviders.get('testing').get('test') as AppVideoConfProvider; Expect(() => manager.registerProviders('testing')).not.toThrow(); Expect(() => manager.unregisterProviders('non-existant')).not.toThrow(); Expect(regInfo.isRegistered).toBe(true); Expect(() => manager.unregisterProviders('testing')).not.toThrow(); Expect(regInfo.isRegistered).toBe(false); } @AsyncTest() public async failToGenerateUrlWithoutProvider() { const manager = new AppVideoConfProviderManager(this.mockManager); const call = TestData.getVideoConfData(); await Expect(async () => manager.generateUrl('test', call)).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "test" is not registered in the system.`, ); manager.addProvider('testing', TestData.getVideoConfProvider()); await Expect(() => manager.generateUrl('test', call)).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "test" is not registered in the system.`, ); } @AsyncTest() public async generateUrl() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('testing', TestData.getVideoConfProvider()); manager.registerProviders('testing'); const call = TestData.getVideoConfData(); SpyOn(AppVideoConfProvider.prototype, 'runGenerateUrl').andReturn('test/first-call'); const url = await manager.generateUrl('test', call); await Expect(url).toBe('test/first-call'); } @AsyncTest() public async generateUrlWithMultipleProvidersAvailable() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('testing', TestData.getVideoConfProvider()); manager.addProvider('testing', TestData.getVideoConfProvider('test2')); manager.registerProviders('testing'); manager.addProvider('secondApp', TestData.getVideoConfProvider('differentProvider')); manager.registerProviders('secondApp'); const call = TestData.getVideoConfData(); const cases: any = [ { name: 'test', call, runGenerateUrl: 'test/first-call', result: 'test/first-call', }, { name: 'test2', call, runGenerateUrl: 'test2/first-call', result: 'test2/first-call', }, { name: 'differentProvider', call, runGenerateUrl: 'differentProvider/first-call', result: 'differentProvider/first-call', }, ]; for (const c of cases) { SpyOn(AppVideoConfProvider.prototype, 'runGenerateUrl').andReturn(c.runGenerateUrl); await Expect(await manager.generateUrl(c.name, c.call)).toBe(c.result); } } @AsyncTest() public async failToGenerateUrlWithUnknownProvider() { const call = TestData.getVideoConfData(); const manager = new AppVideoConfProviderManager(this.mockManager); await Expect(() => manager.generateUrl('unknownProvider', call)).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "unknownProvider" is not registered in the system.`, ); } @AsyncTest() public async failToGenerateUrlWithUnregisteredProvider() { const call = TestData.getVideoConfData(); const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('unregisteredApp', TestData.getVideoConfProvider('unregisteredProvider')); await Expect(() => manager.generateUrl('unregisteredProvider', call)).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "unregisteredProvider" is not registered in the system.`, ); } @AsyncTest() public async failToCustomizeUrlWithoutProvider() { const manager = new AppVideoConfProviderManager(this.mockManager); const call = TestData.getVideoConfDataExtended(); const user = TestData.getVideoConferenceUser(); await Expect(() => manager.customizeUrl('test', call, user, {})).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "test" is not registered in the system.`, ); manager.addProvider('testing', TestData.getVideoConfProvider()); await Expect(() => manager.customizeUrl('test', call, user, {})).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "test" is not registered in the system.`, ); } @AsyncTest() public async customizeUrl() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('testing', TestData.getVideoConfProvider()); manager.registerProviders('testing'); const call = TestData.getVideoConfDataExtended(); const user = TestData.getVideoConferenceUser(); const cases: any = [ { name: 'test', call, user, options: {}, runCustomizeUrl: 'test/first-call#caller', result: 'test/first-call#caller', }, { name: 'test', call, user: undefined, options: {}, runCustomizeUrl: 'test/first-call#', result: 'test/first-call#', }, ]; for (const c of cases) { SpyOn(AppVideoConfProvider.prototype, 'runCustomizeUrl').andReturn(c.runCustomizeUrl); await Expect(await manager.customizeUrl(c.name, c.call, c.user, c.options)).toBe(c.result); } } @AsyncTest() public async customizeUrlWithMultipleProvidersAvailable() { const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('testing', TestData.getVideoConfProvider()); manager.addProvider('testing', TestData.getVideoConfProvider('test2')); manager.registerProviders('testing'); manager.addProvider('secondApp', TestData.getVideoConfProvider('differentProvider')); manager.registerProviders('secondApp'); const call = TestData.getVideoConfDataExtended(); const user = TestData.getVideoConferenceUser(); const cases = [ { name: 'test', call, user, options: {}, runCustomizeUrl: 'test/first-call#caller', result: 'test/first-call#caller', }, { name: 'test', call, user: undefined, options: {}, runCustomizeUrl: 'test/first-call#', result: 'test/first-call#', }, { name: 'test2', call, user, options: {}, runCustomizeUrl: 'test2/first-call#caller', result: 'test2/first-call#caller', }, { name: 'test2', call, user: undefined, options: {}, runCustomizeUrl: 'test2/first-call#', result: 'test2/first-call#', }, { name: 'differentProvider', call, user, options: {}, runCustomizeUrl: 'differentProvider/first-call#caller', result: 'differentProvider/first-call#caller', }, { name: 'differentProvider', call, user: undefined, options: {}, runCustomizeUrl: 'differentProvider/first-call#', result: 'differentProvider/first-call#', }, ]; for (const c of cases) { SpyOn(AppVideoConfProvider.prototype, 'runCustomizeUrl').andReturn(c.runCustomizeUrl); await Expect(await manager.customizeUrl(c.name, c.call, c.user, c.options)).toBe(c.result); } } @AsyncTest() public async failToCustomizeUrlWithUnknownProvider() { const call = TestData.getVideoConfDataExtended(); const user = TestData.getVideoConferenceUser(); const manager = new AppVideoConfProviderManager(this.mockManager); await Expect(() => manager.customizeUrl('unknownProvider', call, user, {})).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "unknownProvider" is not registered in the system.`, ); } @AsyncTest() public async failToCustomizeUrlWithUnregisteredProvider() { const call = TestData.getVideoConfDataExtended(); const user = TestData.getVideoConferenceUser(); const manager = new AppVideoConfProviderManager(this.mockManager); manager.addProvider('unregisteredApp', TestData.getVideoConfProvider('unregisteredProvider')); await Expect(() => manager.customizeUrl('unregisteredProvider', call, user, {})).toThrowErrorAsync( VideoConfProviderNotRegisteredError, `The video conference provider "unregisteredProvider" is not registered in the system.`, ); } }