Files
dspace-angular/src/app/shared/form/form.service.spec.ts
2023-04-11 16:18:20 +02:00

280 lines
8.3 KiB
TypeScript

import { Store, StoreModule } from '@ngrx/store';
import { inject, TestBed, waitForAsync } from '@angular/core/testing';
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { DynamicFormControlModel, DynamicFormGroupModel, DynamicInputModel } from '@ng-dynamic-forms/core';
import { FormService } from './form.service';
import { FormBuilderService } from './builder/form-builder.service';
import { AppState } from '../../app.reducer';
import { formReducer } from './form.reducer';
import { getMockFormBuilderService } from '../mocks/form-builder-service.mock';
describe('FormService test suite', () => {
const config = {
form: {
validatorMap: {
required: 'required',
regex: 'pattern'
}
}
} as any;
const formId = 'testForm';
let service: FormService;
let builderService: FormBuilderService;
let formGroup: UntypedFormGroup;
const formModel: DynamicFormControlModel[] = [
new DynamicInputModel({ id: 'author', value: 'test' }),
new DynamicInputModel({
id: 'title',
validators: {
required: null
},
errorMessages: {
required: 'Title is required'
}
}),
new DynamicInputModel({ id: 'date' }),
new DynamicInputModel({ id: 'description' }),
new DynamicFormGroupModel({
id: 'addressLocation',
group: [
new DynamicInputModel({
id: 'zipCode',
label: 'Zip Code',
placeholder: 'ZIP'
}),
new DynamicInputModel({
id: 'state',
label: 'State',
placeholder: 'State'
}),
new DynamicInputModel({
id: 'city',
label: 'City',
placeholder: 'City'
})
]
}),
];
let controls;
const formData = {
author: ['test'],
title: null,
date: null,
description: null,
addressLocation: {
zipCode: null,
state: null,
city: null
}
};
const formState = {
testForm: {
data: formData,
valid: false,
errors: [],
touched: {}
}
};
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({ formReducer }, {
runtimeChecks: {
strictStateImmutability: false,
strictActionImmutability: false
}
})
]
}).compileComponents();
}));
beforeEach(inject([Store], (store: Store<AppState>) => {
builderService = getMockFormBuilderService();
store
.subscribe((state) => {
state.forms = formState;
});
const author: AbstractControl = new UntypedFormControl('test');
const title: AbstractControl = new UntypedFormControl(undefined, Validators.required);
const date: AbstractControl = new UntypedFormControl(undefined);
const description: AbstractControl = new UntypedFormControl(undefined);
const addressLocation: UntypedFormGroup = new UntypedFormGroup({
zipCode: new UntypedFormControl(undefined),
state: new UntypedFormControl(undefined),
city: new UntypedFormControl(undefined),
});
formGroup = new UntypedFormGroup({ author, title, date, description, addressLocation });
controls = { author, title, date, description , addressLocation };
service = new FormService(builderService, 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(false);
});
});
it('should return form data when getFormData is called', () => {
service.getFormData(formId).subscribe((data) => {
expect(data).toBe(formData);
});
});
it('should return form unique id', () => {
const formId1 = service.getUniqueId(formId);
const formId2 = service.getUniqueId(formId);
expect(formId1).not.toEqual(formId2);
});
it('should validate all form fields', () => {
service.validateAllFormFields(formGroup);
expect(formGroup.controls.author.touched).toBe(true);
expect(formGroup.controls.author.status).toBe('VALID');
expect(formGroup.controls.title.touched).toBe(true);
expect(formGroup.controls.title.status).toBe('INVALID');
expect(formGroup.controls.date.touched).toBe(true);
expect(formGroup.controls.description.touched).toBe(true);
});
it('should add error to field', () => {
let control = controls.description;
let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'description');
let errorKeys: string[];
service.addErrorToField(control, model, 'Test error message');
errorKeys = Object.keys(control.errors);
expect(errorKeys.length).toBe(1);
expect(control.hasError(errorKeys[0])).toBe(true);
expect(formGroup.controls.description.touched).toBe(true);
control = controls.title;
model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'title');
service.addErrorToField(control, model, 'error.required');
errorKeys = Object.keys(control.errors);
expect(errorKeys.length).toBe(1);
expect(control.hasError(errorKeys[0])).toBe(true);
expect(formGroup.controls.description.touched).toBe(true);
});
it('should add errors to fields of concat group', () => {
(builderService as any).isConcatGroup.and.returnValue(true);
let control = controls.addressLocation;
let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'addressLocation');
let errorKeys: string[];
service.addErrorToField(control, model, 'Test error message');
// the group itself should get an error
errorKeys = Object.keys(control.errors);
expect(errorKeys.length).toBe(1);
expect(control.hasError(errorKeys[0])).toBe(true);
expect(control.touched).toBe(true);
// the group's inputs should get an error
Object.values(control.controls).forEach((subControl: AbstractControl) => {
errorKeys = Object.keys(subControl.errors);
expect(errorKeys.length).toBe(1);
expect(subControl.hasError(errorKeys[0])).toBe(true);
expect(subControl.touched).toBe(true);
});
});
it('should remove error from field', () => {
let control = controls.description;
let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'description');
let errorKeys: string[];
service.addErrorToField(control, model, 'Test error message');
errorKeys = Object.keys(control.errors);
service.removeErrorFromField(control, model, errorKeys[0]);
expect(errorKeys.length).toBe(1);
expect(control.hasError(errorKeys[0])).toBe(false);
expect(formGroup.controls.description.touched).toBe(false);
control = controls.title;
model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'title');
service.addErrorToField(control, model, 'error.required');
service.removeErrorFromField(control, model, 'error.required');
expect(errorKeys.length).toBe(1);
expect(control.hasError(errorKeys[0])).toBe(false);
expect(formGroup.controls.description.touched).toBe(false);
});
it('should remove errors from fields of concat group', () => {
(builderService as any).isConcatGroup.and.returnValue(true);
let control = controls.addressLocation;
let model = formModel.find((mdl: DynamicFormControlModel) => mdl.id === 'addressLocation');
let errorKeys: string[];
service.addErrorToField(control, model, 'Test error message');
errorKeys = Object.keys(control.errors);
service.removeErrorFromField(control, model, errorKeys[0]);
// the group itself should no longer have an error
expect(errorKeys.length).toBe(1);
expect(control.hasError(errorKeys[0])).toBe(false);
expect(control.touched).toBe(false);
// the group's inputs should no longer have an error
Object.values(control.controls).forEach((subControl: AbstractControl) => {
errorKeys = Object.keys(subControl.errors);
expect(errorKeys.length).toBe(1);
expect(subControl.hasError(errorKeys[0])).toBe(false);
expect(subControl.touched).toBe(false);
});
});
it('should reset form group', () => {
const control = controls.author;
service.resetForm(formGroup, formModel, formId);
expect(control.value).toBeNull();
});
})
;