Skip to content

Commit 9e90364

Browse files
Add ValidationMessagesComponent tests
1 parent 81b06e7 commit 9e90364

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import { TestBed, ComponentFixture } from '@angular/core/testing';
2+
import { ValidationMessagesComponent } from './validation-messages.component';
3+
import { ControlContainer, FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
4+
import { FormDirective } from '../form/form.directive';
5+
import { Component } from '@angular/core';
6+
import { ValidationMessageComponent } from '../validation-message/validation-message.component';
7+
import { Validators } from '../validators';
8+
import { Subject } from 'rxjs/Subject';
9+
10+
describe('ValidationMessagesComponent', () => {
11+
describe('properties and functions', () => {
12+
let component: ValidationMessagesComponent;
13+
let formGroup: FormGroup;
14+
let firstNameControl: FormControl;
15+
let middleNameControl: FormControl;
16+
let lastNameControl: FormControl;
17+
18+
beforeEach(() => {
19+
firstNameControl = new FormControl('', [
20+
Validators.required('A first name is required'),
21+
Validators.minLength(5, minLength => `First name needs to be at least ${minLength} characters long`)
22+
]);
23+
middleNameControl = new FormControl('', [Validators.required('A middle name is required')]);
24+
lastNameControl = new FormControl('', [
25+
Validators.required('A last name is required'),
26+
Validators.minLength(5, minLength => `Last name needs to be at least ${minLength} characters long`)
27+
]);
28+
formGroup = new FormGroup({
29+
firstName: firstNameControl,
30+
middleName: middleNameControl,
31+
lastName: lastNameControl
32+
});
33+
34+
const controlContainer: any = {
35+
control: formGroup
36+
};
37+
38+
TestBed.configureTestingModule({
39+
declarations: [ValidationMessagesComponent],
40+
providers: [
41+
{ provide: ControlContainer, useValue: controlContainer }
42+
]
43+
});
44+
45+
component = TestBed.createComponent(ValidationMessagesComponent).componentInstance;
46+
});
47+
48+
it(`for property doesn't accept an empty array`, () => {
49+
expect(() => component.for = [])
50+
.toThrowError(`arv-validation-messages doesn't allow declaring an empty array as input to the 'for' attribute.`);
51+
});
52+
53+
it(`for property handles a single input string`, () => {
54+
component.for = 'firstName';
55+
});
56+
57+
it(`for property handles a single input FormControl`, () => {
58+
component.for = firstNameControl;
59+
});
60+
61+
it(`for property handles an array with strings and FormControls`, () => {
62+
component.for = [firstNameControl, 'middleName', lastNameControl];
63+
});
64+
65+
it(`isValid returns true when there are no controls with ValidationErrors and they are touched`, () => {
66+
component.for = firstNameControl;
67+
firstNameControl.setValue('firstName');
68+
firstNameControl.markAsTouched();
69+
70+
expect(component.isValid()).toEqual(true);
71+
});
72+
73+
it(`isValid returns false when there are controls with ValidationErrors and they are touched`, () => {
74+
component.for = [firstNameControl];
75+
firstNameControl.markAsTouched();
76+
77+
expect(component.isValid()).toEqual(false);
78+
});
79+
80+
it(`getErrorMessages returns the first error message per touched control`, () => {
81+
component.for = [firstNameControl, middleNameControl, lastNameControl];
82+
firstNameControl.markAsTouched();
83+
// We skip middleNameControl on purpose, to ensure that it doesn't return it's error.
84+
lastNameControl.markAsTouched();
85+
lastNameControl.setValue('abc');
86+
87+
expect(component.getErrorMessages()).toEqual(['A first name is required', 'Last name needs to be at least 5 characters long']);
88+
});
89+
});
90+
91+
describe('validation is shown when', () => {
92+
let submittedSubject: Subject<{}>;
93+
let fixture: ComponentFixture<TestHostComponent>;
94+
95+
beforeEach(() => {
96+
submittedSubject = new Subject<{}>();
97+
TestBed.configureTestingModule({
98+
imports: [ReactiveFormsModule],
99+
declarations: [ValidationMessagesComponent, ValidationMessageComponent, TestHostComponent],
100+
providers: [{
101+
provide: FormDirective, useValue: {
102+
submitted: submittedSubject
103+
}
104+
}]
105+
});
106+
107+
fixture = TestBed.createComponent(TestHostComponent);
108+
fixture.detectChanges();
109+
});
110+
111+
it(`the associated control is touched`, () => {
112+
fixture.componentInstance.firstNameControl.markAsTouched();
113+
fixture.componentInstance.lastNameControl.markAsTouched();
114+
fixture.detectChanges();
115+
116+
expectValidationIsShown();
117+
});
118+
119+
it(`the form has been submitted`, () => {
120+
submittedSubject.next();
121+
fixture.detectChanges();
122+
123+
expectValidationIsShown();
124+
});
125+
126+
function expectValidationIsShown() {
127+
expect(fixture.nativeElement.querySelector('.invalid-feedback p').textContent).toEqual('A first name is required');
128+
expect(fixture.nativeElement.querySelector('.last-name-required').textContent).toEqual('A last name is required');
129+
}
130+
131+
@Component({
132+
template: `
133+
<arv-validation-messages [for]="firstNameControl"></arv-validation-messages>
134+
<arv-validation-messages [for]="lastNameControl">
135+
<arv-validation-message key="required">
136+
<p class="last-name-required">A last name is required</p>
137+
</arv-validation-message>
138+
</arv-validation-messages>`
139+
})
140+
class TestHostComponent {
141+
firstNameControl: FormControl = new FormControl(null, [Validators.required('A first name is required')]);
142+
lastNameControl: FormControl = new FormControl(null, [Validators.required()]);
143+
}
144+
});
145+
146+
it(`a child validation message without 'for' specified while parent has multiple controls throws an error`, () => {
147+
@Component({
148+
template: `
149+
<arv-validation-messages [for]="[firstNameControl, lastNameControl]">
150+
<arv-validation-message key="required"></arv-validation-message>
151+
</arv-validation-messages>`
152+
})
153+
class TestHostComponent {
154+
firstNameControl: FormControl = new FormControl(null);
155+
lastNameControl: FormControl = new FormControl(null);
156+
}
157+
158+
TestBed.configureTestingModule({
159+
imports: [ReactiveFormsModule],
160+
declarations: [ValidationMessagesComponent, ValidationMessageComponent, TestHostComponent]
161+
});
162+
163+
const fixture = TestBed.createComponent(TestHostComponent);
164+
expect(() => fixture.detectChanges())
165+
.toThrowError(`Specify the FormControl for which the arv-validation-message element with key 'required' should show messages.`);
166+
});
167+
168+
it(`a child validation message with a 'for' specified that's not in the parent throws an error`, () => {
169+
@Component({
170+
template: `
171+
<arv-validation-messages [for]="firstNameControl">
172+
<arv-validation-message [for]="lastNameControl" key="required"></arv-validation-message>
173+
</arv-validation-messages>`
174+
})
175+
class TestHostComponent {
176+
firstNameControl: FormControl = new FormControl(null);
177+
lastNameControl: FormControl = new FormControl(null);
178+
}
179+
180+
TestBed.configureTestingModule({
181+
imports: [ReactiveFormsModule],
182+
declarations: [ValidationMessagesComponent, ValidationMessageComponent, TestHostComponent]
183+
});
184+
185+
const fixture = TestBed.createComponent(TestHostComponent);
186+
expect(() => fixture.detectChanges())
187+
.toThrowError(`A arv-validation-messages element with key 'required' attempts to show messages for a FormControl` +
188+
` that is not declared in the parent arv-validation-messages element.`);
189+
});
190+
191+
it(`a ValidationError without a message and without a child validation message component throws an error`, () => {
192+
@Component({
193+
template: `<arv-validation-messages [for]="firstNameControl"></arv-validation-messages>`
194+
})
195+
class TestHostComponent {
196+
firstNameControl: FormControl = new FormControl(null, [Validators.required()]);
197+
}
198+
199+
TestBed.configureTestingModule({
200+
imports: [ReactiveFormsModule],
201+
declarations: [ValidationMessagesComponent, ValidationMessageComponent, TestHostComponent]
202+
});
203+
204+
const fixture = TestBed.createComponent(TestHostComponent);
205+
expect(() => fixture.detectChanges())
206+
.toThrowError(`There is no suitable arv-validation-message element to show the 'required' error of ''`);
207+
});
208+
209+
it(`validates child validation message as they are shown or hidden through *ngIf`, () => {
210+
@Component({
211+
template: `
212+
<arv-validation-messages [for]="firstNameControl">
213+
<arv-validation-message *ngIf="show" [for]="lastNameControl" key="required"></arv-validation-message>
214+
</arv-validation-messages>`
215+
})
216+
class TestHostComponent {
217+
firstNameControl: FormControl = new FormControl(null);
218+
lastNameControl: FormControl = new FormControl(null);
219+
show = false;
220+
}
221+
222+
TestBed.configureTestingModule({
223+
imports: [ReactiveFormsModule],
224+
declarations: [ValidationMessagesComponent, ValidationMessageComponent, TestHostComponent]
225+
});
226+
227+
const fixture = TestBed.createComponent(TestHostComponent);
228+
fixture.detectChanges();
229+
fixture.componentInstance.show = true;
230+
expect(() => fixture.detectChanges()).toThrowError();
231+
});
232+
});

0 commit comments

Comments
 (0)