Files
crewAI/.github/scripts/issue-gate.test.mjs
2026-08-04 10:48:49 -07:00

167 lines
4.1 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
evaluatePullRequest,
parseIssueReferences,
} from "./issue-gate.mjs";
const repository = "crewAIInc/crewAI";
function pullRequest(overrides = {}) {
return {
body: "Implements #123",
created_at: "2026-08-12T00:00:00Z",
labels: [],
user: { login: "contributor" },
...overrides,
};
}
function issue(overrides = {}) {
return {
number: 123,
state: "open",
labels: [{ name: "state:ready" }],
...overrides,
};
}
async function evaluate(pullOverrides = {}, issueOverrides = {}) {
return evaluatePullRequest({
pullRequest: pullRequest(pullOverrides),
repository,
cutoff: "2026-08-11T00:00:00Z",
getIssue: async () => issue(issueOverrides),
});
}
test("parses shorthand and full repository references", () => {
assert.deepEqual(
parseIssueReferences(
"Implements #123\nImplements crewAIInc/crewAI#456",
repository,
),
[
{ repository, number: 123 },
{ repository, number: 456 },
],
);
});
test("ignores GitHub closing keywords and template placeholders", () => {
assert.deepEqual(
parseIssueReferences(
"Fixes #123\nCloses #456\nImplements #<issue-number>",
repository,
),
[],
);
});
test("deduplicates repeated references", () => {
assert.deepEqual(
parseIssueReferences("Implements #123\nimplements #123", repository),
[{ repository, number: 123 }],
);
});
test("passes an open ready issue", async () => {
const result = await evaluate();
assert.equal(result.ok, true);
assert.equal(result.exempt, false);
assert.equal(result.issueNumber, 123);
});
test("rejects a missing issue reference", async () => {
const result = await evaluate({ body: "No issue yet" });
assert.equal(result.ok, false);
assert.match(result.reason, /does not contain/);
});
test("rejects more than one implementation issue", async () => {
const result = await evaluate({
body: "Implements #123\nImplements #456",
});
assert.equal(result.ok, false);
assert.match(result.reason, /more than one/);
});
test("rejects an issue in another repository", async () => {
const result = await evaluate({
body: "Implements another/project#123",
});
assert.equal(result.ok, false);
assert.match(result.reason, /must belong/);
});
test("rejects a pull request reference masquerading as an issue", async () => {
const result = await evaluate({}, { pull_request: { url: "example" } });
assert.equal(result.ok, false);
assert.match(result.reason, /is not an issue/);
});
test("rejects a closed issue", async () => {
const result = await evaluate({}, { state: "closed" });
assert.equal(result.ok, false);
assert.match(result.reason, /is not open/);
});
test("rejects an issue without the ready label", async () => {
const result = await evaluate({}, { labels: [{ name: "state:design" }] });
assert.equal(result.ok, false);
assert.match(result.reason, /does not have/);
});
test("exempts pull requests created before the cutoff", async () => {
const result = await evaluate({
body: null,
created_at: "2026-08-10T23:59:59Z",
});
assert.equal(result.ok, true);
assert.equal(result.exempt, true);
assert.match(result.reason, /predates/);
});
test("exempts pull requests with an override label", async () => {
const result = await evaluate({
body: null,
labels: [{ name: "issue-gate:override" }],
});
assert.equal(result.ok, true);
assert.equal(result.exempt, true);
assert.match(result.reason, /override/);
});
test("exempts supported automation accounts", async () => {
const result = await evaluate({
body: null,
user: { login: "dependabot[bot]" },
});
assert.equal(result.ok, true);
assert.equal(result.exempt, true);
assert.match(result.reason, /automation account/);
});
test("fails fast for an invalid cutoff", async () => {
await assert.rejects(
evaluatePullRequest({
pullRequest: pullRequest(),
repository,
cutoff: "not-a-date",
getIssue: async () => issue(),
}),
/not a valid date/,
);
});