@@ -24,7 +24,7 @@ import {
2424} from './control-error' ;
2525
2626describe ( 'NgxControlError' , ( ) => {
27- const unitTest = ( test : ( ) => void | Promise < void > ) => async ( ) => {
27+ const isolatedTest = ( test : ( ) => void | Promise < void > ) => async ( ) => {
2828 TestBed . overrideProvider ( TemplateRef , { useValue : undefined } ) ;
2929 TestBed . overrideProvider ( ViewContainerRef , {
3030 useValue : {
@@ -72,12 +72,12 @@ describe('NgxControlError', () => {
7272
7373 it (
7474 'should be created' ,
75- unitTest ( ( ) => expect ( new NgxControlError ( ) ) . toBeTruthy ( ) ) ,
75+ isolatedTest ( ( ) => expect ( new NgxControlError ( ) ) . toBeTruthy ( ) ) ,
7676 ) ;
7777
7878 it (
7979 'should have a context guard' ,
80- unitTest ( ( ) =>
80+ isolatedTest ( ( ) =>
8181 expect (
8282 NgxControlError . ngTemplateContextGuard ( new NgxControlError ( ) , { } ) ,
8383 ) . toBe ( true ) ,
@@ -87,7 +87,7 @@ describe('NgxControlError', () => {
8787 describe ( 'should have an error when the control includes the tracked error and the control is in an error state' , ( ) => {
8888 it (
8989 'respecting track changes' ,
90- unitTest ( ( ) => {
90+ isolatedTest ( ( ) => {
9191 const instance = new NgxControlError ( ) ;
9292
9393 instance . track$ . set ( 'required' ) ;
@@ -106,7 +106,7 @@ describe('NgxControlError', () => {
106106
107107 it (
108108 'when it has at least 1 tracked error ' ,
109- unitTest ( ( ) => {
109+ isolatedTest ( ( ) => {
110110 const instance = new NgxControlError ( ) ;
111111 const control = new FormControl ( '42' , [
112112 Validators . minLength ( 3 ) ,
@@ -130,7 +130,7 @@ describe('NgxControlError', () => {
130130
131131 it (
132132 'respecting error state matcher changes' ,
133- unitTest ( ( ) => {
133+ isolatedTest ( ( ) => {
134134 const instance = new NgxControlError ( ) ;
135135
136136 instance . track$ . set ( 'required' ) ;
@@ -149,7 +149,7 @@ describe('NgxControlError', () => {
149149
150150 it (
151151 'respecting control instance changes' ,
152- unitTest ( ( ) => {
152+ isolatedTest ( ( ) => {
153153 const instance = new NgxControlError ( ) ;
154154
155155 instance . track$ . set ( 'required' ) ;
@@ -169,7 +169,7 @@ describe('NgxControlError', () => {
169169
170170 it (
171171 'DEFAULT_ERROR_STATE_MATCHER should match when the control is: 1. invalid 2. touched or its parent is submitted' ,
172- unitTest ( ( ) => {
172+ isolatedTest ( ( ) => {
173173 const instance = new NgxControlError ( ) ;
174174 const control = new FormControl ( '' , Validators . required ) ;
175175
@@ -243,17 +243,30 @@ describe('NgxControlError', () => {
243243 it ( 'should have an injectable error state matcher' , ( ) => {
244244 const errorStateMatcher = jest . fn ( ) ;
245245
246+ const params = {
247+ error : 'required' ,
248+ control : new FormControl ( '' , Validators . required ) ,
249+ } ;
250+
246251 const [ , controlError ] = render (
247- '<ng-template ngxControlError / >' ,
248- undefined ,
252+ '<span * ngxControlError="control; track: error">42</span >' ,
253+ params ,
249254 provideNgxControlError ( { errorStateMatcher : ( ) => errorStateMatcher } ) ,
250255 ) ;
251256
252257 expect ( controlError . errorStateMatcher$ ( ) ) . toBe ( errorStateMatcher ) ;
253258 } ) ;
254259
255260 it ( 'should use the default error state matcher as default' , ( ) => {
256- const [ , controlError ] = render ( '<ng-template ngxControlError />' ) ;
261+ const params = {
262+ error : 'required' ,
263+ control : new FormControl ( '' , Validators . required ) ,
264+ } ;
265+
266+ const [ , controlError ] = render (
267+ '<span *ngxControlError="control; track: error">42</span>' ,
268+ params ,
269+ ) ;
257270
258271 expect ( controlError . errorStateMatcher$ ( ) ) . toBe (
259272 NGX_DEFAULT_CONTROL_ERROR_STATE_MATCHER ,
@@ -332,4 +345,113 @@ describe('NgxControlError', () => {
332345
333346 expect ( fixture . debugElement . nativeElement . textContent ) . toBe ( '' ) ;
334347 } ) ;
348+
349+ it ( 'should throw when a control cannot be found because there is no parent control' , ( ) => {
350+ expect ( ( ) =>
351+ render ( `
352+ <span *ngxControlError="'name'; track: 'required'">42</span>
353+ ` ) ,
354+ ) . toThrow (
355+ '[NgxControlError]: A control name cannot be specified without a parent FormGroup.' ,
356+ ) ;
357+ } ) ;
358+
359+ it ( 'should throw when a control cannot be found in the parent form group' , ( ) => {
360+ const params = {
361+ form : new FormGroup ( {
362+ name : new FormControl ( '' , Validators . required ) ,
363+ } ) ,
364+ } ;
365+
366+ expect ( ( ) =>
367+ render (
368+ `<form [formGroup]="form">
369+ <span *ngxControlError="'nonExistentControlname'; track: 'required'">42</span>
370+ </form>
371+ ` ,
372+ params ,
373+ ) ,
374+ ) . toThrow (
375+ `[NgxControlError]: Cannot find control with name 'nonExistentControlname'.` ,
376+ ) ;
377+ } ) ;
378+
379+ it ( 'should throw when a control cannot be found in a nested parent form group' , ( ) => {
380+ expect ( ( ) =>
381+ render (
382+ `<form [formGroup]="form">
383+ <div formGroupName="nested">
384+ <span *ngxControlError="'nonExistentControlname'; track: 'required'">42</span>
385+ </div>
386+ </form>
387+ ` ,
388+ {
389+ form : new FormGroup ( {
390+ nested : new FormGroup ( {
391+ name : new FormControl ( '' , Validators . required ) ,
392+ } ) ,
393+ } ) ,
394+ } ,
395+ ) ,
396+ ) . toThrow (
397+ `[NgxControlError]: Cannot find control with name 'nonExistentControlname'.` ,
398+ ) ;
399+
400+ expect ( ( ) =>
401+ render (
402+ `<form [formGroup]="form">
403+ <div formGroupName="nested">
404+ <span *ngxControlError="'name1'; track: 'required'">42</span>
405+ </div>
406+ </form>
407+ ` ,
408+ {
409+ form : new FormGroup ( {
410+ name1 : new FormControl ( '' , Validators . required ) ,
411+ nested : new FormGroup ( {
412+ name2 : new FormControl ( '' , Validators . required ) ,
413+ } ) ,
414+ } ) ,
415+ } ,
416+ ) ,
417+ ) . toThrow ( `[NgxControlError]: Cannot find control with name 'name1'.` ) ;
418+ } ) ;
419+
420+ it ( 'should resolve a nested control by its name' , ( ) => {
421+ const params = {
422+ error : 'required' ,
423+ form : new FormGroup ( {
424+ nested : new FormGroup ( {
425+ name : new FormControl ( '' , Validators . required ) ,
426+ } ) ,
427+ } ) ,
428+ stateMatcher : ( ) => of ( true ) ,
429+ } ;
430+
431+ const [ fixture , controlError ] = render (
432+ `
433+ <form [formGroup]="form">
434+ <div formGroupName="nested">
435+ <label>
436+ <input formControlName="name" />
437+ <span
438+ *ngxControlError="'name'; track: error, errorStateMatcher: stateMatcher"
439+ >42</span>
440+ </label>
441+ </div>
442+ </form>
443+ ` ,
444+ params ,
445+ ) ;
446+
447+ fixture . detectChanges ( ) ;
448+
449+ expect ( fixture . debugElement . nativeElement . textContent ) . toBe ( '42' ) ;
450+
451+ controlError . errorStateMatcher = ( ) => of ( false ) ;
452+
453+ fixture . detectChanges ( ) ;
454+
455+ expect ( fixture . debugElement . nativeElement . textContent ) . toBe ( '' ) ;
456+ } ) ;
335457} ) ;
0 commit comments