Skip to content

Commit

Permalink
TSK-1349: Workbasket access items unit tests (#1246)
Browse files Browse the repository at this point in the history
* TSK-1349: remove html coverage to optimize test speed

* TSK-1349: init workbasket access items testing env

* TSK-1349: update workbasket access items unit tests
  • Loading branch information
cnguyen-de committed Sep 2, 2020
1 parent 827703a commit 88b8486
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 20 deletions.
3 changes: 2 additions & 1 deletion web/jest.config.js
Expand Up @@ -9,7 +9,8 @@ module.exports = {
testMatch: ['**/+(*.)+(spec).+(ts)'],
setupFilesAfterEnv: ['<rootDir>/src/test.ts'],
collectCoverage: true,
coverageReporters: ['html', 'text'],
coverageReporters: ['text'],
// coverageReporters: ['html', 'text'],
coverageDirectory: 'coverage/taskana-web',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
prefix: '<rootDir>/'
Expand Down
Expand Up @@ -6,7 +6,7 @@
<button type="button" (click)="onSubmit()" [disabled]="action === 'COPY'" data-toggle="tooltip" title="Save" class="btn btn-default btn-primary">
<span class="material-icons md-20">save</span>
</button>
<button type="button" (click)="clear()" data-toggle="tooltip" title="Undo Changes" class="btn btn-default">
<button type="button" (click)="clear()" data-toggle="tooltip" title="Undo Changes" class="btn btn-default undo-button">
<span class="material-icons md-20 blue">undo</span>
</button>
</div>
Expand Down Expand Up @@ -115,7 +115,7 @@ <h4 class="panel-header">{{workbasket.name}}
</form>

<!-- ADD ACCESS ITEM -->
<button type="button" (click)="addAccessItem()" data-toggle="tooltip" title="Add new access" class="btn btn-default">
<button type="button" (click)="addAccessItem()" data-toggle="tooltip" title="Add new access" class="btn btn-default add-access-item">
<span class="material-icons md-20 green-blue">add</span>
<span>Add new access</span>
</button>
Expand Down
@@ -0,0 +1,197 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { WorkbasketAccessItemsComponent } from './workbasket-access-items.component';
import { Component, DebugElement, Input } from '@angular/core';
import { Actions, NgxsModule, ofActionDispatched, Store } from '@ngxs/store';
import { Observable, of } from 'rxjs';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TypeAheadComponent } from '../../../shared/components/type-ahead/type-ahead.component';
import { TypeaheadModule } from 'ngx-bootstrap';
import { SavingWorkbasketService } from '../../services/saving-workbaskets.service';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
import { FormsValidatorService } from '../../../shared/services/forms-validator/forms-validator.service';
import { NotificationService } from '../../../shared/services/notifications/notification.service';
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
import { EngineConfigurationState } from '../../../shared/store/engine-configuration-store/engine-configuration.state';
import { ClassificationCategoriesService } from '../../../shared/services/classification-categories/classification-categories.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
import { DomainService } from '../../../shared/services/domain/domain.service';
import { RouterTestingModule } from '@angular/router/testing';
import { SelectedRouteService } from '../../../shared/services/selected-route/selected-route';
import { StartupService } from '../../../shared/services/startup/startup.service';
import { TaskanaEngineService } from '../../../shared/services/taskana-engine/taskana-engine.service';
import { WindowRefService } from '../../../shared/services/window/window.service';
import {
workbasketAccessItemsMock,
engineConfigurationMock,
selectedWorkbasketMock
} from '../../../shared/store/mock-data/mock-store';
import {
GetWorkbasketAccessItems,
UpdateWorkbasketAccessItems
} from '../../../shared/store/workbasket-store/workbasket.actions';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ACTION } from '../../../shared/models/action';
import { WorkbasketAccessItems } from '../../../shared/models/workbasket-access-items';

@Component({ selector: 'taskana-shared-spinner', template: '' })
class SpinnerStub {
@Input() isRunning: boolean;
@Input() positionClass: string;
}

const savingWorkbasketServiceSpy = jest.fn().mockImplementation(
(): Partial<SavingWorkbasketService> => ({
triggeredAccessItemsSaving: jest.fn().mockReturnValue(of(true))
})
);

const requestInProgressServiceSpy = jest.fn().mockImplementation(
(): Partial<RequestInProgressService> => ({
setRequestInProgress: jest.fn()
})
);

const showDialogFn = jest.fn().mockReturnValue(true);
const notificationServiceSpy = jest.fn().mockImplementation(
(): Partial<NotificationService> => ({
triggerError: showDialogFn,
showToast: showDialogFn
})
);

const validateFormInformationFn = jest.fn().mockImplementation((): Promise<any> => Promise.resolve(true));
const formValidatorServiceSpy = jest.fn().mockImplementation(
(): Partial<FormsValidatorService> => ({
isFieldValid: jest.fn().mockReturnValue(true),
validateInputOverflow: jest.fn(),
validateFormInformation: validateFormInformationFn,
get inputOverflowObservable(): Observable<Map<string, boolean>> {
return of(new Map<string, boolean>());
}
})
);

describe('WorkbasketAccessItemsComponent', () => {
let fixture: ComponentFixture<WorkbasketAccessItemsComponent>;
let debugElement: DebugElement;
let component: WorkbasketAccessItemsComponent;
let store: Store;
let actions$: Observable<any>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
FormsModule,
ReactiveFormsModule,
TypeaheadModule.forRoot(),
NgxsModule.forRoot([WorkbasketState, EngineConfigurationState]),
HttpClientTestingModule,
RouterTestingModule.withRoutes([]),
BrowserAnimationsModule
],
declarations: [WorkbasketAccessItemsComponent, TypeAheadComponent, SpinnerStub],
providers: [
{ provide: SavingWorkbasketService, useClass: savingWorkbasketServiceSpy },
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy },
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
{ provide: NotificationService, useClass: notificationServiceSpy },
ClassificationCategoriesService,
WorkbasketService,
DomainService,
SelectedRouteService,
StartupService,
TaskanaEngineService,
WindowRefService
]
}).compileComponents();

fixture = TestBed.createComponent(WorkbasketAccessItemsComponent);
debugElement = fixture.debugElement;
component = fixture.componentInstance;
store = TestBed.inject(Store);
actions$ = TestBed.inject(Actions);
component.workbasket = { ...selectedWorkbasketMock };
component.accessItemsRepresentation = workbasketAccessItemsMock;
store.reset({
...store.snapshot(),
engineConfiguration: engineConfigurationMock,
workbasket: {
workbasketAccessItems: workbasketAccessItemsMock
}
});
fixture.detectChanges();
}));

afterEach(async(() => {
component.workbasket = { ...selectedWorkbasketMock };
}));

it('should create component', () => {
expect(component).toBeTruthy();
});

it('should initialize when accessItems exist', async(() => {
component.action = ACTION.COPY;
let actionDispatched = false;
component.onSave = jest.fn().mockImplementation();
actions$.pipe(ofActionDispatched(GetWorkbasketAccessItems)).subscribe(() => (actionDispatched = true));
component.init();
expect(component.initialized).toBe(true);
expect(actionDispatched).toBe(true);
expect(component.onSave).toHaveBeenCalled();
}));

it("should discard initializing when accessItems don't exist", () => {
component.workbasket._links.accessItems = null;
component.init();
expect(component.initialized).toBe(false);
});

it('should add accessItems when add access item button is clicked', () => {
const addAccessItemButton = debugElement.nativeElement.querySelector('button.add-access-item');
const clearSpy = jest.spyOn(component, 'addAccessItem');
expect(addAccessItemButton.title).toMatch('Add new access');

addAccessItemButton.click();
expect(clearSpy).toHaveBeenCalled();
});

it('should undo changes when undo button is clicked', () => {
const undoButton = debugElement.nativeElement.querySelector('button.undo-button');
const clearSpy = jest.spyOn(component, 'clear');
expect(undoButton.title).toMatch('Undo Changes');

undoButton.click();
expect(clearSpy).toHaveBeenCalled();
});

it('should check all permissions when check all box is checked', () => {
const checkAllSpy = jest.spyOn(component, 'checkAll');
const checkAllButton = debugElement.nativeElement.querySelector('#checkbox-0-00');
expect(checkAllButton).toBeTruthy();

checkAllButton.click();
expect(checkAllSpy).toHaveBeenCalled();
});

it('should dispatch UpdateWorkbasketAccessItems action when save button is triggered', () => {
component.accessItemsRepresentation._links.self.href = 'https://link.mock';
const onSaveSpy = jest.spyOn(component, 'onSave');
let actionDispatched = false;
actions$.pipe(ofActionDispatched(UpdateWorkbasketAccessItems)).subscribe(() => (actionDispatched = true));
component.onSave();
expect(onSaveSpy).toHaveBeenCalled();
expect(actionDispatched).toBe(true);
});

it('should set badge correctly', () => {
component.action = ACTION.READ;
component.setBadge();
expect(component.badgeMessage).toMatch('');

component.action = ACTION.COPY;
component.setBadge();
expect(component.badgeMessage).toMatch(`Copying workbasket: ${component.workbasket.key}`);
});
});
Expand Up @@ -78,7 +78,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
accessItemsRepresentation$: Observable<WorkbasketAccessItemsRepresentation>;

constructor(
private workbasketService: WorkbasketService,
private savingWorkbaskets: SavingWorkbasketService,
private requestInProgressService: RequestInProgressService,
private formBuilder: FormBuilder,
Expand Down Expand Up @@ -111,7 +110,7 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
});
}

ngOnChanges(changes: SimpleChanges) {
ngOnChanges(changes?: SimpleChanges) {
if (!this.initialized && changes.active && changes.active.currentValue === 'accessItems') {
this.init();
}
Expand All @@ -125,7 +124,7 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
}
}

private init() {
init() {
if (!this.workbasket._links.accessItems) {
return;
}
Expand Down Expand Up @@ -243,7 +242,7 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
this.accessItemsGroups.controls[row].get('accessName').setValue(accessItem.name);
}

private onSave() {
onSave() {
this.requestInProgressService.setRequestInProgress(true);
this.store
.dispatch(
Expand All @@ -257,19 +256,19 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
});
}

private setBadge() {
setBadge() {
if (this.action === ACTION.COPY) {
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
}
}

private cloneAccessItems(inputaccessItem): Array<WorkbasketAccessItems> {
cloneAccessItems(inputaccessItem): Array<WorkbasketAccessItems> {
return this.AccessItemsForm.value.accessItemsGroups.map((accessItems: WorkbasketAccessItems) => ({
...accessItems
}));
}

private setWorkbasketIdForCopy(workbasketId: string) {
setWorkbasketIdForCopy(workbasketId: string) {
this.accessItemsGroups.value.forEach((element) => {
delete element.accessItemId;
element.workbasketId = workbasketId;
Expand Down
2 changes: 1 addition & 1 deletion web/src/app/shared/models/workbasket-access-items.ts
Expand Up @@ -23,7 +23,7 @@ export interface WorkbasketAccessItems {
permCustom10: boolean;
permCustom11: boolean;
permCustom12: boolean;
_links: Links;
_links?: Links;
}

export const customFieldCount: number = 12;

0 comments on commit 88b8486

Please sign in to comment.