JavaScript · Cypress
Project management with Cypress
A sprint Kanban you can drag across (or use the move menu), a create-issue modal with label chips, issue pages with sub-task progress and comments, an SVG burndown chart, and a backlog with bulk move to sprint.
App under test
🗂️ TaskBoard
- URL
- /apps/projects
- Sprint
- Sprint 14 · day 6 of 10
- Issue keys
- PA-1 … (next PA-9)
- Login
- not required
Scenarios to automate
Work top to bottom — each one adds a new technique.
- 1
Assignee avatars filter
Beginnerfilter-assignee-* toggles (aria-pressed) and only-mine narrow the board; assert board-count.
- 2
Create-issue validation
Intermediatesave-task with blanks shows task-errors and error-*; a short title is rejected.
- 3
Chips with Enter
IntermediateType in label-input and press Enter (or add-label); remove with remove-label-*.
- 4
Drag across columns
AdvancedDrag a task-card onto col-review (HTML5 DnD); or use move-task-<key>. col-count-* updates.
- 5
Sub-task progress
BeginnerAdd sub-tasks, tick subtask-0 and assert subtask-progress “1/2”.
- 6
SVG chart data
Advancedburndown-point circles carry data-day/data-points; the last point equals burndown-remaining.
- 7
Bulk move
IntermediateTick select-<key> in the backlog and move-to-sprint; the issues appear on the board.
Sample Cypress suite
A working starting point that finds elements every way Cypress can — by role, label, text, id, name, CSS, XPath and data-testid — so you practice them all. Pick your language, switch to data-testid only to compare, or try your own in the Locator Playground.
Cypress runs inside the browser, so it only supports JavaScript and TypeScript — there is no Python, Java or C# version of Cypress. For those languages, see Selenium or Playwright.
// Uses the getByTestId custom command from the Cypress setup (cypress/support/commands.js).
// Locators in this suite: cy.contains ×6 · #id ×2 · [name] ×2 · [placeholder] ×3 · [aria-label] ×2 · getByTestId ×14
describe('TaskBoard — project management', () => {
it('creates an issue and finishes it in the sprint', () => {
cy.visit('/apps/projects');
cy.getByTestId('create-task').click();
cy.get('#task-title').type('Add login rate limiting');
cy.get('[name="task-type"]').select('story');
cy.get('#task-priority').select('high');
cy.get('[name="task-assignee"]').select('amir');
cy.getByTestId('task-points').select('5');
cy.get('[placeholder="Type and press Enter"]').type('security');
cy.contains('button', 'Add').click();
cy.getByTestId('label-chip').should('contain', 'security');
cy.getByTestId('save-task').click();
cy.getByTestId('board-toast').should('contain', 'PA-9 created');
cy.get('[aria-label="To do"]').should('contain', 'Add login rate limiting');
cy.contains('a', 'Add login rate limiting').click();
cy.get('[placeholder="Add a sub-task"]').type('Write tests');
cy.contains('button', 'Add').click();
cy.get('[placeholder="Add a sub-task"]').type('Implement limiter');
cy.contains('button', 'Add').click();
cy.getByTestId('subtask-0').check();
cy.getByTestId('subtask-progress').should('contain', '1/2');
cy.getByTestId('back-to-board').click();
cy.getByTestId('move-task-PA-9').select('done');
cy.get('[aria-label="Done"]').should('contain', 'Add login rate limiting');
cy.contains('a', 'Sprint report').click();
cy.getByTestId('burndown-total').should('contain', '26 pts');
cy.getByTestId('burndown-remaining').should('contain', '18 pts');
cy.contains('a', 'Backlog').click();
cy.getByTestId('select-PA-6').check();
cy.getByTestId('move-to-sprint').click();
cy.getByTestId('backlog-count').should('contain', '2 issues');
});
});