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
25 changes: 12 additions & 13 deletions packages/graph-explorer/src/modules/SchemaGraph/SchemaGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,7 @@ export default function SchemaGraph({ className, ...props }: SchemaGraphProps) {

const handleSidebarSelectionChange = (item: SchemaGraphSelectionItem) => {
setSelection(item);
setGraphSelection(
item.type === "vertex-type"
? {
nodeIds: new Set([item.id]),
edgeIds: new Set(),
groupIds: new Set(),
}
: {
nodeIds: new Set(),
edgeIds: new Set([item.id]),
groupIds: new Set(),
},
);
setGraphSelection(toSelectedElements(item));
};

const hasSchemaData = nodes.length > 0;
Expand Down Expand Up @@ -130,6 +118,17 @@ export default function SchemaGraph({ className, ...props }: SchemaGraphProps) {
);
}

/** Maps a single schema graph selection item to the graph view's selected elements. */
export function toSelectedElements(
item: SchemaGraphSelectionItem,
): SelectedElements {
return {
nodeIds: new Set(item.type === "vertex-type" ? [item.id] : []),
edgeIds: new Set(item.type === "edge-connection" ? [item.id] : []),
groupIds: new Set(),
};
}

/** Maps raw graph selection elements to a SchemaGraphSelection. */
export function toSchemaGraphSelection(
selected: SelectedElements,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import type { ReactNode } from "react";

// @vitest-environment happy-dom
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, test, vi } from "vitest";

import type * as Core from "@/core";

import { TooltipProvider } from "@/components";
import {
createEdgeType,
createVertexType,
Expand All @@ -14,6 +17,10 @@ import {

import { EdgeConnectionRow, PropertiesDetails } from "./Details";

function renderWithTooltips(ui: ReactNode) {
return render(<TooltipProvider>{ui}</TooltipProvider>);
}

vi.mock("@/hooks", async () => {
const actual = await vi.importActual("@/hooks");
return {
Expand Down Expand Up @@ -110,21 +117,38 @@ describe("EdgeConnectionRow", () => {
expect(screen.queryAllByRole("button")).toHaveLength(0);
});

test("renders three buttons (source, edge, target) when onSelectionChange is provided", () => {
render(
test("renders the unselected vertex types as buttons", () => {
renderWithTooltips(
<EdgeConnectionRow
edgeConnection={createEdgeConnection()}
onSelectionChange={() => {}}
/>,
);

expect(screen.getByRole("button", { name: "Person" })).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Company" })).toBeInTheDocument();
expect(screen.getAllByRole("button")).toHaveLength(2);
});

test("does not make the selected vertex type clickable", () => {
renderWithTooltips(
<EdgeConnectionRow
edgeConnection={createEdgeConnection()}
selectedVertexType={createVertexType("Person")}
onSelectionChange={() => {}}
/>,
);

expect(screen.getAllByRole("button")).toHaveLength(3);
expect(
screen.queryByRole("button", { name: "Person" }),
).not.toBeInTheDocument();
expect(screen.getByRole("button", { name: "Company" })).toBeInTheDocument();
});

test("calls onSelectionChange with the source vertex when source button is clicked", async () => {
const user = userEvent.setup();
const onSelectionChange = vi.fn();
render(
renderWithTooltips(
<EdgeConnectionRow
edgeConnection={createEdgeConnection()}
onSelectionChange={onSelectionChange}
Expand All @@ -142,7 +166,7 @@ describe("EdgeConnectionRow", () => {
test("calls onSelectionChange with the target vertex when target button is clicked", async () => {
const user = userEvent.setup();
const onSelectionChange = vi.fn();
render(
renderWithTooltips(
<EdgeConnectionRow
edgeConnection={createEdgeConnection()}
onSelectionChange={onSelectionChange}
Expand All @@ -160,18 +184,48 @@ describe("EdgeConnectionRow", () => {
test("calls onSelectionChange with the edge connection id when edge button is clicked", async () => {
const user = userEvent.setup();
const onSelectionChange = vi.fn();
render(
renderWithTooltips(
<EdgeConnectionRow
edgeConnection={createEdgeConnection()}
selectedVertexType={createVertexType("Person")}
onSelectionChange={onSelectionChange}
/>,
);

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

expect(onSelectionChange).toHaveBeenCalledWith({
type: "edge-connection",
id: "Person-[knows]->Company",
});
});

test("names the edge button by its label without the decorative arrows", () => {
renderWithTooltips(
<EdgeConnectionRow
edgeConnection={createEdgeConnection()}
selectedVertexType={createVertexType("Person")}
onSelectionChange={() => {}}
/>,
);

expect(screen.getByRole("button", { name: "knows" })).toBeInTheDocument();
expect(screen.queryByRole("button", { name: /→/ })).not.toBeInTheDocument();
});

test("explains via tooltip that activating a type changes the selection", async () => {
const user = userEvent.setup();
renderWithTooltips(
<EdgeConnectionRow
edgeConnection={createEdgeConnection()}
onSelectionChange={() => {}}
/>,
);

await user.tab();

expect(
await screen.findAllByText("Change selection to Person"),
).not.toHaveLength(0);
});
});
Loading
Loading