diff --git a/src/signals/contributor-open-pr-monitor.ts b/src/signals/contributor-open-pr-monitor.ts index 4fd8cb3d3..62fa608b3 100644 --- a/src/signals/contributor-open-pr-monitor.ts +++ b/src/signals/contributor-open-pr-monitor.ts @@ -239,6 +239,7 @@ function duplicatePronePullNumbers(openPullRequests: PullRequestRecord[]): Set(); for (const pr of openPullRequests) { const key = normalizeTitle(pr.title); + if (!key) continue; const bucket = byNormalizedTitle.get(key) ?? []; bucket.push(pr); byNormalizedTitle.set(key, bucket); diff --git a/test/unit/contributor-open-pr-monitor-empty-title.test.ts b/test/unit/contributor-open-pr-monitor-empty-title.test.ts new file mode 100644 index 000000000..bb1994773 --- /dev/null +++ b/test/unit/contributor-open-pr-monitor-empty-title.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { __contributorOpenPrMonitorInternals } from "../../src/signals/contributor-open-pr-monitor"; +import type { PullRequestRecord } from "../../src/types"; + +function pr(number: number, title: string, labels: string[] = []): PullRequestRecord { + return { + repoFullName: "acme/widgets", + number, + title, + state: "open", + authorLogin: "contributor", + labels, + linkedIssues: [], + } as PullRequestRecord; +} + +describe("duplicate-prone title grouping", () => { + it("does not group unrelated titles whose normalized form is empty", () => { + const flagged = __contributorOpenPrMonitorInternals.duplicatePronePullNumbers([pr(1, "..."), pr(2, "🎉🎉🎉")]); + expect([...flagged]).toEqual([]); + }); + + it("still groups matching non-empty normalized titles", () => { + const flagged = __contributorOpenPrMonitorInternals.duplicatePronePullNumbers([pr(3, "Fix bug"), pr(4, "fix bug!!")]); + expect([...flagged].sort((a, b) => a - b)).toEqual([3, 4]); + }); + + it("still flags explicit wip and duplicate labels", () => { + const flagged = __contributorOpenPrMonitorInternals.duplicatePronePullNumbers([pr(5, "...", ["wip"]), pr(6, "🎉", ["duplicate"])]); + expect([...flagged].sort((a, b) => a - b)).toEqual([5, 6]); + }); +});