import { test, expect } from '@playwright/test'; test.describe('Wireless Clients', () => { test('can navigate to wireless tab from device page', async ({ page }) => { await page.goto('/devices'); // Navigate to first device const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Look for Wireless tab const wirelessTab = page.locator( 'a[href*="tab=wireless"], button:has-text("Wireless"), a:has-text("Wireless")' ).first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Verify URL includes wireless tab await expect(page).toHaveURL(/tab=wireless/); } } }); test('shows wireless tab badge with client count', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Look for Wireless tab with badge const wirelessTab = page.locator('a:has-text("Wireless")').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { // Check if badge/count is visible (could be 0 or more) const badge = wirelessTab.locator('span'); if (await badge.isVisible({ timeout: 1000 }).catch(() => false)) { // Badge should contain a number const badgeText = await badge.textContent(); expect(badgeText).toMatch(/\d+/); } } } }); test('can view wireless clients list', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for wireless clients table or list const clientsTable = page.locator('table, [role="table"]'); if (await clientsTable.isVisible({ timeout: 2000 }).catch(() => false)) { // Table should have headers const macHeader = page.locator('th:has-text("MAC"), th:has-text("MAC Address")').first(); if (await macHeader.isVisible().catch(() => false)) { await expect(macHeader).toBeVisible(); } } } } }); test('shows signal strength badges', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for signal strength indicators // Signal values are typically shown as "XX dBm" const signalBadge = page.locator(':has-text("dBm")').first(); if (await signalBadge.isVisible({ timeout: 2000 }).catch(() => false)) { const signalText = await signalBadge.textContent(); expect(signalText).toMatch(/-?\d+\s*dBm/); } } } }); test('shows SNR badges', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for SNR indicators // SNR values are typically shown as "XX dB" const snrBadge = page.locator(':has-text(" dB"):not(:has-text("dBm"))').first(); if (await snrBadge.isVisible({ timeout: 2000 }).catch(() => false)) { const snrText = await snrBadge.textContent(); expect(snrText).toMatch(/\d+\s*dB/); } } } }); test('displays client MAC addresses', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for MAC address pattern (XX:XX:XX:XX:XX:XX) const macAddress = page.locator('text=/[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}/i').first(); if (await macAddress.isVisible({ timeout: 2000 }).catch(() => false)) { await expect(macAddress).toBeVisible(); } } } }); test('displays client IP addresses', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for IP address pattern const ipAddress = page.locator('text=/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/').first(); if (await ipAddress.isVisible({ timeout: 2000 }).catch(() => false)) { await expect(ipAddress).toBeVisible(); } } } }); test('shows empty state when no clients connected', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Check for empty state message const emptyState = page.locator( ':has-text("No wireless clients"), :has-text("no clients"), :has-text("empty")' ).first(); // Either show client list or empty state (both are valid) const clientsTable = page.locator('table tbody tr'); const hasClients = await clientsTable.count() > 0; if (!hasClients) { // If no clients, should show empty state if (await emptyState.isVisible({ timeout: 2000 }).catch(() => false)) { await expect(emptyState).toBeVisible(); } } } } }); test('displays TX/RX rates', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for rate indicators (Mbps/Kbps) const rateIndicator = page.locator(':has-text("Mbps"), :has-text("Kbps")').first(); if (await rateIndicator.isVisible({ timeout: 2000 }).catch(() => false)) { await expect(rateIndicator).toBeVisible(); } } } }); test('displays client uptime', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for uptime indicators (hour/minute/second/day/week) const uptimeIndicator = page.locator( ':has-text(" hour"), :has-text(" minute"), :has-text(" day"), :has-text(" week")' ).first(); if (await uptimeIndicator.isVisible({ timeout: 2000 }).catch(() => false)) { await expect(uptimeIndicator).toBeVisible(); } } } }); test('shows table headers for client information', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Check for key table headers const headers = [ 'MAC', 'IP', 'Signal', 'SNR', ]; for (const headerText of headers) { const header = page.locator(`th:has-text("${headerText}")`).first(); if (await header.isVisible({ timeout: 1000 }).catch(() => false)) { await expect(header).toBeVisible(); } } } } }); test('can access wireless tab directly via URL', async ({ page }) => { await page.goto('/devices'); // Get first device URL const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { const deviceUrl = await firstDevice.getAttribute('href'); if (deviceUrl) { // Navigate directly to wireless tab await page.goto(`${deviceUrl}?tab=wireless`); await page.waitForTimeout(500); // Should be on wireless tab await expect(page).toHaveURL(/tab=wireless/); // Wireless content should be visible const wirelessContent = page.locator( 'table, :has-text("MAC"), :has-text("Signal"), :has-text("No wireless clients")' ).first(); if (await wirelessContent.isVisible({ timeout: 2000 }).catch(() => false)) { await expect(wirelessContent).toBeVisible(); } } } }); test('can switch between wireless and other tabs', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Click wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Verify we're on wireless tab await expect(page).toHaveURL(/tab=wireless/); // Switch to another tab (overview, ports, etc.) const overviewTab = page.locator('a[href*="tab=overview"]').first(); if (await overviewTab.isVisible({ timeout: 2000 }).catch(() => false)) { await overviewTab.click(); await page.waitForTimeout(500); // Should be on overview tab now await expect(page).toHaveURL(/tab=overview/); // Switch back to wireless const wirelessTabAgain = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTabAgain.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTabAgain.click(); await page.waitForTimeout(500); // Should be back on wireless tab await expect(page).toHaveURL(/tab=wireless/); } } } } }); test('shows subscriber information when matched', async ({ page }) => { await page.goto('/devices'); const firstDevice = page.locator('a[href*="/devices/"]:not([href*="/devices/new"])').first(); if (await firstDevice.isVisible({ timeout: 2000 }).catch(() => false)) { await firstDevice.click(); await page.waitForTimeout(500); // Navigate to Wireless tab const wirelessTab = page.locator('a[href*="tab=wireless"]').first(); if (await wirelessTab.isVisible({ timeout: 2000 }).catch(() => false)) { await wirelessTab.click(); await page.waitForTimeout(500); // Look for Subscriber column/header const subscriberHeader = page.locator('th:has-text("Subscriber")').first(); if (await subscriberHeader.isVisible({ timeout: 2000 }).catch(() => false)) { await expect(subscriberHeader).toBeVisible(); // If there are clients, check if subscriber names appear const clientRows = page.locator('table tbody tr'); if ((await clientRows.count()) > 0) { // Subscriber column may show names or "—" for unmatched const subscriberCell = page.locator('td').nth(2); // Assuming 3rd column if (await subscriberCell.isVisible({ timeout: 1000 }).catch(() => false)) { await expect(subscriberCell).toBeVisible(); } } } } } }); });