測試一律以子行程執行腳本、比對 stdout 的單行 JSON 與 exit code,因為那正是 七個平台共用的實際呼叫方式,不會因內部重構而破碎。 Gitea 以本機 stub server 替身並錄下每一筆請求,藉此斷言「腳本到底發了哪些 請求」——包含 --dry-run 不得發出任何請求、前一層檢查沒過就不再往下打、 寫入權探針不得挾帶任何要寫入的欄位。git 則在 .tmp/ 下的臨時 repo 跑真實 指令,比 mock 可信且成本低。 lib-exports.test.js 是唯一直接 import lib 的例外:冪等查重與 git 執行點在 CLI 邊界上還沒有消費者,檔頭已註明等 #4 與 #10 落地後即可縮小或移除。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
32 lines
1.1 KiB
JavaScript
32 lines
1.1 KiB
JavaScript
/**
|
|
* 在 .tmp/ 底下開一個真的 git repo。
|
|
* git 操作不做 mock:在臨時 repo 上跑真的 git 比假的 git 可信,成本也低。
|
|
*/
|
|
import { execFileSync } from 'node:child_process';
|
|
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { tmpRoot } from './run-script.js';
|
|
|
|
/**
|
|
* @returns {{dir: string, cleanup: Function}} dir 為已有一顆 commit 的 git repo
|
|
*/
|
|
export function makeTempRepo() {
|
|
mkdirSync(tmpRoot, { recursive: true });
|
|
const dir = mkdtempSync(join(tmpRoot, 'repo-'));
|
|
const git = (...args) =>
|
|
execFileSync('git', args, {
|
|
cwd: dir,
|
|
encoding: 'utf8',
|
|
env: { ...process.env, GIT_CONFIG_GLOBAL: '/dev/null', GIT_CONFIG_SYSTEM: '/dev/null' },
|
|
});
|
|
|
|
git('init', '-q', '-b', 'master');
|
|
git('config', 'user.name', 'tester');
|
|
git('config', 'user.email', 'tester@example.com');
|
|
writeFileSync(join(dir, 'README.md'), '# temp\n');
|
|
git('add', '-A');
|
|
git('commit', '-qm', 'initial');
|
|
|
|
return { dir, cleanup: () => rmSync(dir, { recursive: true, force: true }) };
|
|
}
|