Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/i15-1/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
import Robot from "./routes/Robot";
import Dashboard from "./routes/Dashboard";
import Playlist from "./routes/Playlist";
import Plans from "./routes/Plans";
import { QueueView } from "./routes/QueueView";
import { PlanBrowser } from "@atlas/blueapi-ui";

const navigation: SectionGroup[] = [
{
Expand Down Expand Up @@ -64,7 +64,7 @@ const navigation: SectionGroup[] = [
},
{
name: "Plans",
element: <Plans />,
element: <PlanBrowser />,
},
],
},
Expand Down
16 changes: 0 additions & 16 deletions apps/i15-1/src/routes/Plans.tsx

This file was deleted.

11 changes: 1 addition & 10 deletions apps/visr/src/routes/Plans.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import { PlanBrowser } from "@atlas/blueapi-ui";
import { PlanParameters } from "@atlas/blueapi-ui";
import { usePlans } from "@atlas/blueapi-query";

function JsonFormsPlans() {
const { data } = usePlans();

return (
<PlanBrowser
plans={data ? data.plans : []}
renderPlan={plan => <PlanParameters plan={plan} />}
/>
);
return <PlanBrowser />;
}

export default JsonFormsPlans;
1 change: 1 addition & 0 deletions packages/blueapi-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@jsonforms/material-renderers": "3.6.0",
"@jsonforms/react": "3.6.0",
"@tanstack/react-query": "^5.90.21",
"lucide-react": "^1.24.0",
"react-error-boundary": "^6.0.0"
},
"devDependencies": {
Expand Down
83 changes: 0 additions & 83 deletions packages/blueapi-ui/src/PlanBrowser.test.tsx

This file was deleted.

60 changes: 0 additions & 60 deletions packages/blueapi-ui/src/PlanBrowser.tsx

This file was deleted.

135 changes: 135 additions & 0 deletions packages/blueapi-ui/src/PlanBrowser/PlanBrowser.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import type { Plan, PlansResponse } from "@atlas/blueapi";
import { render, screen, userEvent } from "@atlas/vitest-conf";
import { PlanBrowser } from "./PlanBrowser";
import { usePlans } from "@atlas/blueapi-query";
import { PlanParameters } from "./PlanParameters";
import { useMediaQuery } from "@mui/material";

// mock usePlans hook
vi.mock("@atlas/blueapi-query");
const usePlansMock = vi.mocked(usePlans);
const plansResponse: PlansResponse = {
plans: [
{ name: "Plan 1", schema: {}, description: "" },
{ name: "Plan 2", schema: {}, description: "" },
{ name: "Plan 3", schema: {}, description: "" },
],
};
usePlansMock.mockReturnValue({ data: plansResponse } as any);

// mock JSONForms
const renderPlan = ({ plan }: { plan: Plan }) => (
<div data-testid="plan-view">{plan.name}</div>
);

vi.mock("./PlanParameters");
const paramsComponentMock = vi.mocked(PlanParameters);
paramsComponentMock.mockImplementation(renderPlan);

// render component under test
function renderBrowser() {
return render(<PlanBrowser />);
}

vi.mock("@mui/material", async () => {
const actual =
await vi.importActual<typeof import("@mui/material")>("@mui/material");

return {
...actual,
useMediaQuery: vi.fn(),
};
});

const mockedUseMediaQuery = vi.mocked(useMediaQuery);

describe("PlanBrowser", () => {
describe("Full layout", () => {
beforeEach(() => {
mockedUseMediaQuery.mockReturnValue(true);
});

it("shows a placeholder before initial plan selection and list of plans", () => {
renderBrowser();

expect(screen.getByText("Select a plan")).toBeInTheDocument();
expect(
screen.getByText("Choose from the list to see details."),
).toBeInTheDocument();
});

it("renders plan details when a plan is selected", async () => {
renderBrowser();

const selectedPlan = screen.getByRole("button", { name: "Plan 2" });
const user = userEvent.setup();
await user.click(selectedPlan);

// placeholder disappears...
expect(screen.queryByText("Select a plan")).not.toBeInTheDocument();

// ...plan details appear
const planDetails = screen.getByTestId("plan-view");
expect(planDetails).toBeInTheDocument();
expect(planDetails).toHaveTextContent("Plan 2");
});

it("renders plan details with every selection", async () => {
renderBrowser();

const user = userEvent.setup();
await user.click(screen.getByRole("button", { name: "Plan 3" }));

const planDetails = screen.getByTestId("plan-view");
expect(planDetails).toBeInTheDocument();
expect(planDetails).toHaveTextContent("Plan 3");

await user.click(screen.getByRole("button", { name: "Plan 1" }));
expect(planDetails).toHaveTextContent("Plan 1");
});

it("persists plan details through search/filtering", async () => {
renderBrowser();
const user = userEvent.setup();

// select plan 1
await user.click(screen.getByRole("button", { name: "Plan 1" }));

// plan 1 details appear
const planDetails = screen.getByTestId("plan-view");
expect(planDetails).toHaveTextContent("Plan 1");

// search for a different plan
const searchbox = screen.getByRole("textbox", { name: /search plans/i });
await user.type(searchbox, "Plan 3");

// but user has not selected it, so plan 1 details remain
expect(planDetails).toHaveTextContent("Plan 1");
});
});

describe("Compact layout", () => {
beforeEach(() => {
mockedUseMediaQuery.mockReturnValue(false);
});

it("shows a placeholder before initial plan selection and 'View plans' button", () => {
renderBrowser();

expect(screen.getByText("View plans")).toBeInTheDocument();
expect(
screen.getByText("Choose from the list to see details."),
).toBeInTheDocument();
});

it("opens drawer with plans list when 'View plans' button is clicked", async () => {
renderBrowser();
const user = userEvent.setup();
const button = screen.getByRole("button", { name: "View plans" });
await user.click(button);
plansResponse.plans.forEach(plan =>
expect(screen.getByText(plan.name)).toBeVisible(),
);
});
});
});
Loading
Loading