Commit 76bcdd2b authored by Vitali Stupin's avatar Vitali Stupin

Merge pull request #3 in XTSS/xtss-catalogue from develop to release

* commit 'ca0b2966':
  fixing missing translations
  Adding unit tests
  adding tests
parents 1b2f187c ca0b2966
sonar.projectKey=xtss-catalogue
sonar.sources=src
sonar.sourceEncoding=UTF-8
sonar.exclusions=**/node_modules/**,**/*.spec.ts
sonar.exclusions=**/node_modules/**,**/*.spec.ts,src/environments/**,src/karma.conf.js,src/main.ts
sonar.tests=src
sonar.test.inclusions=**/*.spec.ts
sonar.typescript.lcov.reportPaths=coverage/methods/lcov.info
......
import { AppRoutingModule } from './app-routing.module';
describe('AppModule', () => {
let module: AppRoutingModule;
beforeEach(() => {
module = new AppRoutingModule();
});
it('should be created', () => {
expect(module).toBeTruthy();
});
});
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', () => {
......
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();
});
});
......@@ -2,6 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { HeaderComponent } from './header.component';
import { HttpClientModule } from '@angular/common/http';
import { LanguagesService } from '../languages.service';
describe('HeaderComponent', () => {
let component: HeaderComponent;
......@@ -27,4 +28,11 @@ describe('HeaderComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('should set language', () => {
const languagesService: LanguagesService = TestBed.get(LanguagesService);
spyOn(languagesService, 'setLang').and.returnValue(null);
component.setLang('xxx');
expect(languagesService.setLang).toHaveBeenCalledWith('xxx');
});
});
import { TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { LanguagesService } from './languages.service';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
describe('LanguagesService', () => {
beforeEach(() => TestBed.configureTestingModule({
......@@ -13,4 +13,28 @@ describe('LanguagesService', () => {
const service: LanguagesService = TestBed.get(LanguagesService);
expect(service).toBeTruthy();
});
it('should set default lang with empty localStorage', () => {
const translateService: TranslateService = TestBed.get(TranslateService);
spyOn(translateService, 'setDefaultLang');
spyOn(window.localStorage, 'getItem').and.returnValue(undefined);
TestBed.get(LanguagesService);
expect(translateService.setDefaultLang).toHaveBeenCalledWith('est');
});
it('should set default lang from localStorage', () => {
const translateService: TranslateService = TestBed.get(TranslateService);
spyOn(translateService, 'setDefaultLang');
spyOn(window.localStorage, 'getItem').and.returnValue('ENG');
TestBed.get(LanguagesService);
expect(translateService.setDefaultLang).toHaveBeenCalledWith('eng');
});
it('should set language', () => {
const translateService: TranslateService = TestBed.get(TranslateService);
spyOn(translateService, 'use');
const service = TestBed.get(LanguagesService);
service.setLang('ENG');
expect(translateService.use).toHaveBeenCalledWith('eng');
});
});
......@@ -3,10 +3,12 @@ import { TranslateModule } from '@ngx-translate/core';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { SearchComponent } from './search.component';
import { SubsystemsService } from 'src/app/subsystems.service';
describe('SearchComponent', () => {
let component: SearchComponent;
let fixture: ComponentFixture<SearchComponent>;
let subsystemsService: SubsystemsService;
beforeEach(async(() => {
TestBed.configureTestingModule({
......@@ -21,6 +23,10 @@ describe('SearchComponent', () => {
}));
beforeEach(() => {
subsystemsService = TestBed.get(SubsystemsService);
spyOn(subsystemsService, 'setNonEmpty').and.returnValue(null);
spyOn(subsystemsService, 'setLimit').and.returnValue(null);
spyOn(subsystemsService, 'setFilter').and.returnValue(null);
fixture = TestBed.createComponent(SearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
......@@ -29,4 +35,19 @@ describe('SearchComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('setNonEmpty should work', () => {
component.setNonEmpty(true);
expect(subsystemsService.setNonEmpty).toHaveBeenCalledWith(true);
});
it('setLimit should work', () => {
component.setLimit('50');
expect(subsystemsService.setLimit).toHaveBeenCalledWith('50');
});
it('setFilter should work', () => {
component.setFilter('test');
expect(subsystemsService.setFilter).toHaveBeenCalledWith('test');
});
});
......@@ -3,10 +3,15 @@ import { TranslateModule } from '@ngx-translate/core';
import { HttpClientModule } from '@angular/common/http';
import { SubsystemItemComponent } from './subsystem-item.component';
import { RouterTestingModule } from '@angular/router/testing';
import { SubsystemsService } from 'src/app/subsystems.service';
import { Router } from '@angular/router';
import { PREVIEW_SIZE } from '../../config';
import { Method } from 'src/app/method';
describe('SubsystemItemComponent', () => {
let component: SubsystemItemComponent;
let fixture: ComponentFixture<SubsystemItemComponent>;
let subsystemsService: SubsystemsService;
beforeEach(async(() => {
TestBed.configureTestingModule({
......@@ -17,29 +22,62 @@ describe('SubsystemItemComponent', () => {
TranslateModule.forRoot(),
HttpClientModule,
RouterTestingModule
],
providers: [
{ provide: Router, useValue: {
navigateByUrl: jasmine.createSpy('navigateByUrl')
}}
]
})
.compileComponents();
}));
beforeEach(() => {
subsystemsService = TestBed.get(SubsystemsService);
spyOn(subsystemsService, 'getApiUrlBase').and.returnValue(null);
fixture = TestBed.createComponent(SubsystemItemComponent);
component = fixture.componentInstance;
component.subsystem = {
xRoadInstance: 'XRD',
xRoadInstance: 'INST',
memberClass: 'CLASS',
memberCode: 'CODE',
subsystemCode: 'SUB',
subsystemStatus: 'OK',
fullSubsystemName: 'XRD/CLASS/CODE/SUB',
fullSubsystemName: 'INST/CLASS/CODE/SUB',
methods: []
};
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('getApiUrlBase should work', () => {
component.getApiUrlBase();
expect(subsystemsService.getApiUrlBase).toHaveBeenCalled();
});
it('should preview methods', () => {
expect(component.getMethodsPreview().length).toBe(0);
for (let i = 0; i < PREVIEW_SIZE + 10; i++) {
component.subsystem.methods.push(new Method());
}
expect(component.getMethodsPreview().length).toBe(PREVIEW_SIZE);
});
it('should calculate methods not in preview', () => {
expect(component.getNotInPreview()).toBe(0);
for (let i = 0; i < PREVIEW_SIZE + 10; i++) {
component.subsystem.methods.push(new Method());
}
expect(component.getNotInPreview()).toBe(10);
});
it('should go to detail view', () => {
component.showDetail();
expect(TestBed.get(Router).navigateByUrl).toHaveBeenCalledWith('/INST/CLASS/CODE/SUB');
});
});
......@@ -8,7 +8,7 @@
<p [innerHTML]="'subsystemList.intro.p5' | translate"></p>
<div class="alert alert-warning" role="alert" *ngIf="message">
{{message}}
{{message | translate}}
</div>
<div class="btn-group" role="group" [attr.aria-label]="'subsystemList.selectInstance' | translate">
......
......@@ -5,8 +5,10 @@ import { RouterTestingModule } from '@angular/router/testing';
import { SubsystemListComponent } from './subsystem-list.component';
import { Component, Input } from '@angular/core';
import { Subsystem } from '../subsystem';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, Router, Scroll } from '@angular/router';
import { of } from 'rxjs';
import { SubsystemsService } from '../subsystems.service';
import { ViewportScroller } from '@angular/common';
@Component({selector: 'app-header', template: ''})
class HeaderStubComponent {}
......@@ -20,6 +22,9 @@ class SubsystemItemStubComponent {
describe('SubsystemListComponent', () => {
let component: SubsystemListComponent;
let fixture: ComponentFixture<SubsystemListComponent>;
let getInstanceSpy;
let getInstancesSpy;
let subsystemsService: SubsystemsService;
beforeEach(async(() => {
TestBed.configureTestingModule({
......@@ -31,24 +36,85 @@ describe('SubsystemListComponent', () => {
],
imports: [
TranslateModule.forRoot(),
HttpClientModule,
RouterTestingModule
HttpClientModule
],
providers: [
{ provide: ActivatedRoute, useValue: {
params: of({
instance: 'INST'
})
}},
{ provide: Router, useValue: {
events: of(new Scroll(null, [11, 12], null)),
navigateByUrl: jasmine.createSpy('navigateByUrl')
}}
]
})
.compileComponents();
}));
beforeEach(() => {
// Mocks and spies
TestBed.get(ActivatedRoute).params = of({
instance: 'EE'
});
subsystemsService = TestBed.get(SubsystemsService);
getInstanceSpy = spyOn(subsystemsService, 'getInstance').and.returnValue('INST');
getInstancesSpy = spyOn(subsystemsService, 'getInstances').and.returnValue(['INST']);
spyOn(TestBed.get(ViewportScroller), 'scrollToPosition');
spyOn(subsystemsService, 'setInstance').and.returnValue(null);
spyOn(subsystemsService, 'getDefaultInstance').and.returnValue('DEFINST');
spyOn(TestBed.get(SubsystemsService), 'getApiUrlBase').and.returnValue('base');
});
it('should create', () => {
fixture = TestBed.createComponent(SubsystemListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
it('should redirect on incorrect instance', () => {
getInstancesSpy.and.returnValue(['XXX']);
fixture = TestBed.createComponent(SubsystemListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(TestBed.get(Router).navigateByUrl).toHaveBeenCalledWith('/DEFINST');
});
it('should detect when instance is not selected', () => {
getInstanceSpy.and.returnValue('');
fixture = TestBed.createComponent(SubsystemListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(subsystemsService.setInstance).toHaveBeenCalledWith('INST');
});
it('should detect change instance', () => {
getInstanceSpy.and.returnValue('INST2');
getInstancesSpy.and.returnValue(['INST', 'INST2']);
fixture = TestBed.createComponent(SubsystemListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(subsystemsService.setInstance).toHaveBeenCalledWith('INST');
});
it('should scroll to position', () => {
fixture = TestBed.createComponent(SubsystemListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(TestBed.get(ViewportScroller).scrollToPosition).toHaveBeenCalledWith([11, 12]);
});
it('switchInstance should work', () => {
fixture = TestBed.createComponent(SubsystemListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
component.switchInstance('NEWINST');
expect(TestBed.get(Router).navigateByUrl).toHaveBeenCalledWith('/NEWINST');
});
it('should receive service warnings', () => {
fixture = TestBed.createComponent(SubsystemListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
subsystemsService.warnings.emit('WARN');
expect(component.message).toBe('WARN');
});
});
......@@ -73,7 +73,7 @@ export class SubsystemListComponent implements OnInit, AfterViewInit, OnDestroy
}
// Only reload on switching of instance or when no instance is selected yet on service side
if (this.getInstance() === '' || this.getInstance() !== params.instance) {
this.subsystemsService.setInstance(params.instance ? params.instance : this.subsystemsService.getDefaultInstance());
this.subsystemsService.setInstance(params.instance);
}
});
}
......
<app-header></app-header>
<h3>{{'subsystem.heading' | translate:{"subsystem": subsystemId, "instance": getInstance()} }}</h3>
<h3>{{'subsystem.heading' | translate:{"subsystem": subsystemId, "instance": getInstance() === "" ? paramsInstance : getInstance()} }}</h3>
<p [innerHTML]="'subsystem.intro.p1' | translate"></p>
<div class="alert alert-warning" role="alert" *ngIf="message">
{{message}}
{{message | translate:{"subsystem": subsystemId} }}
</div>
<button type="button" class="btn btn-secondary" (click)="goToList()">{{'subsystem.allSystemsBtn' | translate}}</button>
......
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { Component } from '@angular/core';
import { Component, EventEmitter } from '@angular/core';
import { SubsystemComponent } from './subsystem.component';
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientModule } from '@angular/common/http';
// import { ViewportScroller } from '@angular/common';
// import { SubsystemsService } from '../methods.service';
import { ActivatedRoute } from '@angular/router';
import { of } from 'rxjs';
import { Router, ActivatedRoute, Scroll } from '@angular/router';
import { of, BehaviorSubject } from 'rxjs';
import { SubsystemsService } from '../subsystems.service';
import { ViewportScroller } from '@angular/common';
@Component({selector: 'app-header', template: ''})
class HeaderStubComponent {}
......@@ -15,6 +14,9 @@ class HeaderStubComponent {}
describe('SubsystemComponent', () => {
let component: SubsystemComponent;
let fixture: ComponentFixture<SubsystemComponent>;
let getInstanceSpy;
let getInstancesSpy;
let subsystemsService: SubsystemsService;
beforeEach(async(() => {
TestBed.configureTestingModule({
......@@ -24,40 +26,124 @@ describe('SubsystemComponent', () => {
],
imports: [
TranslateModule.forRoot(),
HttpClientModule,
RouterTestingModule
]/*,
HttpClientModule
],
providers: [
SubsystemsService
]*/
{ provide: ActivatedRoute, useValue: {
params: of({
instance: 'INST',
class: 'CLASS',
member: 'MEMBER',
subsystem: 'SYSTEM'
})
}},
{ provide: Router, useValue: {
events: of(new Scroll(null, [11, 12], null)),
navigateByUrl: jasmine.createSpy('navigateByUrl')
}}
]
})
.compileComponents();
}));
beforeEach(() => {
// Mocks and spies
TestBed.get(ActivatedRoute).params = of({
instance: 'EE',
class: 'CLASS',
member: 'MEMBER',
subsystem: 'SYSTEM'
});
// spyOn(TestBed.get(ViewportScroller), "scrollToPosition").and.callFake(() => {});
subsystemsService = TestBed.get(SubsystemsService);
getInstanceSpy = spyOn(subsystemsService, 'getInstance').and.returnValue('INST');
getInstancesSpy = spyOn(subsystemsService, 'getInstances').and.returnValue(['INST']);
spyOn(TestBed.get(ViewportScroller), 'scrollToPosition');
spyOn(subsystemsService, 'setInstance').and.returnValue(null);
spyOn(TestBed.get(SubsystemsService), 'getApiUrlBase').and.returnValue('base');
subsystemsService.subsystemsSubject = new BehaviorSubject([
{
memberClass: '',
subsystemCode: '',
xRoadInstance: '',
subsystemStatus: '',
memberCode: '',
fullSubsystemName: 'INST/CLASS/MEMBER/SYSTEM',
methods: []
}
]);
});
it('should create', () => {
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(component).toBeTruthy();
});
/*afterEach(() => {
TestBed.resetTestEnvironment()
});*/
it('should detect incorrect instance', () => {
getInstancesSpy.and.returnValue(['XXX']);
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(component.message).toBe('subsystem.incorrectInstanceWarning');
});
it('should create', () => {
expect(component).toBeTruthy();
it('should detect when instance is not selected', () => {
getInstanceSpy.and.returnValue('');
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(subsystemsService.setInstance).toHaveBeenCalledWith('INST');
});
it('should detect change instance', () => {
getInstanceSpy.and.returnValue('INST2');
getInstancesSpy.and.returnValue(['INST', 'INST2']);
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(subsystemsService.setInstance).toHaveBeenCalledWith('INST');
});
it('should detect incorrect subsystem', () => {
subsystemsService.subsystemsSubject = new BehaviorSubject([
{
memberClass: '',
subsystemCode: '',
xRoadInstance: '',
subsystemStatus: '',
memberCode: '',
fullSubsystemName: 'INST/CLASS/MEMBER2/SYSTEM',
methods: []
}
]);
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(component.message).toBe('subsystem.subsystemNotFoundWarning');
});
/*it('scrollToPosition was called', async(() => {
expect(TestBed.get(ViewportScroller).scrollToPosition).toHaveBeenCalledWith([0, 0])
}));*/
it('should scroll to position', () => {
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(TestBed.get(ViewportScroller).scrollToPosition).toHaveBeenCalledWith([11, 12]);
});
it('getApiUrlBase should work', () => {
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
component.getApiUrlBase();
expect(subsystemsService.getApiUrlBase).toHaveBeenCalled();
});
it('goToList should work', () => {
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
component.goToList();
expect(TestBed.get(Router).navigateByUrl).toHaveBeenCalledWith('/INST');
});
it('should receive service warnings', () => {
fixture = TestBed.createComponent(SubsystemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
subsystemsService.warnings.emit('WARN');
expect(component.message).toBe('WARN');
});
});
......@@ -13,6 +13,8 @@ import { filter } from 'rxjs/operators';
export class SubsystemComponent implements OnInit, AfterViewInit, OnDestroy {
subsystemId = '';
message = '';
// Contains instance from route.params (for displaying warning)
paramsInstance = '';
private scrollSubject: BehaviorSubject<any> = new BehaviorSubject(null);
private routerScrollSubscription: Subscription;
private routeSubscription: Subscription;
......@@ -67,18 +69,20 @@ export class SubsystemComponent implements OnInit, AfterViewInit, OnDestroy {
this.routeSubscription = this.route.params.subscribe( params => {
// Checking if instance is correct
if (!this.subsystemsService.getInstances().includes(params.instance)) {
this.message = 'Incorrect instance!';
this.paramsInstance = params.instance;
this.message = 'subsystem.incorrectInstanceWarning';
return;
}
this.subsystemId = params.instance + '/' + params.class + '/' + params.member + '/' + params.subsystem;
// Only reload on switching of instance or when no instance is selected yet on service side
if (this.getInstance() === '' || this.getInstance() !== params.instance) {
this.subsystemsService.setInstance(params.instance ?