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
Optional: Email Server Configuration
Some E2E tests (particularly signup tests) send verification emails. To prevent undeliverable email alerts, you can configure a test email server:
# Add to .env.e2e or create .env.test.local (gitignored)
EMAIL_SERVER_HOST=your-smtp-server.com
EMAIL_SERVER_PORT=587
EMAIL_SERVER_USER=your-username
EMAIL_SERVER_PASSWORD=your-password
[email protected]
TEST_EMAIL_DOMAIN=your-test-domain.com
Alternatives for email testing:
- Ethereal Email: Free fake SMTP service at ethereal.email - catches emails without actually sending them
- MailHog: Local SMTP test server (
docker run -p 1025:1025 -p 8025:8025 mailhog/mailhog) - Your own test server: Configure
TEST_EMAIL_DOMAINto match your test email domain
If not configured, tests will use @example.com addresses (which will fail delivery).
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:
- Load the
.env.e2eenvironment - Start a development server on port 3002 (if not already running)
- Run all Playwright tests
Run with Production Build (Recommended)
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
| Setting | Value | Description |
|---|---|---|
| Port | 3002 | E2E tests run on port 3002 to avoid conflicts with dev server |
| Timeout | 60s | Global test timeout |
| Retries | 2 (CI only) | Tests retry on CI, not locally |
| Workers | 1 (dev) / 6 (prod) | More workers with production build |
| Browser | Chromium | Currently testing on Chrome only |
Environment Variables
| Variable | Description |
|---|---|
E2E_PORT | Override the default port (3002) |
E2E_BASE_URL | Override the base URL for tests |
E2E_VIDEO | Set to on to always record video |
E2E_PROD | Set to on to run against production build |
TEST_EMAIL_DOMAIN | Email domain for test users (default: example.com). Configure with your test email server domain to receive verification emails during signup tests. |
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
- Use API for test data: Create data via API instead of UI for speed and reliability
- Page Object Pattern: Encapsulate page interactions in page objects
- Automatic cleanup: The API fixture automatically cleans up created data after each test
- 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
- Ensure PostgreSQL is running
- Verify
.env.e2ehas correct credentials - 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=onto 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