
Testing Angular Components Using Cypress

Jest Limitations
it can be hard to predict before implementing the component, it can be complex or have an important surface, different interactions can produce the same result. This is why this interaction (i.e. DOM interaction) can be considered as an implementation detail that should not spill out in the tests.
<div>
<h1 *ngIf="condition">Marmicode</h1>
</div>
<div *ngIf="condition">
<h1>Marmicode</h1>
</div>
<div>
<h1 [class.hidden]="!condition">Marmicode</h1>
</div>
<div [class.hidden]="!condition">
<h1>Marmicode</h1>
</div>
h1
hidden
div
h1
hidden
h1
h1
no visual debugging : the most common way of debugging DOM tests in Jest is to dump and analyze HTML snapshots. no time travel : as there is no native visual debugging, there is no easy way to visualize how every action affects the tested component or block. no visual regression testing : without visual rendering, and real browsers, we can't detect visual regressions (e.g. CSS issues) .
Cypress
the test execution time takes more than 100ms, when the test fails, it takes more than 1 minute to locate the file or function containing the root cause of the issue, parallelization needs some effort (e.g. creating distinct accounts / instances / workspaces), some outputs are hard to predict (e.g. number of items that will be displayed).
visual debugging : Cypress runs on some real browsers (Firefox, Chromium-based: Chrome, Edge, Electron) so you can easily debug the DOM. time travel : Cypress saves DOM snapshots after every command so you can easily inspect the DOM before and after every action. visual regression testing : You can easily extend your tests with visual regression tests. Some tools like Percy will not only compare screenshots, but they will render the DOM snapshot on different browsers and viewport dimensions then compare them to the previous builds.
cy.visit()
Cypress + Storybook Combination Limitations
cy.visit('/iframe.html?id=blogpost--default');
cy.get('h1').contains('Testing Angular Components Using Cypress')
less control : we have no way to control inputs, providers, child components, etc... it needs exposing all tested components in Storybook : even though most components we will want to test using Cypress are presentational components that deserve to be exposed in Storybook, we might want to test some container components, blocks, or specific components that shouldn't be exposed in Storybook, we might not need Storybook : if we don't already need Storybook, it might feel cumbersome to add it as a non-negligible layer in the path between Cypress and the tested components, no watch mode : changing the code of a tested component or block will reload the Storybook preview but will not restart the test in Cypress automatically.
Cypress Component Testing
@jscutlery/cypress-mount
@jscutlery/cypress-mount
import { TitleComponent } from '.../src/title.component';
it('should display default title', () => {
mount(TitleComponent);
cy.get('h1').contains('👋 Welcome');
});
@jscutlery/cypress-mount
@jscutlery/cypress-mount
@jscutlery/cypress-mount
Control Inputs
mount(TitleComponent, {
inputs: {appName: 'Marmicode'}
});
cy.get('h1').contains('👋 Welcome to Marmicode');
Override Providers
mount(TitleComponent, {
providers: [
{
provide: Settings,
useValue: {greetings: '🇫🇷 Bienvenue'}
}
]
});
cy.get('h1').contains('🇫🇷 Bienvenue');
Mount Template
mount(`<mc-title></mc-title>`, {
imports: [TitleModule],
})
Storybook & Component Story Format support
@jscutlery/cypress-mount
import { Love } from '.../love.stories.ts';
describe('Love', () => {
it('should show some love', () => {
mountStory(Love);
cy.get('h1').contains('❤️');
});
});
Try it yourself
git clone https://github.com/jscutlery/test-utils
npm install
npx nx e2e cypress-mount-integration --watch
packages/cypress-mount-integration/src/components/demo.spec.ts
Where to go from here?
testing a presentational component or block, testing visual regressions, testing specific browser inconsistencies (e.g. CSS hacks we love) , components have stories in Storybook, current tests are asserting HTML snapshots (in this case, the tests are coupled to implementation details) .