Exploring how one can generate product demo videos from Cypress tests
Example capturing high resolution video of the test run with additional message pop ups (using tiny-toast library injected on cy.visit
)
The movies are generated at 1920x1080, the headless browser is set to the same size. The command log is hidden, thus the app takes the entire video. Here is a still from a movie generated on CI with its dimensions shown.
Related video: WeAreDevs presentation - start watching at minute 32. Presentation slides at slides.com/bahmutov/e2e-in-the-future.
Requires Node v10+
# using NPM
$ npm i -D cypress-movie
# using Yarn
$ yarn add -D cypress-movie
Now you should be able to use cypress-movie
command, see Movies
This project requires native extensions to perform image resizing, thus in your project's cypress.json
file should include
{
"nodeVersion": "system"
}
When using cypress run
the headless browser is set to use 1920x1080 resolution from the cypress/plugins/index.js file. The viewport width and height are also set to the same values using the config object. During the test run, the Command Log is hidden before the test, see cypress/support/index.js file.
Thus, if you have Chrome browser installed, generate full movies in cypress/videos
npm run chrome
You can control the plugin via environment variables or env
object inside cypress.json file.
{
"env": {
"cypress-movie": {
"enabled": true,
"cursorTracking": {
"enabled": false,
"shape": "dot" // Valid values: "dot", "arrow"
},
"width": 1920,
"height": 640
}
}
}
Note: these options change the movie output, they do not disable individual commands.
You can include these commands from the Cypress support file
// cypress/support/index.js
import 'cypress-movie/commands'
// all parameters are optional
cy.toast('Filters: Active / Completed / All', {
duration: 3000,
blocking: true,
})
You can place a text at the bottom of the page
// all parameters are optional
cy.text('This is some text', {
duration: 2000, // how long the text should be there
blocking: true, // wait for the text to hide
textSize: '20pt', // CSS text height
})
See cypress/integration/text-spec.js
You can draw arrows to point at DOM elements using the child cy.arrow()
command
// all options are optional
cy.get('.new-todo').arrow({
duration: 3000,
blocking: true,
pointAt: 'bottomLeft', // or "bottomRight"
offsetX: 0, // move the tip by X pixels
offsetY: 0, // move the tip by Y pixels
strokeWidth: 5 // SVG line width, pixels
color: 'orange', // color name or hex string like "#ff00ff"
})
You can add a text label to the arrow
cy.get('.new-todo').arrow({
text: 'Completed todos only',
textSize: '5vh',
})
See cypress/integration/arrow-spec.js for examples
This module overwrites cy.screenshot command. If you are using cy.screenshot(..., {capture: 'viewport'})
with headless Chrome, then Chrome Debugger Protocol will be used to take the full resolution screenshot. You can resize the output image while preserving the aspect ratio by adding an optional maxWidth
parameter.
cy.screenshot('finish', { capture: 'viewport', maxWidth: 800 })
See cypress/integration/screenshot-spec.js for example.
I could reliably generate 1920x1080 movies on CI only by using headless Chrome browser. For example see GitHub Actions ci.yml file.
If you have ideas in what directions this could go - please open an issue in this repo. I would love to hear them.
Run project with DEBUG=cypress-movie
environment variable to see verbose debug logs
You can record an individual test into a Gif or an MP4 file. Run all tests or a single spec using cypress-movie
command; it will run all tests, but will extract every test if its title contains the 🎥
emoji.
npx cypress-movie
# or use --spec name or wildcard pattern
npx cypress-movie --spec cypress/integration/my-spec.js
npx cypress-movie --spec 'cypress/integration/movies*-spec.js'
The individual movies will be saved in "cypress/movies" folder.
Example gif from cypress/integration/arrow-spec.js
Only the test itself is captured, without any hooks.
You can pass a few arguments to control the output GIF
npx cypress-movie --width 640 --fps 30 --format gif
# --width is the output gif resolution, pixels
# height will be set automatically to preserve the aspect ratio
# default 960
# --fps is frames per second in the output gif
# default 10
# --format is gif or mp4
# default gif
# --browser is browser binary path or name like "chrome", "firefox", "electron"
# default chrome
Author: Gleb Bahmutov <[email protected]> © 2017
License: MIT - do anything with the code, but don't blame me if it does not work.