From 971a677a82a8de40d0d121f0c2e383d4403c7bc8 Mon Sep 17 00:00:00 2001 From: Corinne Krych Date: Wed, 26 Apr 2017 15:38:54 +0200 Subject: [PATCH] Add unit tests --- src/app/areas/area.service.spec.ts | 58 ++++++++- .../collaborator.service.spec.ts | 75 ++++++++++- src/app/spaces/space-name.pipe.spec.ts | 30 +++++ src/app/spaces/space.service.spec.ts | 122 ++++++++++++++++-- .../unique-space-name.directive.spec.ts | 118 +++++++++++++++++ .../spaces/valid-space-name.directive.spec.ts | 52 ++++++++ 6 files changed, 435 insertions(+), 20 deletions(-) create mode 100644 src/app/spaces/space-name.pipe.spec.ts create mode 100644 src/app/spaces/unique-space-name.directive.spec.ts diff --git a/src/app/areas/area.service.spec.ts b/src/app/areas/area.service.spec.ts index e08ead5..72b7009 100644 --- a/src/app/areas/area.service.spec.ts +++ b/src/app/areas/area.service.spec.ts @@ -16,8 +16,10 @@ describe('Service: AreaService', () => { let areaService: AreaService; let mockService: MockBackend; let fakeAuthService: any; + let mockLog: any; beforeEach(() => { + mockLog = jasmine.createSpyObj('Logger', ['error']); fakeAuthService = { getToken: function () { return ''; @@ -28,7 +30,9 @@ describe('Service: AreaService', () => { }; TestBed.configureTestingModule({ providers: [ - Logger, + { + provide: Logger, useValue: mockLog + }, BaseRequestOptions, MockBackend, { @@ -83,8 +87,8 @@ describe('Service: AreaService', () => { let response = { data: responseData, links: {} }; let expectedResponse = cloneDeep(responseData); - it('Get areas', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -93,14 +97,28 @@ describe('Service: AreaService', () => { }) )); }); - + // when areaService.getAllBySpaceId('1').subscribe((data: Area[]) => { + // then expect(data[0].id).toEqual(expectedResponse[0].id); expect(data[0].attributes.name).toEqual(expectedResponse[0].attributes.name); }); })); + it('Get areas in error', async(() => { + // given + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when + areaService.getAllBySpaceId('1').subscribe((data: Area[]) => { + fail('Get areas should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Add new area', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -109,15 +127,30 @@ describe('Service: AreaService', () => { }) )); }); - + // when areaService.create('1', responseData[0]) .subscribe((data: Area) => { + // then expect(data.id).toEqual(expectedResponse[0].id); expect(data.attributes.name).toEqual(expectedResponse[0].attributes.name); }); })); + it('Add new area in error', async(() => { + // given + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when + areaService.create('1', responseData[0]) + .subscribe((data: Area) => { + fail('Add new area should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Get a single area by Id', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -126,14 +159,27 @@ describe('Service: AreaService', () => { }) )); }); - let areaId = '1'; - + // when areaService.getById(areaId) .subscribe((data: Area) => { + // then expect(data.id).toEqual(expectedResponse[0].id); expect(data.attributes.name).toEqual(expectedResponse[0].attributes.name); }); })); + it('Get a single area by Id in error', async(() => { + // given + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + let areaId = '1'; + // when + areaService.getById(areaId) + .subscribe((data: Area) => { + fail('Get a single area by Id should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); }); diff --git a/src/app/collaborators/collaborator.service.spec.ts b/src/app/collaborators/collaborator.service.spec.ts index 101d962..21d6a8b 100644 --- a/src/app/collaborators/collaborator.service.spec.ts +++ b/src/app/collaborators/collaborator.service.spec.ts @@ -1,6 +1,6 @@ import { async, inject, TestBed } from '@angular/core/testing'; -import { BaseRequestOptions, Http, Response, ResponseOptions } from '@angular/http'; -import { MockBackend } from '@angular/http/testing'; +import { BaseRequestOptions, Http, Response, ResponseType, ResponseOptions } from '@angular/http'; +import { MockBackend, MockConnection} from '@angular/http/testing'; import { cloneDeep } from 'lodash'; @@ -15,6 +15,7 @@ describe('Service: CollaboratorService', () => { let collaboratorService: CollaboratorService; let mockService: MockBackend; let fakeAuthService: any; + let mockLog: any; beforeEach(() => { fakeAuthService = { @@ -25,9 +26,12 @@ describe('Service: CollaboratorService', () => { return true; } }; + mockLog = jasmine.createSpyObj('Logger', ['error']); TestBed.configureTestingModule({ providers: [ - Logger, + { + provide: Logger, useValue: mockLog + }, BaseRequestOptions, MockBackend, { @@ -83,8 +87,8 @@ describe('Service: CollaboratorService', () => { let response = { data: responseData, links: {} }; let expectedResponse = cloneDeep(responseData); - it('Get collaborators', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -93,14 +97,28 @@ describe('Service: CollaboratorService', () => { }) )); }); - + // when collaboratorService.getAllBySpaceId('1').subscribe((data: User[]) => { + // then expect(data[0].id).toEqual(expectedResponse[0].id); expect(data[0].attributes.username).toEqual(expectedResponse[0].attributes.username); }); })); + it('Get collaborators in error', async(() => { + // given + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when + collaboratorService.getAllBySpaceId('1').subscribe((data: User[]) => { + fail('get collaboration should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Add new collaborators', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -109,10 +127,57 @@ describe('Service: CollaboratorService', () => { }) )); }); + // when + collaboratorService.addCollaborators('1', responseData) + .subscribe(() => { + // then + expect('1').toEqual('1'); + }); + })); + it('Add new collaborators in error', async(() => { + // given + mockLog.error.and.returnValue(); + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when collaboratorService.addCollaborators('1', responseData) .subscribe(() => { + fail('add collaboration should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + + it('Remove collaborator', async(() => { + // given + mockService.connections.subscribe((connection: any) => { + connection.mockRespond(new Response( + new ResponseOptions({ + body: JSON.stringify({data: ['id1']}), + status: 201 + }) + )); + }); + // when + collaboratorService.removeCollaborator('1', '6abd2970-9407-469d-a8ad-9e18706d732c') + .subscribe(() => { + // then expect('1').toEqual('1'); }); })); + + it('Remove collaborator in error', async(() => { + // given + mockLog.error.and.returnValue(); + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when + collaboratorService.removeCollaborator('1', '6abd2970-9407-469d-a8ad-9e18706d732c') + .subscribe(() => { + fail('remove collaboration should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); }); diff --git a/src/app/spaces/space-name.pipe.spec.ts b/src/app/spaces/space-name.pipe.spec.ts new file mode 100644 index 0000000..d58456e --- /dev/null +++ b/src/app/spaces/space-name.pipe.spec.ts @@ -0,0 +1,30 @@ +import { async, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { SpaceNamePipe } from './space-name.pipe' + +describe('Pipe used for Name Space', () => { + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [SpaceNamePipe] + }); + }); + + it('Replace first underscore with space', async(() => { + // given + let fixture = new SpaceNamePipe(); + // when + let spaceNameTansformed = fixture.transform('a_test_with_space'); + // then + expect(spaceNameTansformed).toEqual('a test with space'); + })); + + it('Do not fail with undefined/nil value', async(() => { + // given + let fixture = new SpaceNamePipe(); + // when + let spaceNameTansformed = fixture.transform(undefined); + // then + expect(spaceNameTansformed).toEqual(undefined); + })); +}); diff --git a/src/app/spaces/space.service.spec.ts b/src/app/spaces/space.service.spec.ts index 79fab06..79e6c25 100644 --- a/src/app/spaces/space.service.spec.ts +++ b/src/app/spaces/space.service.spec.ts @@ -16,8 +16,10 @@ describe('Service: SpaceService', () => { let spaceService: SpaceService; let mockService: MockBackend; let fakeAuthService: any; + let mockLog: any; beforeEach(() => { + mockLog = jasmine.createSpyObj('Logger', ['error']); fakeAuthService = { getToken: function () { return ''; @@ -28,7 +30,9 @@ describe('Service: SpaceService', () => { }; TestBed.configureTestingModule({ providers: [ - Logger, + { + provide: Logger, useValue: mockLog + }, BaseRequestOptions, MockBackend, { @@ -93,6 +97,11 @@ describe('Service: SpaceService', () => { related: 'http://example.com/api/spaces/1/iterations' } }, + collaborators: { + links: { + related: 'http://example.com/api/spaces/1/iterations' + } + }, 'owned-by': { 'data': { 'id': '00000000-0000-0000-0000-000000000000', @@ -107,6 +116,7 @@ describe('Service: SpaceService', () => { it('Get spaces', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -115,8 +125,9 @@ describe('Service: SpaceService', () => { }) )); }); - + // when spaceService.getSpaces().subscribe((data: Space[]) => { + // then expect(data[0].id).toEqual(expectedResponse[0].id); expect(data[0].attributes.name).toEqual(expectedResponse[0].attributes.name); expect(data[0].attributes.description).toEqual(expectedResponse[0].attributes.description); @@ -124,6 +135,7 @@ describe('Service: SpaceService', () => { })); it('Add new space', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -132,19 +144,34 @@ describe('Service: SpaceService', () => { }) )); }); - + // when spaceService.create(responseData[0]) .subscribe((data: Space) => { + // then expect(data.id).toEqual(expectedResponse[0].id); expect(data.attributes.name).toEqual(expectedResponse[0].attributes.name); expect(data.attributes.description).toEqual(expectedResponse[0].attributes.description); }); })); + it('Add new space in error', async(() => { + // given + mockLog.error.and.returnValue(); + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when + spaceService.create(responseData[0]) + .subscribe((data: Space) => { + fail('Add new space should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Update a space', async(() => { + // given let updatedData: Space = cloneDeep(responseData[0]); updatedData.attributes.description = 'Updated description'; - mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -153,16 +180,33 @@ describe('Service: SpaceService', () => { }) )); }); - + // when spaceService.update(updatedData) .subscribe((data: Space) => { + // then expect(data.id).toEqual(updatedData.id); expect(data.attributes.name).toEqual(updatedData.attributes.name); expect(data.attributes.description).toEqual(updatedData.attributes.description); }); })); + it('Update a space in error', async(() => { + // given + let updatedData: Space = cloneDeep(responseData[0]); + mockLog.error.and.returnValue(); + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when + spaceService.update(updatedData) + .subscribe((data: Space) => { + fail('Update a space should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Get a single space', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -171,17 +215,32 @@ describe('Service: SpaceService', () => { }) )); }); - let userName = "testuser"; - + // when spaceService.getSpaceByName(userName,responseData[0].attributes.name) .subscribe((data: Space) => { + // then expect(data.id).toEqual(expectedResponse[0].id); expect(data.attributes.name).toEqual(expectedResponse[0].attributes.name); expect(data.attributes.description).toEqual(expectedResponse[0].attributes.description); }); })); + it('Get a single space in error', async(() => { + // given + mockLog.error.and.returnValue(); + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + let userName = "testuser"; + // when + spaceService.getSpaceByName(userName,responseData[0].attributes.name) + .subscribe((data: Space) => { + fail('Get a single space should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Search a space by name', async(() => { let matchedData: Space[] = cloneDeep(responseData); @@ -202,6 +261,21 @@ describe('Service: SpaceService', () => { }); })); + it('Search a space by name in error', async(() => { + // given + let matchedData: Space[] = cloneDeep(responseData); + mockLog.error.and.returnValue(); + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + // when + spaceService.search("test") + .subscribe((data: Space[]) => { + fail('Search a space by name should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Get spaces by userName', async(() => { mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( @@ -221,7 +295,23 @@ describe('Service: SpaceService', () => { }); })); + it('Get spaces by userName in error', async(() => { + // given + let matchedData: Space[] = cloneDeep(responseData); + mockLog.error.and.returnValue(); + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + let userName = 'testUser'; + // when + spaceService.getSpacesByUser(userName).subscribe((data: Space[]) => { + fail('Get spaces by userName should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + it('Get a single space by Id', async(() => { + // given mockService.connections.subscribe((connection: any) => { connection.mockRespond(new Response( new ResponseOptions({ @@ -230,15 +320,29 @@ describe('Service: SpaceService', () => { }) )); }); - let spaceId = '1'; - + // when spaceService.getSpaceById(spaceId) .subscribe((data: Space) => { + // then expect(data.id).toEqual(expectedResponse[0].id); expect(data.attributes.name).toEqual(expectedResponse[0].attributes.name); expect(data.attributes.description).toEqual(expectedResponse[0].attributes.description); }); })); + it('Get a single space by Id in error', async(() => { + // given + mockService.connections.subscribe((connection: any) => { + connection.mockError(new Error('some error')); + }); + let spaceId = '1'; + // when + spaceService.getSpaceById(spaceId) + .subscribe((data: Space) => { + fail('Get a single space by Id should be in error'); + }, // then + error => expect(error).toEqual('some error')); + })); + }); diff --git a/src/app/spaces/unique-space-name.directive.spec.ts b/src/app/spaces/unique-space-name.directive.spec.ts new file mode 100644 index 0000000..260a7cf --- /dev/null +++ b/src/app/spaces/unique-space-name.directive.spec.ts @@ -0,0 +1,118 @@ +import { async, TestBed } from '@angular/core/testing'; +import { UniqueSpaceNameValidatorDirective } from './unique-space-name.directive' +import { FormsModule, NgForm } from '@angular/forms'; +import { Component } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { SpaceService } from './space.service'; +import { UserService } from 'ngx-login-client'; +import { Space } from '../models/space' +import { Observable, ConnectableObservable } from 'rxjs'; + +@Component({ + template: ` +
+ +
+ ` +}) +class TestSpaceNameComponent { + spaceName: string; +} + +describe('Directive for Name Space', () => { + let spaceServiceSpy: any; + let userServiceSpy: any; + let space: Space; + + beforeEach(() => { + spaceServiceSpy = jasmine.createSpyObj('SpaceService', ['getSpaceByName']); + userServiceSpy = jasmine.createSpy('UserService'); + space = { + name: 'TestSpace', + path: 'testspace', + teams: [], + defaultTeam: null, + 'attributes': { + 'name': 'TestSpace', + description: 'This is a space for unit test', + 'created-at': null, + 'updated-at': null, + 'version': 0 + }, + 'id': '1', + 'type': 'spaces', + 'links': { + 'self': 'http://example.com/api/spaces/1' + }, + 'relationships': { + areas: { + links: { + related: 'http://example.com/api/spaces/1/areas' + } + }, + iterations: { + links: { + related: 'http://example.com/api/spaces/1/iterations' + } + }, + collaborators: { + links: { + related: 'http://example.com/api/spaces/1/iterations' + } + }, + 'owned-by': { + 'data': { + 'id': '00000000-0000-0000-0000-000000000000', + 'type': 'identities' + } + } + } + }; + TestBed.configureTestingModule({ + imports: [FormsModule], + declarations: [TestSpaceNameComponent, UniqueSpaceNameValidatorDirective], + providers:[{provide: SpaceService, useValue: spaceServiceSpy}, {provide: UserService, useValue: userServiceSpy}] + }); + }); + + it('Validate false when 2 spaces exist with same name', async(() => { + // given + let user = { + "attributes": { + "fullName": "name", + "imageURL": "", + "username": "myUser" + }, + "id": "userId", + "type": "userType" + }; + let fixture = TestBed.createComponent(TestSpaceNameComponent); + userServiceSpy.loggedInUser = ConnectableObservable.of(user); + spaceServiceSpy.getSpaceByName.and.returnValue(Observable.of(space)); + + + let comp = fixture.componentInstance; + let debug = fixture.debugElement; + let input = debug.query(By.css('input')); + input.nativeElement.value = 'start' + input.nativeElement.dispatchEvent( new Event('input')); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + // when + input.nativeElement.value = 'TestSpace'; + input.nativeElement.dispatchEvent( new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + let form: NgForm = debug.children[0].injector.get(NgForm); + let control = form.control.get('spaceName'); + // then + expect(control.hasError('unique')).toBe(true); + expect(control.errors.unique.valid).toBeFalsy(); + expect(control.errors.unique.existingSpace.name).toEqual('TestSpace'); + }); + }); + })); +}); + + diff --git a/src/app/spaces/valid-space-name.directive.spec.ts b/src/app/spaces/valid-space-name.directive.spec.ts index ae16083..4ffae7c 100644 --- a/src/app/spaces/valid-space-name.directive.spec.ts +++ b/src/app/spaces/valid-space-name.directive.spec.ts @@ -73,4 +73,56 @@ describe('Directive for Name Space', () => { }); })); + it('Validate false when there is not enough characters', async(() => { + // given + let fixture = TestBed.createComponent(TestSpaceNameComponent); + let comp = fixture.componentInstance; + let debug = fixture.debugElement; + let input = debug.query(By.css('input')); + input.nativeElement.value = 'start'; + input.nativeElement.dispatchEvent( new Event('input')); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + // when + input.nativeElement.value = 'sta'; + input.nativeElement.dispatchEvent( new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + let form: NgForm = debug.children[0].injector.get(NgForm); + let control = form.control.get('spaceName'); + // then + expect(control.hasError('minLength')).toBe(true); + expect(control.errors.minLength.valid).toBeFalsy(); + }); + }); + })); + + it('Validate false when there is too many characters', async(() => { + // given + let fixture = TestBed.createComponent(TestSpaceNameComponent); + let comp = fixture.componentInstance; + let debug = fixture.debugElement; + let input = debug.query(By.css('input')); + input.nativeElement.value = 'start'; + input.nativeElement.dispatchEvent( new Event('input')); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + // when + input.nativeElement.value = 's1234567890123456789012345678901234567890123456789012345678901234567890'; + input.nativeElement.dispatchEvent( new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + let form: NgForm = debug.children[0].injector.get(NgForm); + let control = form.control.get('spaceName'); + // then + expect(control.hasError('maxLength')).toBe(true); + expect(control.errors.maxLength.valid).toBeFalsy(); + }); + }); + })); + }); + +