import { Component, DebugElement, NgModule } from '@angular/core';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { AbstractControl, FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatNativeDateModule } from '@angular/material/core';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { PtDynamicElementComponent } from './dynamic-element.component';
import { PtDynamicFormsComponent } from './dynamic-forms.component';
import { DynamicFormsModule } from './dynamic-forms.module';
import { IPtDynamicElementConfig, PtDynamicElement, PtDynamicType } from './services/dynamic-forms.service';
@Component({
template: `
{{ control.errors['customError'] }}
`,
})
class PtDynamicFormsTestComponent {
elements: IPtDynamicElementConfig[];
}
@Component({
selector: 'prutech-dynamic-input-test',
template: `
`,
})
export class PtDynamicTestComponent {
control: FormControl;
}
@NgModule({
declarations: [PtDynamicTestComponent],
imports: [ReactiveFormsModule],
exports: [PtDynamicTestComponent],
entryComponents: [PtDynamicTestComponent],
})
export class PtDynamicTestModule {
}
describe('Component: PtDynamicForms', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
MatNativeDateModule,
DynamicFormsModule,
PtDynamicTestModule,
],
declarations: [PtDynamicFormsTestComponent],
});
TestBed.compileComponents();
}));
it('should create the component', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
fixture.detectChanges();
expect(component).toBeTruthy();
}),
));
it('should render dynamic elements', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'first_name',
type: PtDynamicType.Text,
},
{
name: 'password',
type: PtDynamicElement.Password,
},
{
name: 'on_it',
type: PtDynamicType.Boolean,
},
{
name: 'age',
type: PtDynamicType.Number,
},
{
name: 'nodes',
type: PtDynamicElement.Slider,
},
{
name: 'description',
type: PtDynamicElement.Textarea,
},
{
name: 'sex',
type: PtDynamicType.Array,
selections: ['M', 'F'],
},
{
name: 'dob',
type: PtDynamicElement.Datepicker,
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(8);
});
}),
));
it('should render dynamic elements and show form invalid because an input is required', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'first_name',
type: PtDynamicType.Text,
required: true,
},
{
name: 'on_it',
type: PtDynamicType.Boolean,
default: true,
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(2);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeFalsy();
/* tslint:disable-next-line */
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({on_it: true}));
});
}),
));
it('should render dynamic elements and show form invalid because a number is less than min', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'first_name',
type: PtDynamicType.Text,
required: true,
},
{
name: 'age',
type: PtDynamicType.Number,
min: 18,
default: 17,
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(2);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeFalsy();
/* tslint:disable-next-line */
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({age: 17}));
});
}),
));
it('should render dynamic elements and show form valid', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
const dob: Date = new Date();
component.elements = [
{
name: 'first_name',
type: PtDynamicType.Text,
required: true,
default: 'name',
},
{
name: 'age',
type: PtDynamicType.Number,
default: 20,
min: 18,
max: 30,
},
{
name: 'dob',
type: PtDynamicType.Date,
default: dob,
required: true,
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(3);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeTruthy();
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({first_name: 'name', age: 20, dob}));
});
}),
));
it('should render dynamic elements and show form invalid because character length is less than minLength', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'password',
type: PtDynamicType.Text,
minLength: 8,
default: 'mypwd',
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(1);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeFalsy();
// tslint:disable-next-line:no-hardcoded-credentials
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({password: 'mypwd'}));
});
}),
));
it('should render dynamic elements and show form invalid because character length is more than maxLength', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'password',
type: PtDynamicType.Text,
maxLength: 8,
default: 'myVeryLongString',
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(1);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeFalsy();
// tslint:disable-next-line:no-hardcoded-credentials
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({password: 'myVeryLongString'}));
});
}),
));
it('should render dynamic elements and show form valid', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'password',
type: PtDynamicType.Text,
minLength: 8,
maxLength: 20,
default: 'mySuperSecretPw',
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(1);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeTruthy();
// tslint:disable-next-line:no-hardcoded-credentials
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({password: 'mySuperSecretPw'}));
});
}),
));
it('should render dynamic elements and show form invalid with custom validation', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'number',
type: PtDynamicType.Number,
default: 15,
appearance: '',
validators: [
{
validator: (control: AbstractControl) => {
const isValid: boolean = control.value > 21 && control.value < 23;
return !isValid ? {length: true} : undefined;
},
},
],
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(1);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeFalsy();
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({number: 15}));
});
}),
));
it('should render dynamic elements and show form invalid with Angular validation', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'hexColor',
type: PtDynamicType.Text,
required: true,
default: '#ZZZZZZ',
validators: [
{
validator: Validators.pattern(/^#[A-Fa-f0-9]{6}$/),
},
],
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(1);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeFalsy();
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({hexColor: '#ZZZZZZ'}));
});
}),
));
it('should render dynamic elements and show form valid with custom validations', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'hexColor',
type: PtDynamicType.Text,
required: true,
default: '#F1F1F1',
validators: [
{
validator: Validators.pattern(/^#[A-Fa-f0-9]{6}$/),
},
],
},
{
name: 'number',
type: PtDynamicType.Number,
default: 22,
validators: [
{
validator: (control: AbstractControl) => {
const isValid: boolean = control.value > 21 && control.value < 23;
return !isValid ? {length: true} : undefined;
},
},
],
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(2);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeTruthy();
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({hexColor: '#F1F1F1', number: 22}));
});
}),
));
it('should render errors with manual validations', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
component.elements = [
{
name: 'customElement',
label: 'Custom Element',
type: PtDynamicType.Text,
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
fixture.detectChanges();
fixture.whenStable().then(() => {
const key: string = 'customElement';
dynamicFormsComponent.controls[key].markAsTouched();
dynamicFormsComponent.controls[key].setErrors({customError: 'CUSTOM_ERROR'});
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.css('#custom-error')).length).toBe(1);
expect(fixture.debugElement.query(By.css('#custom-error')).nativeElement.textContent).toBe('CUSTOM_ERROR');
});
});
});
}),
));
it('should render dynamic elements with one element disabled', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'hexColor',
type: PtDynamicType.Text,
required: true,
default: '#F1F1F1',
},
{
name: 'number',
type: PtDynamicType.Number,
disabled: true,
required: true,
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(2);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeTruthy();
/* tslint:disable-next-line */
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({hexColor: '#F1F1F1'}));
});
}),
));
it('should render disabled file input', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'file',
type: PtDynamicElement.FileInput,
disabled: true,
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
const button: DebugElement = fixture.debugElement.query(By.css('prutech-file-input button'));
const hiddenFileInput: DebugElement = fixture.debugElement.query(By.css('prutech-file-input .prutech-file-input-hidden'));
expect(button.attributes.disabled).not.toBePtll();
expect(hiddenFileInput.attributes.disabled).not.toBePtll();
});
}),
));
it('should render dynamic custom element', async(
inject([], () => {
const fixture: ComponentFixture = TestBed.createComponent(PtDynamicFormsTestComponent);
const component: PtDynamicFormsTestComponent = fixture.debugElement.componentInstance;
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(0);
component.elements = [
{
name: 'custom',
type: PtDynamicTestComponent,
default: 'value',
},
] as IPtDynamicElementConfig[];
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.directive(PtDynamicElementComponent)).length).toBe(1);
const dynamicFormsComponent: PtDynamicFormsComponent = fixture.debugElement.query(
By.directive(PtDynamicFormsComponent),
).componentInstance;
expect(dynamicFormsComponent.valid).toBeTruthy();
expect(JSON.stringify(dynamicFormsComponent.value)).toBe(JSON.stringify({custom: 'value'}));
});
}),
));
});