Skip to content

DemocracyLab/civic-tech-exchange-ui-tests

Repository files navigation

CivicTechExchange UI Parity Tests

End-to-end UI tests for validating parity between the legacy Django/React platform and the new Phoenix/Elixir implementation during the strangling fig migration.

Background

CivicTechExchange is undergoing a platform rewrite from Django/React to Phoenix/Elixir using the strangler fig pattern. This test suite exists to:

  • Ensure feature parity between old and new implementations
  • Catch UI regressions during incremental migration
  • Provide confidence when routing traffic between systems
  • Document expected behavior through executable specifications

Design Principles

  • Independent: This test suite lives in its own repository, separate from both the Django/React and Phoenix/Elixir codebases
  • Portable: Can be run locally on any developer machine
  • Language: Written in JavaScript/TypeScript
  • Framework: Playwright for cross-browser E2E testing

Prerequisites

  • Node.js 18+
  • npm or yarn

Installation

# Clone the repository
git clone <repository-url>
cd civic-tech-exchange-ui-tests

# Install dependencies
npm install

# Install Playwright browsers (first time only)
npx playwright install

Configuration

Copy the example environment file and configure URLs:

cp .env.example .env

Edit .env to point to your running applications:

Running Tests

Basic Commands

# Run all tests (default config)
npm test

Development Commands

# Run with Playwright UI (interactive mode)
npm run test:ui

# Run with browser visible
npm run test:headed

# Run in debug mode
npm run test:debug

Browser-Specific Tests

npm run test:chromium
npm run test:firefox
npm run test:webkit

View Reports

# View default report
npm run report

# View legacy-specific report
npm run report:legacy

# View phoenix-specific report
npm run report:phoenix

Project Structure

civic-tech-exchange-ui-tests/
├── config/
│   ├── legacy.config.ts      # Config for Django/React app
│   └── phoenix.config.ts     # Config for Phoenix/Elixir app
├── tests/
│   ├── fixtures/
│   │   └── test-data.ts      # Shared test data
│   ├── helpers/
│   │   └── page-helpers.ts   # Common page interactions
│   └── example.spec.ts       # Example test file
├── playwright.config.ts      # Base Playwright config
├── tsconfig.json
├── package.json
└── README.md

Writing Tests

Test Structure

Tests are written using Playwright Test. Each test should:

  1. Work identically against both legacy and new implementations
  2. Use flexible selectors that don't rely on implementation details
  3. Focus on user-visible behavior, not internal structure

Example Test

import { test, expect } from '@playwright/test';

test.describe('User Authentication', () => {
  test('should allow users to log in', async ({ page }) => {
    await page.goto('/login');

    await page.getByLabel(/email/i).fill('user@example.com');
    await page.getByLabel(/password/i).fill('password123');
    await page.getByRole('button', { name: /sign in|log in/i }).click();

    // Verify login succeeded - works for both implementations
    await expect(page.getByRole('button', { name: /log out|profile/i })).toBeVisible();
  });
});

Best Practices

  1. Use role-based selectors: getByRole(), getByLabel(), getByText()
  2. Avoid implementation-specific selectors: Don't use CSS classes or React/Phoenix-specific attributes
  3. Use regex for flexibility: /sign in|log in/i matches both "Sign In" and "Log In"
  4. Wait for network idle: Use waitForLoadState('networkidle') for async operations
  5. Abstract differences: Put implementation-specific logic in helper functions

Parity Testing Strategy

CI/CD Integration

In CI, run tests against both implementations in parallel:

jobs:
  test-legacy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npm run test:legacy

  test-phoenix:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npm run test:phoenix

Troubleshooting

Tests fail on one implementation but pass on another

This is expected during migration! Document the difference and decide:

  • Is this a bug in the new implementation? Fix it.
  • Is this intentional new behavior? Update the test.
  • Is this a known gap? Mark the test as skipped for that config.

Flaky tests

  1. Add explicit waits: await page.waitForLoadState('networkidle')
  2. Use toBeVisible() before interacting with elements
  3. Increase timeout for slow operations
  4. Use test retries: test.describe.configure({ retries: 2 })

Browser-specific failures

Run in specific browser to debug:

npx playwright test --project=webkit --debug

Contributing

  1. Write tests that pass against the legacy implementation first
  2. Verify they also pass against Phoenix when that feature is migrated
  3. Use flexible selectors that work for both
  4. Document any intentional behavioral differences

License

MIT

About

Playwright tests for DemocracyLab platform

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published