Spaces:
Runtime error
Runtime error
| import { describe, it } from "node:test"; | |
| import assert from "node:assert/strict"; | |
| import { classifyIssue, isBot } from "../../../scripts/features/lib/classify.mjs"; | |
| const DEFAULT_THRESHOLDS = { | |
| quarantineDays: 14, | |
| overrideThumbs: 5, | |
| overrideCommenters: 3, | |
| }; | |
| function makeIssue(overrides = {}) { | |
| const now = new Date("2026-05-19T00:00:00Z"); | |
| return { | |
| number: 1046, | |
| title: "Test", | |
| url: "https://github.com/x/y/issues/1046", | |
| author: { login: "alice" }, | |
| createdAt: new Date(now.getTime() - 3 * 86400_000).toISOString(), | |
| labels: [{ name: "enhancement" }], | |
| assignees: [], | |
| comments: [], | |
| reactionGroups: [], | |
| timelineItems: [], | |
| ...overrides, | |
| }; | |
| } | |
| describe("isBot", () => { | |
| it("detects [bot] suffix", () => { | |
| assert.equal(isBot({ login: "dependabot[bot]" }), true); | |
| }); | |
| it("detects hardcoded bot names", () => { | |
| assert.equal(isBot({ login: "github-actions" }), true); | |
| assert.equal(isBot({ login: "claude" }), true); | |
| assert.equal(isBot({ login: "copilot" }), true); | |
| }); | |
| it("detects Bot via __typename", () => { | |
| assert.equal(isBot({ login: "anything", __typename: "Bot" }), true); | |
| }); | |
| it("returns false for regular user", () => { | |
| assert.equal(isBot({ login: "alice" }), false); | |
| }); | |
| }); | |
| describe("classifyIssue", () => { | |
| const now = new Date("2026-05-19T00:00:00Z"); | |
| it("3 days old, no engagement β dormant", () => { | |
| const r = classifyIssue(makeIssue(), DEFAULT_THRESHOLDS, now); | |
| assert.equal(r.bucket, "dormant"); | |
| assert.match(r.reason, /age<14/); | |
| }); | |
| it("3 days old, 5 thumbs β absorb (override:thumbs)", () => { | |
| const r = classifyIssue( | |
| makeIssue({ | |
| reactionGroups: [{ content: "THUMBS_UP", users: { totalCount: 5 } }], | |
| }), | |
| DEFAULT_THRESHOLDS, | |
| now | |
| ); | |
| assert.equal(r.bucket, "absorb"); | |
| assert.match(r.reason, /override:thumbs/); | |
| assert.equal(r.thumbs, 5); | |
| }); | |
| it("3 days old, 3 unique non-bot non-author commenters β absorb (override:commenters)", () => { | |
| const r = classifyIssue( | |
| makeIssue({ | |
| comments: [ | |
| { author: { login: "bob" } }, | |
| { author: { login: "carol" } }, | |
| { author: { login: "dave" } }, | |
| ], | |
| }), | |
| DEFAULT_THRESHOLDS, | |
| now | |
| ); | |
| assert.equal(r.bucket, "absorb"); | |
| assert.match(r.reason, /override:commenters/); | |
| assert.equal(r.commenters, 3); | |
| }); | |
| it("3 days old, 4 commenters but 1 is bot β dormant", () => { | |
| const r = classifyIssue( | |
| makeIssue({ | |
| comments: [ | |
| { author: { login: "bob" } }, | |
| { author: { login: "carol" } }, | |
| { author: { login: "dependabot[bot]" } }, | |
| ], | |
| }), | |
| DEFAULT_THRESHOLDS, | |
| now | |
| ); | |
| assert.equal(r.bucket, "dormant"); | |
| assert.equal(r.commenters, 2); | |
| }); | |
| it("3 days old, commenters include author β author excluded", () => { | |
| const r = classifyIssue( | |
| makeIssue({ | |
| comments: [ | |
| { author: { login: "alice" } }, | |
| { author: { login: "bob" } }, | |
| { author: { login: "carol" } }, | |
| ], | |
| }), | |
| DEFAULT_THRESHOLDS, | |
| now | |
| ); | |
| assert.equal(r.bucket, "dormant"); | |
| assert.equal(r.commenters, 2); | |
| }); | |
| it("exactly 14 days old β absorb (age>=14)", () => { | |
| const issue = makeIssue({ | |
| createdAt: new Date(now.getTime() - 14 * 86400_000).toISOString(), | |
| }); | |
| const r = classifyIssue(issue, DEFAULT_THRESHOLDS, now); | |
| assert.equal(r.bucket, "absorb"); | |
| assert.match(r.reason, /age>=14/); | |
| }); | |
| it("20 days old with assignee β skip_assigned (precedence)", () => { | |
| const r = classifyIssue( | |
| makeIssue({ | |
| createdAt: new Date(now.getTime() - 20 * 86400_000).toISOString(), | |
| assignees: [{ login: "alice" }], | |
| }), | |
| DEFAULT_THRESHOLDS, | |
| now | |
| ); | |
| assert.equal(r.bucket, "skip_assigned"); | |
| }); | |
| it("20 days old with open linked PR β skip_has_pr (precedence)", () => { | |
| const r = classifyIssue( | |
| makeIssue({ | |
| createdAt: new Date(now.getTime() - 20 * 86400_000).toISOString(), | |
| timelineItems: [ | |
| { | |
| __typename: "CrossReferencedEvent", | |
| source: { __typename: "PullRequest", state: "OPEN", number: 2400 }, | |
| }, | |
| ], | |
| }), | |
| DEFAULT_THRESHOLDS, | |
| now | |
| ); | |
| assert.equal(r.bucket, "skip_has_pr"); | |
| assert.deepEqual(r.linkedPrs, [{ number: 2400, state: "open" }]); | |
| }); | |
| it("custom thresholds (quarantineDays=7) respected", () => { | |
| const issue = makeIssue({ | |
| createdAt: new Date(now.getTime() - 8 * 86400_000).toISOString(), | |
| }); | |
| const r = classifyIssue(issue, { ...DEFAULT_THRESHOLDS, quarantineDays: 7 }, now); | |
| assert.equal(r.bucket, "absorb"); | |
| }); | |
| }); | |