{"id":15552144,"url":"https://github.com/bahmutov/cypress-movie","last_synced_at":"2025-09-28T22:30:29.185Z","repository":{"id":37036458,"uuid":"140767343","full_name":"bahmutov/cypress-movie","owner":"bahmutov","description":"Generate movies from your Cypress end-to-end tests","archived":false,"fork":false,"pushed_at":"2024-12-24T05:20:32.000Z","size":6993,"stargazers_count":97,"open_issues_count":28,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-12-27T20:29:35.462Z","etag":null,"topics":["cypress","cypress-io","experiment","proof-of-concept"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bahmutov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-12T21:40:17.000Z","updated_at":"2024-11-27T12:03:55.000Z","dependencies_parsed_at":"2023-11-11T06:22:44.339Z","dependency_job_id":"2301848d-03fb-42b5-899d-9a3f825b689f","html_url":"https://github.com/bahmutov/cypress-movie","commit_stats":{"total_commits":121,"total_committers":10,"mean_commits":12.1,"dds":0.4380165289256198,"last_synced_commit":"70b0226534624e5b78244f14f77b2e07dd72d77f"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-movie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-movie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-movie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcypress-movie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bahmutov","download_url":"https://codeload.github.com/bahmutov/cypress-movie/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234565112,"owners_count":18853251,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cypress","cypress-io","experiment","proof-of-concept"],"created_at":"2024-10-02T14:09:29.713Z","updated_at":"2025-09-28T22:30:28.581Z","avatar_url":"https://github.com/bahmutov.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cypress-movie [![ci status][ci image]][ci url] [![renovate-app badge][renovate-badge]][renovate-app] ![cypress version](https://img.shields.io/badge/cypress-7.7.0-brightgreen)\n\n\u003c!--\n[![Trees planted this month](https://cloudsynth.com/tree-badges/i/01EJRHZHPB709P9DYCSR7FGHYJ?period=month)](https://cloudsynth.com/tree-badges/r/01EJRHZHPB709P9DYCSR7FGHYJ)\n--\u003e\n\n\u003e Exploring how one can generate product demo videos from Cypress tests\n\nExample capturing high resolution video of the test run with additional message pop ups (using [tiny-toast](https://github.com/bahmutov/tiny-toast) library injected on `cy.visit`)\n\n![Video at 1920x1080](images/movie-screenshot.png)\n\nThe 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.\n\nRelated video: [WeAreDevs presentation](https://youtu.be/p38bIMC-YOU?t=1949) - start watching at minute 32. Presentation slides at [slides.com/bahmutov/e2e-in-the-future](https://slides.com/bahmutov/e2e-in-the-future).\n\n## Install\n\nRequires Node v10+\n\n```shell\n# using NPM\n$ npm i -D cypress-movie\n# using Yarn\n$ yarn add -D cypress-movie\n```\n\nNow you should be able to use `cypress-movie` command, see [Movies](#movies)\n\nThis project requires native extensions to perform image resizing, thus in your project's `cypress.json` file should include\n\n```json\n{\n  \"nodeVersion\": \"system\"\n}\n```\n\n## Details\n\nWhen using `cypress run` the headless browser is set to use 1920x1080 resolution from the [cypress/plugins/index.js](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](cypress/support/index.js) file.\n\nThus, if you have Chrome browser installed, generate full movies in `cypress/videos`\n\n```shell\nnpm run chrome\n```\n\n## Options\n\nYou can control the plugin via environment variables or `env` object inside [cypress.json](cypress.json) file.\n\n```js\n{\n  \"env\": {\n    \"cypress-movie\": {\n      \"enabled\": true,\n      \"cursorTracking\": {\n        \"enabled\": false,\n        \"shape\": \"dot\" // Valid values: \"dot\", \"arrow\"\n      },\n      \"width\": 1920,\n      \"height\": 640\n    }\n  }\n}\n```\n\nNote: these options change the _movie_ output, they do not disable individual commands.\n\n## Commands\n\nYou can include these commands from the Cypress support file\n\n```js\n// cypress/support/index.js\nimport 'cypress-movie/commands'\n```\n\n### Toast\n\n```js\n// all parameters are optional\ncy.toast('Filters: Active / Completed / All', {\n  duration: 3000,\n  blocking: true,\n})\n```\n\n![Toast image](images/toast.png)\n\n### Text\n\nYou can place a text at the bottom of the page\n\n```javascript\n// all parameters are optional\ncy.text('This is some text', {\n  duration: 2000, // how long the text should be there\n  blocking: true, // wait for the text to hide\n  textSize: '20pt', // CSS text height\n})\n```\n\n![Text command](gifs/text.gif)\n\nSee [cypress/integration/text-spec.js](cypress/integration/text-spec.js)\n\n### Arrows\n\nYou can draw arrows to point at DOM elements using the child `cy.arrow()` command\n\n```js\n// all options are optional\ncy.get('.new-todo').arrow({\n  duration: 3000,\n  blocking: true,\n  pointAt: 'bottomLeft', // or \"bottomRight\"\n  offsetX: 0, // move the tip by X pixels\n  offsetY: 0, // move the tip by Y pixels\n  strokeWidth: 5 // SVG line width, pixels\n  color: 'orange', // color name or hex string like \"#ff00ff\"\n})\n```\n\nYou can add a text label to the arrow\n\n```js\ncy.get('.new-todo').arrow({\n  text: 'Completed todos only',\n  textSize: '5vh',\n})\n```\n\n![Arrow gif](gifs/arrows-from-different-directions-movie.gif)\n\nSee [cypress/integration/arrow-spec.js](cypress/integration/arrow-spec.js) for examples\n\n### cy.screenshot\n\nThis module overwrites [cy.screenshot](https://on.cypress.io/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.\n\n```js\ncy.screenshot('finish', { capture: 'viewport', maxWidth: 800 })\n```\n\nSee [cypress/integration/screenshot-spec.js](cypress/integration/screenshot-spec.js) for example.\n\n## Continuous Integration\n\nI could reliably generate 1920x1080 movies on CI only by using headless Chrome browser. For example see [GitHub Actions ci.yml](.github/workflows/ci.yml) file.\n\n## Feedback\n\nIf you have ideas in what directions this could go - please open an issue in this repo. I would love to hear them.\n\n## Debugging\n\nRun project with `DEBUG=cypress-movie` environment variable to see verbose debug logs\n\n## Movies\n\nYou 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.\n\n```\nnpx cypress-movie\n# or use --spec name or wildcard pattern\nnpx cypress-movie --spec cypress/integration/my-spec.js\nnpx cypress-movie --spec 'cypress/integration/movies*-spec.js'\n```\n\nThe individual movies will be saved in \"cypress/movies\" folder.\n\nExample gif from [cypress/integration/arrow-spec.js](cypress/integration/arrow-spec.js)\n\n![Example movie](gifs/arrows-from-different-directions-movie.gif)\n\nOnly the test itself is captured, without any hooks.\n\n## Arguments\n\nYou can pass a few arguments to control the output GIF\n\n```shell\nnpx cypress-movie --width 640 --fps 30 --format gif\n# --width is the output gif resolution, pixels\n#     height will be set automatically to preserve the aspect ratio\n#     default 960\n# --fps is frames per second in the output gif\n#     default 10\n# --format is gif or mp4\n#     default gif\n# --browser is browser binary path or name like \"chrome\", \"firefox\", \"electron\"\n#     default chrome\n```\n\n### Small print\n\nAuthor: Gleb Bahmutov \u0026lt;gleb.bahmutov@gmail.com\u0026gt; \u0026copy; 2017\n\n- [@bahmutov](https://twitter.com/bahmutov)\n- [glebbahmutov.com](https://glebbahmutov.com)\n- [blog](https://glebbahmutov.com/blog)\n\nLicense: MIT - do anything with the code, but don't blame me if it does not work.\n\n[ci image]: https://github.com/bahmutov/cypress-movie/workflows/ci/badge.svg?branch=master\n[ci url]: https://github.com/bahmutov/cypress-movie/actions\n[renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg\n[renovate-app]: https://renovateapp.com/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fcypress-movie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbahmutov%2Fcypress-movie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fcypress-movie/lists"}