cdbdd01541
Click a header to sort by it (ascending), click again to reverse. Status defaults to known-first (its display string sorts that way naturally, no special-casing needed). IP sorts numerically by octet, not lexically. Ties fall back to IP order so the table doesn't reshuffle mid-poll for devices sharing a sort value (e.g. many unnamed unknowns). Added a Playwright test verifying IP asc/desc and Name asc against real rendered data. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
|
|
const USERNAME = process.env.LOCAL_USERNAME ?? "admin";
|
|
const PASSWORD = process.env.LOCAL_PASSWORD ?? "";
|
|
|
|
async function login(page: import("@playwright/test").Page) {
|
|
await page.goto("/");
|
|
await page.getByPlaceholder("Username").fill(USERNAME);
|
|
await page.getByPlaceholder("Password").fill(PASSWORD);
|
|
await page.getByRole("button", { name: "Sign in" }).click();
|
|
await expect(page.locator(".device-table tbody tr").first()).toBeVisible({ timeout: 15_000 });
|
|
}
|
|
|
|
test("network device table sorts by each column", async ({ page }) => {
|
|
test.skip(!PASSWORD, "LOCAL_PASSWORD not set");
|
|
await login(page);
|
|
|
|
const ipCells = () => page.locator(".device-table tbody tr td:nth-child(2)").allTextContents();
|
|
|
|
// Default: known-first (status ascending).
|
|
const firstBadge = page.locator(".device-table tbody tr td:first-child .device-badge").first();
|
|
await expect(firstBadge).toHaveText("known");
|
|
|
|
// Click IP header -> ascending numeric IP order.
|
|
await page.getByRole("button", { name: "IP" }).click();
|
|
const ascIps = await ipCells();
|
|
const numeric = (ip: string) => ip.split(".").map(Number);
|
|
const sortedAsc = [...ascIps].sort((a, b) => {
|
|
const [an, bn] = [numeric(a), numeric(b)];
|
|
for (let i = 0; i < 4; i++) if (an[i] !== bn[i]) return an[i] - bn[i];
|
|
return 0;
|
|
});
|
|
expect(ascIps).toEqual(sortedAsc);
|
|
|
|
// Click IP header again -> descending.
|
|
await page.getByRole("button", { name: "IP" }).click();
|
|
const descIps = await ipCells();
|
|
expect(descIps).toEqual([...sortedAsc].reverse());
|
|
|
|
// Click a different column (Name) resets to ascending on that column.
|
|
await page.getByRole("button", { name: "Name" }).click();
|
|
const names = await page.locator(".device-table tbody tr td:nth-child(4)").allTextContents();
|
|
const sortedNames = [...names].sort((a, b) => a.localeCompare(b));
|
|
expect(names).toEqual(sortedNames);
|
|
});
|