Compare commits

...

2 Commits

Author SHA1 Message Date
jiantw83 1ad87ac4a4 fix: address triaged review findings 2026-05-14 02:18:17 +00:00
AI Review Bot fb5c28114d chore: update ai-review findings [skip ci] 2026-05-14 02:14:49 +00:00
4 changed files with 55 additions and 8 deletions
+15 -1
View File
@@ -4,6 +4,20 @@
"role": "Maya",
"location": "app/json.test.js",
"suggestion": "在 `readJSONText` 相關的測試中,除了測試檔案過大的情況,也建議增加一個測試案例,驗證當檔案大小剛好等於 `MAX_JSON_BYTES` 時,檔案能夠被成功讀取且不會拋出錯誤。這能確保邊界條件的處理是正確的。",
"is_new": false
},
{
"level": "warning",
"role": "Aria",
"location": "app/gitea.js:14",
"suggestion": "陣列字面量過長,建議將每個元素放在獨立一行,以提高可讀性。例如:\n`return filterDiff(resp.data, [\n '.gitea/',\n '.amazonq/',\n '.claude/',\n '.codex/',\n '.gemini/',\n '.github/',\n 'CLAUDE.md',\n 'GEMINI.md',\n 'TODO.md',\n 'README.md'\n]);`",
"is_new": true
},
{
"level": "warning",
"role": "Aria",
"location": "app/gitea.test.js:64",
"suggestion": "`describe` 區塊的回呼函數不應使用 `async` 關鍵字。`describe` 區塊應同步執行,而異步操作應在 `it` 或 `beforeEach` 等鉤子函數中處理。",
"is_new": true
},
{
@@ -11,6 +25,6 @@
"role": "Maya",
"location": "app/json.test.js",
"suggestion": "在 `validateJSONArrayFile` 函數中,寫入修復後的 JSON 時,有判斷是否需要添加換行符 (`repaired.endsWith('\\n') ? repaired : `${repaired}\\n``)。目前的測試案例只驗證了最終結果包含換行符,但沒有明確測試兩種情況:當 AI 回傳的內容已經包含換行符時,以及不包含換行符時,都能正確處理。建議增加一個測試案例來覆蓋這兩種情況。",
"is_new": true
"is_new": false
}
]
+12 -1
View File
@@ -11,7 +11,18 @@ const api = (path) => `${GITEA_SERVER_URL.replace(/\/$/, '')}/api/v1${path}`;
*/
export async function getPRDiff() {
const resp = await axios.get(api(`/repos/${GITEA_REPOSITORY}/pulls/${PR_NUMBER}.diff`), { headers: headers(), timeout: 60000, httpsAgent });
return filterDiff(resp.data, ['.gitea/', '.amazonq/', '.claude/', '.codex/', '.gemini/', '.github/', 'CLAUDE.md', 'GEMINI.md', 'TODO.md', 'README.md']);
return filterDiff(resp.data, [
'.gitea/',
'.amazonq/',
'.claude/',
'.codex/',
'.gemini/',
'.github/',
'CLAUDE.md',
'GEMINI.md',
'TODO.md',
'README.md',
]);
}
/**
+3 -6
View File
@@ -1,12 +1,11 @@
import { describe, it, afterEach, mock } from 'node:test';
import assert from 'node:assert/strict';
import axios from 'axios';
import { getPRDiff, filterDiff, postComment } from './gitea.js';
afterEach(() => mock.restoreAll());
describe('gitea', async () => {
const { getPRDiff, filterDiff, postComment } = await import('./gitea.js');
describe('gitea', () => {
it('getPRDiff calls Gitea diff API with Authorization header', async () => {
let capturedUrl, capturedOpts;
mock.method(axios, 'get', async (url, opts) => {
@@ -59,9 +58,7 @@ describe('gitea', async () => {
});
});
describe('filterDiff', async () => {
const { filterDiff } = await import('./gitea.js');
describe('filterDiff', () => {
const block = (file) => `diff --git a/${file} b/${file}\n--- a/${file}\n+++ b/${file}\n@@ -1 +1 @@\n-old\n+new\n`;
it('filters out configured folder blocks', () => {
+25
View File
@@ -6,6 +6,7 @@ import path from 'path';
import { stripCodeFence, repairJSONArrayWithAI, validateJSONArrayFile, ensureJSONArrayFileExists } from './json.js';
describe('json helpers', () => {
const MAX_JSON_BYTES = 1024 * 1024;
let workspace;
beforeEach(() => {
@@ -76,6 +77,16 @@ describe('json helpers', () => {
assert.equal(fs.readFileSync(fullPath, 'utf8'), '[]\n');
});
it('reads a valid JSON file whose size equals the maximum limit', async () => {
const fullPath = path.join(workspace, '.gitea/ai-review/findings.json');
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, `[]${' '.repeat(MAX_JSON_BYTES - 2)}`, 'utf8');
const result = await validateJSONArrayFile(fullPath, '.gitea/ai-review/findings.json');
assert.deepEqual(result, { exists: true, valid: true, repaired: false });
});
it('repairs invalid JSON using AI output and rewrites the file', async () => {
const fullPath = path.join(workspace, '.gitea/ai-review/findings.json');
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
@@ -90,6 +101,20 @@ describe('json helpers', () => {
assert.equal(fs.readFileSync(fullPath, 'utf8'), '[{"fixed":true}]\n');
});
it('preserves a trailing newline returned by AI repair', async () => {
const fullPath = path.join(workspace, '.gitea/ai-review/findings.json');
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, '{broken', 'utf8');
const result = await validateJSONArrayFile(fullPath, '.gitea/ai-review/findings.json', async (_fullPath, _label, original) => {
assert.equal(original, '{broken');
return '[{"fixed":true}]\n';
});
assert.deepEqual(result, { exists: true, valid: true, repaired: true });
assert.equal(fs.readFileSync(fullPath, 'utf8'), '[{"fixed":true}]\n');
});
it('throws when AI repair fails', async () => {
const fullPath = path.join(workspace, '.gitea/ai-review/findings.json');
fs.mkdirSync(path.dirname(fullPath), { recursive: true });