Skip to content

bahmutov/cypress-movie

Repository files navigation

cypress-movie ci status renovate-app badge cypress version

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)

Video at 1920x1080

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.

Install

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"
}

Details

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

Options

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.

Commands

You can include these commands from the Cypress support file

// cypress/support/index.js
import 'cypress-movie/commands'

Toast

// all parameters are optional
cy.toast('Filters: Active / Completed / All', {
  duration: 3000,
  blocking: true,
})

Toast image

Text

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
})

Text command

See cypress/integration/text-spec.js

Arrows

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',
})

Arrow gif

See cypress/integration/arrow-spec.js for examples

cy.screenshot

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.

Continuous Integration

I could reliably generate 1920x1080 movies on CI only by using headless Chrome browser. For example see GitHub Actions ci.yml file.

Feedback

If you have ideas in what directions this could go - please open an issue in this repo. I would love to hear them.

Debugging

Run project with DEBUG=cypress-movie environment variable to see verbose debug logs

Movies

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

Example movie

Only the test itself is captured, without any hooks.

Arguments

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

Small print

Author: Gleb Bahmutov <[email protected]> © 2017

License: MIT - do anything with the code, but don't blame me if it does not work.