Файли
openidea/src/features/github/github.test.ts
T
Jaw 55836e1b49 chore: Format the codebase with oxfmt and check formatting in CI (#135)
Run oxfmt once over the whole repository (formatting only, no logic changes) and add `pnpm format:check` to the frontend CI job so unformatted code no longer builds up. `.oxfmtrc.json` now skips the generated theme docs, test fixtures and code blocks inside Markdown.

Co-authored-by: jaw52 <[email protected]>
2026-10-28 19:35:16 +08:00

113 рядки
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { PrCheck, PrReviewComment, PullRequestDetails } from "@/platform/ipc";
import { checksSummary, checksText, diffNotes, fileDiffData, relativeTime, reviewThreads, stateLabel } from "./model";
const comment = (
id: number,
path: string,
line: number | null,
inReplyTo: number | null = null,
side = "RIGHT",
): PrReviewComment => ({
id,
inReplyTo,
path,
line,
originalLine: line ?? 3,
side,
body: `c${id}`,
author: "ann",
createdAt: "2026-10-21T10:00:00Z",
url: "",
diffHunk: "",
});
const summary = {
number: 7,
title: "Fix",
author: "ann",
state: "open" as const,
isDraft: false,
headRef: "fix",
baseRef: "main",
createdAt: "",
updatedAt: "",
labels: [],
reviewDecision: null,
url: "https://github.com/o/r/pull/7",
additions: 1,
deletions: 1,
};
describe("pull request model", () => {
it("labels states", () => {
expect(stateLabel(summary)).toBe("Open");
expect(stateLabel({ ...summary, isDraft: true })).toBe("Draft");
expect(stateLabel({ ...summary, state: "merged" })).toBe("Merged");
});
it("summarises checks", () => {
const c = (status: PrCheck["status"]): PrCheck => ({ name: status, workflow: null, status, url: null });
const s = checksSummary([c("failure"), c("success"), c("success"), c("pending"), c("skipped")]);
expect(s).toEqual({ failed: 1, pending: 1, passed: 2, other: 1 });
expect(checksText(s)).toBe("1 failing, 1 pending, 2 passed, 1 skipped");
expect(checksText(checksSummary([]))).toBe("No checks");
});
it("formats relative times", () => {
const now = Date.parse("2026-10-21T12:00:00Z");
expect(relativeTime("2026-10-21T11:59:30Z", now)).toBe("just now");
expect(relativeTime("2026-10-21T10:00:00Z", now)).toBe("2 hours ago");
expect(relativeTime("2026-10-20T12:00:00Z", now)).toBe("1 day ago");
expect(relativeTime("nonsense", now)).toBe("");
});
it("threads replies under their root, ordered by file and line", () => {
const threads = reviewThreads([
comment(1, "b.ts", 9),
comment(2, "a.ts", 5),
comment(3, "b.ts", 9, 1),
comment(4, "b.ts", 9, 3),
]);
expect(threads.map((t) => [t.root.id, t.replies.map((r) => r.id)])).toEqual([
[2, []],
[1, [3, 4]],
]);
});
it("turns current comments into diff notes", () => {
const notes = diffNotes("a.ts", [
comment(1, "a.ts", 5),
comment(2, "a.ts", null),
comment(3, "a.ts", 2, null, "LEFT"),
comment(4, "b.ts", 1),
]);
expect(notes.map((n) => [n.side, n.line])).toEqual([
["right", 4],
["left", 1],
]);
});
it("builds diff data for renamed and added files", () => {
const pr = { summary, files: [] } as unknown as PullRequestDetails;
const revs = {
base: "b".repeat(40),
head: "h".repeat(40),
root: "/repo",
files: [{ path: "src/new.ts", kind: "renamed" as const, oldPath: "src/old.ts" }],
};
const renamed = fileDiffData(
pr,
{ path: "src/new.ts", additions: 1, deletions: 0, changeType: "RENAMED" },
revs,
[],
);
expect(renamed.path).toBe("/repo/src/new.ts");
expect(renamed.left).toMatchObject({ type: "rev", rev: revs.base, path: "/repo/src/old.ts" });
expect(renamed.right).toMatchObject({ type: "rev", rev: revs.head });
expect(renamed.title).toBe("#7: new.ts");
const added = fileDiffData(pr, { path: "x.md", additions: 1, deletions: 0, changeType: "ADDED" }, revs, []);
expect(added.left).toMatchObject({ type: "text", text: "" });
});
});