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
141 changes: 90 additions & 51 deletions src/components/chunks-panel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ describe("ChunksPanel", () => {
expect(cardMinimumWidth).toBeGreaterThanOrEqual(treeWidth);
});

it("zooms the section tree while keeping the scaled surface measurable", async () => {
it("does not render section tree zoom controls over the canvas", async () => {
const user = userEvent.setup();

render(
Expand All @@ -196,45 +196,55 @@ describe("ChunksPanel", () => {

await user.click(screen.getByRole("button", { name: "Tree" }));

const tree = screen.getByRole("tree", { name: "Parsed chunk sections" });
const surface = screen.getByTestId("chunk-section-tree-zoom-surface");
const initialSurfaceWidth = Number.parseInt(surface.style.width, 10);
expect(
screen.queryByTestId("chunk-section-tree-zoom-overlay"),
).toBeNull();
expect(
screen.queryByRole("group", { name: "Section tree zoom" }),
).toBeNull();
expect(
screen.queryByRole("button", { name: "Zoom in section tree" }),
).toBeNull();
expect(
screen.queryByRole("button", { name: "Zoom out section tree" }),
).toBeNull();
});

expect(tree.style.transform).toBe("scale(1)");
expect(screen.getByText("100%")).toBeTruthy();
it("allows the section tree to zoom out to 30 percent with the mouse wheel", async () => {
const user = userEvent.setup();

await user.click(
screen.getByRole("button", { name: "Zoom in section tree" }),
render(
React.createElement(C, {
chunks: [
{
chunkId: "chunk_1",
type: "text",
content: "Overview text",
sectionPath: "manual.pdf/Overview/Product/Robotics",
sourceTitle: "manual.pdf",
},
],
selectedSource: "manual.pdf",
}),
);

const zoomedInSurfaceWidth = Number.parseInt(surface.style.width, 10);
await user.click(screen.getByRole("button", { name: "Tree" }));

expect(tree.style.transform).toBe("scale(1.1)");
expect(screen.getByText("110%")).toBeTruthy();
expect(zoomedInSurfaceWidth).toBeGreaterThan(initialSurfaceWidth);
const tree = screen.getByRole("tree", { name: "Parsed chunk sections" });
const surface = screen.getByTestId("chunk-section-tree-zoom-surface");
const initialSurfaceWidth = Number.parseInt(surface.style.width, 10);

await user.click(
screen.getByRole("button", { name: "Zoom out section tree" }),
);
await user.click(
screen.getByRole("button", { name: "Zoom out section tree" }),
);
for (let i = 0; i < 7; i += 1) {
fireEvent.wheel(surface, { deltaY: 120 });
}

const zoomedOutSurfaceWidth = Number.parseInt(surface.style.width, 10);

expect(tree.style.transform).toBe("scale(0.9)");
expect(screen.getByText("90%")).toBeTruthy();
expect(zoomedOutSurfaceWidth).toBeLessThan(zoomedInSurfaceWidth);

await user.click(
screen.getByRole("button", { name: "Reset section tree zoom" }),
);

expect(tree.style.transform).toBe("scale(1)");
expect(screen.getByText("100%")).toBeTruthy();
expect(tree.style.transform).toBe("scale(0.3)");
expect(zoomedOutSurfaceWidth).toBeLessThan(initialSurfaceWidth);
});

it("allows the section tree to zoom out to 30 percent", async () => {
it("zooms the section tree with the mouse wheel", async () => {
const user = userEvent.setup();

render(
Expand All @@ -256,24 +266,24 @@ describe("ChunksPanel", () => {

const tree = screen.getByRole("tree", { name: "Parsed chunk sections" });
const surface = screen.getByTestId("chunk-section-tree-zoom-surface");
const initialSurfaceWidth = Number.parseInt(surface.style.width, 10);
const zoomOutButton = screen.getByRole("button", {
name: "Zoom out section tree",
const zoomInEvent = new WheelEvent("wheel", {
cancelable: true,
deltaY: -120,
});

for (let i = 0; i < 7; i += 1) {
await user.click(zoomOutButton);
}
act(() => {
surface.dispatchEvent(zoomInEvent);
});

const zoomedOutSurfaceWidth = Number.parseInt(surface.style.width, 10);
expect(zoomInEvent.defaultPrevented).toBe(true);
expect(tree.style.transform).toBe("scale(1.1)");

expect(tree.style.transform).toBe("scale(0.3)");
expect(screen.getByText("30%")).toBeTruthy();
expect(zoomedOutSurfaceWidth).toBeLessThan(initialSurfaceWidth);
expect(zoomOutButton.hasAttribute("disabled")).toBe(true);
fireEvent.wheel(surface, { deltaY: 120 });

expect(tree.style.transform).toBe("scale(1)");
});

it("keeps section tree zoom controls fixed at the chunk panel top left", async () => {
it("pans the section tree canvas by dragging the background", async () => {
const user = userEvent.setup();

render(
Expand All @@ -293,17 +303,46 @@ describe("ChunksPanel", () => {

await user.click(screen.getByRole("button", { name: "Tree" }));

const overlay = screen.getByTestId("chunk-section-tree-zoom-overlay");
const scrollContent = screen.getByTestId("chunks-scroll-content");
const surface = screen.getByTestId("chunk-section-tree-zoom-surface");
const tree = screen.getByRole("tree", { name: "Parsed chunk sections" });

expect(overlay.className).toContain("absolute");
expect(overlay.className).toContain("left-3");
expect(overlay.className).not.toContain("right-3");
expect(overlay.className).toContain("top-3");
expect(scrollContent.contains(overlay)).toBe(false);
expect(
screen.getByRole("group", { name: "Section tree zoom" }),
).toBeTruthy();
fireEvent.mouseDown(surface, { button: 0, clientX: 100, clientY: 90 });
fireEvent.mouseMove(window, { clientX: 142, clientY: 126 });
fireEvent.mouseUp(window);

expect(tree.style.left).toBe("42px");
expect(tree.style.top).toBe("36px");
expect(surface.className).toContain("cursor-grab");
});

it("uses pointer cursor and Violet colors for clickable section tree chunk nodes", async () => {
const user = userEvent.setup();

render(
React.createElement(C, {
chunks: [
{
chunkId: "robotics_chunk",
type: "text",
content: "Robotics details",
sectionPath: "manual.pdf/Outlook/Robotics",
sourceTitle: "manual.pdf",
},
],
selectedSource: "manual.pdf",
}),
);

await user.click(screen.getByRole("button", { name: "Tree" }));

const chunkNode = screen.getByRole("button", {
name: /Robotics details\s*Text/,
});

expect(chunkNode.className).toContain("cursor-pointer");
expect(chunkNode.className).toContain("border-violet-200");
expect(chunkNode.className).toContain("bg-violet-50");
expect(chunkNode.className).toContain("hover:bg-violet-100");
});

it("returns to the list and focuses a chunk when its tree node is clicked", async () => {
Expand Down
Loading
Loading