Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): migrate core module from UI-lib (DSP-1853) #505

Merged
merged 4 commits into from Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/app/main/declarations/dsp-api-tokens.ts
@@ -0,0 +1,8 @@
import { InjectionToken } from '@angular/core';
import { KnoraApiConfig, KnoraApiConnection } from '@dasch-swiss/dsp-js';

// config for dsp-js-lib (@dasch-swiss/dsp-js) config object
export const DspApiConfigToken = new InjectionToken<KnoraApiConfig>('DSP api configuration');

// connection config for dsp-js-lib (@dasch-swiss/dsp-js) connection
export const DspApiConnectionToken = new InjectionToken<KnoraApiConnection>('DSP api connection instance');
167 changes: 167 additions & 0 deletions src/app/main/services/app-init.service.spec.ts
@@ -0,0 +1,167 @@
import { TestBed } from '@angular/core/testing';
import { AppInitService } from './app-init.service';

describe('TestService', () => {
let service: AppInitService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AppInitService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});

it('should fetch the fully specified config file when method Init is called', async () => {

const fetchSpy = spyOn(window, 'fetch').and.callFake(
path => Promise.resolve(new Response(JSON.stringify({
apiProtocol: 'http',
apiHost: '0.0.0.0',
apiPort: 3333,
apiPath: 'mypath',
jsonWebToken: 'mytoken',
logErrors: true
})))
);

await service.Init('config', { name: 'prod', production: true });

expect(service.dspApiConfig.apiProtocol).toEqual('http');
expect(service.dspApiConfig.apiHost).toEqual('0.0.0.0');
expect(service.dspApiConfig.apiPort).toEqual(3333);
expect(service.dspApiConfig.apiPath).toEqual('mypath');
expect(service.dspApiConfig.jsonWebToken).toEqual('mytoken');
expect(service.dspApiConfig.logErrors).toEqual(true);

expect(service.config['apiProtocol']).toEqual('http');
expect(service.config['apiHost']).toEqual('0.0.0.0');
expect(service.config['apiPort']).toEqual(3333);
expect(service.config['apiPath']).toEqual('mypath');
expect(service.config['jsonWebToken']).toEqual('mytoken');
expect(service.config['logErrors']).toEqual(true);

expect(fetchSpy).toHaveBeenCalledTimes(1);
expect(fetchSpy).toHaveBeenCalledWith('config/config.prod.json');

});

it('should fetch the minimally specified config file when method Init is called', async () => {

const fetchSpy = spyOn(window, 'fetch').and.callFake(
path => Promise.resolve(new Response(JSON.stringify({
apiProtocol: 'http',
apiHost: '0.0.0.0'
})))
);

await service.Init('config', { name: 'prod', production: true });

expect(service.dspApiConfig.apiProtocol).toEqual('http');
expect(service.dspApiConfig.apiHost).toEqual('0.0.0.0');
expect(service.dspApiConfig.apiPort).toEqual(null);
expect(service.dspApiConfig.apiPath).toEqual('');
expect(service.dspApiConfig.jsonWebToken).toEqual('');
expect(service.dspApiConfig.logErrors).toEqual(false);

expect(service.config['apiProtocol']).toEqual('http');
expect(service.config['apiHost']).toEqual('0.0.0.0');
expect(service.config['apiPort']).toEqual(null);
expect(service.config['apiPath']).toEqual('');
expect(service.config['jsonWebToken']).toEqual('');
expect(service.config['logErrors']).toEqual(false);

expect(fetchSpy).toHaveBeenCalledTimes(1);
expect(fetchSpy).toHaveBeenCalledWith('config/config.prod.json');

});

it('should fetch the config file with additional options when method Init is called', async () => {

const fetchSpy = spyOn(window, 'fetch').and.callFake(
path => Promise.resolve(new Response(JSON.stringify({
apiProtocol: 'http',
apiHost: '0.0.0.0',
myOption: true
})))
);

await service.Init('config', { name: 'prod', production: true });

expect(service.dspApiConfig.apiProtocol).toEqual('http');
expect(service.dspApiConfig.apiHost).toEqual('0.0.0.0');
expect(service.dspApiConfig.apiPort).toEqual(null);
expect(service.dspApiConfig.apiPath).toEqual('');
expect(service.dspApiConfig.jsonWebToken).toEqual('');
expect(service.dspApiConfig.logErrors).toEqual(false);

expect(service.config['apiProtocol']).toEqual('http');
expect(service.config['apiHost']).toEqual('0.0.0.0');
expect(service.config['apiPort']).toEqual(null);
expect(service.config['apiPath']).toEqual('');
expect(service.config['jsonWebToken']).toEqual('');
expect(service.config['logErrors']).toEqual(false);
expect(service.config['myOption']).toEqual(true);

expect(fetchSpy).toHaveBeenCalledTimes(1);
expect(fetchSpy).toHaveBeenCalledWith('config/config.prod.json');

});

it('should throw an error if required members are missing on the config object', async () => {

const fetchSpy = spyOn(window, 'fetch').and.callFake(
path => Promise.resolve(new Response(JSON.stringify({})))
);

await expectAsync(service.Init('config', {
name: 'prod',
production: true
}))
.toBeRejectedWith(new Error('config misses required members: apiProtocol and/or apiHost'));

expect(fetchSpy).toHaveBeenCalledTimes(1);
expect(fetchSpy).toHaveBeenCalledWith('config/config.prod.json');

});

it('should throw an error if "apiProtocol" is missing on the config object', async () => {

const fetchSpy = spyOn(window, 'fetch').and.callFake(
path => Promise.resolve(new Response(JSON.stringify({
apiHost: '0.0.0.0'
})))
);

await expectAsync(service.Init('config', {
name: 'prod',
production: true
}))
.toBeRejectedWith(new Error('config misses required members: apiProtocol and/or apiHost'));

expect(fetchSpy).toHaveBeenCalledTimes(1);
expect(fetchSpy).toHaveBeenCalledWith('config/config.prod.json');

});

it('should throw an error if "apiHost" is missing on the config object', async () => {

const fetchSpy = spyOn(window, 'fetch').and.callFake(
path => Promise.resolve(new Response(JSON.stringify({
apiProtocol: 'http'
})))
);

await expectAsync(service.Init('config', {
name: 'prod',
production: true
}))
.toBeRejectedWith(new Error('config misses required members: apiProtocol and/or apiHost'));

expect(fetchSpy).toHaveBeenCalledTimes(1);
expect(fetchSpy).toHaveBeenCalledWith('config/config.prod.json');

});

});
67 changes: 67 additions & 0 deletions src/app/main/services/app-init.service.ts
@@ -0,0 +1,67 @@
import { Injectable } from '@angular/core';
import { KnoraApiConfig } from '@dasch-swiss/dsp-js';

@Injectable({
providedIn: 'root'
})
export class AppInitService {

dspApiConfig: KnoraApiConfig;

config: object;

constructor() {
}

/**
* fetches and initialises the configuration.
*
* @param path path to the config file.
* @param env environment to be used (dev or prod).
*/
Init(path: string, env: { name: string; production: boolean }): Promise<void> {

return new Promise<void>((resolve, reject) => {
fetch(`${path}/config.${env.name}.json`).then(
(response: Response) => response.json()).then(dspApiConfig => {

// check for presence of apiProtocol and apiHost
if (typeof dspApiConfig.apiProtocol !== 'string' || typeof dspApiConfig.apiHost !== 'string') {
throw new Error('config misses required members: apiProtocol and/or apiHost');
}

// make input type safe
const apiPort = (typeof dspApiConfig.apiPort === 'number' ? dspApiConfig.apiPort : null);
const apiPath = (typeof dspApiConfig.apiPath === 'string' ? dspApiConfig.apiPath : '');
const jsonWebToken = (typeof dspApiConfig.jsonWebToken === 'string' ? dspApiConfig.jsonWebToken : '');
const logErrors = (typeof dspApiConfig.logErrors === 'boolean' ? dspApiConfig.logErrors : false);

// init dsp-api configuration
this.dspApiConfig = new KnoraApiConfig(
dspApiConfig.apiProtocol,
dspApiConfig.apiHost,
apiPort,
apiPath,
jsonWebToken,
logErrors
);

// get all options from config
this.config = dspApiConfig;

// set sanitized standard config options
this.config['apiProtocol'] = dspApiConfig.apiProtocol;
this.config['apiHost'] = dspApiConfig.apiHost;
this.config['apiPort'] = apiPort;
this.config['apiPath'] = apiPath;
this.config['jsonWebToken'] = jsonWebToken;
this.config['logErrors'] = logErrors;

resolve();
}
).catch((err) => {
reject(err);
});
});
}
}