Skip to content

Commit 57eced9

Browse files
authored
Consolidate edge discovery into SchemaDiscoveryBoundary (#1530)
- Remove EdgeDiscoveryBoundary in favor of requireEdgeConnections prop on SchemaDiscoveryBoundary - Simplify schema failure tracking: rename edgeConnectionDiscoveryFailed to lastEdgeConnectionSyncFail, remove triedToSync - Add staleTime: Infinity to schema and edge connection queries for explicit cache control - Derive edge connection initialData from Jotai store with edge type filtering - Simplify error handling in schemaSyncQuery and edgeConnectionsQuery
1 parent 71fa5a3 commit 57eced9

File tree

18 files changed

+554
-630
lines changed

18 files changed

+554
-630
lines changed

packages/graph-explorer/src/components/SchemaDiscoveryBoundary.test.tsx

Lines changed: 241 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ vi.mock("@/core", async () => {
88
return {
99
...actual,
1010
useHasActiveSchema: vi.fn(),
11+
useMaybeActiveSchema: vi.fn(),
1112
};
1213
});
1314

@@ -16,10 +17,20 @@ vi.mock("@/hooks/useSchemaSync", () => ({
1617
useCancelSchemaSync: vi.fn(() => vi.fn()),
1718
}));
1819

19-
import { useHasActiveSchema } from "@/core";
20+
vi.mock("@/hooks", async () => {
21+
const actual = await vi.importActual("@/hooks");
22+
return {
23+
...actual,
24+
useTranslations: () => (key: string) => key,
25+
};
26+
});
27+
28+
import { useHasActiveSchema, useMaybeActiveSchema } from "@/core";
2029
import { useSchemaSync } from "@/hooks/useSchemaSync";
30+
import { createRandomEdgeConnection } from "@/utils/testing/randomData";
2131

2232
const mockedUseHasActiveSchema = vi.mocked(useHasActiveSchema);
33+
const mockedUseMaybeActiveSchema = vi.mocked(useMaybeActiveSchema);
2334
const mockedUseSchemaSync = vi.mocked(useSchemaSync);
2435

2536
function createMockSchemaSync(
@@ -28,11 +39,13 @@ function createMockSchemaSync(
2839
return {
2940
schemaDiscoveryQuery: {
3041
isLoading: false,
42+
isFetching: false,
3143
error: null,
3244
refetch: vi.fn(),
3345
} as unknown as ReturnType<typeof useSchemaSync>["schemaDiscoveryQuery"],
3446
edgeDiscoveryQuery: {
3547
isLoading: false,
48+
isFetching: false,
3649
error: null,
3750
refetch: vi.fn(),
3851
} as unknown as ReturnType<typeof useSchemaSync>["edgeDiscoveryQuery"],
@@ -42,128 +55,243 @@ function createMockSchemaSync(
4255
};
4356
}
4457

58+
function mockSchema({
59+
hasSchema = false,
60+
edgeConnections,
61+
}: {
62+
hasSchema?: boolean;
63+
edgeConnections?: ReturnType<typeof createRandomEdgeConnection>[];
64+
} = {}) {
65+
mockedUseHasActiveSchema.mockReturnValue(hasSchema);
66+
mockedUseMaybeActiveSchema.mockReturnValue(
67+
hasSchema ? { vertices: [], edges: [], edgeConnections } : undefined,
68+
);
69+
}
70+
4571
describe("SchemaDiscoveryBoundary", () => {
46-
test("renders children when schema is available", () => {
47-
mockedUseHasActiveSchema.mockReturnValue(true);
48-
mockedUseSchemaSync.mockReturnValue(createMockSchemaSync());
72+
describe("schema only (default)", () => {
73+
test("renders children when schema is available", () => {
74+
mockSchema({ hasSchema: true });
75+
mockedUseSchemaSync.mockReturnValue(createMockSchemaSync());
4976

50-
render(
51-
<SchemaDiscoveryBoundary>
52-
<div>Schema content</div>
53-
</SchemaDiscoveryBoundary>,
54-
);
77+
render(
78+
<SchemaDiscoveryBoundary>
79+
<div>Schema content</div>
80+
</SchemaDiscoveryBoundary>,
81+
);
5582

56-
expect(screen.getByText("Schema content")).toBeInTheDocument();
57-
});
83+
expect(screen.getByText("Schema content")).toBeInTheDocument();
84+
});
5885

59-
test("renders loading state when schema is syncing", () => {
60-
mockedUseHasActiveSchema.mockReturnValue(false);
61-
mockedUseSchemaSync.mockReturnValue(
62-
createMockSchemaSync({
63-
schemaDiscoveryQuery: {
64-
isLoading: true,
65-
error: null,
66-
refetch: vi.fn(),
67-
} as unknown as ReturnType<
68-
typeof useSchemaSync
69-
>["schemaDiscoveryQuery"],
70-
}),
71-
);
72-
73-
render(
74-
<SchemaDiscoveryBoundary>
75-
<div>Schema content</div>
76-
</SchemaDiscoveryBoundary>,
77-
);
78-
79-
expect(screen.getByText("Synchronizing...")).toBeInTheDocument();
80-
expect(screen.queryByText("Schema content")).not.toBeInTheDocument();
81-
});
86+
test("renders loading state when schema is syncing", () => {
87+
mockSchema();
88+
mockedUseSchemaSync.mockReturnValue(
89+
createMockSchemaSync({ isFetching: true }),
90+
);
8291

83-
test("renders loading state when isFetching without schema", () => {
84-
mockedUseHasActiveSchema.mockReturnValue(false);
85-
mockedUseSchemaSync.mockReturnValue(
86-
createMockSchemaSync({
87-
schemaDiscoveryQuery: {
88-
isLoading: false,
89-
isFetching: true,
90-
error: null,
91-
refetch: vi.fn(),
92-
} as unknown as ReturnType<
93-
typeof useSchemaSync
94-
>["schemaDiscoveryQuery"],
95-
}),
96-
);
97-
98-
render(
99-
<SchemaDiscoveryBoundary>
100-
<div>Schema content</div>
101-
</SchemaDiscoveryBoundary>,
102-
);
103-
104-
expect(screen.getByText("Synchronizing...")).toBeInTheDocument();
105-
expect(screen.queryByText("Schema content")).not.toBeInTheDocument();
106-
});
92+
render(
93+
<SchemaDiscoveryBoundary>
94+
<div>Schema content</div>
95+
</SchemaDiscoveryBoundary>,
96+
);
10797

108-
test("renders children when isFetching with existing schema", () => {
109-
mockedUseHasActiveSchema.mockReturnValue(true);
110-
mockedUseSchemaSync.mockReturnValue(
111-
createMockSchemaSync({
112-
schemaDiscoveryQuery: {
113-
isLoading: false,
114-
isFetching: true,
115-
error: null,
116-
refetch: vi.fn(),
117-
} as unknown as ReturnType<
118-
typeof useSchemaSync
119-
>["schemaDiscoveryQuery"],
120-
}),
121-
);
122-
123-
render(
124-
<SchemaDiscoveryBoundary>
125-
<div>Schema content</div>
126-
</SchemaDiscoveryBoundary>,
127-
);
128-
129-
expect(screen.getByText("Schema content")).toBeInTheDocument();
130-
expect(screen.queryByText("Synchronizing...")).not.toBeInTheDocument();
131-
});
98+
expect(screen.getByText("Synchronizing...")).toBeInTheDocument();
99+
expect(screen.queryByText("Schema content")).not.toBeInTheDocument();
100+
});
101+
102+
test("renders children when isFetching with existing schema", () => {
103+
mockSchema({ hasSchema: true });
104+
mockedUseSchemaSync.mockReturnValue(
105+
createMockSchemaSync({ isFetching: true }),
106+
);
107+
108+
render(
109+
<SchemaDiscoveryBoundary>
110+
<div>Schema content</div>
111+
</SchemaDiscoveryBoundary>,
112+
);
113+
114+
expect(screen.getByText("Schema content")).toBeInTheDocument();
115+
expect(screen.queryByText("Synchronizing...")).not.toBeInTheDocument();
116+
});
117+
118+
test("renders error state when schema sync fails", () => {
119+
mockSchema();
120+
mockedUseSchemaSync.mockReturnValue(
121+
createMockSchemaSync({
122+
schemaDiscoveryQuery: {
123+
isFetching: false,
124+
error: new Error("Sync failed"),
125+
refetch: vi.fn(),
126+
} as unknown as ReturnType<
127+
typeof useSchemaSync
128+
>["schemaDiscoveryQuery"],
129+
}),
130+
);
131+
132+
render(
133+
<SchemaDiscoveryBoundary>
134+
<div>Schema content</div>
135+
</SchemaDiscoveryBoundary>,
136+
);
137+
138+
expect(screen.queryByText("Schema content")).not.toBeInTheDocument();
139+
});
140+
141+
test("renders no-schema state when no schema exists", () => {
142+
mockSchema();
143+
mockedUseSchemaSync.mockReturnValue(createMockSchemaSync());
144+
145+
render(
146+
<SchemaDiscoveryBoundary>
147+
<div>Schema content</div>
148+
</SchemaDiscoveryBoundary>,
149+
);
132150

133-
test("renders error state when schema sync fails", () => {
134-
mockedUseHasActiveSchema.mockReturnValue(false);
135-
mockedUseSchemaSync.mockReturnValue(
136-
createMockSchemaSync({
137-
schemaDiscoveryQuery: {
138-
isLoading: false,
139-
error: new Error("Sync failed"),
140-
refetch: vi.fn(),
141-
} as unknown as ReturnType<
142-
typeof useSchemaSync
143-
>["schemaDiscoveryQuery"],
144-
}),
145-
);
146-
147-
render(
148-
<SchemaDiscoveryBoundary>
149-
<div>Schema content</div>
150-
</SchemaDiscoveryBoundary>,
151-
);
152-
153-
expect(screen.queryByText("Schema content")).not.toBeInTheDocument();
151+
expect(screen.getByText("No Schema Available")).toBeInTheDocument();
152+
expect(screen.queryByText("Schema content")).not.toBeInTheDocument();
153+
});
154154
});
155155

156-
test("renders no-schema state when no schema exists", () => {
157-
mockedUseHasActiveSchema.mockReturnValue(false);
158-
mockedUseSchemaSync.mockReturnValue(createMockSchemaSync());
156+
describe("requireEdgeConnections", () => {
157+
test("renders children when edgeConnections is defined", () => {
158+
mockSchema({
159+
hasSchema: true,
160+
edgeConnections: [createRandomEdgeConnection()],
161+
});
162+
mockedUseSchemaSync.mockReturnValue(createMockSchemaSync());
163+
164+
render(
165+
<SchemaDiscoveryBoundary requireEdgeConnections>
166+
<div>Children</div>
167+
</SchemaDiscoveryBoundary>,
168+
);
169+
170+
expect(screen.getByText("Children")).toBeInTheDocument();
171+
});
172+
173+
test("renders children when edgeConnections exists even if edge query has error", () => {
174+
mockSchema({
175+
hasSchema: true,
176+
edgeConnections: [createRandomEdgeConnection()],
177+
});
178+
mockedUseSchemaSync.mockReturnValue(
179+
createMockSchemaSync({
180+
edgeDiscoveryQuery: {
181+
isFetching: false,
182+
error: new Error("Query failed"),
183+
refetch: vi.fn(),
184+
} as unknown as ReturnType<
185+
typeof useSchemaSync
186+
>["edgeDiscoveryQuery"],
187+
}),
188+
);
189+
190+
render(
191+
<SchemaDiscoveryBoundary requireEdgeConnections>
192+
<div>Children</div>
193+
</SchemaDiscoveryBoundary>,
194+
);
195+
196+
expect(screen.getByText("Children")).toBeInTheDocument();
197+
});
198+
199+
test("renders loading when edgeConnections is undefined and queries are fetching", () => {
200+
mockSchema({ hasSchema: true, edgeConnections: undefined });
201+
mockedUseSchemaSync.mockReturnValue(
202+
createMockSchemaSync({ isFetching: true }),
203+
);
204+
205+
render(
206+
<SchemaDiscoveryBoundary requireEdgeConnections>
207+
<div>Children</div>
208+
</SchemaDiscoveryBoundary>,
209+
);
210+
211+
expect(screen.getByText("Synchronizing...")).toBeInTheDocument();
212+
expect(screen.queryByText("Children")).not.toBeInTheDocument();
213+
});
214+
215+
test("renders error when schema query has error", () => {
216+
mockSchema({ hasSchema: false });
217+
mockedUseSchemaSync.mockReturnValue(
218+
createMockSchemaSync({
219+
schemaDiscoveryQuery: {
220+
isFetching: false,
221+
error: new Error("Schema query failed"),
222+
refetch: vi.fn(),
223+
} as unknown as ReturnType<
224+
typeof useSchemaSync
225+
>["schemaDiscoveryQuery"],
226+
}),
227+
);
228+
229+
render(
230+
<SchemaDiscoveryBoundary requireEdgeConnections>
231+
<div>Children</div>
232+
</SchemaDiscoveryBoundary>,
233+
);
234+
235+
expect(screen.queryByText("Children")).not.toBeInTheDocument();
236+
expect(
237+
screen.getByRole("button", { name: /retry/i }),
238+
).toBeInTheDocument();
239+
});
240+
241+
test("renders error when edge query has error and no edge connections", () => {
242+
mockSchema({ hasSchema: true, edgeConnections: undefined });
243+
mockedUseSchemaSync.mockReturnValue(
244+
createMockSchemaSync({
245+
edgeDiscoveryQuery: {
246+
isFetching: false,
247+
error: new Error("Query failed"),
248+
refetch: vi.fn(),
249+
} as unknown as ReturnType<
250+
typeof useSchemaSync
251+
>["edgeDiscoveryQuery"],
252+
}),
253+
);
254+
255+
render(
256+
<SchemaDiscoveryBoundary requireEdgeConnections>
257+
<div>Children</div>
258+
</SchemaDiscoveryBoundary>,
259+
);
260+
261+
expect(screen.queryByText("Children")).not.toBeInTheDocument();
262+
expect(
263+
screen.getByRole("button", { name: /retry/i }),
264+
).toBeInTheDocument();
265+
});
266+
267+
test("renders edge connections empty state when schema exists but no edge connections", () => {
268+
mockSchema({ hasSchema: true, edgeConnections: undefined });
269+
mockedUseSchemaSync.mockReturnValue(createMockSchemaSync());
270+
271+
render(
272+
<SchemaDiscoveryBoundary requireEdgeConnections>
273+
<div>Children</div>
274+
</SchemaDiscoveryBoundary>,
275+
);
276+
277+
expect(
278+
screen.getByText("No edge-connections Available"),
279+
).toBeInTheDocument();
280+
expect(screen.queryByText("Children")).not.toBeInTheDocument();
281+
});
282+
283+
test("renders no-schema state when no schema exists", () => {
284+
mockSchema();
285+
mockedUseSchemaSync.mockReturnValue(createMockSchemaSync());
159286

160-
render(
161-
<SchemaDiscoveryBoundary>
162-
<div>Schema content</div>
163-
</SchemaDiscoveryBoundary>,
164-
);
287+
render(
288+
<SchemaDiscoveryBoundary requireEdgeConnections>
289+
<div>Children</div>
290+
</SchemaDiscoveryBoundary>,
291+
);
165292

166-
expect(screen.getByText("No Schema Available")).toBeInTheDocument();
167-
expect(screen.queryByText("Schema content")).not.toBeInTheDocument();
293+
expect(screen.getByText("No Schema Available")).toBeInTheDocument();
294+
expect(screen.queryByText("Children")).not.toBeInTheDocument();
295+
});
168296
});
169297
});

0 commit comments

Comments
 (0)