@@ -8,7 +8,7 @@ window.Mocha['__zone_patch__'] = false
8
8
import 'zone.js/testing'
9
9
10
10
import { CommonModule } from '@angular/common'
11
- import { Component , ErrorHandler , EventEmitter , Injectable , SimpleChange , SimpleChanges , Type } from '@angular/core'
11
+ import { Component , ErrorHandler , EventEmitter , Injectable , SimpleChange , SimpleChanges , Type , OnChanges } from '@angular/core'
12
12
import {
13
13
ComponentFixture ,
14
14
getTestBed ,
@@ -72,6 +72,23 @@ export interface MountConfig<T> extends TestModuleMetadata {
72
72
componentProperties ?: Partial < { [ P in keyof T ] : T [ P ] } >
73
73
}
74
74
75
+ let activeFixture : ComponentFixture < any > | null = null
76
+
77
+ function cleanup ( ) {
78
+ // Not public, we need to call this to remove the last component from the DOM
79
+ try {
80
+ ( getTestBed ( ) as any ) . tearDownTestingModule ( )
81
+ } catch ( e ) {
82
+ const notSupportedError = new Error ( `Failed to teardown component. The version of Angular you are using may not be officially supported.` )
83
+
84
+ ; ( notSupportedError as any ) . docsUrl = 'https://on.cypress.io/component-framework-configuration'
85
+ throw notSupportedError
86
+ }
87
+
88
+ getTestBed ( ) . resetTestingModule ( )
89
+ activeFixture = null
90
+ }
91
+
75
92
/**
76
93
* Type that the `mount` function returns
77
94
* @type MountResponse<T>
@@ -209,6 +226,8 @@ function setupFixture<T> (
209
226
) : ComponentFixture < T > {
210
227
const fixture = getTestBed ( ) . createComponent ( component )
211
228
229
+ setupComponent ( config , fixture )
230
+
212
231
fixture . whenStable ( ) . then ( ( ) => {
213
232
fixture . autoDetectChanges ( config . autoDetectChanges ?? true )
214
233
} )
@@ -223,17 +242,18 @@ function setupFixture<T> (
223
242
* @param {ComponentFixture<T> } fixture Fixture for debugging and testing a component.
224
243
* @returns {T } Component being mounted
225
244
*/
226
- function setupComponent < T extends { ngOnChanges ? ( changes : SimpleChanges ) : void } > (
245
+ function setupComponent < T > (
227
246
config : MountConfig < T > ,
228
- fixture : ComponentFixture < T > ) : T {
229
- let component : T = fixture . componentInstance
247
+ fixture : ComponentFixture < T > ,
248
+ ) : void {
249
+ let component = fixture . componentInstance as unknown as { [ key : string ] : any } & Partial < OnChanges >
230
250
231
251
if ( config ?. componentProperties ) {
232
252
component = Object . assign ( component , config . componentProperties )
233
253
}
234
254
235
255
if ( config . autoSpyOutputs ) {
236
- Object . keys ( component ) . forEach ( ( key : string , index : number , keys : string [ ] ) => {
256
+ Object . keys ( component ) . forEach ( ( key ) => {
237
257
const property = component [ key ]
238
258
239
259
if ( property instanceof EventEmitter ) {
@@ -252,14 +272,12 @@ function setupComponent<T extends { ngOnChanges? (changes: SimpleChanges): void
252
272
acc [ key ] = new SimpleChange ( null , value , true )
253
273
254
274
return acc
255
- } , { } )
275
+ } , { } as { [ key : string ] : SimpleChange } )
256
276
257
277
if ( Object . keys ( componentProperties ) . length > 0 ) {
258
278
component . ngOnChanges ( simpleChanges )
259
279
}
260
280
}
261
-
262
- return component
263
281
}
264
282
265
283
/**
@@ -295,13 +313,18 @@ export function mount<T> (
295
313
component : Type < T > | string ,
296
314
config : MountConfig < T > = { } ,
297
315
) : Cypress . Chainable < MountResponse < T > > {
316
+ // Remove last mounted component if cy.mount is called more than once in a test
317
+ if ( activeFixture ) {
318
+ cleanup ( )
319
+ }
320
+
298
321
const componentFixture = initTestBed ( component , config )
299
- const fixture = setupFixture ( componentFixture , config )
300
- const componentInstance = setupComponent ( config , fixture )
322
+
323
+ activeFixture = setupFixture ( componentFixture , config )
301
324
302
325
const mountResponse : MountResponse < T > = {
303
- fixture,
304
- component : componentInstance ,
326
+ fixture : activeFixture ,
327
+ component : activeFixture . componentInstance ,
305
328
}
306
329
307
330
const logMessage = typeof component === 'string' ? 'Component' : componentFixture . name
@@ -338,8 +361,4 @@ getTestBed().initTestEnvironment(
338
361
} ,
339
362
)
340
363
341
- setupHooks ( ( ) => {
342
- // Not public, we need to call this to remove the last component from the DOM
343
- getTestBed ( ) [ 'tearDownTestingModule' ] ( )
344
- getTestBed ( ) . resetTestingModule ( )
345
- } )
364
+ setupHooks ( cleanup )
0 commit comments