fix: commit & push now saves pending content and refreshes modified files
Root cause: Two problems caused "0 files changed": 1. loadModifiedFiles() was only called on mount, never refreshed after saves 2. Pending editor content wasn't flushed to disk before git commit Fix: - useEditorSave: add savePending() to flush unsaved content, onAfterSave callback to refresh git status after Cmd+S - useCommitFlow: new hook managing save→commit→push flow with proper sequencing (save pending → refresh files → show dialog → commit) - App.tsx: wire onAfterSave to loadModifiedFiles, use useCommitFlow - git.rs: include stdout in error when stderr is empty (fixes "nothing to commit" message being swallowed) - mock-tauri: track saved files so get_modified_files reflects edits Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
75
src/hooks/useCommitFlow.test.ts
Normal file
75
src/hooks/useCommitFlow.test.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { renderHook, act } from '@testing-library/react'
|
||||
import { useCommitFlow } from './useCommitFlow'
|
||||
|
||||
describe('useCommitFlow', () => {
|
||||
let savePending: vi.Mock
|
||||
let loadModifiedFiles: vi.Mock
|
||||
let commitAndPush: vi.Mock
|
||||
let setToastMessage: vi.Mock
|
||||
|
||||
beforeEach(() => {
|
||||
savePending = vi.fn().mockResolvedValue(undefined)
|
||||
loadModifiedFiles = vi.fn().mockResolvedValue(undefined)
|
||||
commitAndPush = vi.fn().mockResolvedValue('Committed and pushed')
|
||||
setToastMessage = vi.fn()
|
||||
})
|
||||
|
||||
function renderCommitFlow() {
|
||||
return renderHook(() => useCommitFlow({ savePending, loadModifiedFiles, commitAndPush, setToastMessage }))
|
||||
}
|
||||
|
||||
it('openCommitDialog saves pending, refreshes files, then opens dialog', async () => {
|
||||
const { result } = renderCommitFlow()
|
||||
expect(result.current.showCommitDialog).toBe(false)
|
||||
|
||||
await act(async () => {
|
||||
await result.current.openCommitDialog()
|
||||
})
|
||||
|
||||
expect(savePending).toHaveBeenCalledTimes(1)
|
||||
expect(loadModifiedFiles).toHaveBeenCalledTimes(1)
|
||||
expect(result.current.showCommitDialog).toBe(true)
|
||||
})
|
||||
|
||||
it('handleCommitPush saves pending, commits, shows toast, and refreshes files', async () => {
|
||||
const { result } = renderCommitFlow()
|
||||
|
||||
await act(async () => {
|
||||
await result.current.handleCommitPush('test message')
|
||||
})
|
||||
|
||||
expect(savePending).toHaveBeenCalled()
|
||||
expect(commitAndPush).toHaveBeenCalledWith('test message')
|
||||
expect(setToastMessage).toHaveBeenCalledWith('Committed and pushed')
|
||||
expect(loadModifiedFiles).toHaveBeenCalled()
|
||||
expect(result.current.showCommitDialog).toBe(false)
|
||||
})
|
||||
|
||||
it('handleCommitPush shows error toast on failure', async () => {
|
||||
commitAndPush.mockRejectedValueOnce(new Error('push failed'))
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
const { result } = renderCommitFlow()
|
||||
|
||||
await act(async () => {
|
||||
await result.current.handleCommitPush('test')
|
||||
})
|
||||
|
||||
expect(setToastMessage).toHaveBeenCalledWith(expect.stringContaining('Commit failed'))
|
||||
consoleSpy.mockRestore()
|
||||
})
|
||||
|
||||
it('closeCommitDialog closes the dialog', async () => {
|
||||
const { result } = renderCommitFlow()
|
||||
|
||||
await act(async () => {
|
||||
await result.current.openCommitDialog()
|
||||
})
|
||||
expect(result.current.showCommitDialog).toBe(true)
|
||||
|
||||
act(() => {
|
||||
result.current.closeCommitDialog()
|
||||
})
|
||||
expect(result.current.showCommitDialog).toBe(false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user