1
- import { Component , DebugElement , ElementRef , OnInit , Type } from '@angular/core' ;
1
+ import { Component , ElementRef , OnInit , Type } from '@angular/core' ;
2
2
import { ComponentFixture , TestBed } from '@angular/core/testing' ;
3
3
import { By } from '@angular/platform-browser' ;
4
4
import { BrowserAnimationsModule , NoopAnimationsModule } from '@angular/platform-browser/animations' ;
5
5
import { fireEvent , FireFunction , FireObject , getQueriesForElement , prettyDOM } from '@testing-library/dom' ;
6
- import { RenderOptions , RenderResult } from './models' ;
6
+ import { RenderComponentOptions , RenderDirectiveOptions , RenderResult } from './models' ;
7
7
import { createSelectOptions , createType } from './user-events' ;
8
8
9
9
@Component ( { selector : 'wrapper-component' , template : '' } )
10
10
class WrapperComponent implements OnInit {
11
- constructor ( private elemtRef : ElementRef ) { }
11
+ constructor ( private elementRef : ElementRef ) { }
12
12
13
13
ngOnInit ( ) {
14
- this . elemtRef . nativeElement . removeAttribute ( 'ng-version' ) ;
14
+ this . elementRef . nativeElement . removeAttribute ( 'ng-version' ) ;
15
15
}
16
16
}
17
17
18
- export async function render < T > ( template : string , renderOptions : RenderOptions < T > ) : Promise < RenderResult > ;
19
- export async function render < T > ( component : Type < T > , renderOptions ?: RenderOptions < T > ) : Promise < RenderResult > ;
20
- export async function render < T > (
21
- templateOrComponent : string | Type < T > ,
22
- renderOptions : RenderOptions < T > = { } ,
23
- ) : Promise < RenderResult > {
18
+ export async function render < ComponentType > (
19
+ component : Type < ComponentType > ,
20
+ renderOptions ?: RenderComponentOptions < ComponentType > ,
21
+ ) : Promise < RenderResult < ComponentType , ComponentType > > ;
22
+ export async function render < DirectiveType , WrapperType = WrapperComponent > (
23
+ component : Type < DirectiveType > ,
24
+ renderOptions ?: RenderDirectiveOptions < DirectiveType , WrapperType > ,
25
+ ) : Promise < RenderResult < DirectiveType , WrapperType > > ;
26
+
27
+ export async function render < SutType , WrapperType = SutType > (
28
+ sut : Type < SutType > ,
29
+ renderOptions : RenderComponentOptions < SutType > | RenderDirectiveOptions < SutType , WrapperType > = { } ,
30
+ ) : Promise < RenderResult < SutType > > {
24
31
const {
25
32
detectChanges = true ,
26
33
declarations = [ ] ,
27
34
imports = [ ] ,
28
35
providers = [ ] ,
29
36
schemas = [ ] ,
30
37
queries,
38
+ template,
31
39
wrapper = WrapperComponent ,
32
40
componentProperties = { } ,
33
41
componentProviders = [ ] ,
34
42
excludeComponentDeclaration = false ,
35
- } = renderOptions ;
36
-
37
- const isTemplate = typeof templateOrComponent === 'string' ;
38
- const componentDeclarations = declareComponents ( {
39
- templateOrComponent,
40
- wrapper,
41
- isTemplate,
42
- excludeComponentDeclaration,
43
- } ) ;
43
+ } = renderOptions as RenderDirectiveOptions < SutType , WrapperType > ;
44
44
45
45
TestBed . configureTestingModule ( {
46
- declarations : [ ... declarations , ... componentDeclarations ] ,
46
+ declarations : addAutoDeclarations ( sut , { declarations, excludeComponentDeclaration , template , wrapper } ) ,
47
47
imports : addAutoImports ( imports ) ,
48
48
providers : [ ...providers ] ,
49
49
schemas : [ ...schemas ] ,
@@ -58,9 +58,8 @@ export async function render<T>(
58
58
} ) ;
59
59
}
60
60
61
- const fixture = isTemplate
62
- ? createWrapperComponentFixture ( templateOrComponent as string , { wrapper, componentProperties } )
63
- : createComponentFixture ( templateOrComponent as Type < T > , { componentProperties } ) ;
61
+ const fixture = createComponentFixture ( sut , { template, wrapper } ) ;
62
+ setComponentProperties ( fixture , { componentProperties } ) ;
64
63
65
64
await TestBed . compileComponents ( ) ;
66
65
@@ -80,98 +79,71 @@ export async function render<T>(
80
79
{ } as FireFunction & FireObject ,
81
80
) ;
82
81
82
+ const debugElement = fixture . debugElement . query ( By . directive ( sut ) ) ;
83
+
83
84
return {
84
85
fixture,
86
+ debugElement,
85
87
container : fixture . nativeElement ,
86
88
debug : ( element = fixture . nativeElement ) => console . log ( prettyDOM ( element ) ) ,
87
89
detectChanges : ( ) => fixture . detectChanges ( ) ,
88
90
...getQueriesForElement ( fixture . nativeElement , queries ) ,
89
91
...eventsWithDetectChanges ,
90
92
type : createType ( eventsWithDetectChanges ) ,
91
93
selectOptions : createSelectOptions ( eventsWithDetectChanges ) ,
92
- } as any ;
94
+ } ;
93
95
}
94
96
95
- /**
96
- * Creates the wrapper component and sets its the template to the to-be-tested component
97
- */
98
- function createWrapperComponentFixture < T > (
99
- template : string ,
100
- {
101
- wrapper,
102
- componentProperties,
103
- } : {
104
- wrapper : RenderOptions < T > [ 'wrapper' ] ;
105
- componentProperties : RenderOptions < T > [ 'componentProperties' ] ;
106
- } ,
107
- ) : ComponentFixture < any > {
108
- TestBed . overrideComponent ( wrapper , {
109
- set : {
110
- template : template ,
111
- } ,
112
- } ) ;
113
-
114
- const fixture = TestBed . createComponent ( wrapper ) ;
115
- // get the component selector, e.g. <foo color="green"> and <foo> results in foo
116
- const componentSelector = template . match ( / \< ( .* ?) \ / ) || template . match ( / \< ( .* ?) \> / ) ;
117
- if ( ! componentSelector ) {
118
- throw Error ( `Template ${ template } is not valid.` ) ;
97
+ function createComponentFixture < SutType > (
98
+ component : Type < SutType > ,
99
+ { template, wrapper } : Pick < RenderDirectiveOptions < SutType , any > , 'template' | 'wrapper' > ,
100
+ ) : ComponentFixture < SutType > {
101
+ if ( template ) {
102
+ TestBed . overrideTemplate ( wrapper , template ) ;
103
+ return TestBed . createComponent ( wrapper ) ;
119
104
}
120
-
121
- const sut = fixture . debugElement . query ( By . css ( componentSelector [ 1 ] ) ) ;
122
- setComponentProperties ( sut , { componentProperties } ) ;
123
- return fixture ;
124
- }
125
-
126
- /**
127
- * Creates the components and sets its properties
128
- */
129
- function createComponentFixture < T > (
130
- component : Type < T > ,
131
- {
132
- componentProperties = { } ,
133
- } : {
134
- componentProperties : RenderOptions < T > [ 'componentProperties' ] ;
135
- } ,
136
- ) : ComponentFixture < T > {
137
- const fixture = TestBed . createComponent ( component ) ;
138
- setComponentProperties ( fixture , { componentProperties } ) ;
139
- return fixture ;
105
+ return TestBed . createComponent ( component ) ;
140
106
}
141
107
142
- /**
143
- * Set the component properties
144
- */
145
- function setComponentProperties < T > (
146
- fixture : ComponentFixture < T > | DebugElement ,
147
- {
148
- componentProperties = { } ,
149
- } : {
150
- componentProperties : RenderOptions < T > [ 'componentProperties' ] ;
151
- } ,
108
+ function setComponentProperties < SutType > (
109
+ fixture : ComponentFixture < SutType > ,
110
+ { componentProperties = { } } : Pick < RenderDirectiveOptions < SutType , any > , 'componentProperties' > ,
152
111
) {
153
112
for ( const key of Object . keys ( componentProperties ) ) {
154
113
fixture . componentInstance [ key ] = componentProperties [ key ] ;
155
114
}
156
115
return fixture ;
157
116
}
158
117
159
- function declareComponents ( { isTemplate, wrapper, excludeComponentDeclaration, templateOrComponent } ) {
160
- if ( isTemplate ) {
161
- return [ wrapper ] ;
162
- }
118
+ function addAutoDeclarations < SutType > (
119
+ component : Type < SutType > ,
120
+ {
121
+ declarations,
122
+ excludeComponentDeclaration,
123
+ template,
124
+ wrapper,
125
+ } : Pick <
126
+ RenderDirectiveOptions < SutType , any > ,
127
+ 'declarations' | 'excludeComponentDeclaration' | 'template' | 'wrapper'
128
+ > ,
129
+ ) {
130
+ const wrappers = ( ) => {
131
+ return template ? [ wrapper ] : [ ] ;
132
+ } ;
163
133
164
- if ( excludeComponentDeclaration ) {
165
- return [ ] ;
166
- }
134
+ const components = ( ) => {
135
+ return excludeComponentDeclaration ? [ ] : [ component ] ;
136
+ } ;
167
137
168
- return [ templateOrComponent ] ;
138
+ return [ ... declarations , ... wrappers ( ) , ... components ( ) ] ;
169
139
}
170
140
171
141
function addAutoImports ( imports : any [ ] ) {
172
- if ( imports . indexOf ( NoopAnimationsModule ) > - 1 || imports . indexOf ( BrowserAnimationsModule ) > - 1 ) {
173
- return imports ;
174
- }
142
+ const animations = ( ) => {
143
+ const animationIsDefined =
144
+ imports . indexOf ( NoopAnimationsModule ) > - 1 || imports . indexOf ( BrowserAnimationsModule ) > - 1 ;
145
+ return animationIsDefined ? [ ] : [ NoopAnimationsModule ] ;
146
+ } ;
175
147
176
- return [ ...imports , NoopAnimationsModule ] ;
148
+ return [ ...imports , ... animations ( ) ] ;
177
149
}
0 commit comments