towerops/e2e
Graham McIntire 6fd03ace16
feat: add comprehensive wireless client tracking and monitoring
Implements real-time wireless client monitoring with historical tracking,
LiveView UI, proactive alerting, and cross-browser e2e tests.

Phase 1: Historical Tracking
- Add TimescaleDB hypertable for wireless_client_readings
- Batch insert client metrics every 60 seconds from DevicePollerWorker
- 90-day retention with compression after 7 days
- Continuous aggregates for hourly (1 year) and daily (5 years) rollups

Phase 2: LiveView UI
- Add wireless tab to device detail page
- Real-time client list with PubSub updates
- Signal strength and SNR badges with 5-level thresholds
- Display MAC, IP, subscriber, TX/RX rates, distance, uptime
- Subscriber matching via device_subscriber_links
- Empty state handling

Phase 3: Proactive Alerting
- WirelessInsightWorker runs every 5 minutes via Oban cron
- 4 insight types with auto-resolution:
  * wireless_signal_weak: < -75 dBm (warning), < -85 dBm (critical)
  * wireless_snr_low: < 15 dB (warning), < 10 dB (critical)
  * wireless_ap_overloaded: > 50 clients (warning), > 75 clients (critical)
  * wireless_client_missing: expected subscribers not connecting
- Hysteresis thresholds prevent alert flapping
- Multi-organization isolation with proper deduplication

Code Quality:
- Refactored reload_current_tab_data to reduce cyclomatic complexity
- Combined double Enum.filter into single pass for efficiency
- Fixed length/1 comparison to use empty list check
- All Credo checks passing

Testing:
- 28 unit tests (ExUnit) - 100% passing
- 15 e2e tests (Playwright) - 100% passing across chromium/firefox/webkit
- Total: 73 tests, all passing

Files changed:
- lib/towerops/workers/wireless_insight_worker.ex (NEW)
- lib/towerops_web/live/device_live/show.ex (wireless tab + refactoring)
- lib/towerops_web/live/device_live/show.html.heex (wireless template)
- lib/towerops/snmp.ex (5 new query functions)
- lib/towerops/gaiia.ex (list_missing_subscribers)
- lib/towerops/preseem/insight.ex (5 new insight types)
- config/runtime.exs (Oban cron schedule)
- test/support/fixtures/snmp_fixtures.ex (NEW)
- test/towerops/workers/wireless_insight_worker_test.exs (NEW)
- test/towerops_web/live/device_live/show_test.exs (9 new tests)
- e2e/tests/wireless-clients.spec.ts (NEW - 15 cross-browser tests)
2026-03-10 09:57:12 -05:00
..
scripts fix: NimbleTOTP base32 decoding and complete e2e test setup 2026-03-06 16:42:41 -06:00
tests feat: add comprehensive wireless client tracking and monitoring 2026-03-10 09:57:12 -05:00
.env.example fix: NimbleTOTP base32 decoding and complete e2e test setup 2026-03-06 16:42:41 -06:00
.gitignore fix: commit package-lock.json for reproducible e2e test builds 2026-03-08 10:33:21 -05:00
package-lock.json fix: commit package-lock.json for reproducible e2e test builds 2026-03-08 10:33:21 -05:00
package.json fix: NimbleTOTP base32 decoding and complete e2e test setup 2026-03-06 16:42:41 -06:00
playwright.config.ts fix: disable problematic signup-flow tests and adjust e2e timeouts 2026-03-09 11:12:10 -05:00
README.md docs: add TOTP setup guide and test user creation script 2026-03-06 15:06:23 -06:00
setup.sh refactor: remove emoji from e2e scripts and docs 2026-03-06 15:43:02 -06:00
TOTP_SETUP.md fix: update e2e scripts to use correct TOTP API 2026-03-06 15:46:11 -06:00
tsconfig.json fix: update e2e tests to use otplib v13 API and load .env 2026-03-06 15:53:10 -06:00

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