tests done except for sample and samples component

This commit is contained in:
VLE2FE 2020-06-22 10:22:45 +02:00
parent 0d77113704
commit 09598c4ba7
25 changed files with 474 additions and 267 deletions

View File

@ -3,6 +3,9 @@ import { AppComponent } from './app.component';
import {By} from '@angular/platform-browser';
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
import {RouterTestingModule} from '@angular/router/testing';
import {LoginService} from './services/login.service';
let loginServiceSpy: jasmine.SpyObj<LoginService>;
describe('AppComponent', () => {
let component: AppComponent;
@ -10,13 +13,19 @@ describe('AppComponent', () => {
let css; // get native element by css selector
beforeEach(async(() => {
const loginSpy = jasmine.createSpyObj('LoginService', ['login', 'canActivate']);
TestBed.configureTestingModule({
declarations: [ AppComponent ],
imports: [
RbUiComponentsModule,
RouterTestingModule
],
providers: [
{provide: LoginService, useValue: loginSpy}
]
}).compileComponents();
loginServiceSpy = TestBed.inject(LoginService) as jasmine.SpyObj<LoginService>;
}));
beforeEach(() => {

View File

@ -2,9 +2,10 @@ import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/t
import { LoginComponent } from './login.component';
import {LoginService} from '../services/login.service';
import {ValidationService} from '../services/validation.service';
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
import {FormsModule} from '@angular/forms';
import {By} from '@angular/platform-browser';
import {ValidateDirective} from '../validate.directive';
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
let validationServiceSpy: jasmine.SpyObj<ValidationService>;
let loginServiceSpy: jasmine.SpyObj<LoginService>;
@ -20,7 +21,7 @@ describe('LoginComponent', () => {
const loginSpy = jasmine.createSpyObj('LoginService', ['login']);
TestBed.configureTestingModule({
declarations: [ LoginComponent ],
declarations: [ LoginComponent, ValidateDirective ],
imports: [
RbUiComponentsModule,
FormsModule
@ -39,12 +40,15 @@ describe('LoginComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
component.ngOnInit();
fixture.detectChanges();
cssd = (selector) => fixture.debugElement.query(By.css(selector));
css = (selector) => fixture.debugElement.query(By.css(selector)).nativeElement;
});
it('should create', () => {
validationServiceSpy.username.and.returnValue({ok: true, error: ''});
validationServiceSpy.password.and.returnValue({ok: true, error: ''});
expect(component).toBeTruthy();
});
@ -61,27 +65,45 @@ describe('LoginComponent', () => {
expect(css('.message').innerText).toBe('');
});
it('should have a login button', () => {
expect(css('.login-button')).toBeTruthy();
});
it('should display a message when a wrong username was entered', () => {
validationServiceSpy.username.and.returnValue({ok: false, error: 'username must only contain a-z0-9-_.'});
validationServiceSpy.password.and.returnValue({ok: true, error: ''});
cssd('.login-button').triggerEventHandler('click', null);
fixture.detectChanges();
expect(css('.error-messages > div').innerText).toBe('username must only contain a-z0-9-_.');
});
it('should display a message when a wrong password was entered', () => {
it('should have a login button', async () => {
validationServiceSpy.username.and.returnValue({ok: true, error: ''});
validationServiceSpy.password.and.returnValue({ok: true, error: ''});
await fixture.whenStable();
fixture.detectChanges();
expect(css('.login-button')).toBeTruthy();
expect(css('.login-button').disabled).toBeTruthy();
});
it('should reject a wrong username', async () => {
validationServiceSpy.username.and.returnValue({ok: false, error: 'username must only contain a-z0-9-_.'});
component.username = 'ab#';
fixture.detectChanges();
await fixture.whenRenderingDone();
expect(component.loginForm.controls.username.valid).toBeFalsy();
expect(validationServiceSpy.username).toHaveBeenCalledWith('ab#');
});
it('should reject a wrong password', async () => {
validationServiceSpy.password.and.returnValue({ok: false, error: 'password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~'});
component.password = 'abc';
fixture.detectChanges();
await fixture.whenRenderingDone();
expect(component.loginForm.controls.password.valid).toBeFalsy();
expect(validationServiceSpy.password).toHaveBeenCalledWith('abc');
});
it('should enable the login button with valid credentials', async () => {
validationServiceSpy.username.and.returnValue({ok: true, error: ''});
validationServiceSpy.password.and.returnValue({ok: true, error: ''});
loginServiceSpy.login.and.returnValue(new Promise(r => r(true)));
fixture.detectChanges();
await fixture.whenRenderingDone();
cssd('.login-button').triggerEventHandler('click', null);
fixture.detectChanges();
expect(css('.message').innerText).toBe('password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~');
expect(loginServiceSpy.login).not.toHaveBeenCalled();
expect(css('.login-button').disabled).toBeFalsy();
expect(loginServiceSpy.login.calls.count()).toBe(1);
});
it('should call the LoginService with valid credentials', () => {

View File

@ -1,8 +1,7 @@
import {Component, OnInit} from '@angular/core';
import {Component, OnInit, ViewChild} from '@angular/core';
import {ValidationService} from '../services/validation.service';
import {LoginService} from '../services/login.service';
// TODO: catch up with testing
@Component({
selector: 'app-login',
@ -14,6 +13,7 @@ export class LoginComponent implements OnInit {
username = ''; // credentials
password = '';
message = ''; // message below login fields
@ViewChild('loginForm') loginForm;
constructor(

View File

@ -0,0 +1,7 @@
import { BaseModel } from './base.model';
describe('BaseModel', () => {
it('should create an instance', () => {
expect(new BaseModel()).toBeTruthy();
});
});

View File

@ -0,0 +1,10 @@
export class BaseModel {
deserialize(input: any): this {
Object.assign(this, input);
return this;
}
sendFormat(): this {
return this;
}
}

View File

@ -1,13 +1,7 @@
import {Deserializable} from './deserializable.model';
import {BaseModel} from './base.model';
// TODO: put all deserialize methods in one place
export class CustomFieldsModel implements Deserializable{
export class CustomFieldsModel extends BaseModel {
name = '';
qty = 0;
deserialize(input: any): this {
Object.assign(this, input);
return this;
}
}

View File

@ -1,5 +0,0 @@
// import { DeserializableModel } from './deserializable.model';
//
// describe('DeserializableModel', () => {
//
// });

View File

@ -1,3 +0,0 @@
export interface Deserializable {
deserialize(input: any): this;
}

View File

@ -1,5 +0,0 @@
import { IdModel } from './id.model';
describe('IdModel', () => {
});

View File

@ -1,9 +1,8 @@
import _ from 'lodash';
import {Deserializable} from './deserializable.model';
import {IdModel} from './id.model';
import {SendFormat} from './sendformat.model';
import {BaseModel} from './base.model';
export class MaterialModel implements Deserializable, SendFormat {
export class MaterialModel extends BaseModel {
_id: IdModel = null;
name = '';
supplier = '';
@ -14,11 +13,6 @@ export class MaterialModel implements Deserializable, SendFormat {
private numberTemplate = {color: '', number: ''};
numbers: {color: string, number: string}[] = [_.cloneDeep(this.numberTemplate)];
deserialize(input: any): this {
Object.assign(this, input);
return this;
}
sendFormat() {
return _.pick(this, ['name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers']);
}

View File

@ -1,15 +1,15 @@
import _ from 'lodash';
import {IdModel} from './id.model';
import {SendFormat} from './sendformat.model';
import {Deserializable} from './deserializable.model';
import {BaseModel} from './base.model';
export class MeasurementModel implements Deserializable, SendFormat{
export class MeasurementModel extends BaseModel {
_id: IdModel = null;
sample_id: IdModel = null;
measurement_template: IdModel;
values: {[prop: string]: any} = {};
constructor(measurementTemplate: IdModel = null) {
super();
this.measurement_template = measurementTemplate;
}

View File

@ -1,11 +1,10 @@
import _ from 'lodash';
import {Deserializable} from './deserializable.model';
import {IdModel} from './id.model';
import {SendFormat} from './sendformat.model';
import {MaterialModel} from './material.model';
import {MeasurementModel} from './measurement.model';
import {BaseModel} from './base.model';
export class SampleModel implements Deserializable, SendFormat {
export class SampleModel extends BaseModel {
_id: IdModel = null;
color = '';
number = '';

View File

@ -1,5 +0,0 @@
// import { SendformatModel } from './sendformat.model';
//
// describe('SendformatModel', () => {
//
// });

View File

@ -1,3 +0,0 @@
export interface SendFormat {
sendFormat(omit?: string[]): {[prop: string]: any};
}

View File

@ -1,14 +1,9 @@
import {Deserializable} from './deserializable.model';
import {IdModel} from './id.model';
import {BaseModel} from './base.model';
export class TemplateModel implements Deserializable{
export class TemplateModel extends BaseModel {
_id: IdModel = null;
name = '';
version = 1;
parameters: {name: string, range: {[prop: string]: any}}[] = [];
deserialize(input: any): this {
Object.assign(this, input);
return this;
}
}

View File

@ -1,3 +1,4 @@
<script src="rb-table.component.ts"></script>
<table>
<ng-content></ng-content>
</table>

View File

@ -1,25 +1,27 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SampleComponent } from './sample.component';
describe('SampleComponent', () => {
let component: SampleComponent;
let fixture: ComponentFixture<SampleComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SampleComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SampleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
// import { async, ComponentFixture, TestBed } from '@angular/core/testing';
//
// import { SampleComponent } from './sample.component';
//
// // TODO
//
// describe('SampleComponent', () => {
// let component: SampleComponent;
// let fixture: ComponentFixture<SampleComponent>;
//
// beforeEach(async(() => {
// TestBed.configureTestingModule({
// declarations: [ SampleComponent ]
// })
// .compileComponents();
// }));
//
// beforeEach(() => {
// fixture = TestBed.createComponent(SampleComponent);
// component = fixture.componentInstance;
// fixture.detectChanges();
// });
//
// it('should create', () => {
// expect(component).toBeTruthy();
// });
// });

View File

@ -1,25 +1,27 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SamplesComponent } from './samples.component';
describe('SamplesComponent', () => {
let component: SamplesComponent;
let fixture: ComponentFixture<SamplesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SamplesComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SamplesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
// import { async, ComponentFixture, TestBed } from '@angular/core/testing';
//
// import { SamplesComponent } from './samples.component';
//
// // TODO
//
// describe('SamplesComponent', () => {
// let component: SamplesComponent;
// let fixture: ComponentFixture<SamplesComponent>;
//
// beforeEach(async(() => {
// TestBed.configureTestingModule({
// declarations: [ SamplesComponent ]
// })
// .compileComponents();
// }));
//
// beforeEach(() => {
// fixture = TestBed.createComponent(SamplesComponent);
// component = fixture.componentInstance;
// fixture.detectChanges();
// });
//
// it('should create', () => {
// expect(component).toBeTruthy();
// });
// });

View File

@ -1,53 +1,136 @@
// import { TestBed } from '@angular/core/testing';
// import { ApiService } from './api.service';
// import {HttpClient} from '@angular/common/http';
// import {LocalStorageService} from 'angular-2-local-storage';
// import {Observable} from 'rxjs';
//
// let apiService: ApiService;
// let httpClientSpy: jasmine.SpyObj<HttpClient>;
// let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
//
// describe('ApiService', () => {
// beforeEach(() => {
// const httpSpy = jasmine.createSpyObj('HttpClient', ['get']);
// const localStorageSpy = jasmine.createSpyObj('LocalStorageService', ['get']);
//
// TestBed.configureTestingModule({
// providers: [
// ApiService,
// {provide: HttpClient, useValue: httpSpy},
// {provide: LocalStorageService, useValue: localStorageSpy}
// ]
// });
//
// apiService = TestBed.inject(ApiService);
// httpClientSpy = TestBed.inject(HttpClient) as jasmine.SpyObj<HttpClient>;
// localStorageServiceSpy = TestBed.inject(LocalStorageService) as jasmine.SpyObj<LocalStorageService>;
// });
//
// it('should be created', () => {
// expect(apiService).toBeTruthy();
// });
//
// it('should do get requests without auth if not available', () => {
// const getReturn = new Observable();
// httpClientSpy.get.and.returnValue(getReturn);
// localStorageServiceSpy.get.and.returnValue(undefined);
//
// const result = apiService.get('/testurl');
// expect(result).toBe(getReturn);
// expect(httpClientSpy.get).toHaveBeenCalledWith('/testurl', {});
// expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
// });
// it('should do get requests with basic auth if available', () => {
// const getReturn = new Observable();
// httpClientSpy.get.and.returnValue(getReturn);
// localStorageServiceSpy.get.and.returnValue('basicAuth');
//
// const result = apiService.get('/testurl');
// expect(result).toBe(getReturn);
// expect(httpClientSpy.get).toHaveBeenCalledWith('/testurl', jasmine.any(Object)); // could not test http headers better
// expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
// });
// });
import {async, TestBed} from '@angular/core/testing';
import { ApiService } from './api.service';
import {HttpClient} from '@angular/common/http';
import {LocalStorageService} from 'angular-2-local-storage';
import {Observable} from 'rxjs';
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
let apiService: ApiService;
let httpClientSpy: jasmine.SpyObj<HttpClient>;
let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
let modalServiceSpy: jasmine.SpyObj<ModalService>;
// TODO: test options
describe('ApiService', () => {
beforeEach(() => {
const httpSpy = jasmine.createSpyObj('HttpClient', ['get', 'post', 'put', 'delete']);
const localStorageSpy = jasmine.createSpyObj('LocalStorageService', ['get']);
const modalSpy = jasmine.createSpyObj('ModalService', ['openComponent']);
TestBed.configureTestingModule({
providers: [
ApiService,
{provide: HttpClient, useValue: httpSpy},
{provide: LocalStorageService, useValue: localStorageSpy},
{provide: ModalService, useValue: modalSpy}
]
});
apiService = TestBed.inject(ApiService);
httpClientSpy = TestBed.inject(HttpClient) as jasmine.SpyObj<HttpClient>;
localStorageServiceSpy = TestBed.inject(LocalStorageService) as jasmine.SpyObj<LocalStorageService>;
modalServiceSpy = TestBed.inject(ModalService) as jasmine.SpyObj<ModalService>;
});
it('should be created', () => {
expect(apiService).toBeTruthy();
});
it('shows an error message when the request fails', () => {
const getReturn = new Observable(observer => {
observer.error('error');
});
httpClientSpy.get.and.returnValue(getReturn);
localStorageServiceSpy.get.and.returnValue(undefined);
modalServiceSpy.openComponent.and.returnValue({instance: {message: ''}} as any);
apiService.get('/testurl');
expect(httpClientSpy.get).toHaveBeenCalledWith('/api/testurl', {});
expect(modalServiceSpy.openComponent.calls.count()).toBe(1);
});
it('returns the error message if the callback function had an error parameter', () => {
const getReturn = new Observable(observer => {
observer.error('error');
});
httpClientSpy.get.and.returnValue(getReturn);
localStorageServiceSpy.get.and.returnValue(undefined);
modalServiceSpy.openComponent.and.returnValue({instance: {message: ''}} as any);
apiService.get('/testurl', (data, error) => {
expect(modalServiceSpy.openComponent.calls.count()).toBe(0);
expect(error).toBe('error');
});
});
it('should do get requests without auth if not available', async(() => {
const getReturn = new Observable(observer => {
observer.next('data');
});
httpClientSpy.get.and.returnValue(getReturn);
localStorageServiceSpy.get.and.returnValue(undefined);
apiService.get('/testurl', res => {
expect(res).toBe('data');
expect(httpClientSpy.get).toHaveBeenCalledWith('/api/testurl', {});
expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
});
}));
it('should do get requests with basic auth if available', async(() => {
const getReturn = new Observable(observer => {
observer.next('data');
});
httpClientSpy.get.and.returnValue(getReturn);
localStorageServiceSpy.get.and.returnValue('basicAuth');
apiService.get('/testurl', res => {
expect(res).toBe('data');
expect(httpClientSpy.get).toHaveBeenCalledWith('/api/testurl', jasmine.any(Object)); // could not test http headers better
expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
});
}));
it('should do post requests', async(() => {
const resReturn = new Observable(observer => {
observer.next('data');
});
httpClientSpy.post.and.returnValue(resReturn);
localStorageServiceSpy.get.and.returnValue('basicAuth');
apiService.post('/testurl', 'reqData', res => {
expect(res).toBe('data');
expect(httpClientSpy.post).toHaveBeenCalledWith('/api/testurl', 'reqData', jasmine.any(Object));
expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
});
}));
it('should do put requests', async(() => {
const resReturn = new Observable(observer => {
observer.next('data');
});
httpClientSpy.put.and.returnValue(resReturn);
localStorageServiceSpy.get.and.returnValue('basicAuth');
apiService.put('/testurl', 'reqData', res => {
expect(res).toBe('data');
expect(httpClientSpy.put).toHaveBeenCalledWith('/api/testurl', 'reqData', jasmine.any(Object));
expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
});
}));
it('should do delete requests', async(() => {
const resReturn = new Observable(observer => {
observer.next('data');
});
httpClientSpy.delete.and.returnValue(resReturn);
localStorageServiceSpy.get.and.returnValue('basicAuth');
apiService.delete('/testurl', res => {
expect(res).toBe('data');
expect(httpClientSpy.delete).toHaveBeenCalledWith('/api/testurl', jasmine.any(Object));
expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
});
}));
});

View File

@ -5,6 +5,7 @@ import {Observable} from 'rxjs';
import {ErrorComponent} from '../error/error.component';
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
@Injectable({
providedIn: 'root'
})
@ -37,9 +38,14 @@ export class ApiService {
private requestErrorHandler<T>(observable: Observable<any>, f: (data?: T, err?) => void) {
observable.subscribe(data => {
f(data, undefined);
}, () => {
const modalRef = this.modalService.openComponent(ErrorComponent);
modalRef.instance.message = 'Network request failed!';
}, err => {
if (f.length === 2) {
f(undefined, err);
}
else {
const modalRef = this.modalService.openComponent(ErrorComponent);
modalRef.instance.message = 'Network request failed!';
}
});
}

View File

@ -2,15 +2,34 @@ import { TestBed } from '@angular/core/testing';
import { AutocompleteService } from './autocomplete.service';
let autocompleteService: AutocompleteService;
describe('AutocompleteService', () => {
let service: AutocompleteService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AutocompleteService);
TestBed.configureTestingModule({
providers: [AutocompleteService]
});
autocompleteService = TestBed.inject(AutocompleteService);
});
it('should be created', () => {
expect(service).toBeTruthy();
expect(autocompleteService).toBeTruthy();
});
it('should should return a bind function', () => {
expect(autocompleteService.bind('a', ['b'])).toBeTruthy();
});
it('should return search results', () => {
autocompleteService.search(['aa', 'ab', 'bb'], 'a').subscribe(res => {
expect(res).toEqual(['aa', 'ab']);
});
});
it('should return an empty array if no result was found', () => {
autocompleteService.search(['aa', 'ab', 'bb'], 'c').subscribe(res => {
expect(res).toEqual([]);
});
});
});

View File

@ -9,11 +9,11 @@ export class AutocompleteService {
constructor() { }
bind(ref, list) {
bind(ref, list: string[]) {
return this.search.bind(ref, list);
}
search(arr, str) {
search(arr: string[], str: string) {
const qs = new QuickScore(arr);
return of(str === '' ? [] : qs.search(str).map(e => e.item));
}

View File

@ -1,81 +1,87 @@
// import { TestBed } from '@angular/core/testing';
//
// import { LoginService } from './login.service';
// import {LocalStorageService} from 'angular-2-local-storage';
// import {ApiService} from './api.service';
// import {Observable} from 'rxjs';
//
// let loginService: LoginService;
// let apiServiceSpy: jasmine.SpyObj<ApiService>;
// let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
//
// describe('LoginService', () => {
// beforeEach(() => {
// const apiSpy = jasmine.createSpyObj('ApiService', ['get']);
// const localStorageSpy = jasmine.createSpyObj('LocalStorageService', ['set', 'remove']);
//
// TestBed.configureTestingModule({
// providers: [
// LoginService,
// {provide: ApiService, useValue: apiSpy},
// {provide: LocalStorageService, useValue: localStorageSpy}
// ]
// });
// loginService = TestBed.inject(LoginService);
// apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
// localStorageServiceSpy = TestBed.inject(LocalStorageService) as jasmine.SpyObj<LocalStorageService>;
// });
//
// it('should be created', () => {
// expect(loginService).toBeTruthy();
// });
//
// describe('login', () => {
// it('should store the basic auth', () => {
// localStorageServiceSpy.set.and.returnValue(true);
// apiServiceSpy.get.and.returnValue(new Observable());
// loginService.login('username', 'password');
// expect(localStorageServiceSpy.set).toHaveBeenCalledWith('basicAuth', 'dXNlcm5hbWU6cGFzc3dvcmQ=');
// });
//
// it('should remove the basic auth if login fails', () => {
// localStorageServiceSpy.set.and.returnValue(true);
// localStorageServiceSpy.remove.and.returnValue(true);
// apiServiceSpy.get.and.returnValue(new Observable(o => o.error()));
// loginService.login('username', 'password');
// expect(localStorageServiceSpy.remove.calls.count()).toBe(1);
// expect(localStorageServiceSpy.remove).toHaveBeenCalledWith('basicAuth');
// });
//
// it('should resolve true when login succeeds', async () => {
// localStorageServiceSpy.set.and.returnValue(true);
// apiServiceSpy.get.and.returnValue(new Observable(o => o.next({status: 'Authorization successful', method: 'basic'})));
// expect(await loginService.login('username', 'password')).toBeTruthy();
// });
//
// it('should resolve false when a wrong result comes in', async () => {
// localStorageServiceSpy.set.and.returnValue(true);
// apiServiceSpy.get.and.returnValue(new Observable(o => o.next({status: 'xxx', method: 'basic'})));
// expect(await loginService.login('username', 'password')).toBeFalsy();
// });
//
// it('should resolve false on an error', async () => {
// localStorageServiceSpy.set.and.returnValue(true);
// apiServiceSpy.get.and.returnValue(new Observable(o => o.error()));
// expect(await loginService.login('username', 'password')).toBeFalsy();
// });
// });
//
// describe('canActivate', () => {
// it('should return false at first', () => {
// expect(loginService.canActivate(null, null)).toBeFalsy();
// });
//
// it('returns true if login was successful', async () => {
// localStorageServiceSpy.set.and.returnValue(true);
// apiServiceSpy.get.and.returnValue(new Observable(o => o.next({status: 'Authorization successful', method: 'basic'})));
// await loginService.login('username', 'password');
// expect(loginService.canActivate(null, null)).toBeTruthy();
// });
// });
// });
import { TestBed } from '@angular/core/testing';
import { LoginService } from './login.service';
import {LocalStorageService} from 'angular-2-local-storage';
import {ApiService} from './api.service';
let loginService: LoginService;
let apiServiceSpy: jasmine.SpyObj<ApiService>;
let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
describe('LoginService', () => {
beforeEach(() => {
const apiSpy = jasmine.createSpyObj('ApiService', ['get']);
const localStorageSpy = jasmine.createSpyObj('LocalStorageService', ['set', 'remove']);
TestBed.configureTestingModule({
providers: [
LoginService,
{provide: ApiService, useValue: apiSpy},
{provide: LocalStorageService, useValue: localStorageSpy}
]
});
loginService = TestBed.inject(LoginService);
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
localStorageServiceSpy = TestBed.inject(LocalStorageService) as jasmine.SpyObj<LocalStorageService>;
});
it('should be created', () => {
expect(loginService).toBeTruthy();
});
describe('login', () => {
it('should store the basic auth', () => {
localStorageServiceSpy.set.and.returnValue(true);
apiServiceSpy.get.and.callFake(() => {});
loginService.login('username', 'password');
expect(localStorageServiceSpy.set).toHaveBeenCalledWith('basicAuth', 'dXNlcm5hbWU6cGFzc3dvcmQ=');
});
it('should remove the basic auth if login fails', () => {
localStorageServiceSpy.set.and.returnValue(true);
localStorageServiceSpy.remove.and.returnValue(true);
apiServiceSpy.get.and.callFake((a, b) => {b(undefined, 'error'); });
loginService.login('username', 'password');
expect(localStorageServiceSpy.remove.calls.count()).toBe(1);
expect(localStorageServiceSpy.remove).toHaveBeenCalledWith('basicAuth');
});
it('should resolve true when login succeeds', async () => {
localStorageServiceSpy.set.and.returnValue(true);
apiServiceSpy.get.and.callFake((a, b) => {b({status: 'Authorization successful', method: 'basic'} as any, undefined); });
expect(await loginService.login('username', 'password')).toBeTruthy();
});
it('should resolve false when a wrong result comes in', async () => {
localStorageServiceSpy.set.and.returnValue(true);
apiServiceSpy.get.and.callFake((a, b) => {b({status: 'xxx', method: 'basic'} as any, undefined); });
expect(await loginService.login('username', 'password')).toBeFalsy();
});
it('should resolve false on an error', async () => {
localStorageServiceSpy.set.and.returnValue(true);
apiServiceSpy.get.and.callFake((a, b) => {b(undefined, 'error'); });
expect(await loginService.login('username', 'password')).toBeFalsy();
});
});
describe('canActivate', () => {
it('should return false at first', done => {
apiServiceSpy.get.and.callFake((a, b) => {b(undefined, 'error'); });
loginService.canActivate(null, null).subscribe(res => {
expect(res).toBeFalsy();
done();
});
});
it('returns true if login was successful', async done => {
localStorageServiceSpy.set.and.returnValue(true);
apiServiceSpy.get.and.callFake((a, b) => {b({status: 'Authorization successful', method: 'basic'} as any, undefined); });
await loginService.login('username', 'password');
loginService.canActivate(null, null).subscribe(res => {
expect(res).toBeTruthy();
done();
});
});
});
});

View File

@ -28,8 +28,87 @@ describe('ValidationService', () => {
expect(validationService.password('Abc123!#')).toEqual({ok: true, error: ''});
});
it('should return an error on an incorrect password', () => {
expect(validationService.password('Abc123')).toEqual({ok: false, error: 'password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~'});
it('should return an error on a password too short', () => {
expect(validationService.password('Abc123')).toEqual({ok: false, error: 'password must have at least 8 characters'});
});
it('should return an error on a password without a lowercase letter', () => {
expect(validationService.password('ABC123!#')).toEqual({ok: false, error: 'password must have at least one lowercase character'});
});
it('should return an error on a password without an uppercase letter', () => {
expect(validationService.password('abc123!#')).toEqual({ok: false, error: 'password must have at least one uppercase character'});
});
it('should return an error on a password without a number', () => {
expect(validationService.password('Abcabc!#')).toEqual({ok: false, error: 'password must have at least one number'});
});
it('should return an error on a password without a special character', () => {
expect(validationService.password('Abc12345')).toEqual({ok: false, error: 'password must have at least one of the following characters !"#%&\'()*+,-.\\/:;<=>?@[]^_`{|}~'});
});
it('should return an error on a password with a character not allowed', () => {
expect(validationService.password('Abc123!€')).toEqual({ok: false, error: 'password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~'});
});
it('should return true on a correct string', () => {
expect(validationService.string('Abc')).toEqual({ok: true, error: ''});
});
it('should return an error on a string too long', () => {
expect(validationService.string('abcabcabcbabcbabcabcabacbabcabcabcbabcbabcabcabacbabcabcabcbabcbabcabcabacbabcabcabcbabcbabcabcabacbabcabcabcbabcbabcabcabacbacab')).toEqual({ok: false, error: 'must contain max 128 characters'});
});
it('should return true on a string in the list', () => {
expect(validationService.stringOf('Abc', ['Abc', 'Def'])).toEqual({ok: true, error: ''});
});
it('should return an error on a string not in the list', () => {
expect(validationService.stringOf('abc', ['Abc', 'Def'])).toEqual({ok: false, error: 'must be one of Abc, Def'});
});
it('should return true on a string of correct length', () => {
expect(validationService.stringLength('Abc', 5)).toEqual({ok: true, error: ''});
});
it('should return an error on a string longer than specified', () => {
expect(validationService.stringLength('Abc', 2)).toEqual({ok: false, error: 'must contain max 2 characters'});
});
it('should return true on a number in the range', () => {
expect(validationService.minMax(2, -2, 2)).toEqual({ok: true, error: ''});
});
it('should return an error on a number below the range', () => {
expect(validationService.minMax(0, 1, 3)).toEqual({ok: false, error: 'must be between 1 and 3'});
});
it('should return an error on a number above the range', () => {
expect(validationService.minMax(3.1, 1, 3)).toEqual({ok: false, error: 'must be between 1 and 3'});
});
it('should return true on a number above min', () => {
expect(validationService.min(2, -2)).toEqual({ok: true, error: ''});
});
it('should return an error on a number below min', () => {
expect(validationService.min(0, 1)).toEqual({ok: false, error: 'must not be below 1'});
});
it('should return true on a number below max', () => {
expect(validationService.max(2, 2)).toEqual({ok: true, error: ''});
});
it('should return an error on a number above max', () => {
expect(validationService.max(2, 1)).toEqual({ok: false, error: 'must not be above 1'});
});
it('should return true on a string not in the list', () => {
expect(validationService.unique('Abc', ['Def', 'Ghi'])).toEqual({ok: true, error: ''});
});
it('should return an error on a string from the list', () => {
expect(validationService.unique('Abc', ['Abc', 'Def'])).toEqual({ok: false, error: 'values must be unique'});
});
});

View File

@ -107,7 +107,7 @@ export class ValidationService {
}
max(data, max) {
const {ignore, error} = Joi.number().allow('').min(max).validate(data);
const {ignore, error} = Joi.number().allow('').max(max).validate(data);
if (error) {
return {ok: false, error: `must not be above ${max}`};
}