Test Automation

From Zero to Cypress Framework: How to Build a Test Automation Setup That Scales

From zero to a Cypress framework that scales — build a test automation setup that survives real projects. POM, structure, CI/CD and maintainability.

4 min read
From Zero to Cypress Framework: How to Build a Test Automation Setup That Scales
Advertisement
What You Will Learn
Step 1: Initialize the Project
Step 2: Add TypeScript Support
Step 3: Linting + Code Quality
Step 4: Pre-Commit Hooks (Prevent Bad Commits)

If you’ve ever started a new automation project, you know the first few weeks feel magical — everything works locally, your first few tests pass, and you think, “This is easy.”

But fast forward a few months, and things start to fall apart:
⚙️ Inconsistent results.
🧩 Messy folder structures.
🐛 Flaky tests.
📉 CI pipeline chaos.

This happens because most teams treat Cypress as a tool, not a framework.
Let’s change that.

In this guide, we’ll go end-to-end — from project setup to a scalable, CI-ready Cypress framework with TypeScript, linting, reporting, and pre-commit hooks.

Step 1: Initialize the Project

Start from a clean workspace.

mkdir cypress-framework
cd cypress-framework
npm init -y
npm install cypress --save-dev
npx cypress open

This creates the default structure:

cypress/
├── e2e/
├── fixtures/
├── support/
cypress.config.js

Run your first sample test to make sure Cypress boots up correctly.

Step 2: Add TypeScript Support

Cypress supports TypeScript out of the box, but we’ll set it up properly for scalability.

npm install typescript ts-node @types/node --save-dev

Create a tsconfig.json:

{
"compilerOptions": {
"target": "es2018",
"lib": ["es2018", "dom"],
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"types": ["cypress"]
},
"include": ["cypress/**/*.ts"]
}

Rename your .js files under /e2e and /support to .ts.

✅ Benefit: Strong typing for commands, utilities, and fixtures.
✅ Prevents silly runtime errors.

Step 3: Linting + Code Quality

Good frameworks enforce standards.

npm install eslint eslint-plugin-cypress --save-dev

Create .eslintrc.js:

module.exports = {
env: {
browser: true,
es2021: true,
'cypress/globals': true,
},
extends: ['eslint:recommended', 'plugin:cypress/recommended'],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['cypress'],
rules: {
semi: ['error', 'always'],
quotes: ['error', 'single'],
},
};

Run lint:

npx eslint cypress/**/*.ts

Step 4: Pre-Commit Hooks (Prevent Bad Commits)

Install Husky and lint-staged to enforce quality before every git commit.

npm install husky lint-staged --save-dev
npx husky install
npm set-script prepare "husky install"

Add a pre-commit hook:

npx husky add .husky/pre-commit "npx lint-staged"

Now configure lint-staged in your package.json:

"lint-staged": {
"*.ts": "eslint --fix"
}

✅ Ensures no one pushes broken code.
✅ Keeps your repo clean and consistent.

Step 5: Framework Folder Structure

Let’s make it maintainable.

cypress/
├── e2e/
│ ├── auth/
│ │ ├── login.cy.ts
│ │ ├── signup.cy.ts
│ ├── dashboard/
│ ├── analytics.cy.ts
│ ├── reports.cy.ts

├── support/
│ ├── commands/
│ │ ├── login.ts
│ │ ├── api.ts
│ ├── utils/
│ │ ├── dateHelper.ts
│ │ ├── intercepts.ts
│ ├── e2e.ts

├── fixtures/
│ ├── users.json
│ ├── products.json

├── config/
│ ├── dev.json
│ ├── staging.json
│ ├── prod.json

├── plugins/
│ ├── index.ts

├── reports/
├── screenshots/
├── videos/

✅ Domain-based separation
✅ Easy scalability
✅ Clear ownership

Step 6: Reporting Integration (Allure / Mochawesome)

Example using Mochawesome:

npm install mochawesome mochawesome-merge mochawesome-report-generator --save-dev

Add reporter to config:

// cypress.config.ts
import { defineConfig } from 'cypress'

export default defineConfig({
e2e: {
reporter: 'mochawesome',
reporterOptions: {
reportDir: 'cypress/reports',
overwrite: false,
html: false,
json: true,
},
},
});

Merge + generate report:

npx mochawesome-merge cypress/reports/*.json > cypress/reports/output.json
npx marge cypress/reports/output.json

Boom 💥 — a clean HTML report for management.

Step 7: Parallel Execution in CI/CD

Use GitHub Actions or GitLab CI to parallelize tests by folders:

jobs:
cypress-run:
runs-on: ubuntu-latest
strategy:
matrix:
group: [auth, dashboard, api]
steps:
- uses: actions/checkout@v3
- uses: cypress-io/github-action@v6
with:
spec: cypress/e2e/${{ matrix.group }}/**
record: true

✅ Parallel runs
✅ Auto artifacts
✅ Consistent pipelines

Bonus: Auto Retry Flaky Tests

npm install cypress-retries --save-dev
// cypress.config.ts
import 'cypress-retries';
// Example usage
it('should load dashboard', { retries: 2 }, () => {
cy.visit('/dashboard');
cy.contains('Analytics');
});

🧠 Final Thoughts

The difference between test scripts and a test framework is engineering.

If you want your automation to scale like your app does:

  • Use TypeScript for type safety
  • Use linting and hooks for quality
  • Use proper reporting for visibility
  • Design like a developer, test like an engineer

💬 Pro tip: Don’t aim for “tests that pass.”
Aim for a system that sustains — clean, maintainable, and production-ready.

More Relevant Articles

Frequently Asked Questions

Why do Cypress automation projects often face issues like inconsistent results and flaky tests?
This happens because most teams treat Cypress as a tool, not a framework. This can lead to inconsistent results, messy folder structures, flaky tests, and CI pipeline chaos.
What are the advantages of integrating TypeScript into a Cypress test automation framework?
TypeScript provides strong typing for commands, utilities, and fixtures within your Cypress framework. This setup helps prevent silly runtime errors, ensuring more reliable test execution.
How do pre-commit hooks contribute to maintaining code quality in a Cypress framework?
Pre-commit hooks, enforced with tools like Husky and lint-staged, ensure that no one pushes broken code to the repository. This process keeps your automation framework clean and consistent by enforcing quality before every git commit.
Advertisement
Found this helpful? Clap to let Shahnawaz know — you can clap up to 50 times.