Files
paste.es/docs/e2e.md
Malin bc9f96cbd4 feat: rebrand Hemmelig to paste.es for cloudhost.es
- Set Spanish as default language with ephemeral/encrypted privacy focus
- Translate all user-facing strings and legal pages to Spanish
- Replace Norwegian flag with Spanish flag in footer
- Remove Hemmelig/terces.cloud links, add cloudhost.es sponsorship
- Rewrite PrivacyPage: zero data collection, ephemeral design emphasis
- Rewrite TermsPage: Spanish law, RGPD, paste.es/CloudHost.es references
- Update PWA manifest, HTML meta tags, package.json branding
- Rename webhook headers to X-Paste-Event / X-Paste-Signature
- Update API docs title and contact to paste.es / cloudhost.es

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 09:30:19 +01:00

4.8 KiB

End-to-End Testing with Playwright

Hemmelig uses Playwright for end-to-end integration testing.

Setup

Playwright and browsers are installed as dev dependencies. If you need to install browser dependencies on your system:

sudo npx playwright install-deps

Test Database

The e2e tests automatically use a separate test database (database/hemmelig-test.db) that is:

  1. Created fresh before each test run
  2. Migrated with the latest schema
  3. Seeded with a test user
  4. Deleted after tests complete

This ensures tests don't affect your development database.

Test User Credentials (created automatically):

  • Email: e2e-test@hemmelig.local
  • Username: e2etestuser
  • Password: E2ETestPassword123!

Running Tests

# Run all e2e tests
npm run test:e2e

# Run tests with interactive UI
npm run test:e2e:ui

# Run tests in debug mode
npm run test:e2e:debug

# Run a specific test file
npx playwright test tests/e2e/secret.spec.ts

# Run tests in headed mode (see the browser)
npx playwright test --headed

Test Structure

Tests are located in tests/e2e/:

File Description
auth.spec.ts Authentication tests (setup, login, registration)
home.spec.ts Homepage and secret form tests
secret.spec.ts Secret creation, viewing, and deletion flows
navigation.spec.ts Navigation and routing tests
fixtures.ts Shared test fixtures (authenticatedPage)
global-setup.ts Creates test database and user before tests
global-teardown.ts Cleans up test database after tests

Configuration

The Playwright configuration is in playwright.config.ts:

  • Test directory: tests/e2e/
  • Base URL: http://localhost:5173
  • Browser: Chromium (Desktop Chrome)
  • Web server: Automatically starts Vite with test database
  • Global setup: Creates fresh test database and test user
  • Global teardown: Deletes test database

Writing Tests

Basic Test Structure

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

test.describe('Feature Name', () => {
    test('should do something', async ({ page }) => {
        await page.goto('/');

        // Interact with elements
        await page.locator('.ProseMirror').fill('My secret');
        await page.getByRole('button', { name: /create/i }).click();

        // Assert results
        await expect(page.getByText(/success/i)).toBeVisible();
    });
});

Using Authenticated Page Fixture

For tests that require authentication:

import { expect, test } from './fixtures';

test('should create a secret when logged in', async ({ authenticatedPage }) => {
    await authenticatedPage.goto('/');
    // authenticatedPage is already logged in with test user
    await expect(authenticatedPage.locator('.ProseMirror')).toBeVisible();
});

Common Patterns

Interacting with the secret editor:

const editor = page.locator('.ProseMirror');
await editor.click();
await editor.fill('Secret content');

Creating and viewing a secret:

// Create
await page.goto('/');
await page.locator('.ProseMirror').fill('My secret');
await page
    .getByRole('button', { name: /create/i })
    .first()
    .click();

// Get the URL
const urlInput = page.locator('input[readonly]').first();
const secretUrl = await urlInput.inputValue();

// View
await page.goto(secretUrl);
await page.getByRole('button', { name: /unlock/i }).click();

CI Integration

Tests run in CI with these settings (from playwright.config.ts):

  • forbidOnly: true - Fails if .only is left in tests
  • retries: 2 - Retries failed tests twice
  • workers: 1 - Single worker to prevent conflicts

GitHub Actions Example

- name: Install Playwright Browsers
  run: npx playwright install --with-deps chromium

- name: Run E2E Tests
  run: npm run test:e2e

Viewing Test Reports

After running tests, view the HTML report:

npx playwright show-report

Debugging Failed Tests

  1. Run in debug mode: npm run test:e2e:debug
  2. Run with UI: npm run test:e2e:ui
  3. View traces: Failed tests generate traces in test-results/
  4. Screenshots: Failed tests save screenshots automatically

Best Practices

  1. Use data-testid for stable selectors when possible
  2. Prefer user-facing selectors like getByRole, getByText, getByPlaceholder
  3. Add appropriate timeouts for async operations
  4. Keep tests independent - each test should work in isolation
  5. Use .first() when multiple elements match to avoid strict mode violations