FOSS · MIT—Open-source agent-swarm, the operating system for all your AI agents→
How-To/Build a Cypress Page Object Model Framework with AI & MCP in 2026 | desplega.ai

Build a Cypress Page Object Model Framework with AI & MCP in 2026 | desplega.ai

Learn how to build a scalable Cypress Page Object Model framework in 2026 using MCP chat mode and AI-powered E2E testing with desplega.ai.

The Page Object Model (POM) has been a durable way to organize Cypress tests for years, and in 2026 the workflow changes again: AI agents that speak the Model Context Protocol (MCP) can read your page classes, infer user journeys, and write entire spec files for you. This guide shows you how to combine a clean POM architecture with desplega.ai's MCP chat mode so your team writes less boilerplate and ships faster. If you're new to MCP in editors, start with our Cursor MCP setup guide before continuing.

Scaffold Your Cypress Project Structure

A solid POM framework starts with a predictable directory layout. Create a dedicated folder for page classes, another for reusable component objects, and keep fixtures and support files separate. This separation pays off the moment your suite grows past a handful of specs — selectors live in one place, test logic in another, and AI agents can parse the structure without ambiguity.

mkdir cypress-pom-ai && cd cypress-pom-ai
npm init -y
npm install -D cypress typescript
npx cypress open

# Create POM directory structure
mkdir -p cypress/pages cypress/components cypress/fixtures cypress/support

Define Your Base Page Class

Every page object should inherit a common foundation. The BasePage class centralizes navigation, test-id selection, and load-state checks. By using a fluent interface (returning this from each method), your specs read like natural-language user stories — which also makes them easier for the AI to understand and extend.

// cypress/pages/BasePage.ts
export class BasePage {
  protected url: string = '/';

  visit(path?: string) {
    cy.visit(path ?? this.url);
    return this;
  }

  getByTestId(testId: string) {
    return cy.get(`[data-testid="${testId}"]`);
  }

  waitForPageLoad() {
    cy.get('body').should('be.visible');
    return this;
  }
}

Build Feature-Specific Page Objects

With the base in place, model each major screen as a class that extends it. Keep selectors and DOM interactions inside the class — never inline them in specs. This discipline is what makes the POM scale to hundreds of tests, and it's exactly the structure the MCP server looks for when it generates new specs on your behalf.

// cypress/pages/LoginPage.ts
import { BasePage } from './BasePage';

export class LoginPage extends BasePage {
  protected url = '/login';

  fillEmail(email: string) {
    this.getByTestId('email-input').type(email);
    return this;
  }

  fillPassword(password: string) {
    this.getByTestId('password-input').type(password);
    return this;
  }

  submit() {
    this.getByTestId('login-submit').click();
    return this;
  }

  assertErrorVisible() {
    this.getByTestId('login-error').should('be.visible');
    return this;
  }
}

Connect Desplega.ai MCP Chat Mode for AI-Generated Tests

MCP (Model Context Protocol) is the standardized way for AI assistants to read your codebase and call tools. Drop the desplega.ai qa-use MCP server into your editor's config and the chat mode gains direct access to your cypress/pages folder, fixtures, and recent test runs. From there it can generate, refactor, and debug specs in real time.

// .cursor/mcp.json  (or your editor's MCP config)
{
  "mcpServers": {
    "desplega-qa": {
      "command": "npx",
      "args": ["-y", "@desplega.ai/qa-use-mcp@latest"],
      "env": {
        "QA_USE_API_KEY": "<your-api-key>",
        "PROJECT_ROOT": "${workspaceFolder}"
      }
    }
  }
}

Generate E2E Specs via AI Chat Prompts

With the MCP server connected, you can describe a user journey in plain English and the AI returns a complete spec that respects your POM. Treat the AI like a junior engineer: give it the page class name, the scenarios to cover, and any business rules. Review the output, tweak assertions, and commit.

// Prompt example sent to MCP chat:
// "Using LoginPage from cypress/pages/LoginPage.ts,
//  generate a full Cypress spec covering: happy path login,
//  invalid credentials, and empty field validation."

// AI-generated output example:
import { LoginPage } from '../pages/LoginPage';

const login = new LoginPage();

describe('Login — AI-generated via MCP', () => {
  beforeEach(() => login.visit());

  it('logs in with valid credentials', () => {
    login.fillEmail('user@example.com').fillPassword('Secret123!').submit();
    cy.url().should('include', '/dashboard');
  });

  it('shows error on invalid credentials', () => {
    login.fillEmail('bad@example.com').fillPassword('wrong').submit();
    login.assertErrorVisible();
  });

  it('blocks submission with empty fields', () => {
    login.submit();
    cy.get('[data-testid="email-input"]:invalid').should('exist');
  });
});

Run and Validate Tests Locally and in CI

Local runs are fine for development, but real confidence comes from repeatable CI execution with screenshots and videos preserved as artifacts. Run the generated specs directly with Cypress first, then use qa-use MCP chat to inspect failures, compare screenshots, and tighten selectors or assertions before the suite grows.

# Run the generated POM specs locally
npx cypress run \
  --spec "cypress/e2e/**/*.cy.ts" \
  --browser chrome

# Then ask qa-use MCP chat to inspect cypress/screenshots and cypress/videos
# when a generated spec fails or flakes.

Integrate into CI/CD with AI-Assisted Triage

The final step closes the loop: every pull request triggers your full POM suite, stores failure artifacts, and gives the AI assistant enough context to classify each failure as a product bug, a flaky test, or infrastructure noise. Engineers stop spending hours sifting through screenshots — they get a focused triage prompt and ship with confidence.

# .github/workflows/e2e.yml
name: E2E — Cypress POM + Desplega AI
on: [push, pull_request]

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Run E2E on Desplega cloud
        uses: cypress-io/github-action@v6
        with:
          spec: 'cypress/e2e/**/*.cy.ts'
          browser: chrome

      - name: Upload Cypress artifacts
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: cypress-artifacts
          path: |
            cypress/screenshots
            cypress/videos