test(pr-comments): 議題也讀得了,不再先打 PR 端點

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-17 09:19:07 +00:00
co-authored by Claude Opus 5
parent 051fe0ded4
commit 3b7e3bdfc7
+39 -8
View File
@@ -25,10 +25,14 @@ function routes(overrides = {}, options = {}) {
general = [], general = [],
reviews = [], reviews = [],
pull = { number: INDEX, title: 'feat/pr-comments/main', html_url: `https://x/${INDEX}`, state: 'open' }, pull = { number: INDEX, title: 'feat/pr-comments/main', html_url: `https://x/${INDEX}`, state: 'open' },
isPull = true,
} = options; } = options;
const base = healthyRoutes(REPO, { const base = healthyRoutes(REPO, {
[`GET /api/v1/repos/${REPO}/pulls/${INDEX}`]: { status: 200, body: pull }, [`GET /api/v1/repos/${REPO}/issues/${INDEX}`]: {
status: 200,
body: { ...pull, ...(isPull ? { pull_request: { merged: false } } : {}) },
},
[`GET /api/v1/repos/${REPO}/issues/${INDEX}/comments`]: { [`GET /api/v1/repos/${REPO}/issues/${INDEX}/comments`]: {
status: 200, status: 200,
body: general.map((c, i) => ({ body: general.map((c, i) => ({
@@ -357,18 +361,48 @@ test('帶出 PR 的識別資訊,讓回報不必再查一次', async (t) => {
assert.equal(json.data.state, 'open'); assert.equal(json.data.state, 'open');
}); });
test('PR 不存在時回可區分的錯誤碼', async (t) => { test('議題不存在時回可區分的錯誤碼', async (t) => {
const stub = await withStub(t, { const stub = await withStub(t, {
[`GET /api/v1/repos/${REPO}/pulls/${INDEX}`]: { status: 404, body: { message: 'not found' } }, [`GET /api/v1/repos/${REPO}/issues/${INDEX}`]: { status: 404, body: { message: 'not found' } },
}, FULL); }, FULL);
const { code, json } = await run([], stub); const { code, json } = await run([], stub);
assert.equal(code, 1); assert.equal(code, 1);
assert.equal(json.error.code, 'PULL_NOT_FOUND'); assert.equal(json.error.code, 'ISSUE_NOT_FOUND');
assert.match(json.error.message, new RegExp(String(INDEX))); assert.match(json.error.message, new RegExp(String(INDEX)));
}); });
test('純議題也讀得到:先讀 issue 再決定要不要翻 review', async (t) => {
// 每個 PR 都是議題,議題不一定是 PR。先打 /pulls 的話,純議題會 404,
// 而 /sdlc-sync 的輸入正是純議題——整個流程在讀到第一則留言之前就斷了
const stub = await withStub(t, {}, {
isPull: false,
general: [{ body: '這顆議題上的決策', reactions: [] }],
reviews: [],
});
const { code, json } = await run([], stub);
assert.equal(code, 0, JSON.stringify(json));
assert.equal(json.data.類型, '議題');
assert.deepEqual(json.data.留言.map((c) => c.內容), ['這顆議題上的決策']);
assert.equal(
stub.requests.some((r) => r.path.includes('/pulls/')),
false,
'純議題不該去打 PR 的端點',
);
});
test('是 PR 時類型標成 PR,並照樣讀 review', async (t) => {
const stub = await withStub(t, {}, FULL);
const { json } = await run([], stub);
assert.equal(json.data.類型, 'PR');
assert.ok(json.data.留言.some((c) => c.類型 === '總評'));
});
// ── --dry-run ───────────────────────────────────────────────────── // ── --dry-run ─────────────────────────────────────────────────────
test('--dry-run 印出將發出的請求,且不碰 Gitea', async (t) => { test('--dry-run 印出將發出的請求,且不碰 Gitea', async (t) => {
@@ -381,11 +415,8 @@ test('--dry-run 印出將發出的請求,且不碰 Gitea', async (t) => {
assert.deepEqual( assert.deepEqual(
json.data.requests.map((r) => `${r.method} ${r.path}`), json.data.requests.map((r) => `${r.method} ${r.path}`),
[ [
'GET /user', `GET /repos/${REPO}/issues/${INDEX}`,
`GET /repos/${REPO}/pulls/${INDEX}`,
`GET /repos/${REPO}/issues/${INDEX}/comments`, `GET /repos/${REPO}/issues/${INDEX}/comments`,
`GET /repos/${REPO}/pulls/${INDEX}/reviews`,
`GET /repos/${REPO}/issues/${INDEX}/timeline`,
], ],
); );
assert.match(json.data.note, /reaction|review/); assert.match(json.data.note, /reaction|review/);