BRIDGE_Modul-S_prod / src /modules /routing.test.tsx
BRIDGE Platform Agent
feat(platform): BRIDGE Modules hub with /modules/e and /modules/s routed workspaces
1955a0f
Raw History Blame Contribute Delete
4.81 kB
import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MemoryRouter, Routes, Route } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import ModuleHub from "./ModuleHub";
import ModuleShell from "./ModuleShell";
import { LaunchProvider } from "./LaunchContext";
import { ThemeProvider } from "../context/ThemeContext";
import { ApiKeyProvider } from "../context/ApiKeyContext";
import { EDashboard, SCampaigns } from "./lazyPages";
import { apiClient } from "../lib/apiClient";
vi.mock("recharts", () => ({
ResponsiveContainer: ({ children }: any) => <div>{children}</div>,
AreaChart: () => <div>AreaChart</div>,
Area: () => <div />,
XAxis: () => <div />,
YAxis: () => <div />,
Tooltip: () => <div />,
LineChart: () => <div>LineChart</div>,
BarChart: () => <div>BarChart</div>,
Line: () => <div />,
Bar: () => <div />,
CartesianGrid: () => <div />,
Legend: () => <div />,
PieChart: () => <div>PieChart</div>,
Pie: () => <div />,
Cell: () => <div />,
}));
vi.mock("../lib/apiClient", () => ({
apiClient: { get: vi.fn().mockResolvedValue({ data: [] }) },
}));
vi.mock("../lib/supabaseClient", () => ({
supabase: null,
isSupabaseConfigured: false,
}));
function makeWrapper(initialEntries: string[]) {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false, gcTime: 0 } },
});
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<ApiKeyProvider>
<MemoryRouter initialEntries={initialEntries}>
<LaunchProvider>
<Routes>
<Route path="/" element={<ModuleHub />} />
<Route path="/modules/e" element={<ModuleShell module="e" />}>
<Route index element={<EDashboard />} />
</Route>
<Route path="/modules/s" element={<ModuleShell module="s" />}>
<Route path="campaigns" element={<SCampaigns />} />
</Route>
</Routes>
</LaunchProvider>
</MemoryRouter>
</ApiKeyProvider>
</ThemeProvider>
</QueryClientProvider>
);
}
describe("BRIDGE platform routing", () => {
beforeEach(() => {
vi.clearAllMocks();
(apiClient.get as any).mockResolvedValue({ data: [] });
});
it("hub renders both module launcher cards with direct-launch buttons", () => {
render(makeWrapper(["/"]));
expect(screen.getAllByText(/BRIDGE/).length).toBeGreaterThan(0);
expect(screen.getByRole("button", { name: /Launch Module E/i })).toBeTruthy();
expect(screen.getByRole("button", { name: /Launch Module S/i })).toBeTruthy();
expect(screen.getByText(/Direct URLs/i)).toBeTruthy();
});
it("direct URL load of /modules/e mounts the E shell with its launch guard", async () => {
render(makeWrapper(["/modules/e"]));
expect(screen.getByTestId("module-shell-e")).toBeTruthy();
expect(screen.getByTestId("module-launch-animation")).toBeTruthy();
// Real dashboard primitives assemble — StatCards carry real titles
await waitFor(() => {
expect(screen.getAllByText(/Total Leads/i).length).toBeGreaterThan(0);
});
});
it("direct URL load of /modules/s mounts the S shell with the S campaign page", async () => {
render(makeWrapper(["/modules/s/campaigns"]));
expect(screen.getByTestId("module-shell-s")).toBeTruthy();
expect(screen.getByTestId("module-launch-animation")).toBeTruthy();
await waitFor(() => {
expect(document.querySelector('[data-module="s"]')).toBeTruthy();
});
});
it("launch animation reveals the workspace when completed", async () => {
vi.useFakeTimers({ shouldAdvanceTime: true });
try {
render(makeWrapper(["/modules/e"]));
expect(screen.getByTestId("module-launch-animation")).toBeTruthy();
// Watchdog completes the assembly (slow-motion budget ≈ 3.3s)
await vi.advanceTimersByTimeAsync(4000);
await waitFor(() => {
expect(screen.queryByTestId("module-launch-animation")).toBeNull();
});
} finally {
vi.useRealTimers();
}
});
it("launching Module S from the hub routes to /modules/s", async () => {
const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime });
vi.useFakeTimers({ shouldAdvanceTime: true });
try {
render(makeWrapper(["/"]));
await user.click(screen.getByRole("button", { name: /Launch Module S/i }));
await vi.advanceTimersByTimeAsync(4000);
await waitFor(() => {
expect(screen.getByTestId("module-shell-s")).toBeTruthy();
});
} finally {
vi.useRealTimers();
}
});
});