Question
Cypress Component Testing in Angular Shadow Dom Components
I am trying to run Cypress component testing on a library of Angular components. Currently, all of my components have shadowDom turned on. Which seems to be causing me a problem when running multiple tests on a single component, as cypress appears to be struggling to destroy shadowDom components between it
statements.
I tried three different scenarios to get something that works and they all have problems, which I will outline below. The questions I have are:
- Am I doing something wrong to work with ShadowDom Angular components?
- If this is a Cypress issue, is there a work around I can apply to get this up and running?
I have made a minimum reproduction here: https://github.com/jclark86613/cypress-shadow-comps
Scenario 1
I mount the component in a beforeEach
the first test will pass, but the second (identical) test will fail.
ShadowDom = false, this scenario works ShadowDom = true, this scenario does not work
cy.ts
describe('TestShadowComponent', () => {
beforeEach(() => {
mount(TestShadowComponent);
})
it('should display the title', () => {
cy.get('button', {includeShadowDom: true}).should('have.text', 'My Button')
})
it('should display the title', () => {
cy.get('button', {includeShadowDom: true}).should('have.text', 'My Button')
})
})
error
TypeError
Cannot set property message of [object DOMException] which has only a getter
Because this error occurred during a before each hook we are skipping the remaining tests in the current suite: TestShadowComponent
Scenario 2
I mount the component in each it
block. This also always fails on the second identical test, but with a different error.
ShadowDom = false, this senario works ShadowDom = true, this senario does not work
cy.ts
describe('TestShadowComponent', () => {
it('should display the title', () => {
mount(TestShadowComponent);
cy.get('button', {includeShadowDom: true}).should('have.text', 'My Button')
})
it('should display the title', () => {
mount(TestShadowComponent);
cy.get('button', {includeShadowDom: true}).should('have.text', 'My Button')
})
})
error
NotSupportedError
Failed to execute 'attachShadow' on 'Element': Shadow root cannot be created on a host which already hosts a shadow tree.
Scenario 3
I mount the component once in a before
block. This scenario works for my basic tests, but they no longer detect the output spies. I suspect that using before
to mount a component is bad practice as it can allow state to bleed between tests. however, if turn shadowDom off and change before
to beforeEach
this scenario begins to work.
cy.ts
describe('TestShadowComponent', () => {
before(() => {
mount(TestShadowComponent, {autoSpyOutputs: true});
})
it('should display the title', () => {
cy.get('button', {includeShadowDom: true}).should('have.text', 'My Button')
})
it('should display the title', () => {
cy.get('button', {includeShadowDom: true}).should('have.text', 'My Button')
})
it('should click the button', () => {
cy.get('button', {includeShadowDom: true}).click()
// does click spy exists
cy.get('@clickSpy').should('have.been.called')
})
})
error
CypressError
cy.get() could not find a registered alias for: @clickSpy.
You have not aliased anything yet.