JavaScript · Cypress
CRM with Cypress
A leads table with filters, select-all and bulk assign, a new-lead modal with duplicate checks, an activity log, convert-to-deal, and a Kanban pipeline you can drag cards across.
App under test
📈 SalesPulse
- URL
- /apps/crm
- sales@crm.dev
- Password
- Crm@123
- Stages
- Qualified → Won/Lost
Scenarios to automate
Work top to bottom — each one adds a new technique.
- 1
Table filters
BeginnerCombine lead-search, lead-status-filter and lead-source-filter; assert lead-count and rows.
- 2
Select all & bulk assign
Intermediateselect-all-leads ticks every visible row; bulk-owner + apply-bulk updates owner-<id> cells.
- 3
New lead validation
Intermediatesave-lead with an existing email shows “already exists”; bad phone/value show error-*.
- 4
Activity log
IntermediateSwitch activity-note/call/email, save, and assert the newest activity-item text.
- 5
Convert to deal
Advancedconvert-lead → deal-value + deal-close → lead-status becomes Converted and converted-banner appears.
- 6
Kanban via menu
IntermediateChange move-deal-<company> and verify the card is inside stage-<id> and stage-total-* updates.
- 7
Kanban drag & drop
AdvancedDrag a deal-card onto another stage-* column (HTML5 DnD — dispatch events in Selenium/Cypress).
- 8
Dashboard KPIs
BeginnerWinning a deal changes kpi-won and kpi-win-rate on the dashboard.
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 ×5 · [name] ×4 · [aria-label] ×4 · getByTestId ×10
describe('SalesPulse — CRM', () => {
it('adds a lead and moves the deal through the pipeline', () => {
cy.visit('/apps/crm');
cy.get('#crm-email').type('sales@crm.dev');
cy.get('[name="crm-password"]').type('Crm@123');
cy.contains('button', 'Sign in').click();
cy.location('pathname').should('include', '/apps/crm/dashboard');
cy.getByTestId('nav-leads').click();
cy.getByTestId('new-lead').click();
cy.get('#lead-name').type('Grace Lee');
cy.get('[name="lead-company"]').type('Globex Corp');
cy.get('#lead-email').type('grace@globex.com');
cy.get('[name="lead-phone"]').type('5550142233');
cy.getByTestId('lead-source').select('linkedin');
cy.get('#lead-value').type('45000');
cy.contains('button', 'Save lead').click();
cy.getByTestId('leads-toast').should('contain', 'created');
cy.getByTestId('leads-table').should('contain', 'Globex Corp');
// Newest lead is listed first
cy.getByTestId('open-lead').eq(0).click();
cy.getByTestId('lead-title').should('contain', 'Grace Lee');
cy.contains('button', 'Log call').click();
cy.get('[aria-label="Activity details"]').type('Intro call — interested in the annual plan');
cy.contains('button', 'Save call').click();
cy.getByTestId('activity-timeline').should('contain', 'annual plan');
cy.contains('button', 'Convert to deal').click();
cy.get('[name="deal-value"]').type('45000');
cy.get('#deal-close').select('30');
cy.contains('button', 'Create deal').click();
cy.getByTestId('lead-status').should('contain', 'Converted');
cy.getByTestId('view-pipeline').click();
cy.get('[aria-label="Qualified"]').should('contain', 'Globex Corp');
cy.get('[aria-label="Move Globex Corp"]').select('proposal');
cy.get('[aria-label="Proposal"]').should('contain', 'Globex Corp');
cy.getByTestId('stage-total-proposal').should('contain', '$212,000');
});
});