Files
Genarrative/scripts/pre-commit-format.test.mjs
T
kdletters e118d66699
Project CI / Repository checks (push) Successful in 53s
Project CI / Frontend tests (push) Successful in 3m9s
Project CI / Backend tests (push) Successful in 4m19s
Project CI / Native shell tests (push) Successful in 16m9s
增加提交前 TypeScript 自动格式化
接入 Husky 与 lint-staged,仅格式化暂存的 TS/TSX 文件
补充部分暂存和未暂存内容隔离回归测试
更新共享开发工作流中的提交前格式化规则
2026-08-12 10:43:29 +08:00

92 lines
2.7 KiB
JavaScript

import assert from 'node:assert/strict';
import { execFileSync, spawnSync } from 'node:child_process';
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { delimiter, dirname, join, resolve } from 'node:path';
import { test } from 'node:test';
import { fileURLToPath } from 'node:url';
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const packageJson = JSON.parse(
readFileSync(join(repoRoot, 'package.json'), 'utf8'),
);
test('pre-commit hook 仅格式化暂存的 TypeScript 快照', () => {
assert.equal(packageJson.scripts.prepare, 'husky');
assert.equal(packageJson.scripts['format:staged'], 'lint-staged');
assert.deepEqual(packageJson['lint-staged'], {
'*.{ts,tsx}': 'prettier --write',
});
assert.equal(
readFileSync(join(repoRoot, '.husky', 'pre-commit'), 'utf8'),
'npm run format:staged\n',
);
const tempRepo = mkdtempSync(
join(tmpdir(), 'genarrative-pre-commit-format-'),
);
try {
git(tempRepo, 'init', '--quiet');
git(tempRepo, 'config', 'user.email', 'pre-commit-test@example.invalid');
git(tempRepo, 'config', 'user.name', 'Pre-commit Test');
const sourcePath = join(tempRepo, 'sample.ts');
writeFileSync(sourcePath, 'const original = 1;\nconst keep = 2;\n');
git(tempRepo, 'add', 'sample.ts');
git(
tempRepo,
'-c',
'commit.gpgsign=false',
'commit',
'--quiet',
'-m',
'baseline',
);
writeFileSync(sourcePath, 'const original={value:1}\nconst keep = 2;\n');
git(tempRepo, 'add', 'sample.ts');
writeFileSync(
sourcePath,
'const original={value:1}\nconst keep={unstaged:true}\n',
);
const lintStaged = spawnSync(
process.execPath,
[
join(repoRoot, 'node_modules', 'lint-staged', 'bin', 'lint-staged.js'),
'--config',
'-',
],
{
cwd: tempRepo,
encoding: 'utf8',
env: {
...process.env,
PATH: `${join(repoRoot, 'node_modules', '.bin')}${delimiter}${process.env.PATH ?? ''}`,
},
input: JSON.stringify(packageJson['lint-staged']),
},
);
assert.equal(
lintStaged.status,
0,
`${lintStaged.stdout ?? ''}${lintStaged.stderr ?? ''}`,
);
assert.equal(
git(tempRepo, 'show', ':sample.ts'),
'const original = { value: 1 };\nconst keep = 2;\n',
);
assert.equal(
readFileSync(sourcePath, 'utf8'),
'const original = { value: 1 };\nconst keep={unstaged:true}\n',
);
} finally {
rmSync(tempRepo, { force: true, recursive: true });
}
});
function git(cwd, ...args) {
return execFileSync('git', args, { cwd, encoding: 'utf8' });
}