From 876dba289232e99d394864ebbdb2a0282d6cce33 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 10 May 2018 17:24:09 +0200 Subject: [PATCH] Added tests --- src/app/shared/chips/chips.component.spec.ts | 79 ++++++++ src/app/shared/form/form.actions.ts | 7 +- src/app/shared/form/form.component.spec.ts | 64 ++++--- src/app/shared/form/form.reducer.spec.ts | 174 ++++++++++++++++++ src/app/shared/form/form.reducers.ts | 6 +- src/app/shared/form/form.service.spec.ts | 73 ++++++++ src/app/shared/form/form.service.ts | 2 +- .../uploader/uploader.component.spec.ts | 91 +++++++++ 8 files changed, 457 insertions(+), 39 deletions(-) create mode 100644 src/app/shared/chips/chips.component.spec.ts create mode 100644 src/app/shared/form/form.reducer.spec.ts create mode 100644 src/app/shared/form/form.service.spec.ts create mode 100644 src/app/shared/uploader/uploader.component.spec.ts diff --git a/src/app/shared/chips/chips.component.spec.ts b/src/app/shared/chips/chips.component.spec.ts new file mode 100644 index 0000000000..add22b5d42 --- /dev/null +++ b/src/app/shared/chips/chips.component.spec.ts @@ -0,0 +1,79 @@ +// Load the implementations that should be tested +import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing'; +import 'rxjs/add/observable/of'; + +import { Chips } from './models/chips.model'; +import { UploaderService } from '../uploader/uploader.service'; +import { ChipsComponent } from './chips.component'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { SortablejsModule } from 'angular-sortablejs'; + +function createTestComponent(html: string, type: { new(...args: any[]): T }): ComponentFixture { + TestBed.overrideComponent(type, { + set: {template: html} + }); + const fixture = TestBed.createComponent(type); + + fixture.detectChanges(); + return fixture as ComponentFixture; +} + +describe('Chips component', () => { + + let testComp: TestComponent; + let testFixture: ComponentFixture; + let html; + + // async beforeEach + beforeEach(async(() => { + + TestBed.configureTestingModule({ + imports: [ + NgbModule.forRoot(), + SortablejsModule.forRoot({ animation: 150 }), + ], + declarations: [ + ChipsComponent, + TestComponent, + ], // declare the test component + providers: [ + ChangeDetectorRef, + ChipsComponent, + UploaderService + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); + + })); + + // synchronous beforeEach + beforeEach(() => { + html = ` + `; + + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + it('should create Chips Component', inject([ChipsComponent], (app: ChipsComponent) => { + + expect(app).toBeDefined(); + })); + +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + + public chips = new Chips([]); + +} diff --git a/src/app/shared/form/form.actions.ts b/src/app/shared/form/form.actions.ts index 681add077e..b1d5f2b3e3 100644 --- a/src/app/shared/form/form.actions.ts +++ b/src/app/shared/form/form.actions.ts @@ -15,9 +15,9 @@ export const FormActionTypes = { FORM_CHANGE: type('dspace/form/FORM_CHANGE'), FORM_REMOVE: type('dspace/form/FORM_REMOVE'), FORM_STATUS_CHANGE: type('dspace/form/FORM_STATUS_CHANGE'), - FORM_ADD_ERROR: type('dspace/form/ADD_ERROR'), - FORM_REMOVE_ERROR: type('dspace/form/REMOVE_ERROR'), - CLEAR_ERRORS: type('dspace/form/CLEAR_ERRORS'), + FORM_ADD_ERROR: type('dspace/form/FORM_ADD_ERROR'), + FORM_REMOVE_ERROR: type('dspace/form/FORM_REMOVE_ERROR'), + FORM_CLEAR_ERRORS: type('dspace/form/FORM_CLEAR_ERRORS'), }; /* tslint:disable:max-classes-per-file */ @@ -122,5 +122,6 @@ export class FormAddError implements Action { */ export type FormAction = FormInitAction | FormChangeAction + | FormRemoveAction | FormStatusChangeAction | FormAddError diff --git a/src/app/shared/form/form.component.spec.ts b/src/app/shared/form/form.component.spec.ts index a0489a5ab8..efc6383603 100644 --- a/src/app/shared/form/form.component.spec.ts +++ b/src/app/shared/form/form.component.spec.ts @@ -1,40 +1,25 @@ // Load the implementations that should be tested +import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing'; import { CommonModule } from '@angular/common'; +import { BrowserModule } from '@angular/platform-browser'; +import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { - Component, - CUSTOM_ELEMENTS_SCHEMA, - DebugElement -} from '@angular/core'; - -import { - async, - ComponentFixture, - inject, - TestBed, -} from '@angular/core/testing'; - -import { StoreModule } from '@ngrx/store'; - +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/observable/of'; +import { DynamicFormControlModel, DynamicFormValidationService, DynamicInputModel } from '@ng-dynamic-forms/core'; +import { Store } from '@ngrx/store'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; - -import Spy = jasmine.Spy; +import { TranslateModule } from '@ngx-translate/core'; import { FormComponent } from './form.component'; import { FormService } from './form.service'; -import { DynamicFormControlModel, DynamicFormValidationService, DynamicInputModel } from '@ng-dynamic-forms/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormBuilderService } from './builder/form-builder.service'; -import { SubmissionFormsConfigService } from '../../core/config/submission-forms-config.service'; -import { ResponseCacheService } from '../../core/cache/response-cache.service'; -import { RequestService } from '../../core/data/request.service'; -import { ObjectCacheService } from '../../core/cache/object-cache.service'; -import { Observable } from 'rxjs/Observable'; +import { FormState } from './form.reducers'; function createTestComponent(html: string, type: { new(...args: any[]): T }): ComponentFixture { TestBed.overrideComponent(type, { - set: { template: html } + set: {template: html} }); const fixture = TestBed.createComponent(type); @@ -110,7 +95,14 @@ describe('Form component', () => { const formBuilderServiceStub = { createFormGroup: (formModel) => new FormGroup(TEST_FORM_GROUP) } - const submissionFormsConfigServiceStub = { } + const submissionFormsConfigServiceStub = {}; + + const store: Store = jasmine.createSpyObj('store', { + /* tslint:disable:no-empty */ + dispatch: {}, + /* tslint:enable:no-empty */ + select: Observable.of({}) + }); // async beforeEach beforeEach(async(() => { @@ -121,17 +113,22 @@ describe('Form component', () => { CommonModule, FormsModule, ReactiveFormsModule, - StoreModule.forRoot({}), NgbModule.forRoot(), + TranslateModule.forRoot() ], declarations: [ FormComponent, TestComponent, ], // declare the test component providers: [ + ChangeDetectorRef, + DynamicFormValidationService, + FormBuilderService, FormComponent, - { provide: FormService, useValue: formServiceStub }, - { provide: FormBuilderService, useValue: formBuilderServiceStub }, + FormService, + { + provide: Store, useValue: store + } ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); @@ -141,17 +138,17 @@ describe('Form component', () => { // synchronous beforeEach beforeEach(() => { html = ` - `; + [displaySubmit]="displaySubmit">`; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; - }); it('should create Form Component', inject([FormComponent], (app: FormComponent) => { + expect(app).toBeDefined(); })); @@ -166,6 +163,7 @@ class TestComponent { public formId; public formModel: DynamicFormControlModel[]; + public displaySubmit = false; constructor() { this.formId = 'testForm'; diff --git a/src/app/shared/form/form.reducer.spec.ts b/src/app/shared/form/form.reducer.spec.ts new file mode 100644 index 0000000000..64141a15b6 --- /dev/null +++ b/src/app/shared/form/form.reducer.spec.ts @@ -0,0 +1,174 @@ +import { formReducer } from './form.reducers'; +import { + FormAddError, + FormChangeAction, + FormInitAction, + FormRemoveAction, + FormStatusChangeAction +} from './form.actions'; + +describe('formReducer', () => { + + it('should set init state of the form', () => { + const state = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': null, + 'dc.date.issued': null, + 'dc.description': null + }, + valid: false, + errors: [] + } + }; + const formId = 'testForm'; + const formData = { + 'dc.contributor.author': null, + 'dc.title': null, + 'dc.date.issued': null, + 'dc.description': null + }; + const valid = false; + const action = new FormInitAction(formId, formData, valid); + const newState = formReducer({}, action); + + expect(newState).toEqual(state); + }); + + it('should change form data on form change', () => { + const initState = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': null, + 'dc.date.issued': null, + 'dc.description': null + }, + valid: false, + errors: [] + } + }; + const state = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }, + valid: false, + errors: [] + } + }; + const formId = 'testForm'; + const formData = { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }; + + const action = new FormChangeAction(formId, formData); + const newState = formReducer(initState, action); + + expect(newState).toEqual(state); + }); + + it('should change form status on form status change', () => { + const initState = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }, + valid: false, + errors: [] + } + }; + const state = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }, + valid: true, + errors: [] + } + }; + const formId = 'testForm'; + + const action = new FormStatusChangeAction(formId, true); + const newState = formReducer(initState, action); + + expect(newState).toEqual(state); + }); + + it('should add error to form state', () => { + const initState = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }, + valid: true, + errors: [] + } + }; + + const state = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }, + valid: true, + errors: [ + { + fieldId: 'dc.title', + message: 'Not valid' + } + ] + } + }; + + const formId = 'testForm'; + const fieldId = 'dc.title'; + const message = 'Not valid'; + + const action = new FormAddError(formId, fieldId, message); + const newState = formReducer(initState, action); + + expect(newState).toEqual(state); + }); + + it('should remove form state', () => { + const initState = { + testForm: { + data: { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }, + valid: true, + errors: [] + } + }; + + const formId = 'testForm'; + + const action = new FormRemoveAction(formId); + const newState = formReducer(initState, action); + + expect(newState).toEqual({}); + }); +}); diff --git a/src/app/shared/form/form.reducers.ts b/src/app/shared/form/form.reducers.ts index 04d7d28d85..d06db331eb 100644 --- a/src/app/shared/form/form.reducers.ts +++ b/src/app/shared/form/form.reducers.ts @@ -86,14 +86,16 @@ function initForm(state: FormState, action: FormInitAction): FormState { return Object.assign({}, state, { [ action.payload.formId ]: { data: action.payload.formData, - valid: action.payload.valid + valid: action.payload.valid, + errors: [] } }); } else { const newState = Object.assign({}, state); newState[ action.payload.formId ] = Object.assign({}, newState[ action.payload.formId ], { data: action.payload.formData, - valid: action.payload.valid + valid: action.payload.valid, + errors: [] } ); return newState; diff --git a/src/app/shared/form/form.service.spec.ts b/src/app/shared/form/form.service.spec.ts new file mode 100644 index 0000000000..b72bbbd0d6 --- /dev/null +++ b/src/app/shared/form/form.service.spec.ts @@ -0,0 +1,73 @@ +import { Store, StoreModule } from '@ngrx/store'; +import { async, inject, TestBed } from '@angular/core/testing'; +import 'rxjs/add/observable/of'; +import { FormService } from './form.service'; +import { FormBuilderService } from './builder/form-builder.service'; +import { AppState } from '../../app.reducer'; +import { DynamicPathable } from '@ng-dynamic-forms/core/src/model/misc/dynamic-form-control-path.model'; +import { DynamicFormControlModel } from '@ng-dynamic-forms/core'; +import { formReducer } from './form.reducers'; + +describe('FormService', () => { + const formId = 'testForm'; + let service: FormService; + const formData = { + 'dc.contributor.author': null, + 'dc.title': ['test'], + 'dc.date.issued': null, + 'dc.description': null + }; + const formState = { + testForm: { + data: formData, + valid: true, + errors: [] + } + }; + + const formBuilderServiceStub: any = { + getPath: (model: DynamicPathable) => [], + /* tslint:disable:no-empty */ + clearAllModelsValue: (groupModel: DynamicFormControlModel[]) => { + } + /* tslint:enable:no-empty */ + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({formReducer}) + ], + providers: [ + {provide: FormBuilderService, useValue: formBuilderServiceStub}, + ] + }).compileComponents(); + })); + + beforeEach(inject([Store], (store: Store) => { + store + .subscribe((state) => { + state.forms = formState; + }); + service = new FormService(formBuilderServiceStub, store); + })); + + it('should check whether form state is init', () => { + service.isFormInitialized(formId).subscribe((init) => { + expect(init).toBe(true); + }); + }); + + it('should return form status when isValid is called', () => { + service.isValid(formId).subscribe((status) => { + expect(status).toBe(true); + }); + }); + + it('should return form data when getFormData is called', () => { + service.getFormData(formId).subscribe((data) => { + expect(data).toBe(formData); + }); + }); + +}); diff --git a/src/app/shared/form/form.service.ts b/src/app/shared/form/form.service.ts index 9d7b18acbc..2adef27179 100644 --- a/src/app/shared/form/form.service.ts +++ b/src/app/shared/form/form.service.ts @@ -31,7 +31,7 @@ export class FormService { /** * Method to retrieve form's data from state */ - public getFormData(formId: string): Observable { + public getFormData(formId: string): Observable { return this.store.select(formObjectFromIdSelector(formId)) .filter((state) => isNotUndefined(state)) .map((state) => state.data) diff --git a/src/app/shared/uploader/uploader.component.spec.ts b/src/app/shared/uploader/uploader.component.spec.ts new file mode 100644 index 0000000000..f1e12e7693 --- /dev/null +++ b/src/app/shared/uploader/uploader.component.spec.ts @@ -0,0 +1,91 @@ +// Load the implementations that should be tested +import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, inject, TestBed, } from '@angular/core/testing'; + +import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; + +import { UploaderService } from './uploader.service'; +import { UploaderOptions } from './uploader-options.model'; +import { UploaderComponent } from './uploader.component'; +import { FileUploadModule } from 'ng2-file-upload'; +import { TranslateModule } from '@ngx-translate/core'; + +function createTestComponent(html: string, type: { new(...args: any[]): T }): ComponentFixture { + TestBed.overrideComponent(type, { + set: {template: html} + }); + const fixture = TestBed.createComponent(type); + + fixture.detectChanges(); + return fixture as ComponentFixture; +} + +describe('Chips component', () => { + + let testComp: TestComponent; + let testFixture: ComponentFixture; + let html; + + // async beforeEach + beforeEach(async(() => { + + TestBed.configureTestingModule({ + imports: [ + FileUploadModule, + TranslateModule.forRoot() + ], + declarations: [ + UploaderComponent, + TestComponent, + ], // declare the test component + providers: [ + ChangeDetectorRef, + ScrollToService, + UploaderComponent, + UploaderService + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); + + })); + + // synchronous beforeEach + beforeEach(() => { + html = ` + `; + + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + it('should create Uploader Component', inject([UploaderComponent], (app: UploaderComponent) => { + + expect(app).toBeDefined(); + })); + +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + public uploadFilesOptions: UploaderOptions = { + url: 'http://test', + authToken: null, + disableMultipart: false, + itemAlias: null + }; + + /* tslint:disable:no-empty */ + public onBeforeUpload = () => { + }; + + onCompleteItem(event) { + } + + /* tslint:enable:no-empty */ +}