- 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
311 lines
6.5 KiB
Markdown
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)
|