# 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 = ''; ``` ### 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

<%= @device.name %>

``` 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 `) ### 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)