Skip to main content

End-to-End Testing

This guide covers how to run and write end-to-end (E2E) tests for TestPlanIt using Playwright.

Prerequisites

  • Node.js 20+ and pnpm installed
  • PostgreSQL database available
  • TestPlanIt development environment set up

Setup

1. Create E2E Test Database

E2E tests require a separate database from your development database. This ensures tests run on clean, predictable data.

# Create a new PostgreSQL database for E2E tests
createdb testplanit_e2e

# Or via psql
psql -c "CREATE DATABASE testplanit_e2e;"

2. Configure Environment

From the testplanit/ directory, copy the example environment file:

cd testplanit
cp .env.e2e.example .env.e2e

Edit .env.e2e and update the database connection:

DATABASE_URL="postgresql://user:password@localhost:5432/testplanit_e2e?schema=public"

The example file includes sensible defaults for:

  • NextAuth configuration
  • Valkey/Redis connection
  • MinIO/S3 storage
  • Default admin credentials for tests

3. Install Playwright Browsers

cd testplanit
pnpm exec playwright install

4. Setup the E2E Database

Run migrations and seed the E2E database with test data:

pnpm test:e2e:setup-db

Running Tests

All E2E test commands are run from the testplanit/ directory.

Run All Tests

pnpm test:e2e

This will:

  1. Load the .env.e2e environment
  2. Start a development server on port 3002 (if not already running)
  3. Run all Playwright tests

For faster and more stable tests, use a production build:

pnpm test:e2e:prod

This builds the application first, then runs tests against the production build with more parallel workers.

Complete Setup + Run

To set up the database and run tests in one command:

pnpm test:e2e:run

Interactive UI Mode

Debug and explore tests visually:

pnpm test:e2e:ui

Headed Mode

Watch the browser as tests execute:

pnpm test:e2e:headed

Debug Mode

Step through tests with Playwright Inspector:

pnpm test:e2e:debug

View Test Report

After running tests, view the HTML report:

pnpm test:e2e:report

Test Configuration

The Playwright configuration is in testplanit/e2e/playwright.config.ts.

Key Settings

SettingValueDescription
Port3002E2E tests run on port 3002 to avoid conflicts with dev server
Timeout60sGlobal test timeout
Retries2 (CI only)Tests retry on CI, not locally
Workers1 (dev) / 6 (prod)More workers with production build
BrowserChromiumCurrently testing on Chrome only

Environment Variables

VariableDescription
E2E_PORTOverride the default port (3002)
E2E_BASE_URLOverride the base URL for tests
E2E_VIDEOSet to on to always record video
E2E_PRODSet to on to run against production build

Project Structure

testplanit/e2e/
├── playwright.config.ts # Playwright configuration
├── global-setup.ts # Authentication setup (runs once)
├── setup-db.ts # Database seeding script
├── fixtures/
│ ├── index.ts # Test fixtures
│ └── api.fixture.ts # API helper for test data
├── page-objects/
│ ├── base.page.ts # Base page object
│ ├── signin.page.ts # Sign-in page
│ └── repository/
│ └── repository.page.ts
├── tests/
│ ├── auth/ # Authentication tests
│ └── repository/ # Repository feature tests
├── .auth/ # Stored auth state (gitignored)
├── playwright-report/ # HTML reports (gitignored)
└── test-results/ # Test artifacts (gitignored)

Writing Tests

Adding New Test Files

Place new test files in the tests/ directory, organized by feature:

tests/
├── auth/ # Authentication-related tests
│ └── auth.spec.ts
├── repository/ # Repository feature tests
│ └── Test Repository Management/
│ ├── folder-creation.spec.ts
│ ├── test-case-management.spec.ts
│ └── ...
└── <new-feature>/ # Add new feature directories as needed
└── <test-name>.spec.ts

Test files must use the .spec.ts extension to be picked up by Playwright.

Using Page Objects

import { test, expect } from "../../fixtures";
import { RepositoryPage } from "../../page-objects/repository/repository.page";

test("should create a folder", async ({ page }) => {
const repositoryPage = new RepositoryPage(page);
await repositoryPage.goto(1); // Project ID

await repositoryPage.createFolder("My New Folder");
await repositoryPage.verifyFolderExists("My New Folder");
});

Using the API Fixture

Create test data via API for faster, more reliable tests:

test("should display test cases", async ({ api, page }) => {
// Create test data via API
const folderId = await api.createFolder(1, "Test Folder");
await api.createTestCase(1, folderId, "Test Case 1");

// Navigate and verify
const repositoryPage = new RepositoryPage(page);
await repositoryPage.goto(1);
await repositoryPage.selectFolder(folderId);
await repositoryPage.verifyTestCaseExists("Test Case 1");

// Cleanup is automatic via the api fixture
});

Best Practices

  1. Use API for test data: Create data via API instead of UI for speed and reliability
  2. Page Object Pattern: Encapsulate page interactions in page objects
  3. Automatic cleanup: The API fixture automatically cleans up created data after each test
  4. Isolated database: Tests run against a separate database to avoid affecting development data

Troubleshooting

Authentication Issues

If tests fail with authentication errors:

rm -rf testplanit/e2e/.auth/
pnpm test:e2e

Database Connection Issues

  1. Ensure PostgreSQL is running
  2. Verify .env.e2e has correct credentials
  3. Re-run database setup: pnpm test:e2e:setup-db

Port Conflicts

If port 3002 is in use:

E2E_PORT=3003 pnpm test:e2e

Slow Tests

  • Use E2E_PROD=on to run against production build
  • Use API fixture to create test data instead of UI
  • Use test.only() to run a single test during development

Flaky Tests

  • Check for timing issues and add proper waits
  • Use await expect(locator).toBeVisible() instead of fixed delays
  • Increase timeouts for slow operations