Volto Cypress Writer
Use this skill when writing, updating, reviewing, or debugging Cypress tests for Volto add-ons in frontend/src/addons/*.
Workflow
- Inspect the target add-on before editing:
cypress.config.jscypress/support/e2e.jscypress/support/commands.js- existing
cypress/support/*.jshelpers - nearby
cypress/e2e/*.cy.jsspecs
- Follow the add-on's local file layout, naming, and helper style.
- Put specs in
frontend/src/addons/<addon>/cypress/e2e/*.cy.js. - Put reusable feature helpers in
cypress/support/<feature>.js. - Keep global Cypress commands minimal; prefer imported helpers for feature-specific flows.
- Improve fragile selectors and waits when touching nearby test code.
UI-First Rule
New tests must set up state, navigate, edit, save, and assert through the browser UI.
- Do not add or call
cy.request()setup helpers for new tests unless the user explicitly asks for legacy/API-seeded style. - Existing REST helpers such as
autologin,createContent, andremoveContentmay be read for context, but do not copy them into new UI-first flows. - Use the UI for the behavior under test even when an older suite uses API shortcuts.
- If UI-only setup is impractical for a narrow reason, stop and explain the constraint before changing the approach.
Selectors
- Prefer stable
data-cyordata-testidselectors. - If stable selectors are missing and component edits are in scope, add explicit test selectors to the component instead of relying on DOM shape.
- Use role, label, placeholder, or visible text when they describe the user's intent.
- Avoid positional selectors like
:nth-child()and style-driven selectors like.ui.basic.icon.button.... - If Volto or Semantic UI markup forces a fragile selector, hide it behind a named helper such as
openBlockChooser()orsaveCurrentPage(). - Keep assertions user-visible where possible: URL, heading, block text, saved view output, modal state, toolbar state, validation message.
Reliability
- Each spec must pass independently; do not depend on previous tests.
- Use
beforeEachfor browser state and content setup. - Prefer Cypress retry-ability:
cy.get(...).should(...),cy.contains(...).should(...), and URL assertions. - Prefer
cy.intercept().as()andcy.wait('@alias')for network-dependent transitions. - Avoid arbitrary
cy.wait(ms). If a Volto editor limitation requires one, keep it local and add a short comment explaining why. - Avoid per-command
{ timeout: ... }; wait for observable UI or network state instead. If a timeout override is unavoidable, keep it local and document the reason. - Split chains after actions before assertions:
cy.get('[data-cy="toolbar-save"]').click();
cy.get('[data-cy="view-page"]').should('be.visible');
- Avoid
{ force: true }unless Volto overlays or hidden controls make it unavoidable; explain the reason in a helper or nearby comment. - Do not suppress uncaught exceptions broadly unless the test target is a known third-party integration and the user accepts that tradeoff.
Volto Add-on Patterns
- Add-on Cypress config usually sets
baseUrl: 'http://localhost:3000'and passes Plone API settings throughCYPRESS_API_PATH,RAZZLE_DEV_PROXY_API_PATH, orRAZZLE_INTERNAL_API_PATH. - Add-on tests normally live beside the add-on, not in root
frontend/cypress/e2e. - Cypress tests for add-ons must pass against both Volto 18 and Volto 17 unless the user explicitly scopes the task to one version.
- For block tests, cover the edit flow and the saved view:
- create or navigate to a page through the UI
- add the block through the block chooser
- configure the fields through the sidebar or inline editor
- save
- assert the view mode output
- For editor interactions, prefer existing Slate helpers if the add-on already has them. Add focused helpers only when they reduce repeated low-level selection/type logic.
Commands
Run add-on Cypress commands from frontend/src/addons/<addon> when the add-on has its own Makefile.
Start by checking the add-on's available targets:
make help
Default Volto 18 flow:
make; make start
make cypress-run
make cypress-open
Volto 17 compatibility flow:
VOLTO_VERSION=17 make; make start
make cypress-run
VOLTO_VERSION selects the add-on environment during make; it does not change Cypress itself. Run Cypress against the Volto version that is currently started.
Run one spec from the add-on directory:
../../../node_modules/cypress/bin/cypress run --spec "cypress/e2e/<spec>.cy.js"
If the local binary is not convenient, npx can run the installed Cypress package:
npx cypress run --spec "cypress/e2e/<spec>.cy.js"
Useful debugging and CI-style targets:
make shell
make check-ci
make cypress-ci
make shell opens a shell in the add-on frontend container. make check-ci and make cypress-ci are common hidden targets in these add-ons; confirm they exist in the target add-on's Makefile before using them.
Useful non-Cypress checks:
make lint
make prettier
make stylelint
make test
Use the smallest relevant command for verification. For a Cypress-only add-on change, prefer the target add-on's make cypress-run in both Volto 18 and Volto 17 environments.
Review Checklist
- The test exercises the feature like a user, not by mutating backend state.
- Selectors are stable or wrapped in named helpers.
- The test asserts both edit-time behavior and saved output when relevant.
- The suite can run test cases independently.
- The Cypress behavior works in both Volto 18 and Volto 17, or the version-specific limitation is clearly reported.
- Network or async transitions wait on observable conditions, not fixed sleeps.
- Per-command
{ timeout: ... }overrides are avoided or explicitly justified. - Helpers are local to the add-on unless multiple specs in the add-on need them.
- The command used to verify is reported back to the user.