diff --git a/src/app/app-routing.module.spec.ts b/src/app/app-routing.module.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4e550a7d316d5c7211c4332b75bdc921ed934be2 --- /dev/null +++ b/src/app/app-routing.module.spec.ts @@ -0,0 +1,13 @@ +import { AppRoutingModule } from './app-routing.module'; + +describe('AppModule', () => { + let module: AppRoutingModule; + + beforeEach(() => { + module = new AppRoutingModule(); + }); + + it('should be created', () => { + expect(module).toBeTruthy(); + }); +}); diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index cb606ea7e9fb2386d5ee97153d9a7a34bc6e6344..c50815f65c22916a61a520d09e79ea0b413031e0 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,5 +1,5 @@ import { TestBed, async } from '@angular/core/testing'; -import {RouterTestingModule} from '@angular/router/testing'; +import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { diff --git a/src/app/app.module.spec.ts b/src/app/app.module.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..0105df3f4a0a37c832d6017c74c2c35ece1a4e4f --- /dev/null +++ b/src/app/app.module.spec.ts @@ -0,0 +1,20 @@ +import { AppModule, HttpLoaderFactory } from './app.module'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; + +describe('AppModule', () => { + let module: AppModule; + let httpClientSpy: { get: jasmine.Spy }; + + beforeEach(() => { + httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']); + module = new AppModule(); + }); + + it('should be created', () => { + expect(module).toBeTruthy(); + }); + + it('HttpLoaderFactory should work', () => { + expect(HttpLoaderFactory(httpClientSpy as any) instanceof TranslateHttpLoader).toBeTruthy(); + }); +}); diff --git a/src/app/subsystems.service.spec.ts b/src/app/subsystems.service.spec.ts index 13246d8b98c83f3993df0c6bc6dbf6ccf078548c..3a6adc91f38a38c3af4653a5e5cae3a602abeb71 100644 --- a/src/app/subsystems.service.spec.ts +++ b/src/app/subsystems.service.spec.ts @@ -1,34 +1,294 @@ -import { TestBed } from '@angular/core/testing'; -import { TranslateModule } from '@ngx-translate/core'; import { SubsystemsService } from './subsystems.service'; -import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { HttpClient } from '@angular/common/http'; +import { of, defer } from 'rxjs'; +import { Subsystem } from './subsystem'; +import { Method } from './method'; +import { HttpErrorResponse } from '@angular/common/http'; +import { tick, fakeAsync } from '@angular/core/testing'; +import { FILTER_DEBOUNCE, DEFAULT_LIMIT, INSTANCES } from './config'; describe('SubsystemsService', () => { + let httpClientSpy: { get: jasmine.Spy }; let service: SubsystemsService; - let httpClient: HttpClient; - let httpTestingController: HttpTestingController; - - beforeEach(() => TestBed.configureTestingModule({ - imports: [ - TranslateModule.forRoot(), - HttpClientTestingModule - ] - })); beforeEach(() => { - httpClient = TestBed.get(HttpClient); - httpTestingController = TestBed.get(HttpTestingController); - service = TestBed.get(SubsystemsService); + httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']); + service = new SubsystemsService(httpClientSpy as any); }); it('should be created', () => { expect(service).toBeTruthy(); }); - /*it('should set instance', () => { + it('should set instance on HTTP OK', () => { + const sourceSubsystems = [ + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER', + methods: [ + { + methodStatus: 'OK', + serviceCode: 'SERVICE', + wsdl: 'URL', + serviceVersion: 'VER' + } + ] + }, + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER2', + methods: [] + } + ]; + const expectedSubsystems = [ + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER', + fullSubsystemName: 'INST/CLASS/MEMBER/SYSTEM', + methods: [ + { + methodStatus: 'OK', + serviceCode: 'SERVICE', + wsdl: 'URL', + serviceVersion: 'VER', + fullMethodName: 'INST/CLASS/MEMBER/SYSTEM/SERVICE/VER' + } + ] + }, + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER2', + fullSubsystemName: 'INST/CLASS/MEMBER2/SYSTEM', + methods: [] + } + ]; + httpClientSpy.get.and.returnValue(of(sourceSubsystems)); + // Setting value to test resetting of values + service.subsystemsSubject.next([new Subsystem()]); + service.filteredSubsystemsSubject.next([new Subsystem()]); + service.setInstance('EE'); + expect(httpClientSpy.get).toHaveBeenCalledWith('https://www.x-tee.ee/catalogue/EE/wsdls/index.json'); + expect(service.subsystemsSubject.value).toEqual(expectedSubsystems); + // No filters yet + expect(service.filteredSubsystemsSubject.value).toEqual(expectedSubsystems); + }); + + it('should set instance on HTTP ERROR', fakeAsync(() => { + const errorResponse = new HttpErrorResponse({error: 'error', status: 404, statusText: 'Not Found'}); + httpClientSpy.get.and.returnValue(defer(() => Promise.reject(errorResponse))); + // Setting value to test resetting of values + service.subsystemsSubject.next([new Subsystem()]); + service.filteredSubsystemsSubject.next([new Subsystem()]); service.setInstance('EE'); - // expect(service).toBeTruthy(); - // httpTestingController.expectOne('https://x-tee.ee/catalogue/EE/wsdls/index.json'); - });*/ + // Waiting for some (unknown) asynchronous work + tick(); + expect(httpClientSpy.get).toHaveBeenCalledWith('https://www.x-tee.ee/catalogue/EE/wsdls/index.json'); + expect(service.subsystemsSubject.value).toEqual([]); + expect(service.filteredSubsystemsSubject.value).toEqual([]); + })); + + it('should filter nonEmpty subsystems', () => { + const sourceSubsystems = [ + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER', + fullSubsystemName: 'INST/CLASS/MEMBER/SYSTEM', + methods: [{} as Method] + }, + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER2', + fullSubsystemName: 'INST/CLASS/MEMBER2/SYSTEM', + methods: [] + } + ]; + const expectedSubsystems = [ + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER', + fullSubsystemName: 'INST/CLASS/MEMBER/SYSTEM', + methods: [{} as Method] + } + ]; + service.subsystemsSubject.next(sourceSubsystems); + service.setNonEmpty(true); + expect(service.filteredSubsystemsSubject.value).toEqual(expectedSubsystems); + }); + + it('should set filter for subsystems', fakeAsync(() => { + const sourceSubsystems = [ + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER', + fullSubsystemName: 'INST/CLASS/MEMBER/SYSTEM', + methods: [ + { + methodStatus: 'OK', + serviceCode: 'SERVICE', + wsdl: 'URL', + serviceVersion: 'VER', + fullMethodName: 'INST/CLASS/MEMBER/SYSTEM/SERVICE/VER' + }, + { + methodStatus: 'OK', + serviceCode: 'SERVICE2', + wsdl: 'URL', + serviceVersion: 'VER', + fullMethodName: 'INST/CLASS/MEMBER/SYSTEM/SERVICE2/VER' + } + ] + }, + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER2', + fullSubsystemName: 'INST/CLASS/MEMBER2/SYSTEM', + methods: [] + } + ]; + const expectedSubsystems1 = [ + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER2', + fullSubsystemName: 'INST/CLASS/MEMBER2/SYSTEM', + methods: [] + } + ]; + const expectedSubsystems2 = [ + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER', + fullSubsystemName: 'INST/CLASS/MEMBER/SYSTEM', + methods: [ + { + methodStatus: 'OK', + serviceCode: 'SERVICE2', + wsdl: 'URL', + serviceVersion: 'VER', + fullMethodName: 'INST/CLASS/MEMBER/SYSTEM/SERVICE2/VER' + } + ] + } + ]; + service.subsystemsSubject.next(sourceSubsystems); + + // Search member without methods + service.setFilter('MEMBER2'); + // Waiting for a debounce time to apply filter + tick(FILTER_DEBOUNCE); + expect(service.filteredSubsystemsSubject.value).toEqual(expectedSubsystems1); + + // Search member with multiple methods + service.setFilter('SERVICE2'); + // Waiting for a debounce time to apply filter + tick(FILTER_DEBOUNCE); + expect(service.filteredSubsystemsSubject.value).toEqual(expectedSubsystems2); + + // Search with limit + const sourceSubsystems2 = []; + for (let i = 0; i < DEFAULT_LIMIT + 1; i++) { + sourceSubsystems2.push( + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER' + i, + fullSubsystemName: 'INST/CLASS/MEMBER' + i + '/SYSTEM', + methods: [] + } + ); + } + service.subsystemsSubject.next(sourceSubsystems2); + service.setFilter('MEMBER'); + // Waiting for a debounce time to apply filter + tick(FILTER_DEBOUNCE); + expect(service.filteredSubsystemsSubject.value.length).toEqual(DEFAULT_LIMIT); + })); + + it('should set limit', () => { + const sourceSubsystems = []; + for (let i = 0; i < 51; i++) { + sourceSubsystems.push( + { + memberClass: 'CLASS', + subsystemCode: 'SYSTEM', + xRoadInstance: 'INST', + subsystemStatus: 'OK', + memberCode: 'MEMBER' + i, + fullSubsystemName: 'INST/CLASS/MEMBER' + i + '/SYSTEM', + methods: [] + } + ); + } + service.subsystemsSubject.next(sourceSubsystems); + + service.setLimit('all'); + expect(service.filteredSubsystemsSubject.value.length).toEqual(51); + + service.setLimit('50'); + expect(service.filteredSubsystemsSubject.value.length).toEqual(50); + + service.setLimit('20'); + expect(service.filteredSubsystemsSubject.value.length).toEqual(20); + + service.setLimit('10'); + expect(service.filteredSubsystemsSubject.value.length).toEqual(10); + }); + + it('getLimit should work', () => { + expect(service.getLimit()).toEqual(DEFAULT_LIMIT.toString()); + + service.setLimit('all'); + expect(service.getLimit()).toEqual('all'); + }); + + it('getInstances should work', () => { + expect(service.getInstances()).toEqual(Object.keys(INSTANCES)); + }); + + it('getDefaultInstance should work', () => { + expect(service.getDefaultInstance()).toEqual(Object.keys(INSTANCES)[0]); + }); + + it('getInstance should work', () => { + // Default value + expect(service.getInstance()).toEqual(''); + }); + + it('getApiUrlBase should work', () => { + // Default value + expect(service.getApiUrlBase()).toEqual(''); + }); }); diff --git a/src/app/subsystems.service.ts b/src/app/subsystems.service.ts index db72f12fb7312f76aefa37d9dfb466013e54a819..afee0653c76c544d8ab6fda7531a8ebcd073020d 100644 --- a/src/app/subsystems.service.ts +++ b/src/app/subsystems.service.ts @@ -96,6 +96,7 @@ export class SubsystemsService { */ private handleError(result?: T) { return (error: any): Observable => { + // TODO: translation! this.emitWarning('Error while loading data from server!'); // Let the app keep running by returning an empty result. return of(result);