195 lines
7.4 KiB
JavaScript
195 lines
7.4 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { classifyEvent } from '../src/events.js';
|
|
|
|
const opts = { ownerLogin: 'selimaj-dev', triggerPhrase: '@claude' };
|
|
|
|
function issueCommentPayload(overrides = {}) {
|
|
return {
|
|
action: 'created',
|
|
comment: { user: { login: 'selimaj-dev' }, body: '@claude please fix this' },
|
|
issue: { number: 42, title: 'Bug', body: 'It is broken', pull_request: undefined },
|
|
repository: { full_name: 'selimaj-dev/repo', default_branch: 'main' },
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test('triggers on an issue comment from the owner mentioning the phrase', () => {
|
|
const { trigger, reason } = classifyEvent('issue_comment', issueCommentPayload(), opts);
|
|
assert.equal(reason, null);
|
|
assert.deepEqual(trigger, {
|
|
repo: 'selimaj-dev/repo',
|
|
issueNumber: 42,
|
|
issueTitle: 'Bug',
|
|
issueBody: 'It is broken',
|
|
isPullRequest: false,
|
|
defaultBranch: 'main',
|
|
requestText: '@claude please fix this',
|
|
author: 'selimaj-dev',
|
|
});
|
|
});
|
|
|
|
test('marks isPullRequest true when issue.pull_request is present', () => {
|
|
const payload = issueCommentPayload({ issue: { number: 7, title: 'PR', body: '', pull_request: { url: 'x' } } });
|
|
const { trigger } = classifyEvent('issue_comment', payload, opts);
|
|
assert.equal(trigger.isPullRequest, true);
|
|
});
|
|
|
|
test('ignores comments not from the configured owner', () => {
|
|
const payload = issueCommentPayload({ comment: { user: { login: 'someone-else' }, body: '@claude do it' } });
|
|
const { trigger, reason } = classifyEvent('issue_comment', payload, opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /is not the configured owner/);
|
|
});
|
|
|
|
test('ignores comments without the trigger phrase', () => {
|
|
const payload = issueCommentPayload({ comment: { user: { login: 'selimaj-dev' }, body: 'just a note' } });
|
|
const { trigger, reason } = classifyEvent('issue_comment', payload, opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /trigger phrase/);
|
|
});
|
|
|
|
test('ignores non-created issue_comment actions', () => {
|
|
const payload = issueCommentPayload({ action: 'deleted' });
|
|
const { trigger, reason } = classifyEvent('issue_comment', payload, opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /not handled/);
|
|
});
|
|
|
|
test('triggers on a new issue whose body mentions the phrase', () => {
|
|
const payload = {
|
|
action: 'opened',
|
|
issue: { number: 1, title: 'New issue', body: 'please @claude help', user: { login: 'selimaj-dev' } },
|
|
repository: { full_name: 'selimaj-dev/repo', default_branch: 'main' },
|
|
};
|
|
const { trigger } = classifyEvent('issues', payload, opts);
|
|
assert.ok(trigger);
|
|
assert.equal(trigger.requestText, 'please @claude help');
|
|
});
|
|
|
|
test('ignores unrelated event names', () => {
|
|
const { trigger, reason } = classifyEvent('push', {}, opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /not handled/);
|
|
});
|
|
|
|
test('ignores null/undefined payload without throwing', () => {
|
|
assert.doesNotThrow(() => classifyEvent('issue_comment', null, opts));
|
|
assert.doesNotThrow(() => classifyEvent('issue_comment', undefined, opts));
|
|
});
|
|
|
|
test('ignores payload missing repository/issue info', () => {
|
|
const payload = issueCommentPayload({ repository: { full_name: undefined } });
|
|
const { trigger, reason } = classifyEvent('issue_comment', payload, opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /missing repository or issue/);
|
|
});
|
|
|
|
test('defaults default_branch to main when absent', () => {
|
|
const payload = issueCommentPayload({ repository: { full_name: 'a/b', default_branch: undefined } });
|
|
const { trigger } = classifyEvent('issue_comment', payload, opts);
|
|
assert.equal(trigger.defaultBranch, 'main');
|
|
});
|
|
|
|
function pullRequestPayload(overrides = {}) {
|
|
return {
|
|
action: 'opened',
|
|
pull_request: { number: 5, title: 'Add feature', body: 'please @claude review', user: { login: 'selimaj-dev' } },
|
|
repository: { full_name: 'selimaj-dev/repo', default_branch: 'main' },
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test('triggers on a new pull request whose body mentions the phrase', () => {
|
|
const { trigger, reason } = classifyEvent('pull_request', pullRequestPayload(), opts);
|
|
assert.equal(reason, null);
|
|
assert.deepEqual(trigger, {
|
|
repo: 'selimaj-dev/repo',
|
|
issueNumber: 5,
|
|
issueTitle: 'Add feature',
|
|
issueBody: 'please @claude review',
|
|
isPullRequest: true,
|
|
defaultBranch: 'main',
|
|
requestText: 'please @claude review',
|
|
author: 'selimaj-dev',
|
|
});
|
|
});
|
|
|
|
test('triggers on an edited pull request body', () => {
|
|
const { trigger } = classifyEvent('pull_request', pullRequestPayload({ action: 'edited' }), opts);
|
|
assert.ok(trigger);
|
|
});
|
|
|
|
test('ignores pull_request actions other than opened/edited', () => {
|
|
const { trigger, reason } = classifyEvent('pull_request', pullRequestPayload({ action: 'closed' }), opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /not handled/);
|
|
});
|
|
|
|
test('ignores pull requests not from the configured owner', () => {
|
|
const payload = pullRequestPayload({ pull_request: { number: 5, title: 'x', body: '@claude help', user: { login: 'someone-else' } } });
|
|
const { trigger, reason } = classifyEvent('pull_request', payload, opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /is not the configured owner/);
|
|
});
|
|
|
|
function pullRequestReviewCommentPayload(overrides = {}) {
|
|
return {
|
|
action: 'created',
|
|
comment: { user: { login: 'selimaj-dev' }, body: '@claude fix this line' },
|
|
pull_request: { number: 9, title: 'PR title', body: 'pr description' },
|
|
repository: { full_name: 'selimaj-dev/repo', default_branch: 'main' },
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test('triggers on a pull request review (inline) comment mentioning the phrase', () => {
|
|
const { trigger, reason } = classifyEvent('pull_request_review_comment', pullRequestReviewCommentPayload(), opts);
|
|
assert.equal(reason, null);
|
|
assert.deepEqual(trigger, {
|
|
repo: 'selimaj-dev/repo',
|
|
issueNumber: 9,
|
|
issueTitle: 'PR title',
|
|
issueBody: 'pr description',
|
|
isPullRequest: true,
|
|
defaultBranch: 'main',
|
|
requestText: '@claude fix this line',
|
|
author: 'selimaj-dev',
|
|
});
|
|
});
|
|
|
|
test('ignores non-created pull_request_review_comment actions', () => {
|
|
const { trigger, reason } = classifyEvent(
|
|
'pull_request_review_comment',
|
|
pullRequestReviewCommentPayload({ action: 'deleted' }),
|
|
opts,
|
|
);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /not handled/);
|
|
});
|
|
|
|
function pullRequestReviewPayload(overrides = {}) {
|
|
return {
|
|
action: 'submitted',
|
|
review: { user: { login: 'selimaj-dev' }, body: '@claude address these comments' },
|
|
pull_request: { number: 11, title: 'PR title', body: 'pr description' },
|
|
repository: { full_name: 'selimaj-dev/repo', default_branch: 'main' },
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test('triggers on a submitted pull request review mentioning the phrase', () => {
|
|
const { trigger, reason } = classifyEvent('pull_request_review', pullRequestReviewPayload(), opts);
|
|
assert.equal(reason, null);
|
|
assert.equal(trigger.requestText, '@claude address these comments');
|
|
assert.equal(trigger.isPullRequest, true);
|
|
assert.equal(trigger.issueNumber, 11);
|
|
});
|
|
|
|
test('ignores pull_request_review without the trigger phrase', () => {
|
|
const payload = pullRequestReviewPayload({ review: { user: { login: 'selimaj-dev' }, body: 'looks good' } });
|
|
const { trigger, reason } = classifyEvent('pull_request_review', payload, opts);
|
|
assert.equal(trigger, null);
|
|
assert.match(reason, /trigger phrase/);
|
|
});
|