towerops/e2e/README.md
Graham McIntire 17bf1f83e8
feat: add Playwright e2e test suite
- Set up Playwright in dedicated e2e directory
- Multi-environment support (local, staging)
- TOTP authentication handling with otplib
- Test coverage for organizations, devices, alerts, status indicators
- Helper utilities for common test operations
- Comprehensive README with setup and usage instructions
- Setup script for quick initialization
2026-03-06 15:02:56 -06:00

311 lines
6.5 KiB
Markdown

# Towerops E2E Tests
End-to-end tests using Playwright for testing the Towerops application against local development or staging environments.
## Setup
### 1. Install Dependencies
```bash
cd e2e
npm install
npx playwright install
```
### 2. Create Test User
You need a test user with TOTP enabled:
**Option A: Using Phoenix Console (Recommended)**
```elixir
# Start console
cd ..
iex -S mix
# Create test user
alias Towerops.{Accounts, Organizations, Repo}
{:ok, user} = Accounts.register_user(%{
email: "test@example.com",
password: "TestPassword123!",
password_confirmation: "TestPassword123!"
})
# Enable TOTP (this will print the secret)
{:ok, credential} = Accounts.create_user_credential(user, %{
type: :totp,
totp_secret: "JBSWY3DPEHPK3PXP" # Use this secret in .env
})
# Create an organization for the test user
{:ok, org} = Organizations.create_organization(%{name: "Test Org"}, user.id)
```
**Option B: Using the Web UI**
1. Register a new user at http://localhost:4000/users/register
2. Log in and enable TOTP in settings
3. Get the TOTP secret from the database:
```sql
SELECT totp_secret FROM user_credentials WHERE user_id = '<user-id>';
```
### 3. Configure Environment
```bash
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:
```bash
cd ..
mix phx.server
```
Then run tests:
```bash
cd e2e
npm test
```
### Against Staging
```bash
npm run test:staging
```
### Other Commands
```bash
# 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:
```typescript
import { test, expect } from '@playwright/test';
```
3. Write tests using Playwright's API
Example:
```typescript
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:
```heex
<div data-test="device-card">
<h3 data-test="device-name"><%= @device.name %></h3>
</div>
```
Then in tests:
```typescript
await page.locator('[data-test="device-card"]').first().click();
```
### 2. Wait for Network Idle
For LiveView pages with dynamic content:
```typescript
await page.waitForLoadState('networkidle');
```
### 3. Use Semantic Selectors
Prefer role-based selectors when possible:
```typescript
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByRole('heading', { name: 'Devices' }).toBeVisible();
```
### 4. Handle Optional Elements
Check if elements exist before interacting:
```typescript
if (await page.getByText('No results').count() > 0) {
// Handle empty state
}
```
### 5. Avoid Hard Timeouts
Use `waitFor` methods instead of `waitForTimeout`:
```typescript
// Good
await page.getByText('Success').waitFor();
// Bad
await page.waitForTimeout(3000);
```
## CI/CD Integration
### GitHub Actions / GitLab CI
```yaml
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
```bash
# 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
```bash
# 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:
```typescript
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
```bash
# Reinstall browsers
npx playwright install --with-deps
```
## Resources
- [Playwright Documentation](https://playwright.dev/)
- [Playwright Test API](https://playwright.dev/docs/api/class-test)
- [Best Practices](https://playwright.dev/docs/best-practices)
- [Debugging Guide](https://playwright.dev/docs/debug)