mirror of
https://github.com/ipnet-mesh/meshcore-hub.git
synced 2026-08-07 01:13:11 +02:00
acacea0d85
Adds a checkbox filter to the Routes page that narrows the list to routes owned by the current user. The filter is URL-driven (?mine=true), cached server-side automatically via the existing key builder, and only shown to operators/admins (members can't own routes). Backend: mine query param on GET /api/v1/routes filters by created_by matching the caller's X-User-Id. Legacy NULL routes are excluded. Tests: - Backend: 6 new TestRouteMineFilter tests (own/other/null/admin/default) - Vitest: 6 new tests (param passing, role gating, checkbox state) - E2E: new seed route owned by pw-operator + mine filter spec
99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { OPERATOR_STATE } from "../utils/helpers";
|
|
|
|
test.use({ storageState: OPERATOR_STATE });
|
|
|
|
const ROUTE_LABEL = "Op From \u2192 Op To";
|
|
const SEEDED_LEGACY = "Alpha Site \u2192 Bravo Site";
|
|
const SEEDED_OWNED = "Op North \u2192 Op South";
|
|
|
|
test.describe.serial("routes (operator)", () => {
|
|
test("operator can manage routes; admin visibility tier is hidden", async ({
|
|
page,
|
|
}) => {
|
|
await page.goto("/routes");
|
|
|
|
// Operators see the seeded community route and the add button.
|
|
const seededCard = page.locator(
|
|
`[data-testid="route-card"][data-route-label="${SEEDED_LEGACY}"]`,
|
|
);
|
|
await expect(seededCard).toBeVisible();
|
|
await expect(page.getByTestId("add-route")).toBeVisible();
|
|
|
|
// The seeded route has NULL created_by — operator must NOT see edit/delete.
|
|
await expect(seededCard.getByTestId("edit-route")).toHaveCount(0);
|
|
await expect(seededCard.getByTestId("delete-route")).toHaveCount(0);
|
|
|
|
// The visibility dropdown must NOT offer the admin tier to an operator.
|
|
await page.getByTestId("add-route").click();
|
|
const modal = page.locator('[data-testid="route-modal"]');
|
|
await expect(modal).toBeVisible();
|
|
const visibility = page.getByTestId("route-visibility");
|
|
await expect(visibility.locator("option[value='admin']")).toHaveCount(0);
|
|
await visibility.selectOption("operator");
|
|
await expect(visibility).toHaveValue("operator");
|
|
|
|
await page.getByTestId("route-from").fill("Op From");
|
|
await page.getByTestId("route-to").fill("Op To");
|
|
|
|
await page.getByTestId("route-path-search").fill("Alpha");
|
|
await page.getByTestId("node-search-result").first().click();
|
|
await page.getByTestId("route-path-search").fill("Bravo");
|
|
await page.getByTestId("node-search-result").first().click();
|
|
await expect(page.getByTestId("route-path-chip")).toHaveCount(2);
|
|
|
|
await page.getByTestId("route-save").click();
|
|
await expect(modal).toHaveCount(0);
|
|
|
|
const card = page.locator(
|
|
`[data-testid="route-card"][data-route-label="${ROUTE_LABEL}"]`,
|
|
);
|
|
await expect(card).toBeVisible();
|
|
|
|
// Operator owns the route they just created — edit/delete should be present.
|
|
await card.getByTestId("edit-route").click();
|
|
await expect(modal).toBeVisible();
|
|
await expect(page.getByTestId("route-from")).toHaveValue("Op From");
|
|
await page.getByTestId("route-cancel").click();
|
|
|
|
// Operator can delete the route they created.
|
|
await card.getByTestId("delete-route").click();
|
|
const confirm = page.locator("dialog.modal-open");
|
|
await expect(confirm).toBeVisible();
|
|
await confirm.getByRole("button", { name: "Delete" }).click();
|
|
await expect(card).toHaveCount(0);
|
|
});
|
|
|
|
test("mine filter shows only routes the operator owns", async ({ page }) => {
|
|
await page.goto("/routes");
|
|
|
|
const legacyCard = page.locator(
|
|
`[data-testid="route-card"][data-route-label="${SEEDED_LEGACY}"]`,
|
|
);
|
|
const ownedCard = page.locator(
|
|
`[data-testid="route-card"][data-route-label="${SEEDED_OWNED}"]`,
|
|
);
|
|
|
|
// Both the legacy (NULL created_by) and operator-owned routes are visible.
|
|
await expect(legacyCard).toBeVisible();
|
|
await expect(ownedCard).toBeVisible();
|
|
|
|
// Open the filter panel and toggle "mine".
|
|
await page.locator("#filter-toggle").check();
|
|
await page.getByTestId("routes-mine-toggle").check();
|
|
|
|
// URL reflects the filter state.
|
|
await expect(page).toHaveURL(/mine=true/);
|
|
|
|
// Legacy route (NULL created_by) disappears; owned route stays.
|
|
await expect(legacyCard).toHaveCount(0);
|
|
await expect(ownedCard).toBeVisible();
|
|
|
|
// Turn the filter off — both routes return.
|
|
await page.getByTestId("routes-mine-toggle").uncheck();
|
|
await expect(page).not.toHaveURL(/mine=true/);
|
|
await expect(legacyCard).toBeVisible();
|
|
await expect(ownedCard).toBeVisible();
|
|
});
|
|
});
|