feat(FN-803): add ahead/behind commit lists to Git Manager Remotes tab
- Add backend API routes for remote commit lists (local-ahead, remote-ahead, all commits by branch) - Surface ahead/behind commit counts and expandable commit lists in Remotes tab UI - Add expand/collapse rows showing commit hash, message, author, and relative date - Style commit list rows with alternating backgrounds and monospace hashes - Add comprehensive tests for API routes and GitManagerModal component - Update README documentation for Git Manager Remotes tab
This commit is contained in:
@@ -909,6 +909,8 @@ import {
|
||||
fetchGitStatus,
|
||||
fetchGitCommits,
|
||||
fetchCommitDiff,
|
||||
fetchAheadCommits,
|
||||
fetchRemoteCommits,
|
||||
fetchGitBranches,
|
||||
fetchGitWorktrees,
|
||||
createBranch,
|
||||
@@ -994,6 +996,66 @@ describe("Git Management API", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchAheadCommits", () => {
|
||||
it("returns commits ahead of upstream", async () => {
|
||||
const commits = [
|
||||
{ hash: "abc123", shortHash: "abc", message: "Fix bug", author: "User", date: "2026-01-01", parents: [] },
|
||||
];
|
||||
globalThis.fetch = vi.fn().mockReturnValue(mockFetchResponse(true, commits));
|
||||
|
||||
const result = await fetchAheadCommits();
|
||||
|
||||
expect(result).toEqual(commits);
|
||||
expect(globalThis.fetch).toHaveBeenCalledWith("/api/git/commits/ahead", {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
});
|
||||
|
||||
it("returns empty array when no upstream", async () => {
|
||||
globalThis.fetch = vi.fn().mockReturnValue(mockFetchResponse(true, []));
|
||||
|
||||
const result = await fetchAheadCommits();
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchRemoteCommits", () => {
|
||||
it("fetches commits for a remote with default params", async () => {
|
||||
const commits = [
|
||||
{ hash: "def456", shortHash: "def", message: "Remote commit", author: "User", date: "2026-01-01", parents: [] },
|
||||
];
|
||||
globalThis.fetch = vi.fn().mockReturnValue(mockFetchResponse(true, commits));
|
||||
|
||||
const result = await fetchRemoteCommits("origin");
|
||||
|
||||
expect(result).toEqual(commits);
|
||||
expect(globalThis.fetch).toHaveBeenCalledWith("/api/git/remotes/origin/commits", {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
});
|
||||
|
||||
it("includes ref and limit in query", async () => {
|
||||
globalThis.fetch = vi.fn().mockReturnValue(mockFetchResponse(true, []));
|
||||
|
||||
await fetchRemoteCommits("origin", "main", 5);
|
||||
|
||||
expect(globalThis.fetch).toHaveBeenCalledWith("/api/git/remotes/origin/commits?ref=main&limit=5", {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
});
|
||||
|
||||
it("encodes remote name in URL", async () => {
|
||||
globalThis.fetch = vi.fn().mockReturnValue(mockFetchResponse(true, []));
|
||||
|
||||
await fetchRemoteCommits("my-remote");
|
||||
|
||||
expect(globalThis.fetch).toHaveBeenCalledWith("/api/git/remotes/my-remote/commits", {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("fetchGitBranches", () => {
|
||||
it("returns branches array", async () => {
|
||||
const branches = [{ name: "main", isCurrent: true, remote: "origin/main" }];
|
||||
|
||||
Reference in New Issue
Block a user