Q10 of 48 · Cypress
What are Cypress hooks (before, beforeEach) and how are they different from before/after in Mocha?
Short answer
Short answer: Cypress uses Mocha's hooks: `before` (once per file), `beforeEach` (per test), `afterEach` (per test), `after` (once per file). They behave the same as in Mocha — but Cypress 10+ defaults to `testIsolation: true`, which clears state (cookies, localStorage) between tests, making `beforeEach` setup essential.
Detail
Cypress's test runner is Mocha with a custom UI, so the hook semantics are inherited unchanged:
before(() => { ... })runs once before all tests in the file.beforeEach(() => { ... })runs before every test.afterEachandaftermirror those, in reverse.
The Cypress-specific wrinkle is test isolation. Since Cypress 12, testIsolation: true is the default — between tests, Cypress clears cookies, localStorage, and sessionStorage. State you set up in before (e.g., logging in) doesn't survive to subsequent tests; you need beforeEach plus cy.session for caching.
For setup that's expensive but stateless (e.g., seeding the database), before is fine. For anything that touches the browser (auth tokens, cookies), use beforeEach + cy.session.
The other gotcha is that hooks are per-spec-file, not global. Cross-file setup belongs in cypress/support/e2e.ts, which Cypress auto-loads before every spec.
Don't put Cypress commands in synchronous-style assertions inside hooks — they're queued like the rest of Cypress.
// EXAMPLE
checkout.cy.ts
describe('Checkout', () => {
before(() => {
cy.task('seedDb', { user: 'alice' }); // once per file
});
beforeEach(() => {
cy.session('alice', () => {
cy.request('POST', '/api/login', { email: 'alice@x.com' });
});
cy.visit('/cart');
});
it('shows the cart total', () => {
cy.get('[data-test=total]').should('contain', '£');
});
afterEach(() => {
cy.task('clearTestArtifacts');
});
});