cypress-svelte-unit-test
Component testing for Svelte apps using the open source Cypress.io E2E test runner v4.5.0+
Videos
I have recorded a series of short (3-4 minutes) videos showing Cypress + cypress-svelte-unit-test
in action. See the playlist
- Writing the first component test
- Pass props to the component
- Testing message dispatch
- Style component during testing
- Stubbing window.fetch
- Using experimental fetch polyfill
Install
Requires Node version 8 or above and Cypress v4.5.0+
# Install this plugin and test spec preprocessor
npm install --save-dev cypress-svelte-unit-test
# if Cypress is not installed already
npx install --save-dev cypress
- Tell Cypress to use your
rollup.config.js
to bundle specs using cypress/plugins/index.js:
module.exports = (on) => {
// @bahmutov/cy-rollup is already a dependency of cypress-svelte-unit-test
const filePreprocessor = require('@bahmutov/cy-rollup')
on('file:preprocessor', filePreprocessor())
}
⚠️ Turn the experimental component support on in yourcypress.json
. You can also specify where component spec files are located. For example, to have them located insrc
folder use:
{
"experimentalComponentTesting": true,
"componentFolder": "src",
"testFiles": "**/*spec.js"
}
See cypress.json in this project.
- Write a test!
import HelloWorld from './HelloWorld.svelte'
import { mount } from 'cypress-svelte-unit-test'
it('shows greeting', () => {
mount(HelloWorld, {
props: {
name: 'World',
},
})
cy.contains('h1', 'Hello World!')
})
Watch Writing the first component test
Known issues
- need to load images differently to transform relative paths
Code coverage
Instrument your code
See rollup.config.js how you can instrument source files. In short:
// npm i -D rollup-plugin-istanbul
import istanbul from 'rollup-plugin-istanbul'
plugins: [
istanbul({
include: ['cypress/components/**'],
exclude: ['**/*spec.js'],
}),
]
In Cypress iframe you should see the code coverage object under window.__coverage__
.
Coverage report
To merge coverage and generate reports we need to use @cypress/code-coverage plugin.
npm i -D @cypress/code-coverage
Add it to your cypress/support/index.js file
import '@cypress/code-coverage/support'
Add the plugin to your cypress/plugins/index.js file
module.exports = (on, config) => {
const filePreprocessor = require('@bahmutov/cy-rollup')
on('file:preprocessor', filePreprocessor())
require('@cypress/code-coverage/task')(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}
After the tests finish, you should see messages in the Command Log
And find generated reports in coverage
folder. For example, to open the HTML report
open coverage/lcov-report/index.html
Warning: I am not sure the coverage numbers are making 100% sense for Svelte files.
Svelte v3
This component adaptor is meant for Svelte v3. If you need Svelte v2 support, check out branch svelte-v2
Use
Import your Svelte component and mount using the provided function. Pass component options and global document options (like a global CSS)
Props
/// <reference types="cypress" />
import App from '../components/ChainedBalls.svelte'
import { mount } from 'cypress-svelte-unit-test'
describe('SVG animation', () => {
it('shows chained balls', () => {
cy.viewport(960, 500)
const style = `
line {
stroke: gray;
stroke-width: 2px;
}
`
mount(
App,
{
props: {
width: 960,
height: 500,
},
},
{ style },
)
cy.get('circle').should('have.length', 50)
})
})
Watch Pass props to the component
Styles
You can use local styles, local CSS file path (relative to the the Cypress project root) or external stylesheets. See styles example. You can surround the component with HTML and mount the component into the element with ID "here", see cypress/components/mount-html
const props = {...}
mount(HelloWorld, props, {
html: `
<div class="test-page">
this is a test
<div id="here"></div>
this is after component
</div>
`,
style: `
body {
background: pink
}
.test-page {
background: cyan
}
#here {
background: yellow
}
`,
})
Watch Style component during testing
Callbacks
You can listen for messages from the component by supplying an object of callbacks.
mount(TodoItem, {
props: {
id: 'todo-id',
text: 'write a test',
complete: false,
},
callbacks: {
remove: cy.stub().as('remove'),
toggle: cy.stub().as('toggle'),
'inner-message': cy.stub().as('inner-message'),
},
})
See cypress/components/callbacks.
Watch Testing message dispatch
Examples
Basic examples
Svelte components copied from https://svelte.dev/examples
All components and tests are in cypress/components folder
Test | Description |
---|---|
animation | Chained balls SVG animation |
callbacks | Listen for messages dispatched from the component |
global-handlers | Attaches event listeners to document and window |
hello | Hello, component testing! |
image | Loading Rick-Roll image |
named-exports | Nice Audio player test |
nested | Checking nested components and local styles |
pin | Keypad pin test |
reactive | Svelte reactive props, declarations and statements |
rx | Fetching GitHub users as a reactive stream |
styles | Shows inline, CSS and external stylesheet styles in spec |
tutorial | A few components and tests from Svelte tutorial |
mocking-fetch | Mocking window.fetch before mounting the component |
mocking-network | Polyfills window.fetch automatically and tests the component |
External examples
You can find larger Svelte example application with component tests under GitHub topic cypress-svelte-unit-test-example
Name | Description |
---|---|
svelte-ts-example | Writing Svelte components and tests using TypeScript |
Related tools
Same feature for unit testing components from other framesworks using Cypress
- cypress-vue-unit-test
- cypress-react-unit-test
- cypress-cycle-unit-test
- cypress-svelte-unit-test
- cypress-angular-unit-test
- cypress-hyperapp-unit-test
- cypress-angularjs-unit-test
Small print
Author: Gleb Bahmutov <[email protected]> © 2018
License: MIT - do anything with the code, but don't blame me if it does not work.
Support: if you find any problems with this module, email / tweet / open issue on Github
MIT License
Copyright (c) 2018 Gleb Bahmutov <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.