feat(search): add role-aware backend search and truthful n8n status
Two new endpoints. GET /api/v1/search returns bounded typed results (vehicle, booking, data-quality-issue, application section) instead of the frontend guessing routes from regex patterns against public-ref prefixes; data-quality and manager-only sections are filtered server-side by role, and customers are deliberately never returned since no customer detail route exists in this PoC. GET /api/v1/integrations/status aggregates outbox delivery counts (pending/delivering/succeeded/failed) into a single truthful n8n state (disabled/unavailable/degraded/operational/no_evidence) instead of the UI showing whichever status the single most recent event happened to be in -- a vehicle_status_conflict-style bug where one stale failure or one lucky success could misreport the dispatcher's actual health. Also fixes a real config gap this surfaced: MCP_HUB_REGISTRATION_ENABLED was documented in .env.example but had no corresponding Settings field, so it was silently ignored by pydantic-settings' extra="ignore" and never actually read anywhere in the codebase.
This commit is contained in:
@@ -20,16 +20,50 @@ test("control-centre shell exposes landmarks, persisted readiness and active nav
|
||||
await expect(page.getByRole("link", { name: "Overview" }).first()).toHaveAttribute("aria-current", "page");
|
||||
});
|
||||
|
||||
test("global search supports its keyboard shortcut and public references", async ({ page }) => {
|
||||
test("global search supports its keyboard shortcut and finds a vehicle by reference", async ({ page }) => {
|
||||
await page.keyboard.press("Control+k");
|
||||
const search = page.getByRole("searchbox", { name: "Search MobilityOps" });
|
||||
const search = page.getByRole("combobox", { name: "Search MobilityOps" });
|
||||
await expect(search).toBeFocused();
|
||||
await search.fill("MO-024");
|
||||
await search.press("Enter");
|
||||
const result = page.getByRole("option", { name: /MO-024/ });
|
||||
await expect(result).toBeVisible();
|
||||
await result.click();
|
||||
await expect(page).toHaveURL(/\/vehicles\/MO-024$/);
|
||||
await expect(page.getByRole("heading", { name: "MO-024" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("global search supports arrow-key navigation and Enter to select", async ({ page }) => {
|
||||
const search = page.getByRole("combobox", { name: "Search MobilityOps" });
|
||||
await search.fill("fleet");
|
||||
await expect(page.getByRole("option", { name: /Fleet/ })).toBeVisible();
|
||||
await search.press("ArrowDown");
|
||||
await search.press("Enter");
|
||||
await expect(page).toHaveURL(/\/vehicles$/);
|
||||
});
|
||||
|
||||
test("global search shows a no-results state and closes on Escape", async ({ page }) => {
|
||||
const search = page.getByRole("combobox", { name: "Search MobilityOps" });
|
||||
await search.fill("zzz-nothing-matches-zzz");
|
||||
await expect(page.getByText(/No matches for/)).toBeVisible();
|
||||
await search.press("Escape");
|
||||
await expect(page.getByRole("listbox")).not.toBeVisible();
|
||||
});
|
||||
|
||||
test("global search finds a booking and a data-quality issue by reference", async ({ page }) => {
|
||||
const search = page.getByRole("combobox", { name: "Search MobilityOps" });
|
||||
await search.fill("BK-DEMO-RETURN");
|
||||
const bookingResult = page.getByRole("option", { name: /BK-DEMO-RETURN/ });
|
||||
await expect(bookingResult).toBeVisible();
|
||||
await bookingResult.click();
|
||||
await expect(page).toHaveURL(/\/bookings\/BK-DEMO-RETURN$/);
|
||||
|
||||
await search.fill("DQ-DEMO-OVERLAP");
|
||||
const issueResult = page.getByRole("option", { name: /DQ-DEMO-OVERLAP/ });
|
||||
await expect(issueResult).toBeVisible();
|
||||
await issueResult.click();
|
||||
await expect(page).toHaveURL(/\/data-quality\/DQ-DEMO-OVERLAP$/);
|
||||
});
|
||||
|
||||
test("return review separates capture from irreversible commit", async ({ page }) => {
|
||||
await page.goto("/bookings/BK-DEMO-RETURN");
|
||||
await page.getByLabel("End odometer (km)").fill("60000");
|
||||
|
||||
Reference in New Issue
Block a user