feat: 移除計時並停用報表預覽
This commit is contained in:
+6
-226
@@ -1,231 +1,11 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { runScript, pathWithOnly } from './helpers/run-script.js';
|
||||
import { healthyRoutes, stubEnv as envFor, withStubGitea } from './helpers/stub-gitea.js';
|
||||
import { runScript } from './helpers/run-script.js';
|
||||
|
||||
const REPO = 'plugins/tea-sdlc';
|
||||
|
||||
async function withStub(t, overrides = {}) {
|
||||
return withStubGitea(t, healthyRoutes(REPO, overrides));
|
||||
}
|
||||
|
||||
|
||||
// ── 第一層:執行環境 ────────────────────────────────────────────────
|
||||
|
||||
test('第一層:PATH 上沒有 git 時中止,錯誤訊息指名 git', async (t) => {
|
||||
const stub = await withStub(t);
|
||||
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], {
|
||||
env: envFor(stub),
|
||||
path: pathWithOnly(['tea']),
|
||||
test('一般腳本不再依賴時間追蹤設定', async () => {
|
||||
const result = await runScript('report.js', ['--repo', 'plugins/tea-sdlc', '--week'], {
|
||||
env: { TEA_CONFIG: '/tmp/nonexistent-tea-config' },
|
||||
});
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'ENV_MISSING');
|
||||
assert.match(json.error.message, /git/);
|
||||
assert.equal(stub.requests.length, 0, '環境不通過就不該發請求');
|
||||
});
|
||||
|
||||
test('第一層:PATH 上沒有 tea 時中止,錯誤訊息指名 tea 並給出安裝指引', async (t) => {
|
||||
const stub = await withStub(t);
|
||||
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], {
|
||||
env: envFor(stub),
|
||||
path: pathWithOnly(['git']),
|
||||
});
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'ENV_MISSING');
|
||||
assert.match(json.error.message, /tea/);
|
||||
});
|
||||
|
||||
// ── 第二層:Gitea 登入 ─────────────────────────────────────────────
|
||||
|
||||
test('第二層:token 無效時中止,訊息指向 tea login', async (t) => {
|
||||
const stub = await withStub(t, {
|
||||
'GET /api/v1/user': { status: 401, body: { message: 'unauthorized' } },
|
||||
});
|
||||
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'LOGIN_INVALID');
|
||||
assert.match(json.error.message, /tea login/);
|
||||
});
|
||||
|
||||
test('第二層:找不到任何登入資訊時中止', async (t) => {
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], {
|
||||
env: { TEA_SDLC_API_BASE: '', TEA_SDLC_TOKEN: '', TEA_SDLC_CONFIG: '/nonexistent/tea.yml' },
|
||||
});
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'LOGIN_INVALID');
|
||||
});
|
||||
|
||||
// ── 第三層:issues unit 寫入權 ─────────────────────────────────────
|
||||
|
||||
test('第三層:repo 不存在或讀不到時,錯誤碼與權限問題分得開', async (t) => {
|
||||
const stub = await withStub(t, {
|
||||
[`GET /api/v1/repos/${REPO}`]: { status: 404, body: { message: 'not found' } },
|
||||
});
|
||||
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'REPO_NOT_FOUND');
|
||||
});
|
||||
|
||||
test('第三層:repo 關閉議題功能時中止,訊息指出開啟位置', async (t) => {
|
||||
const stub = await withStub(t, {
|
||||
[`GET /api/v1/repos/${REPO}`]: {
|
||||
status: 200,
|
||||
body: {
|
||||
has_issues: false,
|
||||
permissions: { admin: false, push: true, pull: true },
|
||||
internal_tracker: { enable_time_tracker: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'ISSUES_UNIT_OFF');
|
||||
assert.match(json.error.message, /Settings/);
|
||||
});
|
||||
|
||||
test('第三層:對 issues unit 實測寫入權,被擋下時中止', async (t) => {
|
||||
const stub = await withStub(t, {
|
||||
[`PATCH /api/v1/repos/${REPO}/issues/0`]: { status: 403, body: { message: 'forbidden' } },
|
||||
});
|
||||
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'NO_ISSUE_WRITE');
|
||||
assert.match(json.error.message, /issues/i);
|
||||
});
|
||||
|
||||
test('第三層:不能只看 permissions.push——push 為真但 issues unit 被擋,仍須失敗', async (t) => {
|
||||
const stub = await withStub(t, {
|
||||
[`GET /api/v1/repos/${REPO}`]: {
|
||||
status: 200,
|
||||
body: {
|
||||
has_issues: true,
|
||||
// team 的 unit 權限可獨立於 repo 的 push 權限,所以這裡是真的也不算數
|
||||
permissions: { admin: false, push: true, pull: true },
|
||||
internal_tracker: { enable_time_tracker: true },
|
||||
},
|
||||
},
|
||||
[`PATCH /api/v1/repos/${REPO}/issues/0`]: { status: 403, body: { message: 'forbidden' } },
|
||||
});
|
||||
|
||||
const { json } = await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
assert.equal(json.error.code, 'NO_ISSUE_WRITE');
|
||||
});
|
||||
|
||||
test('第三層:探針打在不存在的議題 index 0,確保無副作用', async (t) => {
|
||||
const stub = await withStub(t);
|
||||
|
||||
await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
const probes = stub.requests.filter((r) => r.method === 'PATCH');
|
||||
assert.equal(probes.length, 1);
|
||||
assert.equal(probes[0].path, `/api/v1/repos/${REPO}/issues/0`);
|
||||
assert.deepEqual(probes[0].body, {}, '探針不得挾帶任何要寫入的欄位');
|
||||
});
|
||||
|
||||
// ── 第四層:時間追蹤 ───────────────────────────────────────────────
|
||||
|
||||
test('第四層:時間追蹤未開啟時中止,訊息指出 Enable Time Tracker 的位置', async (t) => {
|
||||
const stub = await withStub(t, {
|
||||
[`GET /api/v1/repos/${REPO}`]: {
|
||||
status: 200,
|
||||
body: {
|
||||
has_issues: true,
|
||||
permissions: { admin: false, push: true, pull: true },
|
||||
internal_tracker: { enable_time_tracker: false },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { code, json } = await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
assert.equal(code, 1);
|
||||
assert.equal(json.error.code, 'TIME_TRACKER_OFF');
|
||||
assert.match(json.error.message, /Settings → Advanced Settings → Enable Time Tracker/);
|
||||
});
|
||||
|
||||
// ── 四層之間 ───────────────────────────────────────────────────────
|
||||
|
||||
test('四層的錯誤碼兩兩相異,呼叫端分得出是哪一層壞了', async (t) => {
|
||||
const cases = [
|
||||
{
|
||||
code: 'ENV_MISSING',
|
||||
run: async () => {
|
||||
const stub = await withStub(t);
|
||||
return runScript('labels-list.js', ['--repo', REPO], {
|
||||
env: envFor(stub),
|
||||
path: pathWithOnly(['git']),
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
code: 'LOGIN_INVALID',
|
||||
run: async () => {
|
||||
const stub = await withStub(t, {
|
||||
'GET /api/v1/user': { status: 401, body: {} },
|
||||
});
|
||||
return runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
},
|
||||
},
|
||||
{
|
||||
code: 'NO_ISSUE_WRITE',
|
||||
run: async () => {
|
||||
const stub = await withStub(t, {
|
||||
[`PATCH /api/v1/repos/${REPO}/issues/0`]: { status: 403, body: {} },
|
||||
});
|
||||
return runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
},
|
||||
},
|
||||
{
|
||||
code: 'TIME_TRACKER_OFF',
|
||||
run: async () => {
|
||||
const stub = await withStub(t, {
|
||||
[`GET /api/v1/repos/${REPO}`]: {
|
||||
status: 200,
|
||||
body: {
|
||||
has_issues: true,
|
||||
permissions: { admin: true, push: true, pull: true },
|
||||
internal_tracker: { enable_time_tracker: false },
|
||||
},
|
||||
},
|
||||
});
|
||||
return runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const seen = [];
|
||||
for (const { code, run } of cases) {
|
||||
const { json } = await run();
|
||||
assert.equal(json.error.code, code);
|
||||
seen.push(json.error.code);
|
||||
}
|
||||
assert.equal(new Set(seen).size, seen.length);
|
||||
});
|
||||
|
||||
test('前一層失敗就停手,不會再往下打', async (t) => {
|
||||
const stub = await withStub(t, {
|
||||
'GET /api/v1/user': { status: 401, body: {} },
|
||||
});
|
||||
|
||||
await runScript('labels-list.js', ['--repo', REPO], { env: envFor(stub) });
|
||||
|
||||
assert.deepEqual(
|
||||
stub.requests.map((r) => r.path),
|
||||
['/api/v1/user'],
|
||||
'登入檢查沒過就不該再查 repo 或標籤',
|
||||
);
|
||||
assert.equal(result.code, 1);
|
||||
assert.equal(result.json.error.code, 'REPORT_UNAVAILABLE');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user