Advanced Topics
Custom commands, plugins, page objects, and CI integration patterns.
Custom Commands
Cypress.Commands.add defines reusable cy.login() style commands in support/commands.ts. TypeScript augmentation declares command signatures for autocomplete.
Keep commands thin—call API for login token then set cookie rather than slow UI login every test unless testing login itself.
Cypress.Commands.add("login", (email: string, password: string) => {
cy.session([email, password], () => {
cy.request("POST", "/api/login", { email, password });
});
});
declare global {
namespace Cypress {
interface Chainable {
login(email: string, password: string): Chainable<void>;
}
}
}Plugins
Plugins extend config via setupNodeEvents—tasks, browser launch, code coverage, grep filtering. @cypress/grep runs tagged subsets; cypress-real-events adds realistic pointer events.
Evaluate plugin maintenance before adopting—pin versions and test upgrades in branch.
async setupNodeEvents(on, config) {
require("@cypress/grep/src/plugin")(config);
on("task", { log(message) { console.log(message); return null; } });
return config;
}Page Object Pattern
Page objects encapsulate selectors and actions for a page—LoginPage.visit(), LoginPage.submit(). Reduces duplication without hiding Cypress retry semantics inside async await antipatterns.
Prefer composable functions over deep inheritance hierarchies. Co-locate selectors with page object class.
class LoginPage {
visit() { cy.visit("/login"); }
fillEmail(email: string) { cy.get('[data-cy="email"]').type(email); }
submit() { cy.get('[data-cy="submit"]').click(); }
}Continuous Integration
Run cypress run in CI with start-server-and-test or wait-on to boot app. Parallelize with Cypress Cloud or sorry-cypress for on-prem.
Record runs to Cypress Cloud for flake detection, timing trends, and spec load balancing.
- Set CYPRESS_RECORD_KEY secret for Cloud recording
- Use docker image cypress/included for consistent browser versions
- Split specs across parallel containers by timing from Cloud data
"ci:e2e": "start-server-and-test dev http://localhost:3000 'cypress run'"
Cross-Origin and Security
cy.origin() navigates and runs commands in different origin after superdomain change. Required for OAuth flows and embedded apps.
Chrome Web Security disabled in Cypress for cross-origin convenience—do not assume identical browser security behavior in production user browsers for all edge cases.
cy.origin("https://auth.example.com", () => {
cy.get('input[name="username"]').type("user");
});