Files
homelab-monitor/e2e/tests/device-table-sort.spec.ts
T
jhodgkin cdbdd01541
CI / web (push) Successful in 17s
CI / api (push) Successful in 24s
Make the network device table sortable by column
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>
2026-07-12 22:48:51 -06:00

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);
});