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' }); }