towerops/e2e/tests/devices.spec.ts
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

93 lines
3.1 KiB
TypeScript

import { test, expect } from '@playwright/test';
test.describe('Devices', () => {
test.beforeEach(async ({ page }) => {
// Navigate to organizations and select the first one
await page.goto('/orgs');
await page.locator('[data-test="organization-card"]').first().click();
await expect(page).toHaveURL(/\/orgs\/[^\/]+/);
});
test('can view devices list', async ({ page }) => {
// Navigate to devices
await page.getByRole('link', { name: /devices/i }).click();
// Check URL
await expect(page).toHaveURL(/\/devices/);
// Check for page heading
await expect(page.getByRole('heading', { name: /devices/i })).toBeVisible();
});
test('devices list shows device information', async ({ page }) => {
await page.goto('/devices');
// Wait for devices to load
await page.waitForSelector('[data-test="device-row"], [data-role="device-item"]', {
timeout: 5000,
}).catch(() => {
// If no test attributes, just check for any table rows or list items
return page.waitForSelector('table tbody tr, [role="list"] > div');
});
// Check that device rows contain expected information
// Adjust selectors based on your actual markup
const firstDevice = page.locator('table tbody tr, [role="list"] > div').first();
await expect(firstDevice).toBeVisible();
// Device should have a name and status indicator
// These will need to be adjusted based on your actual DOM structure
});
test('can view device details', async ({ page }) => {
await page.goto('/devices');
// Wait for devices to load
await page.waitForLoadState('networkidle');
// Click first device
const firstDeviceLink = page.locator('table tbody tr a, [data-test="device-link"]').first();
await firstDeviceLink.click();
// Should navigate to device detail page
await expect(page).toHaveURL(/\/devices\/[^\/]+/);
// Check for device detail sections
// Adjust these based on your actual device detail page
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
});
test('can search/filter devices', async ({ page }) => {
await page.goto('/devices');
// Look for search input
const searchInput = page.getByPlaceholder(/search|filter/i);
// If search exists, test it
if (await searchInput.count() > 0) {
await searchInput.fill('test');
await page.waitForTimeout(500); // Wait for debounce/filtering
// Results should update
// This is a basic check - adjust based on your implementation
}
});
test('device status indicators work', async ({ page }) => {
await page.goto('/devices');
await page.waitForLoadState('networkidle');
// Check for status indicators (up/down/warning)
// Adjust based on your status indicator implementation
const statusIndicators = page.locator('[data-status], .status-indicator, [class*="status-"]');
if (await statusIndicators.count() > 0) {
const firstStatus = statusIndicators.first();
await expect(firstStatus).toBeVisible();
// Status should have appropriate styling/color
// You might check for specific classes or aria attributes
}
});
});