1
- import { Component , EnvironmentProviders , ModuleWithProviders , Provider , ProviderToken , Type } from '@angular/core' ;
2
- import { ComponentFixture , TestBed , TestBedStatic , TestModuleMetadata } from '@angular/core/testing' ;
1
+ import { Component , ProviderToken , Type } from '@angular/core' ;
2
+ import { ComponentFixture , TestBed , TestBedStatic } from '@angular/core/testing' ;
3
3
import { MaybeArray , Merge , NonEmptyString , Nullable } from '../../models/shared.model' ;
4
4
import { assertComponent } from './assert-component' ;
5
5
import { assertComponentFixture } from './assert-fixture' ;
6
6
import { getComponentAnnotation } from './component-annotation' ;
7
+ import { buildComponentTools } from './component-tools' ;
7
8
import { ComponentTestBed } from './models' ;
9
+ import { AnyProvider , Declaration , Importation } from './models/metadata-type.model' ;
10
+ import { ComponentSetup } from './models/setup-fn.model' ;
8
11
import { InjectionStore } from './store' ;
9
12
10
- export class ComponentTestBedFactory < ComponentType , Injected extends InjectionStore = InjectionStore > {
13
+ export class ComponentTestBedFactory < ComponentType , Store extends InjectionStore = InjectionStore > {
11
14
12
15
public constructor (
13
16
private rootComponent : Type < ComponentType > ,
14
17
) {
15
- this . annotation = getComponentAnnotation ( rootComponent ) ;
16
- assertComponent ( rootComponent , this . annotation ) ;
17
- }
18
+ const annotation : Nullable < Component > = getComponentAnnotation ( rootComponent ) ;
19
+ assertComponent ( rootComponent , annotation ) ;
18
20
19
- private readonly annotation : Nullable < Component > ;
21
+ ( annotation ?. standalone )
22
+ ? this . import ( this . rootComponent )
23
+ : this . declare ( this . rootComponent ) ;
24
+ }
20
25
21
26
private testBed : TestBedStatic = TestBed ;
22
27
private fixture : ComponentFixture < ComponentType > = null ! ;
23
- private injected : Map < ProviderToken < any > , string > = new Map ( ) ;
28
+
29
+ private imports : Set < Importation > = new Set ( ) ;
30
+ private declarations : Set < Declaration > = new Set ( ) ;
31
+ private providers : Set < AnyProvider > = new Set ( ) ;
32
+
33
+ private injectedMap : Map < ProviderToken < any > , string > = new Map ( ) ;
24
34
25
35
/**
26
36
* Import one module or one standalone component / directive / pipe into the `ComponentTestBed`.
27
37
*/
28
- public import ( importation : Type < any > | ModuleWithProviders < any > ) : this
38
+ public import ( importation : Importation ) : this
29
39
/**
30
40
* Import many modules or many standalone components / directives / pipes into the `ComponentTestBed`.
31
41
*/
32
- public import ( imports : ( Type < any > | ModuleWithProviders < any > ) [ ] ) : this
33
- public import ( oneOrManyImports : MaybeArray < Type < any > | ModuleWithProviders < any > > ) : this
34
- public import ( oneOrManyImports : MaybeArray < Type < any > | ModuleWithProviders < any > > ) : this {
35
- return this . configure ( 'imports' , oneOrManyImports ) ;
42
+ public import ( imports : Importation [ ] ) : this
43
+ public import ( oneOrManyImports : MaybeArray < Importation > ) : this {
44
+ makeArray ( oneOrManyImports ) . forEach ( v => this . imports . add ( v ) ) ;
45
+ return this ;
36
46
}
37
47
38
48
/**
39
49
* Add one provider into the `ComponentTestBed`.
40
50
*/
41
- public provide ( provider : Provider | EnvironmentProviders ) : this
51
+ public provide ( provider : AnyProvider ) : this
42
52
/**
43
53
* Add many providers into the `ComponentTestBed`.
44
54
*/
45
- public provide ( providers : ( Provider | EnvironmentProviders ) [ ] ) : this
46
- public provide ( oneOrManyProviders : MaybeArray < Provider | EnvironmentProviders > ) : this
47
- public provide ( oneOrManyProviders : MaybeArray < Provider | EnvironmentProviders > ) : this {
48
- return this . configure ( 'providers' , oneOrManyProviders ) ;
55
+ public provide ( providers : AnyProvider [ ] ) : this
56
+ public provide ( oneOrManyProviders : MaybeArray < AnyProvider > ) : this {
57
+ makeArray ( oneOrManyProviders ) . forEach ( v => this . providers . add ( v ) ) ;
58
+ return this ;
49
59
}
50
60
51
61
/**
52
62
* Declare one non standalone component, directive or pipe into the `ComponentTestBed`.
53
63
*/
54
- public declare ( declaration : Type < any > ) : this
64
+ public declare ( declaration : Declaration ) : this
55
65
/**
56
66
* Declare many non standalone components, directives and pipes into `ComponentTestBed`.
57
67
*/
58
- public declare ( declarations : Type < any > [ ] ) : this
59
- public declare ( oneOrManyDeclarations : MaybeArray < Type < any > > ) : this
60
- public declare ( oneOrManyDeclarations : MaybeArray < Type < any > > ) : this {
61
- return this . configure ( 'declarations' , oneOrManyDeclarations ) ;
68
+ public declare ( declarations : Declaration [ ] ) : this
69
+ public declare ( oneOrManyDeclarations : MaybeArray < Declaration > ) : this {
70
+ makeArray ( oneOrManyDeclarations ) . forEach ( v => this . declarations . add ( v ) ) ;
71
+ return this ;
72
+ }
73
+
74
+ private async configureModule ( ) : Promise < void > {
75
+ this . testBed . configureTestingModule ( {
76
+ imports : [ ...this . imports . values ( ) ] ,
77
+ declarations : [ ...this . declarations . values ( ) ] ,
78
+ providers : [ ...this . providers . values ( ) ] ,
79
+ } ) ;
80
+
81
+ await this . testBed . compileComponents ( ) ;
62
82
}
63
83
64
- public inject < key extends string , T > ( name : NonEmptyString < key > , token : ProviderToken < T > ) : ComponentTestBed < ComponentType , InjectionStore < Merge < Injected [ 'injected' ] & { [ k in key ] : T } > > > {
65
- this . injected . set ( token , name ) ;
84
+ /**
85
+ * Inject an instance by token into the `ComponentTestBed`.
86
+ *
87
+ * Retrieve it into the `ComponentTools.injected` by autocompletion.
88
+ * @param name the key to access the instance.
89
+ * @param token the provider token.
90
+ */
91
+ public inject < key extends string , T > ( name : NonEmptyString < key > , token : ProviderToken < T > ) : ComponentTestBed < ComponentType , InjectionStore < Merge < Store [ 'injected' ] & { [ k in key ] : T } > > > {
92
+ this . injectedMap . set ( token , name ) ;
66
93
return this as any ;
67
94
}
68
95
69
- private configure ( key : keyof TestModuleMetadata , itemS : MaybeArray < unknown > ) : this {
70
- const defs : unknown [ ] = Array . isArray ( itemS ) ? itemS : [ itemS ] ;
71
- this . testBed . configureTestingModule ( { [ key ] : defs } ) ;
72
- return this ;
96
+ /**
97
+ * Compile the `ComponentTestBed` before each test.
98
+ */
99
+ public compileEach ( ) : void {
100
+ beforeEach ( ( ) => this . compile ( ) ) ;
101
+ }
102
+
103
+ /**
104
+ * Compile the `ComponentTestBed` to create the `rootComponent` fixture.
105
+ */
106
+ public async compile ( ) : Promise < void > {
107
+ await this . configureModule ( ) ;
108
+ this . fixture = this . testBed . createComponent ( this . rootComponent ) ;
109
+ }
110
+
111
+ /**
112
+ * Not compatible with `beforeAll` and `afterAll`.
113
+ */
114
+ public setup ( action : ComponentSetup < ComponentType , Store [ 'injected' ] > ) : jasmine . ImplementationCallback {
115
+ return ( action . length > 1 )
116
+ ? ( done : DoneFn ) => action ( buildComponentTools ( this ) , done )
117
+ : ( ) => action ( buildComponentTools ( this ) , null ! ) ;
73
118
}
74
119
75
120
/**
@@ -83,17 +128,8 @@ export class ComponentTestBedFactory<ComponentType, Injected extends InjectionSt
83
128
expect ( this . fixture . componentInstance ) . toBeTruthy ( ) ;
84
129
} ) ;
85
130
}
131
+ }
86
132
87
- /**
88
- * Compile the `ComponentTestBed` to create the `rootComponent` fixture.
89
- */
90
- public async compile ( ) : Promise < void > {
91
- ( this . annotation ?. standalone )
92
- ? this . import ( this . rootComponent )
93
- : this . declare ( this . rootComponent ) ;
94
-
95
- await this . testBed . compileComponents ( ) ;
96
-
97
- this . fixture = this . testBed . createComponent ( this . rootComponent ) ;
98
- }
133
+ function makeArray < T > ( itemS : MaybeArray < T > ) : T [ ] {
134
+ return ( Array . isArray ( itemS ) ) ? itemS : [ itemS ] ;
99
135
}
0 commit comments