updated
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import crypto from 'node:crypto';
|
||||
import { createServer } from '../src/server.js';
|
||||
import { createLogger } from '../src/logger.js';
|
||||
|
||||
process.env.LOG_LEVEL = 'error';
|
||||
const logger = createLogger({});
|
||||
|
||||
function baseConfig(overrides = {}) {
|
||||
return { ownerLogin: 'selimaj-dev', triggerPhrase: '@claude', webhookSecret: null, ...overrides };
|
||||
}
|
||||
|
||||
async function withServer(config, fn) {
|
||||
const triggers = [];
|
||||
const server = createServer({ config, logger, onTrigger: (t) => triggers.push(t) });
|
||||
await new Promise((resolve) => server.listen(0, resolve));
|
||||
const { port } = server.address();
|
||||
try {
|
||||
await fn(`http://127.0.0.1:${port}`, triggers);
|
||||
} finally {
|
||||
await new Promise((resolve) => server.close(resolve));
|
||||
}
|
||||
}
|
||||
|
||||
function issuePayload() {
|
||||
return {
|
||||
action: 'created',
|
||||
comment: { user: { login: 'selimaj-dev' }, body: '@claude fix it' },
|
||||
issue: { number: 1, title: 't', body: 'b' },
|
||||
repository: { full_name: 'o/r', default_branch: 'main' },
|
||||
};
|
||||
}
|
||||
|
||||
test('GET /healthz returns 200 without touching onTrigger', async () => {
|
||||
await withServer(baseConfig(), async (base, triggers) => {
|
||||
const res = await fetch(`${base}/healthz`);
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(triggers.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
test('rejects non-POST, non-health requests', async () => {
|
||||
await withServer(baseConfig(), async (base) => {
|
||||
const res = await fetch(base, { method: 'GET' });
|
||||
assert.equal(res.status, 405);
|
||||
});
|
||||
});
|
||||
|
||||
test('accepts a matching issue_comment and calls onTrigger', async () => {
|
||||
await withServer(baseConfig(), async (base, triggers) => {
|
||||
const res = await fetch(base, {
|
||||
method: 'POST',
|
||||
headers: { 'X-Gitea-Event': 'issue_comment', 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(issuePayload()),
|
||||
});
|
||||
assert.equal(res.status, 202);
|
||||
assert.equal(triggers.length, 1);
|
||||
assert.equal(triggers[0].repo, 'o/r');
|
||||
});
|
||||
});
|
||||
|
||||
test('does not call onTrigger for an unrelated author', async () => {
|
||||
await withServer(baseConfig(), async (base, triggers) => {
|
||||
const payload = issuePayload();
|
||||
payload.comment.user.login = 'someone-else';
|
||||
await fetch(base, {
|
||||
method: 'POST',
|
||||
headers: { 'X-Gitea-Event': 'issue_comment' },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
assert.equal(triggers.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
test('accepts requests with no event header (health probes) without error', async () => {
|
||||
await withServer(baseConfig(), async (base, triggers) => {
|
||||
const res = await fetch(base, { method: 'POST', body: '{}' });
|
||||
assert.equal(res.status, 202);
|
||||
assert.equal(triggers.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
test('rejects a request with a bad signature when a secret is configured', async () => {
|
||||
await withServer(baseConfig({ webhookSecret: 's3cret' }), async (base, triggers) => {
|
||||
const res = await fetch(base, {
|
||||
method: 'POST',
|
||||
headers: { 'X-Gitea-Event': 'issue_comment', 'X-Gitea-Signature': 'wrong' },
|
||||
body: JSON.stringify(issuePayload()),
|
||||
});
|
||||
assert.equal(res.status, 401);
|
||||
assert.equal(triggers.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
test('accepts a request with a correct signature when a secret is configured', async () => {
|
||||
const secret = 's3cret';
|
||||
await withServer(baseConfig({ webhookSecret: secret }), async (base, triggers) => {
|
||||
const body = JSON.stringify(issuePayload());
|
||||
const sig = crypto.createHmac('sha256', secret).update(body).digest('hex');
|
||||
const res = await fetch(base, {
|
||||
method: 'POST',
|
||||
headers: { 'X-Gitea-Event': 'issue_comment', 'X-Gitea-Signature': sig },
|
||||
body,
|
||||
});
|
||||
assert.equal(res.status, 202);
|
||||
assert.equal(triggers.length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('does not crash on invalid JSON body', async () => {
|
||||
await withServer(baseConfig(), async (base, triggers) => {
|
||||
const res = await fetch(base, {
|
||||
method: 'POST',
|
||||
headers: { 'X-Gitea-Event': 'issue_comment' },
|
||||
body: 'not json',
|
||||
});
|
||||
assert.equal(res.status, 202); // already acknowledged before parse failure
|
||||
assert.equal(triggers.length, 0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user