Skip to content

Commit b8c0859

Browse files
test(api): align issue-rag unit suites with #10040 schema validation
Update validateIssueRagInput and route rejection expectations so length bounds live on RetrieveIssueContextInput and empty/malformed bodies map to invalid_body, matching the discovery schema gate. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 372d59f commit b8c0859

2 files changed

Lines changed: 32 additions & 10 deletions

File tree

test/unit/issue-rag-mcp.test.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe, expect, it } from "vitest";
22
import { runIssueRagRetrieval, validateIssueRagInput } from "../../src/mcp/issue-rag";
33
import { emptyIssueRagTelemetry } from "../../src/review/issue-rag-retrieval";
4+
import { PREFLIGHT_LIMITS } from "@loopover/contract";
45
import { createTestEnv } from "../helpers/d1";
56

67
describe("runIssueRagRetrieval (#4293)", () => {
@@ -21,33 +22,40 @@ describe("runIssueRagRetrieval (#4293)", () => {
2122
});
2223
});
2324

24-
it("rejects oversized repos and invalid labels", () => {
25-
expect(validateIssueRagInput({ owner: "acme", repo: "r".repeat(101), title: "Add observability context for self-hosted review planning failures" })).toMatchObject({
26-
ok: false,
27-
reason: "repo_too_long",
28-
});
25+
it("rejects invalid labels and over-long bodies (length bounds for owner/repo/title live on the schema)", () => {
26+
// #10040: repo/title max-length are on RetrieveIssueContextInput; this helper only rejects after trim /
27+
// per-label length / body length / topK shape.
2928
expect(
3029
validateIssueRagInput({
3130
owner: "acme",
3231
repo: "demo",
3332
title: "Add observability context for self-hosted review planning failures",
34-
labels: ["x".repeat(101)],
33+
labels: ["x".repeat(PREFLIGHT_LIMITS.labelChars + 1)],
3534
}),
3635
).toMatchObject({ ok: false, reason: "invalid_labels" });
36+
expect(
37+
validateIssueRagInput({
38+
owner: "acme",
39+
repo: "demo",
40+
title: "Add observability context for self-hosted review planning failures",
41+
body: "x".repeat(PREFLIGHT_LIMITS.bodyChars + 1),
42+
}),
43+
).toMatchObject({ ok: false, reason: "body_too_long" });
3744
});
3845

3946
it("covers validation branches for owner/title/body/labels/topK normalization", () => {
4047
expect(validateIssueRagInput({ owner: "", repo: "demo", title: "Add observability context for self-hosted review planning failures" })).toMatchObject({
4148
ok: false,
4249
reason: "owner_and_repo_required",
4350
});
51+
// #10040: over-long title is a schema concern; whitespace-only title is the helper's title_required.
4452
expect(
4553
validateIssueRagInput({
4654
owner: "acme",
4755
repo: "demo",
48-
title: "x".repeat(301),
56+
title: " ",
4957
}),
50-
).toMatchObject({ ok: false, reason: "title_too_long" });
58+
).toMatchObject({ ok: false, reason: "title_required" });
5159
expect(
5260
validateIssueRagInput({
5361
owner: "acme",

test/unit/routes-issue-rag.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ describe("issue-rag retrieve route (#4293)", () => {
6161
const app = createApp();
6262
const env = createTestEnv();
6363

64+
// #10040: empty title fails IssueRagRetrieveRequestSchema.min(1) → invalid_body before the hand-rolled pass.
6465
const invalid = await app.request(
6566
ISSUE_RAG_PATH,
6667
{
@@ -71,7 +72,20 @@ describe("issue-rag retrieve route (#4293)", () => {
7172
env,
7273
);
7374
expect(invalid.status).toBe(400);
74-
await expect(invalid.json()).resolves.toMatchObject({ status: "invalid_request", reason: "title_required" });
75+
await expect(invalid.json()).resolves.toMatchObject({ status: "invalid_request", reason: "invalid_body" });
76+
77+
// Whitespace-only title clears the schema min(1) then fails validateIssueRagInput's post-trim check.
78+
const whitespaceTitle = await app.request(
79+
ISSUE_RAG_PATH,
80+
{
81+
method: "POST",
82+
headers: { authorization: `Bearer ${env.LOOPOVER_API_TOKEN}`, "content-type": "application/json" },
83+
body: JSON.stringify({ owner: "repo-owner", repo: "owned-repo", title: " " }),
84+
},
85+
env,
86+
);
87+
expect(whitespaceTitle.status).toBe(400);
88+
await expect(whitespaceTitle.json()).resolves.toMatchObject({ status: "invalid_request", reason: "title_required" });
7589

7690
const malformed = await app.request(
7791
ISSUE_RAG_PATH,
@@ -83,7 +97,7 @@ describe("issue-rag retrieve route (#4293)", () => {
8397
env,
8498
);
8599
expect(malformed.status).toBe(400);
86-
await expect(malformed.json()).resolves.toMatchObject({ status: "invalid_request", reason: "owner_and_repo_required" });
100+
await expect(malformed.json()).resolves.toMatchObject({ status: "invalid_request", reason: "invalid_body" });
87101
});
88102

89103
it("allows sessions through the path allowlist and scopes repo access", async () => {

0 commit comments

Comments
 (0)