Files
compound-engineering-plugin…/tests/resolve-pr-feedback-pagination.test.ts

70 lines
2.9 KiB
TypeScript

import { readFileSync } from "fs"
import path from "path"
import { describe, expect, test } from "bun:test"
/**
* The two GraphQL fetch scripts in ce-resolve-pr-feedback must paginate.
*
* Issue #798: previous versions used fixed `first: N` page sizes with no
* cursor loop, so PRs with more than one page of review threads / comments /
* reviews silently dropped everything past page 1. The skill then reported
* "0 of 0 resolved" while real findings sat unanswered.
*
* `gh api graphql --paginate` follows only one `pageInfo` per response, so
* `get-pr-comments` must issue a separate paginated query for each top-level
* connection. `get-thread-for-comment` paginates the single `reviewThreads`
* connection it queries.
*/
const SCRIPTS_DIR = path.join(
process.cwd(),
"plugins/compound-engineering/skills/ce-resolve-pr-feedback/scripts",
)
const PAGE_INFO_SELECTION = /pageInfo\s*\{\s*hasNextPage\s+endCursor\s*\}/
function read(name: string): string {
return readFileSync(path.join(SCRIPTS_DIR, name), "utf8")
}
describe("ce-resolve-pr-feedback scripts paginate GraphQL connections (issue #798)", () => {
test("get-pr-comments uses --paginate for every top-level connection", () => {
const body = read("get-pr-comments")
const paginateCount = (body.match(/gh api graphql --paginate\b/g) ?? []).length
expect(
paginateCount,
"get-pr-comments must issue three paginated queries (reviewThreads, comments, reviews); `gh api graphql --paginate` only follows the outermost pageInfo per response, so combining them in one query silently drops everything past page 1.",
).toBeGreaterThanOrEqual(3)
})
test("get-pr-comments paginates every connection it queries", () => {
const body = read("get-pr-comments")
for (const conn of ["reviewThreads", "comments", "reviews"]) {
const re = new RegExp(`${conn}\\(first:\\s*\\d+,\\s*after:\\s*\\$endCursor\\)`)
expect(
re.test(body),
`get-pr-comments must call ${conn}(first: N, after: $endCursor); fixed page sizes truncate on long-lived PRs.`,
).toBe(true)
}
})
test("get-pr-comments selects pageInfo { hasNextPage endCursor } in each query", () => {
const body = read("get-pr-comments")
const matches = body.match(new RegExp(PAGE_INFO_SELECTION.source, "g")) ?? []
expect(
matches.length,
"Each paginated GraphQL query must select pageInfo { hasNextPage endCursor } so `gh api graphql --paginate` can drive the cursor loop.",
).toBeGreaterThanOrEqual(3)
})
test("get-thread-for-comment paginates the reviewThreads connection", () => {
const body = read("get-thread-for-comment")
expect(
body,
"get-thread-for-comment must paginate reviewThreads, otherwise comment lookups fail on PRs with >100 threads.",
).toMatch(/gh api graphql --paginate\b/)
expect(body).toMatch(/reviewThreads\(first:\s*\d+,\s*after:\s*\$endCursor\)/)
expect(body).toMatch(PAGE_INFO_SELECTION)
})
})