daf5b7be92
- Changes panel: a working file opens in a CodeMirror editor with its diff inline (DiffEditor.tsx, @codemirror/merge, lazy-loaded); Changes folds the unchanged lines, Whole file shows them; side by side at 50/50 and full width; a Revert per block; original from HEAD or the branch's merge base (`mergeBase` on GET /git/changes?range=branch) - Every diff: green = line added whole, red = removed whole, blue = edited in place (--diff-mod) - History drawn as a commit graph (#58: `parents` on GET /git/log, --date-order; lib/commitGraph.ts) - Per-workspace never-stage list, drawn orange in the Files tree (--kept); closed Terminal rows past three deleted - Status bar plan quota for Claude (per account) and Codex (GET /api/pricing/quota, server/lib/quota.js); compact hover panel that stays open, Refresh button with a spinner - Settings → Appearance holds language, theme and pet; Ctrl+Shift+C copies; compact sidebar navigation and short session times
52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
/**
|
|
* @file Tests for the Changes panel's folder tree: grouping by folder,
|
|
* compacting single-child chains, counts, ordering and the per-folder file list.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
import { describe, it, expect } from "vitest";
|
|
import { changeTree, treeFiles } from "../changeTree";
|
|
|
|
const rows = [
|
|
"app2/Services/TwitterService.php",
|
|
"app2/Services/Redis/SlowAlertRedisService.php",
|
|
"app2/Enums/Redis/RedisSlowAlertKey.php",
|
|
"config/monitoring.php",
|
|
"config/app.php",
|
|
"README.md",
|
|
].map((path) => ({ path }));
|
|
|
|
describe("changeTree", () => {
|
|
const root = changeTree(rows);
|
|
|
|
it("puts root files at the top level and counts every file", () => {
|
|
expect(root.count).toBe(6);
|
|
expect(root.files.map((f) => f.name)).toEqual(["README.md"]);
|
|
expect(root.dirs.map((d) => d.name)).toEqual(["app2", "config"]);
|
|
});
|
|
|
|
it("compacts a folder chain with nothing else in it", () => {
|
|
const app2 = root.dirs[0]!;
|
|
expect(app2.count).toBe(3);
|
|
expect(app2.dirs.map((d) => [d.name, d.path])).toEqual([
|
|
["Enums/Redis", "app2/Enums/Redis"],
|
|
["Services", "app2/Services"],
|
|
]);
|
|
// Services holds a file, so it is not folded into Redis.
|
|
expect(app2.dirs[1]!.dirs[0]!.name).toBe("Redis");
|
|
});
|
|
|
|
it("sorts files by name and lists a folder's files", () => {
|
|
expect(root.dirs[1]!.files.map((f) => f.name)).toEqual(["app.php", "monitoring.php"]);
|
|
expect(treeFiles(root.dirs[0]!).map((f) => f.path)).toHaveLength(3);
|
|
});
|
|
});
|
|
|
|
describe("changeTree — an untracked folder", () => {
|
|
it("shows git's `dir/` entry as a named row in its parent folder", () => {
|
|
const root = changeTree([{ path: "docs/plans/analytics-parity/" }, { path: "docs/x.md" }]);
|
|
const docs = root.dirs[0]!;
|
|
expect(docs.files.map((f) => f.name)).toEqual(["x.md"]);
|
|
expect(docs.dirs[0]!.files.map((f) => f.name)).toEqual(["analytics-parity/"]);
|
|
});
|
|
});
|