Cypress
Set up Cypress for end-to-end testing and integrate test results with TestKase.
Overview
Cypress is a JavaScript end-to-end testing framework built for the modern web. It features time-travel debugging, automatic waiting, real-time reloads, and consistent results with its unique architecture that runs tests directly in the browser.
To integrate Cypress results with TestKase, use either:
--format junitwith JUnit XML output (viamocha-junit-reporter)--format cypresswith Mochawesome JSON output (viacypress-mochawesome-reporter)
Prerequisites
- Node.js 18+
- A web application to test (running locally or deployed)
Installation
Install Cypress as a dev dependency:
npm install --save-dev cypressOpen Cypress for the first time to generate the default directory structure:
npx cypress openThis creates the cypress/ directory with scaffolded folders and example specs.
Project Setup
Create or update cypress.config.js in your project root:
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
specPattern: 'cypress/e2e/**/*.cy.{js,ts}',
supportFile: 'cypress/support/e2e.js',
},
});Directory Structure
After setup, your Cypress project will have this structure:
cypress/
e2e/ # Test spec files
fixtures/ # Test data (JSON files)
support/ # Custom commands and setup
e2e.js # Support file loaded before each spec
cypress.config.jsWriting Tests
Create a test file (e.g., cypress/e2e/login.cy.js):
// cypress/e2e/login.cy.js
describe('Login', () => {
beforeEach(() => {
cy.visit('/login');
});
it('[48271] should login with valid credentials', () => {
cy.get('[data-testid="email"]').type('user@example.com');
cy.get('[data-testid="password"]').type('password123');
cy.get('[data-testid="login-button"]').click();
cy.url().should('include', '/dashboard');
});
it('[48272] should display error for invalid password', () => {
cy.get('[data-testid="email"]').type('user@example.com');
cy.get('[data-testid="password"]').type('wrong');
cy.get('[data-testid="login-button"]').click();
cy.get('.error-message').should('be.visible');
});
it('[48273] should require email field', () => {
cy.get('[data-testid="login-button"]').click();
cy.get('[data-testid="email-error"]').should('contain', 'Email is required');
});
});Each test name includes a 5-digit Automation ID in square brackets. The @testkase/reporter CLI
extracts these IDs using the regex \[(\d{5})\]. For the example above, the extracted Automation IDs are:
48271→ linked to the "valid login" test case in TestKase48272→ linked to the "invalid password" test case in TestKase48273→ linked to the "email required" test case in TestKase
Generate Automation IDs in TestKase first, then embed them in your it() names. The [XXXXX] pattern
can appear anywhere in the test name — the reporter extracts all 5-digit IDs found in brackets.
Running Tests
Run tests in headless mode:
npx cypress runOpen the interactive Test Runner:
npx cypress openGenerating JUnit XML Output
Install the mocha-junit-reporter package:
npm install --save-dev mocha-junit-reporterAdd the reporter configuration to cypress.config.js:
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
specPattern: 'cypress/e2e/**/*.cy.{js,ts}',
supportFile: 'cypress/support/e2e.js',
},
reporter: 'mocha-junit-reporter',
reporterOptions: {
mochaFile: 'test-results/junit-[hash].xml',
toConsole: false,
},
});Then run tests as usual:
npx cypress runThe JUnit XML files will be written to the test-results/ directory.
The [hash] placeholder in mochaFile ensures each spec file generates a unique XML file, preventing
overwrites when running multiple specs. You can point the reporter to a specific file or use a glob pattern.
TestKase Integration
After generating the JUnit XML files, report results to TestKase:
npx @testkase/reporter report \
--token $TESTKASE_PAT \
--project-id PRJ-1 \
--org-id 1173 \
--cycle-id TCYCLE-5 \
--format junit \
--results-file "test-results/junit-*.xml"--cycle-id is optional. If not provided, results are reported to TCYCLE-1 — the master test cycle for the project.
If you have a single output file (without the [hash] pattern), point to it directly:
--results-file test-results/junit.xmlAutomation ID Mapping
The reporter extracts 5-digit Automation IDs from Cypress test names using the [XXXXX] bracket pattern:
| Test Code | Extracted ID |
|---|---|
it('[48271] should login with valid credentials', ...) | 48271 |
it('[48272] should display error for invalid password', ...) | 48272 |
describe('Cart', () => { it('[48273] calculates total', ...) }) | 48273 |
The [XXXXX] pattern can appear anywhere in the it() name. The describe block structure does
not affect the Automation ID — only the 5-digit number inside brackets matters.
Complete Example
1. Test File
// cypress/e2e/login.cy.js
describe('Login', () => {
beforeEach(() => {
cy.visit('/login');
});
it('[48271] should login with valid credentials', () => {
cy.get('[data-testid="email"]').type('user@example.com');
cy.get('[data-testid="password"]').type('password123');
cy.get('[data-testid="login-button"]').click();
cy.url().should('include', '/dashboard');
});
it('[48272] should display error for invalid password', () => {
cy.get('[data-testid="email"]').type('user@example.com');
cy.get('[data-testid="password"]').type('wrong');
cy.get('[data-testid="login-button"]').click();
cy.get('.error-message').should('be.visible');
});
});2. Run Tests (JUnit output configured in cypress.config.js)
npx cypress run3. Report Results to TestKase
npx @testkase/reporter report \
--token $TESTKASE_PAT \
--project-id PRJ-1 \
--org-id 1173 \
--cycle-id TCYCLE-5 \
--format junit \
--results-file "test-results/junit-*.xml"Troubleshooting
Multiple XML files generated
When using mocha-junit-reporter with the [hash] pattern, each spec file produces a separate XML file.
This is expected behavior. You have two options:
-
Use a glob pattern to pass all files to the reporter:
--results-file "test-results/junit-*.xml" -
Use a single file by removing the
[hash]placeholder (note that results from multiple specs will overwrite each other unless you run a single spec):reporterOptions: { mochaFile: 'test-results/junit.xml', }
Cypress not finding test files
Verify that your specPattern in cypress.config.js matches your test file names and locations:
e2e: {
specPattern: 'cypress/e2e/**/*.cy.{js,ts}',
}Common issues:
- Test files use
.spec.jsextension instead of.cy.js— update the pattern to include both - Test files are in the wrong directory — ensure they are under
cypress/e2e/ - The
e2econfig block is missing fromcypress.config.js
baseUrl connection refused
Cypress cannot connect to your application if it is not running. Ensure your dev server is started before running tests:
# Start your app first
npm run dev &
# Then run Cypress
npx cypress runFor CI environments, use the start-server-and-test package to start the server and run tests in sequence:
npm install --save-dev start-server-and-test{
"scripts": {
"dev": "next dev",
"test:e2e": "start-server-and-test dev http://localhost:3000 'cypress run'"
}
}