/* * Copyright (C) 2019 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ import {TestBed} from '@angular/core/testing'; import {SCIndexResponse} from '@openstapps/core'; import {StAppsWebHttpClient} from '../data/data.provider'; import {StorageProvider} from '../storage/storage.provider'; import {ConfigProvider, STORAGE_KEY_CONFIG} from './config.provider'; import { ConfigFetchError, ConfigInitError, SavedConfigNotAvailable, WrongConfigVersionInStorage, } from './errors'; describe('ConfigProvider', () => { let configProvider: ConfigProvider; let storageProviderSpy: jasmine.SpyObj; beforeEach(() => { const storageProviderMethodSpy = jasmine.createSpyObj('StorageProvider', ['init', 'get', 'has', 'put']); const webHttpClientMethodSpy = jasmine.createSpyObj('StAppsWebHttpClient', ['request']); TestBed.configureTestingModule({ imports: [], providers: [ ConfigProvider, { provide: StorageProvider, useValue: storageProviderMethodSpy, }, { provide: StAppsWebHttpClient, useValue: webHttpClientMethodSpy, }, ], }); configProvider = TestBed.get(ConfigProvider); storageProviderSpy = TestBed.get(StorageProvider); }); it('should fetch app configuration', async () => { spyOn(configProvider.client, 'handshake').and.returnValue(sampleIndexResponse); const result = await configProvider.fetch(); expect(result).toEqual(sampleIndexResponse); }); it('should throw error on fetch with error response', async () => { spyOn(configProvider.client, 'handshake').and.throwError(''); let error = new Error(''); try { await configProvider.fetch(); } catch (err) { error = err; } expect(error).toEqual(new ConfigFetchError()); }); it('should init from remote and saved config not available', async () => { storageProviderSpy.has.and.returnValue(false); spyOn(configProvider.client, 'handshake').and.returnValue(sampleIndexResponse); try { await configProvider.init(); } catch (error) { expect(error).toEqual(new SavedConfigNotAvailable()); } expect(storageProviderSpy.has).toHaveBeenCalled(); expect(storageProviderSpy.get).toHaveBeenCalledTimes(0); expect(configProvider.client.handshake).toHaveBeenCalled(); expect(configProvider.initialised).toBe(true); expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); }); it('should init from storage with remote fails', async () => { storageProviderSpy.has.and.returnValue(true); storageProviderSpy.get.and.returnValue(sampleIndexResponse); spyOn(configProvider.client, 'handshake').and.throwError(''); let error = new Error(''); try { await configProvider.init(); } catch (err) { error = err; } expect(error).toEqual(new ConfigFetchError()); expect(storageProviderSpy.has).toHaveBeenCalled(); expect(storageProviderSpy.get).toHaveBeenCalled(); expect(configProvider.initialised).toBe(true); expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); }); it('should throw error on failed initialisation', async () => { storageProviderSpy.has.and.returnValue(false); spyOn(configProvider.client, 'handshake').and.throwError(''); let error = null; try { await configProvider.init(); } catch (err) { error = err; } expect(error).toEqual(new ConfigInitError()); }); it('should throw error on wrong config version in storage', async () => { storageProviderSpy.has.and.returnValue(true); const wrongConfig = JSON.parse(JSON.stringify(sampleIndexResponse)); wrongConfig.backend.SCVersion = '0.1.0'; storageProviderSpy.get.and.returnValue(wrongConfig); spyOn(configProvider.client, 'handshake').and.returnValue(sampleIndexResponse); let error = null; try { await configProvider.init(); } catch (err) { error = err; } expect(error).toEqual(new WrongConfigVersionInStorage('1.0.0', '0.1.0')); }); it('should throw error on saved app configuration not available', async () => { storageProviderSpy.has.and.returnValue(false); let error = new Error(''); try { await configProvider.loadLocal(); } catch (err) { error = err; } expect(error).toEqual(new SavedConfigNotAvailable()); }); it('should save app configuration', async () => { await configProvider.save(sampleIndexResponse); expect(storageProviderSpy.put).toHaveBeenCalledWith(STORAGE_KEY_CONFIG, sampleIndexResponse); }); it('should set app configuration', async () => { await configProvider.set(sampleIndexResponse); expect(storageProviderSpy.put).toHaveBeenCalled(); }); it('should return app configuration value', async () => { storageProviderSpy.has.and.returnValue(true); storageProviderSpy.get.and.returnValue(sampleIndexResponse); spyOn(configProvider.client, 'handshake').and.returnValue(sampleIndexResponse); await configProvider.init(); expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); }); it('should return app configuration value if only saved config is available and fetch fails', async () => { storageProviderSpy.has.and.returnValue(true); storageProviderSpy.get.and.returnValue(sampleIndexResponse); spyOn(configProvider.client, 'handshake').and.throwError(''); expect(await configProvider.getValue('name')).toEqual(sampleIndexResponse.app.name); }); }); const sampleIndexResponse: SCIndexResponse = { app: { campusPolygon: { coordinates: [[[1, 2]], [[1, 2]]], type: 'Polygon', }, features: { widgets: false, }, menus: [ { icon: 'icon', id: 'main', items: [ { icon: 'icon', route: '/index', title: 'start', translations: { de: { title: 'Start', }, en: { title: 'start', }, }, }, ], name: 'main', translations: { de: { name: 'Haupt', }, en: { name: 'main', }, }, }, ], name: 'StApps', privacyPolicyUrl: 'foo.bar', settings: [ { categories: ['credentials'], input: { defaultValue: '', inputType: 'text', }, name: 'username', order: 0, origin: { indexed: '2018-09-11T12:30:00Z', name: 'Dummy', }, translations: { de: { categories: ['Anmeldedaten'], name: 'Benutzername', }, en: { categories: ['Credentials'], name: 'Username', }, }, type: 'setting', uid: '', }, ], }, backend: { SCVersion: '1.0.0', hiddenTypes: [ 'date series', 'diff', 'floor', ], name: 'Technische Universität Berlin', namespace: '909a8cbc-8520-456c-b474-ef1525f14209', sortableFields: [ { fieldName: 'name', sortTypes: ['ducet'], }, { fieldName: 'type', sortTypes: ['ducet'], }, { fieldName: 'categories', onlyOnTypes: [ 'academic event', 'building', 'catalog', 'dish', 'point of interest', 'room', ], sortTypes: ['ducet'], }, { fieldName: 'geo.point.coordinates', onlyOnTypes: [ 'building', 'point of interest', 'room', ], sortTypes: ['distance'], }, { fieldName: 'geo.point.coordinates', onlyOnTypes: [ 'building', 'point of interest', 'room', ], sortTypes: ['distance'], }, { fieldName: 'inPlace.geo.point.coordinates', onlyOnTypes: [ 'date series', 'dish', 'floor', 'organization', 'point of interest', 'room', 'ticket', ], sortTypes: ['distance'], }, { fieldName: 'offers', onlyOnTypes: [ 'dish', ], sortTypes: ['price'], }, ], }, };