test(ai-review review): 補上 Review 發布測試
This commit is contained in:
+64
-1
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { saveFindings, parseLocation, postNewCriticalComments } from './comments.js';
|
import { saveFindings, parseLocation, postNewCriticalComments, postFindingsReview } from './comments.js';
|
||||||
import { FINDINGS_PATH } from './config.js';
|
import { FINDINGS_PATH } from './config.js';
|
||||||
|
|
||||||
describe('saveFindings', () => {
|
describe('saveFindings', () => {
|
||||||
@@ -185,3 +185,66 @@ describe('postNewCriticalComments', () => {
|
|||||||
assert.ok(issueCalls.every(b => criticalCommentPattern.test(b)));
|
assert.ok(issueCalls.every(b => criticalCommentPattern.test(b)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('postFindingsReview', () => {
|
||||||
|
it('posts one review with statistics and sorted line comments', async () => {
|
||||||
|
const reviewCalls = [];
|
||||||
|
const findings = [
|
||||||
|
{ level: 'info', role: 'Maya', location: 'app/c.js:30', suggestion: 'I', is_new: true },
|
||||||
|
{ level: 'critical', role: 'Rex', location: 'app/a.js:10', suggestion: 'C', is_new: false },
|
||||||
|
{ level: 'warning', role: 'Leo', location: 'app/b.js:20', suggestion: 'W', is_new: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
await postFindingsReview(findings, {
|
||||||
|
postReview: async (args) => { reviewCalls.push(args); },
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(reviewCalls.length, 1);
|
||||||
|
assert.match(reviewCalls[0].body, /總問題:3 筆/);
|
||||||
|
assert.match(reviewCalls[0].body, /可標註檔案與行數:3 筆/);
|
||||||
|
assert.match(reviewCalls[0].body, /嚴重:1 筆/);
|
||||||
|
assert.match(reviewCalls[0].body, /警告:1 筆/);
|
||||||
|
assert.match(reviewCalls[0].body, /建議:1 筆/);
|
||||||
|
assert.deepEqual(
|
||||||
|
reviewCalls[0].comments.map(c => c.path),
|
||||||
|
['app/a.js', 'app/b.js', 'app/c.js'],
|
||||||
|
);
|
||||||
|
assert.deepEqual(
|
||||||
|
reviewCalls[0].comments.map(c => c.new_position),
|
||||||
|
[10, 20, 30],
|
||||||
|
);
|
||||||
|
assert.match(reviewCalls[0].comments[0].body, /嚴重等級/);
|
||||||
|
assert.match(reviewCalls[0].comments[0].body, /審查員.*Rex/s);
|
||||||
|
assert.match(reviewCalls[0].comments[0].body, /問題.*app\/a\.js:10/s);
|
||||||
|
assert.match(reviewCalls[0].comments[0].body, /建議.*C/s);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('only adds comments for findings with parseable file and line', async () => {
|
||||||
|
const reviewCalls = [];
|
||||||
|
await postFindingsReview([
|
||||||
|
{ level: 'critical', role: 'Rex', location: 'app/a.js', suggestion: 'missing line', is_new: true },
|
||||||
|
{ level: 'warning', role: 'Leo', location: 'app/b.js:20', suggestion: 'line', is_new: true },
|
||||||
|
], {
|
||||||
|
postReview: async (args) => { reviewCalls.push(args); },
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(reviewCalls.length, 1);
|
||||||
|
assert.match(reviewCalls[0].body, /總問題:2 筆/);
|
||||||
|
assert.match(reviewCalls[0].body, /可標註檔案與行數:1 筆/);
|
||||||
|
assert.match(reviewCalls[0].body, /無法標註檔案與行數:1 筆/);
|
||||||
|
assert.equal(reviewCalls[0].comments.length, 1);
|
||||||
|
assert.equal(reviewCalls[0].comments[0].path, 'app/b.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses an explicit problem field when present', async () => {
|
||||||
|
const reviewCalls = [];
|
||||||
|
await postFindingsReview([
|
||||||
|
{ level: 'warning', role: 'Leo', location: 'app/a.js:5', problem: '命名不清楚', suggestion: '改成具體名稱' },
|
||||||
|
], {
|
||||||
|
postReview: async (args) => { reviewCalls.push(args); },
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.match(reviewCalls[0].comments[0].body, /問題.*命名不清楚/s);
|
||||||
|
assert.match(reviewCalls[0].comments[0].body, /建議.*改成具體名稱/s);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
+27
-1
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, afterEach, mock } from 'node:test';
|
import { describe, it, afterEach, mock } from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { getPRDiff, filterDiff, postComment, postPullReviewComment, getCommitMessageBySha, getBranchHeadCommitMessage, shouldSkipBotCommit, getBotReviewOutcome } from './gitea.js';
|
import { getPRDiff, filterDiff, postComment, postPullReviewComment, postPullReview, getCommitMessageBySha, getBranchHeadCommitMessage, shouldSkipBotCommit, getBotReviewOutcome } from './gitea.js';
|
||||||
|
|
||||||
afterEach(() => mock.restoreAll());
|
afterEach(() => mock.restoreAll());
|
||||||
|
|
||||||
@@ -82,6 +82,32 @@ describe('gitea', () => {
|
|||||||
await assert.rejects(() => postPullReviewComment({ path: 'a.js', line: 1, body: 'x' }), /not in diff/);
|
await assert.rejects(() => postPullReviewComment({ path: 'a.js', line: 1, body: 'x' }), /not in diff/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('postPullReview posts one review with multiple comments', async () => {
|
||||||
|
let capturedUrl, capturedBody, capturedOpts;
|
||||||
|
mock.method(axios, 'post', async (url, body, opts) => {
|
||||||
|
capturedUrl = url;
|
||||||
|
capturedBody = body;
|
||||||
|
capturedOpts = opts;
|
||||||
|
return { data: { id: 9 } };
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await postPullReview({
|
||||||
|
body: 'summary',
|
||||||
|
comments: [{ path: 'app/a.js', new_position: 10, body: 'comment' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(result, { id: 9 });
|
||||||
|
assert.ok(capturedUrl.includes('/api/v1/repos/'));
|
||||||
|
assert.ok(capturedUrl.endsWith('/reviews'));
|
||||||
|
assert.equal(capturedBody.event, 'COMMENT');
|
||||||
|
assert.equal(capturedBody.body, 'summary');
|
||||||
|
assert.equal(capturedBody.comments.length, 1);
|
||||||
|
assert.equal(capturedBody.comments[0].path, 'app/a.js');
|
||||||
|
assert.equal(capturedBody.comments[0].new_position, 10);
|
||||||
|
assert.equal(capturedBody.comments[0].body, 'comment');
|
||||||
|
assert.ok(capturedOpts.headers['Authorization'].startsWith('token '));
|
||||||
|
});
|
||||||
|
|
||||||
it('getCommitMessageBySha reads commit message from Gitea API', async () => {
|
it('getCommitMessageBySha reads commit message from Gitea API', async () => {
|
||||||
let capturedUrl;
|
let capturedUrl;
|
||||||
mock.method(axios, 'get', async (url) => {
|
mock.method(axios, 'get', async (url) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user