diff --git a/app/resolve.test.js b/app/resolve.test.js index e9a1d19..0d8410d 100644 --- a/app/resolve.test.js +++ b/app/resolve.test.js @@ -32,6 +32,18 @@ describe('parseBotReviewComment', () => { assert.equal(f.suggestion, '移除硬編碼密鑰'); }); + it('falls back to 問題 content when 建議 is absent', () => { + const body = '**審查員**:Maya\n**問題**:缺少邊界測試'; + const f = parseBotReviewComment(body); + assert.equal(f.problem, '缺少邊界測試'); + assert.equal(f.suggestion, '缺少邊界測試'); + }); + + it('defaults level to warning when 嚴重等級/等級 is missing', () => { + const body = '**審查員**:Maya\n**問題**:p\n**建議**:s'; + assert.equal(parseBotReviewComment(body).level, 'warning'); + }); + it('returns null for free-form human comments', () => { assert.equal(parseBotReviewComment('我覺得這段可以再想想'), null); assert.equal(parseBotReviewComment(''), null); @@ -93,6 +105,23 @@ describe('judgeConversationsResolved', () => { assert.deepEqual(verdicts, [{ idx: 0, resolved: false }]); }); + it('filters out AI results missing idx or resolved and keeps valid ones', async () => { + const items = [{ idx: 0 }, { idx: 1 }]; + const chatFn = async () => [{ resolved: true }, { idx: 1, resolved: true }, { idx: 0 }]; + const verdicts = await judgeConversationsResolved(items, chatFn); + assert.deepEqual(verdicts, [ + { idx: 0, resolved: false }, // {idx:0} 缺 resolved → 視為 false;缺 idx 的整筆被過濾 + { idx: 1, resolved: true }, + ]); + }); + + it('propagates errors thrown by chatFn to the caller', async () => { + await assert.rejects( + () => judgeConversationsResolved([{ idx: 0 }], async () => { throw new Error('LLM down'); }), + /LLM down/, + ); + }); + it('returns [] for no items', async () => { assert.deepEqual(await judgeConversationsResolved([]), []); }); @@ -134,6 +163,20 @@ describe('reconcileConversations', () => { assert.equal(result.carriedFindings.length, 2); }); + it('treats all conversations as unresolved when the judge throws', async () => { + const resolvedIds = []; + const deps = baseDeps(); + deps.judge = async () => { throw new Error('judge boom'); }; + deps.resolveComment = async (id) => { resolvedIds.push(id); return { ok: true }; }; + + const result = await reconcileConversations(deps); + + assert.deepEqual(resolvedIds, []); // 無任何對話被 resolve + assert.equal(result.resolvedCount, 0); + assert.equal(result.carriedFindings.length, 2); // a.js + b.js 皆加回(c.js 已解決略過) + assert.deepEqual(result.carriedFindings.map(f => f.suggestion).sort(), ['fix one', 'fix two']); + }); + it('returns empty result and does not throw when listing comments fails', async () => { const result = await reconcileConversations({ listComments: async () => { throw new Error('boom'); } }); assert.deepEqual(result, { resolvedFindings: [], carriedFindings: [], resolvedCount: 0, unresolvedCount: 0 });