From 3b7e3bdfc7db13e329eb0d05bbb13839189bbbd3 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Thu, 17 Sep 2026 09:19:07 +0000 Subject: [PATCH] =?UTF-8?q?test(pr-comments):=20=E8=AD=B0=E9=A1=8C?= =?UTF-8?q?=E4=B9=9F=E8=AE=80=E5=BE=97=E4=BA=86=EF=BC=8C=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E5=85=88=E6=89=93=20PR=20=E7=AB=AF=E9=BB=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- test/pr-comments.test.js | 47 +++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/test/pr-comments.test.js b/test/pr-comments.test.js index 7456048..8997312 100644 --- a/test/pr-comments.test.js +++ b/test/pr-comments.test.js @@ -25,10 +25,14 @@ function routes(overrides = {}, options = {}) { general = [], reviews = [], pull = { number: INDEX, title: 'feat/pr-comments/main', html_url: `https://x/${INDEX}`, state: 'open' }, + isPull = true, } = options; 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`]: { status: 200, body: general.map((c, i) => ({ @@ -357,18 +361,48 @@ test('帶出 PR 的識別資訊,讓回報不必再查一次', async (t) => { assert.equal(json.data.state, 'open'); }); -test('PR 不存在時回可區分的錯誤碼', async (t) => { +test('議題不存在時回可區分的錯誤碼', async (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); const { code, json } = await run([], stub); 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))); }); +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 ───────────────────────────────────────────────────── test('--dry-run 印出將發出的請求,且不碰 Gitea', async (t) => { @@ -381,11 +415,8 @@ test('--dry-run 印出將發出的請求,且不碰 Gitea', async (t) => { assert.deepEqual( json.data.requests.map((r) => `${r.method} ${r.path}`), [ - 'GET /user', - `GET /repos/${REPO}/pulls/${INDEX}`, + `GET /repos/${REPO}/issues/${INDEX}`, `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/);