Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(angular): handle mounting teardown before tests #23098

Merged
merged 6 commits into from Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
58 changes: 27 additions & 31 deletions npm/angular/src/mount.ts
Expand Up @@ -19,6 +19,9 @@ import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing'
import {
setupHooks,
} from '@cypress/mount-utils'

/**
* Additional module configurations needed while mounting the component, like
Expand Down Expand Up @@ -82,14 +85,6 @@ export type MountResponse<T> = {
*/
fixture: ComponentFixture<T>

/**
* Configures and initializes environment and provides methods for creating components and services.
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/TestBed
*/
testBed: TestBed

/**
* The instance of the root component class
*
Expand Down Expand Up @@ -134,41 +129,29 @@ function bootstrapModule<T> (
*
* @param {Type<T> | string} component Angular component being mounted or its template
* @param {MountConfig} config TestBed configuration passed into the mount function
* @returns {TestBed} TestBed
* @returns {Type<T>} componentFixture
*/
function initTestBed<T> (
component: Type<T> | string,
config: MountConfig<T>,
): { testBed: TestBed, componentFixture: Type<T> } {
): Type<T> {
const { providers, ...configRest } = config

const testBed: TestBed = getTestBed()

testBed.resetTestEnvironment()

testBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
{
teardown: { destroyAfterEach: false },
},
)

const componentFixture = createComponentFixture(component) as Type<T>

testBed.configureTestingModule({
TestBed.configureTestingModule({
...bootstrapModule(componentFixture, configRest),
})

if (providers != null) {
testBed.overrideComponent(componentFixture, {
TestBed.overrideComponent(componentFixture, {
add: {
providers,
},
})
}

return { testBed, componentFixture }
return componentFixture
}

@Component({ selector: 'cy-wrapper-component', template: '' })
Expand Down Expand Up @@ -196,16 +179,15 @@ function createComponentFixture<T> (
* Creates the ComponentFixture
*
* @param {Type<T>} component Angular component being mounted
* @param {TestBed} testBed TestBed
* @param {MountConfig<T>} config MountConfig

* @returns {ComponentFixture<T>} ComponentFixture
*/
function setupFixture<T> (
component: Type<T>,
testBed: TestBed,
config: MountConfig<T>,
): ComponentFixture<T> {
const fixture = testBed.createComponent(component)
const fixture = TestBed.createComponent(component)

fixture.whenStable().then(() => {
fixture.autoDetectChanges(config.autoDetectChanges ?? true)
Expand Down Expand Up @@ -277,12 +259,11 @@ export function mount<T> (
component: Type<T> | string,
config: MountConfig<T> = { },
): Cypress.Chainable<MountResponse<T>> {
const { testBed, componentFixture } = initTestBed(component, config)
const fixture = setupFixture(componentFixture, testBed, config)
const componentFixture = initTestBed(component, config)
const fixture = setupFixture(componentFixture, config)
const componentInstance = setupComponent(config, fixture)

const mountResponse: MountResponse<T> = {
testBed,
fixture,
component: componentInstance,
}
Expand Down Expand Up @@ -311,3 +292,18 @@ export const createOutputSpy = <T>(alias: string) => {

return emitter as any
}

// Only needs to run once, we reset before each test
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
{
teardown: { destroyAfterEach: false },
},
)

setupHooks(() => {
// Not public, we need to call this to remove the last component from the DOM
TestBed['tearDownTestingModule']()
TestBed.resetTestingModule()
})
8 changes: 0 additions & 8 deletions npm/webpack-dev-server/cypress/e2e/angular.cy.ts
Expand Up @@ -69,13 +69,5 @@ for (const project of WEBPACK_REACT) {
cy.waitForSpecToFinish()
cy.get('.passed > .num').should('contain', 1)
})

it('proves out mount API', () => {
cy.visitApp()

cy.contains('mount.cy.ts').click()
cy.waitForSpecToFinish()
cy.get('.passed > .num').should('contain', 10)
})
})
}
10 changes: 10 additions & 0 deletions system-tests/project-fixtures/angular/src/app/mount.cy.ts
Expand Up @@ -95,4 +95,14 @@ describe("angular mount", () => {
cy.get('button').click()
cy.get('@clickedSpy').should('have.been.calledWith', true)
})

describe("teardown", () => {
beforeEach(() => {
cy.get("[id^=root]").should("not.exist");
});

it("should mount", () => {
cy.mount(ButtonOutputComponent);
});
});
});
16 changes: 16 additions & 0 deletions system-tests/test/component_testing_spec.ts
Expand Up @@ -106,3 +106,19 @@ describe(`React major versions with Webpack`, function () {
})
}
})

const ANGULAR_MAJOR_VERSIONS = ['13', '14']

describe(`Angular CLI major versions`, () => {
systemTests.setup()

for (const majorVersion of ANGULAR_MAJOR_VERSIONS) {
systemTests.it(`v${majorVersion} with mount tests`, {
project: `angular-${majorVersion}`,
spec: 'src/app/mount.cy.ts',
testingType: 'component',
browser: 'chrome',
expectedExitCode: 0,
})
}
})