1
+
2
+ import { View } from "tns-core-modules/ui/core/view" ;
3
+ import { topmost } from "tns-core-modules/ui/frame" ;
4
+ import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base" ;
1
5
import { ComponentFixture , TestBed } from "@angular/core/testing" ;
2
6
import { NgModule , Type } from "@angular/core" ;
3
7
import { NativeScriptModule } from "../../nativescript.module" ;
4
8
import { platformBrowserDynamicTesting } from "@angular/platform-browser-dynamic/testing" ;
5
9
import { NS_COMPILER_PROVIDERS } from "../../platform" ;
6
10
import { NATIVESCRIPT_TESTING_PROVIDERS , NativeScriptTestingModule } from "../index" ;
7
11
import { CommonModule } from "@angular/common" ;
12
+ /**
13
+ * Get a reference to the root application view.
14
+ */
15
+ export function testingRootView ( ) : View {
16
+ return topmost ( ) . currentPage . content ;
17
+ }
18
+
19
+ /**
20
+ * Declared test contexts. When the suite is done this map should be empty if all lifecycle
21
+ * calls have happened as expected.
22
+ * @private
23
+ */
24
+ const activeTestFixtures : ComponentFixture < any > [ ] [ ] = [ ] ;
8
25
9
26
/**
10
27
* Return a promise that resolves after (durationMs) milliseconds
@@ -14,19 +31,13 @@ export function promiseWait(durationMs: number) {
14
31
}
15
32
16
33
/**
17
- * Render a component using the TestBed helper, and return a promise that resolves when the
18
- * ComponentFixture is fully initialized.
34
+ * Perform basic TestBed environment initialization. Call this once in the main entry point to your tests.
19
35
*/
20
- export function nTestBedRender < T > ( componentType : Type < T > ) : Promise < ComponentFixture < T > > {
21
- const fixture = TestBed . createComponent ( componentType ) ;
22
- fixture . detectChanges ( ) ;
23
- return fixture . whenRenderingDone ( )
24
- // TODO(jd): it seems that the whenStable and whenRenderingDone utilities of ComponentFixture
25
- // do not work as expected. I looked at how to fix it and it's not clear how to provide
26
- // a {N} specific subclass, because ComponentFixture is newed directly rather than injected
27
- // What to do about it? Maybe fakeAsync can help? For now just setTimeout for 100ms (x_X)
28
- . then ( promiseWait ( 100 ) )
29
- . then ( ( ) => fixture ) ;
36
+ export function nTestBedInit ( ) {
37
+ TestBed . initTestEnvironment (
38
+ NativeScriptTestingModule ,
39
+ platformBrowserDynamicTesting ( NS_COMPILER_PROVIDERS )
40
+ ) ;
30
41
}
31
42
32
43
/**
@@ -55,6 +66,7 @@ export function nTestBedBeforeEach(
55
66
imports : any [ ] = [ ] ,
56
67
entryComponents : any [ ] = [ ] ) {
57
68
return ( done ) => {
69
+ activeTestFixtures . push ( [ ] ) ;
58
70
// If there are no entry components we can take the simple path.
59
71
if ( entryComponents . length === 0 ) {
60
72
TestBed . configureTestingModule ( {
@@ -96,30 +108,59 @@ export function nTestBedBeforeEach(
96
108
done ( ) ;
97
109
} ) ;
98
110
} ;
99
-
100
- }
101
-
102
- /**
103
- * Perform basic TestBed environment initialization. Call this once in the main entry point to your tests.
104
- */
105
- export function nBasicTestBedInit ( ) {
106
- TestBed . initTestEnvironment (
107
- NativeScriptTestingModule ,
108
- platformBrowserDynamicTesting ( NS_COMPILER_PROVIDERS )
109
- ) ;
110
111
}
111
112
112
113
/**
113
114
* Helper for a basic component TestBed clean up.
114
115
* @param resetEnv When true the testing environment will be reset
115
116
* @param resetFn When resetting the environment, use this init function
116
117
*/
117
- export function nTestBedAfterEach ( resetEnv = true , resetFn = nBasicTestBedInit ) {
118
+ export function nTestBedAfterEach ( resetEnv = true , resetFn = nTestBedInit ) {
118
119
return ( ) => {
120
+ if ( activeTestFixtures . length === 0 ) {
121
+ throw new Error (
122
+ `There are no more declared fixtures.` +
123
+ `Did you call "nTestBedBeforeEach" and "nTestBedAfterEach" an equal number of times?`
124
+ ) ;
125
+ }
126
+ const root = testingRootView ( ) as LayoutBase ;
127
+ const fixtures = activeTestFixtures . pop ( ) ;
128
+ fixtures . forEach ( ( fixture ) => {
129
+ root . removeChild ( fixture . nativeElement ) ;
130
+ fixture . destroy ( ) ;
131
+ } ) ;
119
132
TestBed . resetTestingModule ( ) ;
120
133
if ( resetEnv ) {
121
134
TestBed . resetTestEnvironment ( ) ;
122
135
resetFn ( ) ;
123
136
}
124
137
} ;
125
138
}
139
+
140
+ /**
141
+ * Render a component using the TestBed helper, and return a promise that resolves when the
142
+ * ComponentFixture is fully initialized.
143
+ */
144
+ export function nTestBedRender < T > ( componentType : Type < T > ) : Promise < ComponentFixture < T > > {
145
+ const fixture = TestBed . createComponent ( componentType ) ;
146
+ fixture . detectChanges ( ) ;
147
+ return fixture . whenRenderingDone ( )
148
+ // TODO(jd): it seems that the whenStable and whenRenderingDone utilities of ComponentFixture
149
+ // do not work as expected. I looked at how to fix it and it's not clear how to provide
150
+ // a {N} specific subclass, because ComponentFixture is newed directly rather than injected
151
+ // What to do about it? Maybe fakeAsync can help? For now just setTimeout for 100ms (x_X)
152
+ . then ( promiseWait ( 100 ) )
153
+ . then ( ( ) => {
154
+ const list = activeTestFixtures [ activeTestFixtures . length - 1 ] ;
155
+ if ( ! list ) {
156
+ console . warn (
157
+ "nTestBedRender called without nTestBedBeforeEach/nTestBedAfter each. " +
158
+ "You are responsible for calling 'fixture.destroy()' when your test is done " +
159
+ "in order to clean up the components that are created."
160
+ ) ;
161
+ } else {
162
+ list . push ( fixture ) ;
163
+ }
164
+ return fixture ;
165
+ } ) ;
166
+ }
0 commit comments