15e217fcb4
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
55 lines
2.7 KiB
JavaScript
55 lines
2.7 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { buildVerifyReceipt } from './produce-verify-receipt.mjs';
|
|
import { verifyReceiptSig } from './verify-receipt.mjs';
|
|
|
|
const KEY = 'signer-key';
|
|
const FP = 'a'.repeat(64);
|
|
|
|
describe('buildVerifyReceipt (producer pure core)', () => {
|
|
it('сюита не прошла → {ok:false, reason:suite-not-passed}, расписки нет', () => {
|
|
expect(buildVerifyReceipt({ codeFingerprint: FP, suitePassed: false, signerKey: KEY }))
|
|
.toEqual({ ok: false, reason: 'suite-not-passed' });
|
|
});
|
|
it('нет ключа подписанта → {ok:false, reason:no-signer-key} (fail-CLOSE)', () => {
|
|
expect(buildVerifyReceipt({ codeFingerprint: FP, suitePassed: true, signerKey: '' }))
|
|
.toEqual({ ok: false, reason: 'no-signer-key' });
|
|
});
|
|
it('сюита прошла + ключ → подписанная расписка occurrence=lastOccurrence+1', () => {
|
|
const r = buildVerifyReceipt({ codeFingerprint: FP, suitePassed: true, lastOccurrence: 4, signerKey: KEY });
|
|
expect(r.ok).toBe(true);
|
|
expect(r.receipt.occurrence).toBe(5);
|
|
expect(r.receipt.code_fingerprint).toBe(FP);
|
|
expect(verifyReceiptSig(r.receipt, KEY)).toBe(true);
|
|
});
|
|
});
|
|
|
|
import { stagedFingerprint } from './produce-verify-receipt.mjs';
|
|
|
|
describe('stagedFingerprint (детерминирован, порядок файлов не важен)', () => {
|
|
it('одинаковая карта {путь:содержимое} → одинаковый хеш независимо от порядка', () => {
|
|
const a = stagedFingerprint({ 'b.js': '2', 'a.js': '1' });
|
|
const b = stagedFingerprint({ 'a.js': '1', 'b.js': '2' });
|
|
expect(a).toBe(b);
|
|
expect(a).toMatch(/^[0-9a-f]{64}$/);
|
|
});
|
|
it('изменение содержимого → другой хеш', () => {
|
|
expect(stagedFingerprint({ 'a.js': '1' })).not.toBe(stagedFingerprint({ 'a.js': '2' }));
|
|
});
|
|
});
|
|
|
|
import { resolveVitestConfig } from './produce-verify-receipt.mjs';
|
|
|
|
describe('resolveVitestConfig (выбор конфига сюиты от корня репо)', () => {
|
|
const norm = (s) => String(s).replace(/\\/g, '/');
|
|
it('есть app/vitest.config.tools.mjs → root=app, config из app', () => {
|
|
const r = resolveVitestConfig('/repo', (p) => norm(p).endsWith('app/vitest.config.tools.mjs'));
|
|
expect(norm(r.root)).toBe('/repo/app');
|
|
expect(norm(r.config)).toBe('/repo/app/vitest.config.tools.mjs');
|
|
});
|
|
it('нет app/-конфига → root=корень репо, config из корня', () => {
|
|
const r = resolveVitestConfig('/repo', () => false);
|
|
expect(norm(r.root)).toBe('/repo');
|
|
expect(norm(r.config)).toBe('/repo/vitest.config.tools.mjs');
|
|
});
|
|
});
|