Skip to content

Commit e8c1b88

Browse files
committed
test(api): adds coverage for GraphQL partial error extraction
1 parent 4c88b8d commit e8c1b88

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

tests/services/api.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,40 @@ describe("fetchIssues", () => {
416416
expect(pushNotification).not.toHaveBeenCalled();
417417
});
418418

419+
it("extracts partial data from GraphqlResponseError and stops pagination", async () => {
420+
vi.mocked(pushNotification).mockClear();
421+
422+
// Simulate a GraphqlResponseError: has .data with valid nodes + errors
423+
const partialError = Object.assign(new Error("Some nodes failed to resolve"), {
424+
data: {
425+
search: {
426+
issueCount: 5,
427+
pageInfo: { hasNextPage: true, endCursor: "cursor-partial" },
428+
nodes: [{ ...graphqlIssueNode, databaseId: 42 }, null],
429+
},
430+
rateLimit: { remaining: 4990, resetAt: new Date(Date.now() + 3600000).toISOString() },
431+
},
432+
});
433+
const octokit = makeIssueOctokit(async () => {
434+
throw partialError;
435+
});
436+
437+
const result = await fetchIssues(
438+
octokit as unknown as ReturnType<typeof import("../../src/app/services/github").getClient>,
439+
[testRepo],
440+
"octocat"
441+
);
442+
443+
// Valid node from partial data is returned
444+
expect(result.issues.length).toBe(1);
445+
expect(result.issues[0].id).toBe(42);
446+
// Error is recorded
447+
expect(result.errors.length).toBe(1);
448+
expect(result.errors[0].message).toContain("Some nodes failed to resolve");
449+
// Only 1 graphql call — did NOT try to paginate after partial error
450+
expect(octokit.graphql).toHaveBeenCalledTimes(1);
451+
});
452+
419453
it("throws when octokit is null", async () => {
420454
await expect(fetchIssues(null, [testRepo], "octocat")).rejects.toThrow(
421455
"No GitHub client available"
@@ -691,6 +725,39 @@ describe("fetchPullRequests", () => {
691725
expect(pushNotification).not.toHaveBeenCalled();
692726
});
693727

728+
it("extracts partial PR data from GraphqlResponseError and stops pagination", async () => {
729+
vi.mocked(pushNotification).mockClear();
730+
731+
const partialError = Object.assign(new Error("Partial node resolution failure"), {
732+
data: {
733+
search: {
734+
issueCount: 3,
735+
pageInfo: { hasNextPage: true, endCursor: "cursor-partial" },
736+
nodes: [{ ...graphqlPRNode, databaseId: 77 }],
737+
},
738+
rateLimit: { remaining: 4990, resetAt: new Date(Date.now() + 3600000).toISOString() },
739+
},
740+
});
741+
const octokit = makePROctokit(async (_query, variables) => {
742+
const q = (variables as Record<string, unknown>).q as string;
743+
if (q.includes("involves:")) throw partialError;
744+
return makeGraphqlPRResponse([]);
745+
});
746+
747+
const result = await fetchPullRequests(
748+
octokit as unknown as ReturnType<typeof import("../../src/app/services/github").getClient>,
749+
[testRepo],
750+
"octocat"
751+
);
752+
753+
expect(result.pullRequests.length).toBe(1);
754+
expect(result.pullRequests[0].id).toBe(77);
755+
expect(result.errors.length).toBe(1);
756+
expect(result.errors[0].message).toContain("Partial node resolution failure");
757+
// involves query: 1 call (threw partial, stopped). review-requested: 1 call = 2 total
758+
expect(octokit.graphql).toHaveBeenCalledTimes(2);
759+
});
760+
694761
it("caps at 1000 PRs and warns via pushNotification", async () => {
695762
vi.mocked(pushNotification).mockClear();
696763

0 commit comments

Comments
 (0)