towerops/e2e/README.md
Graham McIntire 0bdec8653f
docs: add TOTP setup guide and test user creation script
- Add comprehensive TOTP_SETUP.md with multiple setup options
- Create scripts/create_test_user.exs for automated test user creation
- Update .gitignore to exclude Playwright browser binaries and artifacts
- Update README to reference TOTP setup guide
2026-03-06 15:06:23 -06:00

6 KiB

Towerops E2E Tests

End-to-end tests using Playwright for testing the Towerops application against local development or staging environments.

Setup

1. Install Dependencies

cd e2e
npm install
npx playwright install

2. Create Test User

You need a test user with TOTP enabled.

Quick Setup (Recommended):

# From the Phoenix app directory
cd ..
mix run e2e/scripts/create_test_user.exs

This creates a test user with known credentials and outputs the configuration for your .env file.

For detailed TOTP setup instructions, see TOTP_SETUP.md

3. Configure Environment

cp .env.example .env

Edit .env and set:

  • TEST_USER_EMAIL - Your test user email
  • TEST_USER_PASSWORD - Your test user password
  • TEST_USER_TOTP_SECRET - TOTP secret from step 2

Running Tests

Local Development

Make sure Phoenix is running first:

cd ..
mix phx.server

Then run tests:

cd e2e
npm test

Against Staging

npm run test:staging

Other Commands

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

# Run tests with browser visible
npm run test:headed

# Debug a specific test
npm run test:debug -- tests/devices.spec.ts

# Generate tests by recording actions
npm run codegen

# View last test report
npm run report

Test Organization

tests/auth.setup.ts

Authentication setup that runs before all other tests. Logs in once and saves the session state so other tests don't need to authenticate.

Test Files

  • organizations.spec.ts - Organization listing and switching
  • devices.spec.ts - Device listing, details, search/filter
  • alerts.spec.ts - Alert viewing, filtering, resolution

Adding New Tests

  1. Create a new .spec.ts file in tests/
  2. Import test utilities:
    import { test, expect } from '@playwright/test';
    
  3. Write tests using Playwright's API

Example:

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

test.describe('My Feature', () => {
  test('can do something', async ({ page }) => {
    await page.goto('/my-page');
    await expect(page.getByRole('heading')).toBeVisible();
  });
});

Configuration

Environment Variables

  • BASE_URL - Base URL of the application (default: http://localhost:4000)
  • TEST_USER_EMAIL - Test user email
  • TEST_USER_PASSWORD - Test user password
  • TEST_USER_TOTP_SECRET - TOTP secret for test user

Playwright Config

Edit playwright.config.ts to:

  • Add/remove browsers
  • Change timeout settings
  • Configure reporters
  • Add mobile viewports
  • Enable video recording

Best Practices

1. Use Data Test Attributes

Add data-test attributes to important elements in your templates:

<div data-test="device-card">
  <h3 data-test="device-name"><%= @device.name %></h3>
</div>

Then in tests:

await page.locator('[data-test="device-card"]').first().click();

2. Wait for Network Idle

For LiveView pages with dynamic content:

await page.waitForLoadState('networkidle');

3. Use Semantic Selectors

Prefer role-based selectors when possible:

await page.getByRole('button', { name: 'Submit' }).click();
await page.getByRole('heading', { name: 'Devices' }).toBeVisible();

4. Handle Optional Elements

Check if elements exist before interacting:

if (await page.getByText('No results').count() > 0) {
  // Handle empty state
}

5. Avoid Hard Timeouts

Use waitFor methods instead of waitForTimeout:

// Good
await page.getByText('Success').waitFor();

// Bad
await page.waitForTimeout(3000);

CI/CD Integration

GitHub Actions / GitLab CI

e2e-tests:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 18
    - name: Install dependencies
      run: |
        cd e2e
        npm ci
        npx playwright install --with-deps
    - name: Run tests
      run: |
        cd e2e
        BASE_URL=${{ secrets.STAGING_URL }} npm test
      env:
        TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
        TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
        TEST_USER_TOTP_SECRET: ${{ secrets.TEST_USER_TOTP_SECRET }}
    - name: Upload test results
      if: always()
      uses: actions/upload-artifact@v3
      with:
        name: playwright-report
        path: e2e/playwright-report/

Debugging

Visual Debugging

# Open test in UI mode
npm run test:ui

# Run specific test with browser visible
npm run test:headed -- tests/devices.spec.ts

Debug Mode

# Opens Playwright Inspector
npm run test:debug -- tests/devices.spec.ts

Screenshots and Videos

Failed tests automatically capture:

  • Screenshots (in test-results/)
  • Videos (in test-results/)
  • Traces (view with npx playwright show-trace <trace-file>)

Console Logs

Add console logging in tests:

test('debug test', async ({ page }) => {
  page.on('console', msg => console.log('Browser:', msg.text()));
  await page.goto('/devices');
});

Troubleshooting

"Authentication failed" or TOTP errors

  • Verify TOTP secret is correct in .env
  • Check test user exists and has TOTP enabled
  • Ensure test user has access to at least one organization

Tests timing out

  • Increase timeout in playwright.config.ts
  • Check Phoenix server is running
  • Verify BASE_URL is correct
  • Check network connectivity to staging

"Element not found" errors

  • Add data-test attributes to elements
  • Use page.waitForLoadState('networkidle') before assertions
  • Check if LiveView is fully mounted before interacting

Browser not launching

# Reinstall browsers
npx playwright install --with-deps

Resources