feat: version diffs work now

This commit is contained in:
2026-02-16 14:03:09 +01:00
parent 3c9d4b6bce
commit b19e92f729
13 changed files with 655 additions and 20 deletions

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import { render, screen, fireEvent } from '@testing-library/react';
import { GitDiffView } from '../../../src/renderer/components/GitDiffView/GitDiffView';
import { useAppStore } from '../../../src/renderer/store';
@@ -58,6 +58,23 @@ describe('GitDiffView', () => {
original: '# old line',
modified: '# new line',
}),
getCommitDiffContent: vi.fn().mockResolvedValue({
commitHash: 'abc123def456',
original: '--- posts/first.md\nold',
modified: '--- posts/first.md\nnew',
files: [
{
filePath: 'posts/first.md',
original: 'old',
modified: 'new',
},
{
filePath: 'src/main.ts',
original: 'const oldValue = 1;',
modified: 'const newValue = 2;',
},
],
}),
},
app: {
...(window as any).electronAPI?.app,
@@ -79,4 +96,33 @@ describe('GitDiffView', () => {
expect(screen.getByText('keepOriginal:true')).toBeInTheDocument();
expect(screen.getByText('keepModified:true')).toBeInTheDocument();
});
it('loads commit diff content when a commit tab identifier is used', async () => {
render(<GitDiffView filePath="commit:abc123def456" />);
const diffEditor = await screen.findByTestId('monaco-diff-editor');
expect(diffEditor).toBeInTheDocument();
expect(await screen.findByRole('combobox', { name: /changed files/i })).toBeInTheDocument();
expect(screen.getByRole('button', { name: /previous file/i })).toBeDisabled();
expect(screen.getByRole('button', { name: /next file/i })).toBeEnabled();
expect((window as any).electronAPI.git.getCommitDiffContent).toHaveBeenCalledWith('/repo/path', 'abc123def456');
expect(diffEditor).toHaveTextContent(/original:\s*old/);
expect(diffEditor).toHaveTextContent(/modified:\s*new/);
expect(screen.getByText('language:markdown')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: /next file/i }));
expect(diffEditor).toHaveTextContent(/original:\s*const oldValue = 1;/);
expect(diffEditor).toHaveTextContent(/modified:\s*const newValue = 2;/);
expect(screen.getByText('language:typescript')).toBeInTheDocument();
expect(screen.getByRole('button', { name: /previous file/i })).toBeEnabled();
expect(screen.getByRole('button', { name: /next file/i })).toBeDisabled();
fireEvent.click(screen.getByRole('button', { name: /previous file/i }));
expect(diffEditor).toHaveTextContent(/original:\s*old/);
expect(diffEditor).toHaveTextContent(/modified:\s*new/);
expect(screen.getByRole('button', { name: /previous file/i })).toBeDisabled();
expect(screen.getByRole('button', { name: /next file/i })).toBeEnabled();
});
});

View File

@@ -35,6 +35,7 @@ describe('GitSidebar', () => {
getStatus: vi.fn().mockResolvedValue({ files: [], counts: { untracked: 0, modified: 0, deleted: 0, renamed: 0, staged: 0, total: 0 } }),
getDiff: vi.fn().mockResolvedValue({ filePath: 'posts/a.md', patch: 'diff --git a/posts/a.md b/posts/a.md' }),
getDiffContent: vi.fn().mockResolvedValue({ filePath: 'posts/a.md', original: '', modified: '' }),
getCommitDiffContent: vi.fn().mockResolvedValue({ commitHash: 'abc123', original: '', modified: '' }),
getHistory: vi.fn().mockResolvedValue([]),
fetch: vi.fn().mockResolvedValue({ success: true }),
pull: vi.fn().mockResolvedValue({ success: true }),
@@ -171,6 +172,72 @@ describe('GitSidebar', () => {
expect(getStore().tabs[0]).toMatchObject({ type: 'git-diff', id: 'git-diff:posts/first.md', isTransient: false });
});
it('single click on a commit opens a transient git-diff commit tab', async () => {
(window as any).electronAPI.git.getRepoState = vi.fn().mockResolvedValue({
isRepo: true,
rootPath: '/repo/path',
currentBranch: 'main',
hasRemote: true,
});
(window as any).electronAPI.git.getHistory = vi.fn().mockResolvedValue([
{
hash: 'abc123def456',
shortHash: 'abc123d',
date: '2026-02-16T10:00:00.000Z',
subject: 'feat: add sidebar history click',
author: 'Dev One',
},
]);
render(<GitSidebar />);
const commitItem = await screen.findByRole('button', { name: /feat: add sidebar history click/i });
await act(async () => {
fireEvent.click(commitItem);
});
expect(getStore().tabs).toHaveLength(1);
expect(getStore().tabs[0]).toMatchObject({
type: 'git-diff',
id: 'git-diff:commit:abc123def456',
isTransient: true,
});
});
it('double click on a commit opens a persistent git-diff commit tab', async () => {
(window as any).electronAPI.git.getRepoState = vi.fn().mockResolvedValue({
isRepo: true,
rootPath: '/repo/path',
currentBranch: 'main',
hasRemote: true,
});
(window as any).electronAPI.git.getHistory = vi.fn().mockResolvedValue([
{
hash: 'abc123def456',
shortHash: 'abc123d',
date: '2026-02-16T10:00:00.000Z',
subject: 'feat: add sidebar history click',
author: 'Dev One',
},
]);
render(<GitSidebar />);
const commitItem = await screen.findByRole('button', { name: /feat: add sidebar history click/i });
await act(async () => {
fireEvent.doubleClick(commitItem);
});
expect(getStore().tabs).toHaveLength(1);
expect(getStore().tabs[0]).toMatchObject({
type: 'git-diff',
id: 'git-diff:commit:abc123def456',
isTransient: false,
});
});
it('initializes repository and refreshes repo state after clicking Initialize Git', async () => {
const getRepoStateMock = vi
.fn()

View File

@@ -0,0 +1,81 @@
import React from 'react';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import { TabBar } from '../../../src/renderer/components/TabBar/TabBar';
import { useAppStore } from '../../../src/renderer/store';
describe('TabBar', () => {
beforeEach(() => {
vi.clearAllMocks();
(window as any).addEventListener = vi.fn();
(window as any).removeEventListener = vi.fn();
if (!(globalThis as any).ResizeObserver) {
(globalThis as any).ResizeObserver = class {
observe() {}
disconnect() {}
};
}
useAppStore.setState({
activeProject: {
id: 'project-1',
name: 'Test Project',
slug: 'test-project',
isActive: true,
dataPath: '/repo/path',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
tabs: [
{ type: 'git-diff', id: 'git-diff:commit:abc123def456', isTransient: false },
],
activeTabId: 'git-diff:commit:abc123def456',
media: [],
dirtyPosts: new Set<string>(),
sidebarVisible: true,
});
(window as any).electronAPI = {
...(window as any).electronAPI,
git: {
...(window as any).electronAPI?.git,
getHistory: vi.fn().mockResolvedValue([
{
hash: 'abc123def456',
shortHash: 'abc123d',
date: '2026-02-16T10:00:00.000Z',
subject: 'feat: improve commit diff tabs',
author: 'Dev One',
},
]),
},
app: {
...(window as any).electronAPI?.app,
getDefaultProjectPath: vi.fn().mockResolvedValue('/repo/path'),
},
posts: {
...(window as any).electronAPI?.posts,
get: vi.fn(),
},
chat: {
...(window as any).electronAPI?.chat,
getConversation: vi.fn(),
onTitleUpdated: vi.fn(() => () => {}),
},
importDefinitions: {
...(window as any).electronAPI?.importDefinitions,
get: vi.fn(),
onNameUpdated: vi.fn(() => () => {}),
},
};
});
it('renders commit subject in git-diff commit tab titles when available', async () => {
render(<TabBar />);
expect(await screen.findByText('abc123d feat: improve commit diff tabs')).toBeInTheDocument();
expect((window as any).electronAPI.git.getHistory).toHaveBeenCalledWith('/repo/path', 200);
});
});