115 lines
3.5 KiB
TypeScript
115 lines
3.5 KiB
TypeScript
import fs from 'fs';
|
|
import os from 'os';
|
|
import path from 'path';
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
buildVerificationCommand,
|
|
computeVerificationSnapshot,
|
|
isVerificationProfile,
|
|
runVerificationRequest,
|
|
} from './verification.js';
|
|
|
|
describe('verification helpers', () => {
|
|
it('recognizes only fixed verification profiles', () => {
|
|
expect(isVerificationProfile('test')).toBe(true);
|
|
expect(isVerificationProfile('typecheck')).toBe(true);
|
|
expect(isVerificationProfile('build')).toBe(true);
|
|
expect(isVerificationProfile('lint')).toBe(false);
|
|
});
|
|
|
|
it('builds deterministic commands for each profile', () => {
|
|
const repoDir = fs.mkdtempSync(
|
|
path.join(os.tmpdir(), 'ejclaw-verification-'),
|
|
);
|
|
fs.writeFileSync(path.join(repoDir, 'package.json'), JSON.stringify({}));
|
|
|
|
expect(buildVerificationCommand('test', repoDir)).toMatchObject({
|
|
file: 'npm',
|
|
args: ['test'],
|
|
requiredScript: 'test',
|
|
});
|
|
expect(buildVerificationCommand('typecheck', repoDir)).toMatchObject({
|
|
file: 'npm',
|
|
args: ['run', 'typecheck'],
|
|
requiredScript: 'typecheck',
|
|
});
|
|
expect(buildVerificationCommand('build', repoDir)).toMatchObject({
|
|
file: 'npm',
|
|
args: ['run', 'build'],
|
|
requiredScript: 'build',
|
|
});
|
|
});
|
|
|
|
it('selects the workspace package manager for verification commands', () => {
|
|
const repoDir = fs.mkdtempSync(
|
|
path.join(os.tmpdir(), 'ejclaw-verification-pnpm-'),
|
|
);
|
|
fs.writeFileSync(
|
|
path.join(repoDir, 'package.json'),
|
|
JSON.stringify({ packageManager: 'pnpm@10.11.0' }),
|
|
);
|
|
|
|
expect(buildVerificationCommand('typecheck', repoDir)).toMatchObject({
|
|
file: 'corepack',
|
|
args: ['pnpm', 'run', 'typecheck'],
|
|
commandText: 'corepack pnpm run typecheck',
|
|
requiredScript: 'typecheck',
|
|
});
|
|
});
|
|
|
|
it('computes a stable snapshot over the readable workspace inputs', () => {
|
|
const repoDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ejclaw-snapshot-'));
|
|
fs.mkdirSync(path.join(repoDir, 'src'), { recursive: true });
|
|
fs.mkdirSync(path.join(repoDir, 'node_modules'), { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join(repoDir, 'src', 'index.ts'),
|
|
'export const x = 1;\n',
|
|
);
|
|
fs.writeFileSync(path.join(repoDir, '.env'), 'SECRET=1\n');
|
|
|
|
const first = computeVerificationSnapshot(repoDir).snapshotId;
|
|
fs.writeFileSync(path.join(repoDir, '.env'), 'SECRET=2\n');
|
|
const second = computeVerificationSnapshot(repoDir).snapshotId;
|
|
fs.writeFileSync(
|
|
path.join(repoDir, 'src', 'index.ts'),
|
|
'export const x = 2;\n',
|
|
);
|
|
const third = computeVerificationSnapshot(repoDir).snapshotId;
|
|
|
|
expect(second).toBe(first);
|
|
expect(third).not.toBe(first);
|
|
});
|
|
|
|
it('fails verification when node_modules contains only cache noise', async () => {
|
|
const repoDir = fs.mkdtempSync(
|
|
path.join(os.tmpdir(), 'ejclaw-verification-noise-'),
|
|
);
|
|
fs.mkdirSync(path.join(repoDir, 'node_modules', '.vite'), {
|
|
recursive: true,
|
|
});
|
|
fs.writeFileSync(
|
|
path.join(repoDir, 'package.json'),
|
|
JSON.stringify({
|
|
scripts: {
|
|
test: 'vitest run',
|
|
typecheck: 'tsc --noEmit',
|
|
build: 'tsc',
|
|
},
|
|
}),
|
|
);
|
|
|
|
const result = await runVerificationRequest(
|
|
{
|
|
requestId: 'req-noise',
|
|
profile: 'typecheck',
|
|
},
|
|
{ repoDir },
|
|
);
|
|
|
|
expect(result.ok).toBe(false);
|
|
expect(result.error).toContain('installed node_modules tree');
|
|
});
|
|
});
|