1import type { ThreadPullRequestLink } from "@t3tools/contracts";
2import { resolveThreadPullRequestChains } from "@t3tools/shared/threadPullRequests";
3import { describe, expect, it } from "vite-plus/test";
4
5import { pullRequestListLines } from "./pullRequestListLines";
6
7function link(
8 number: number,
9 head: string,
10 base: string,
11 updatedAt: string,
12 stack: ThreadPullRequestLink["stack"] = null,
13): ThreadPullRequestLink {
14 return {
15 host: "github.com",
16 repository: "acme/web",
17 number,
18 url: `https://github.com/acme/web/pull/${number}`,
19 source: "manual",
20 linkedAt: "2026-01-01T00:00:00.000Z",
21 snapshot: {
22 state: "open",
23 title: `PR ${number}`,
24 headBranch: head,
25 baseBranch: base,
26 isDraft: false,
27 updatedAt,
28 syncedAt: updatedAt,
29 },
30 stack,
31 };
32}
33
34describe("pullRequestListLines", () => {
35 it("orders newest first and keeps a stack together under its base layer", () => {
36 const lines = pullRequestListLines(
37 resolveThreadPullRequestChains([
38 link(1, "a", "main", "2026-01-01T10:00:00Z"),
39 link(2, "b", "a", "2026-01-01T12:00:00Z"),
40 link(9, "solo", "main", "2026-01-01T11:00:00Z"),
41 link(5, "old", "main", "2026-01-01T09:00:00Z"),
42 ]),
43 );
44 expect(lines.map((line) => [line.link.number, line.depth, line.stack?.size ?? null])).toEqual([
45 // The stack's newest layer is #2 at 12:00, so the whole stack outranks #9 at 11:00.
46 [1, 0, 2],
47 [2, 1, null],
48 [9, 0, null],
49 [5, 0, null],
50 ]);
51 });
52
53 it("marks native stacks on their base layer", () => {
54 const stack = {
55 kind: "native" as const,
56 id: "1",
57 number: 1,
58 url: "https://github.com/acme/web/stacks/1",
59 base: "main",
60 layers: [
61 { number: 3, headBranch: "x", state: "open" as const },
62 { number: 4, headBranch: "y", state: "open" as const },
63 ],
64 };
65 const lines = pullRequestListLines(
66 resolveThreadPullRequestChains([
67 link(4, "y", "x", "2026-01-01T10:00:00Z", stack),
68 link(3, "x", "main", "2026-01-01T10:00:00Z", stack),
69 ]),
70 );
71 expect(lines.map((line) => [line.link.number, line.depth, line.stack?.kind ?? null])).toEqual([
72 [3, 0, "native"],
73 [4, 1, null],
74 ]);
75 });
76});