2026-07-21 05:17:30 +02:00
|
|
|
import test from 'node:test';
|
|
|
|
|
import assert from 'node:assert/strict';
|
|
|
|
|
import { DatabaseSync } from 'node:sqlite';
|
|
|
|
|
import { createReceiptStore, validateReceipt } from '../src/receipts.mjs';
|
|
|
|
|
const valid = {
|
|
|
|
|
schemaVersion: 1,
|
|
|
|
|
eventType: 'deployment',
|
|
|
|
|
eventId: 'goonk-prod-1',
|
|
|
|
|
project: 'goonk',
|
|
|
|
|
occurredAt: '2026-07-20T20:00:00Z',
|
|
|
|
|
result: 'success',
|
|
|
|
|
source: { commit: '577a62e' },
|
|
|
|
|
verification: { health: 'healthy' },
|
|
|
|
|
};
|
|
|
|
|
test('validates v1', () => {
|
|
|
|
|
assert.deepEqual(validateReceipt(valid), []);
|
|
|
|
|
assert.ok(validateReceipt({}).length);
|
|
|
|
|
});
|
|
|
|
|
test('is idempotent and public projection is allowlisted', async () => {
|
|
|
|
|
const db = new DatabaseSync(':memory:'),
|
|
|
|
|
store = createReceiptStore(db, 'goonk:secret');
|
|
|
|
|
const req = () => ({
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { authorization: 'Bearer secret' },
|
|
|
|
|
async *[Symbol.asyncIterator]() {
|
|
|
|
|
yield JSON.stringify(valid);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
const res = () => {
|
|
|
|
|
const x = { status: 0, body: '' };
|
|
|
|
|
x.writeHead = (s) => {
|
|
|
|
|
x.status = s;
|
|
|
|
|
return x;
|
|
|
|
|
};
|
|
|
|
|
x.end = (b) => {
|
|
|
|
|
x.body = b;
|
|
|
|
|
return x;
|
|
|
|
|
};
|
|
|
|
|
return x;
|
|
|
|
|
};
|
|
|
|
|
let r = res();
|
|
|
|
|
await store.handle(req(), r, '/api/v1/events');
|
|
|
|
|
assert.equal(r.status, 201);
|
|
|
|
|
r = res();
|
|
|
|
|
await store.handle(req(), r, '/api/v1/events');
|
|
|
|
|
assert.equal(JSON.parse(r.body).duplicate, true);
|
|
|
|
|
r = res();
|
|
|
|
|
await store.handle({ method: 'GET', headers: {} }, r, '/api/v1/public/projects/goonk/latest');
|
|
|
|
|
const out = JSON.parse(r.body);
|
|
|
|
|
assert.equal(out.deployment.commit, '577a62e');
|
|
|
|
|
assert.equal(out.deployment.payload, undefined);
|
|
|
|
|
});
|