Skip to content

Commit 85276f4

Browse files
committed
Fix gremlin counts
1 parent b1f63bc commit 85276f4

File tree

2 files changed

+87
-18
lines changed

2 files changed

+87
-18
lines changed

packages/graph-explorer/src/connector/gremlin/neighborCounts.test.ts

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createVertexId } from "@/core";
1+
import { createVertexId, EntityRawId } from "@/core";
22
import { neighborCounts } from "./neighborCounts";
33
import { query } from "@/utils";
44
import { NeighborCount } from "../useGEFetchTypes";
@@ -7,6 +7,7 @@ import {
77
createGremlinResponse,
88
createRandomVertexId,
99
} from "@/utils/testing";
10+
import { GMap } from "./types";
1011

1112
describe("neighborCounts", () => {
1213
it("should return empty for an empty request", async () => {
@@ -42,6 +43,7 @@ describe("neighborCounts", () => {
4243
counts: {
4344
label1: 3,
4445
label2: 9,
46+
label3: 9,
4547
},
4648
};
4749
const response = createResponse({
@@ -116,18 +118,86 @@ describe("neighborCounts", () => {
116118
)
117119
`);
118120
});
121+
122+
it("should handle error response", async () => {
123+
const mockFetch = vi.fn().mockResolvedValue({
124+
code: 500,
125+
detailedMessage: "Internal server error occurred",
126+
});
127+
128+
await expect(
129+
neighborCounts(mockFetch, {
130+
vertexIds: [createVertexId("123")],
131+
})
132+
).rejects.toThrow("Internal server error occurred");
133+
});
134+
135+
it("should handle empty response data", async () => {
136+
const mockFetch = vi
137+
.fn()
138+
.mockResolvedValue(createGremlinResponse(createGMap({})));
139+
140+
const result = await neighborCounts(mockFetch, {
141+
vertexIds: [createVertexId("123")],
142+
});
143+
144+
expect(result.counts).toEqual([]);
145+
});
146+
147+
it("should handle vertex with zero neighbors", async () => {
148+
const vertexId = createRandomVertexId();
149+
const expected: NeighborCount = {
150+
vertexId,
151+
totalCount: 0,
152+
counts: {},
153+
};
154+
const response = createResponse(expected);
155+
const mockFetch = vi.fn().mockResolvedValue(response);
156+
157+
const result = await neighborCounts(mockFetch, {
158+
vertexIds: [vertexId],
159+
});
160+
161+
expect(result.counts).toEqual([expected]);
162+
});
163+
164+
it("should handle mixed vertex ID types", async () => {
165+
const stringId = createVertexId("string-id");
166+
const numberId = createVertexId(42);
167+
const expected1: NeighborCount = {
168+
vertexId: stringId,
169+
totalCount: 5,
170+
counts: { type1: 5 },
171+
};
172+
const expected2: NeighborCount = {
173+
vertexId: numberId, // Gremlin converts number IDs to strings
174+
totalCount: 3,
175+
counts: { type2: 3 },
176+
};
177+
const response = createResponse(expected1, expected2);
178+
const mockFetch = vi.fn().mockResolvedValue(response);
179+
180+
const result = await neighborCounts(mockFetch, {
181+
vertexIds: [stringId, numberId],
182+
});
183+
184+
expect(result.counts).toHaveLength(2);
185+
expect(result.counts).toEqual(
186+
expect.arrayContaining([
187+
expect.objectContaining(expected1),
188+
expect.objectContaining(expected2),
189+
])
190+
);
191+
});
119192
});
120193

121194
function createResponse(...counts: NeighborCount[]) {
122195
return createGremlinResponse(
123196
createGMap(
124-
counts.reduce(
125-
(prev, curr) => {
126-
prev[String(curr.vertexId)] = createGMap(curr.counts);
127-
return prev;
128-
},
129-
{} as Record<string, any>
130-
)
197+
counts.reduce((prev, curr) => {
198+
prev.set(curr.vertexId, createGMap(curr.counts));
199+
return prev;
200+
}, new Map<EntityRawId, GMap>())
131201
)
132202
);
133203
}

packages/graph-explorer/src/connector/gremlin/neighborCounts.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,20 @@ export async function neighborCounts(
8383
}))
8484
.reduce(
8585
(acc, curr) => {
86-
// TODO: In a future set of changes we should pass the full lsit of types
87-
// up to the UI so that it can list them out properly, but since this is a
88-
// rather large change I am defering that work.
89-
const type = curr.type.split("::")[0] ?? "";
90-
acc[type] = curr.count;
86+
const types = curr.type.split("::");
87+
for (const type of types) {
88+
acc[type] = (acc[type] ?? 0) + curr.count;
89+
}
9190
return acc;
9291
},
9392
{} as Record<string, number>
9493
);
9594

96-
// Sum up all the type counts
97-
const totalCount = Object.values(countsByType).reduce(
98-
(acc, curr) => acc + curr,
99-
0
100-
);
95+
// Total up the unique neighbors
96+
const totalCount = countsByTypeMap
97+
.values()
98+
.map(gValue => gValue["@value"])
99+
.reduce((acc, curr) => acc + curr, 0);
101100

102101
return {
103102
vertexId: createVertexId(extractRawId(key)),

0 commit comments

Comments
 (0)