Repository navigation
Expand file tree
/
Copy pathpullRequestStackSnapshot.test.ts
More file actions
97 lines (95 loc) · 3.46 KB
/
Copy pathpullRequestStackSnapshot.test.ts
File metadata and controls
97 lines (95 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import type { ThreadPullRequestLink } from "@t3tools/contracts";
import { ProjectId } from "@t3tools/contracts";
import { describe, expect, it } from "vite-plus/test";
import { savedPullRequestStack, pullRequestStackView } from "./pullRequestStackSnapshot";
const reference = {
projectId: ProjectId.make("project"),
host: "github.com",
repository: "acme/web",
number: 2,
};
const link: ThreadPullRequestLink = {
host: "github.com",
repository: "acme/web",
number: 2,
url: "https://github.com/acme/web/pull/2",
source: "manual",
linkedAt: "2026-09-09T10:00:00Z",
snapshot: {
title: "Top layer",
headBranch: "top",
baseBranch: "bottom",
state: "open",
isDraft: false,
updatedAt: null,
syncedAt: "2026-09-09T10:00:00Z",
},
stack: {
kind: "native",
id: "stack",
number: 3,
url: "https://github.com/acme/web/pull/3",
base: "main",
layers: [
{ number: 1, headBranch: "bottom", state: "open" },
{ number: 2, headBranch: "top", state: "open" },
],
},
};
describe("saved stack navigation", () => {
it("preserves all native layers even when only one has a linked snapshot, without action SHAs", () => {
const saved = savedPullRequestStack([link], reference);
expect(saved?.layers).toEqual([
{ number: 1, headBranch: "bottom", state: "open" },
{ number: 2, headBranch: "top", state: "open", title: "Top layer", isDraft: false },
]);
expect(savedPullRequestStack([link], { ...reference, number: 1 })?.number).toBe(3);
});
it("does not borrow stacks across hosts or repositories", () => {
expect(savedPullRequestStack([link], { ...reference, host: "enterprise.example" })).toBeNull();
expect(savedPullRequestStack([link], { ...reference, repository: "other/web" })).toBeNull();
expect(savedPullRequestStack([link], { ...reference, host: undefined })).toBeNull();
});
it("honors a newer saved removal across linked threads", () => {
expect(
savedPullRequestStack(
[
link,
{
...link,
stack: null,
snapshot: { ...link.snapshot!, syncedAt: "2026-09-09T11:00:00Z" },
},
],
reference,
),
).toBeNull();
});
it("shows saved data during loading and marks a failed refresh stale", () => {
const saved = savedPullRequestStack([link], reference);
const query = { data: null, isSuccess: false, isPending: true, error: null };
expect(pullRequestStackView(query, saved)).toMatchObject({
data: saved,
isFresh: false,
notice: expect.stringContaining("Refreshing"),
});
expect(
pullRequestStackView({ ...query, isPending: false, error: "Rate limited" }, saved),
).toMatchObject({ data: saved, isFresh: false, notice: expect.stringContaining("stale") });
});
it("prefers refreshed data and honors a successful absence", () => {
const saved = savedPullRequestStack([link], reference);
const query = { data: saved, isSuccess: true, isPending: false, error: null };
expect(pullRequestStackView(query, null)).toEqual({ data: saved, isFresh: true, notice: null });
expect(pullRequestStackView({ ...query, data: null }, saved)).toEqual({
data: null,
isFresh: true,
notice: null,
});
expect(pullRequestStackView({ ...query, isPending: true }, saved).isFresh).toBe(true);
expect(pullRequestStackView({ ...query, data: null, isPending: true }, saved)).toMatchObject({
data: null,
isFresh: true,
});
});
});