From cb8c11ed3b6f5868cc95063005379ab46d77dd78 Mon Sep 17 00:00:00 2001 From: Siddharth Gelera Date: Fri, 29 May 2026 12:55:17 +0530 Subject: [PATCH] test: for git reset --- src/simulation.test.ts | 38 ++++++++++++++++++++++++++++++++++ src/watcher.test.ts | 47 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/src/simulation.test.ts b/src/simulation.test.ts index 1dbf29b..ba0fff2 100644 --- a/src/simulation.test.ts +++ b/src/simulation.test.ts @@ -132,6 +132,44 @@ describe('git state simulation scenarios', () => { expect(committed.changes[0]?.current).toBeUndefined(); }); + it('unstages modified file on mixed reset', async () => { + const sim = await trackSimulationWithTrackedFile('reset-mixed.ts', 'v1\n'); + + await sim.write('reset-mixed.ts', 'v2\n', { label: 'edit before reset' }); + const staged = await sim.gitAdd('reset-mixed.ts', { label: 'stage before reset' }); + expect(staged.tree).toContain('[M staged]'); + + const reset = await sim.gitReset('mixed', { label: 'mixed reset' }); + expect(reset.changes).toHaveLength(1); + expect(reset.tree).toContain('[M unstaged]'); + expect(reset.changes[0]).toMatchObject({ + path: 'reset-mixed.ts', + previous: { staged: true, unstaged: false }, + current: { + path: 'reset-mixed.ts', + status: 'modified', + staged: false, + unstaged: true, + }, + }); + }); + + it('clears dirty tracked state on hard reset', async () => { + const sim = await trackSimulationWithTrackedFile('reset-hard.ts', 'v1\n'); + + await sim.write('reset-hard.ts', 'v2\n', { label: 'edit before hard reset' }); + await sim.gitAdd('reset-hard.ts', { label: 'stage before hard reset' }); + + const reset = await sim.gitReset('hard', { label: 'hard reset' }); + expect(reset.changes).toHaveLength(1); + expect(reset.tree).not.toContain('[M'); + expect(reset.changes[0]).toMatchObject({ + path: 'reset-hard.ts', + current: undefined, + }); + expect(sim.getState()).toEqual([]); + }); + it('does not emit extra events for unchanged filesystem writes', async () => { const sim = await trackSimulationWithTrackedFile('stable.ts', 'same\n'); diff --git a/src/watcher.test.ts b/src/watcher.test.ts index 20175b8..4b8dc9d 100644 --- a/src/watcher.test.ts +++ b/src/watcher.test.ts @@ -43,6 +43,14 @@ async function simpleGitAdd(repoPath: string, filePath: string): Promise { await simpleGit(repoPath).add(filePath); } +async function simpleGitReset( + repoPath: string, + mode: 'soft' | 'mixed' | 'hard', +): Promise { + const { simpleGit } = await import('simple-git'); + await simpleGit(repoPath).reset([`--${mode}`]); +} + afterEach(async () => { await Promise.all( tempRepos.splice(0).map((repo) => fs.rm(repo, { recursive: true, force: true })), @@ -144,6 +152,45 @@ describe('createGitStateWatcher', () => { await watcher.close(); }); + it('emits when git metadata changes on mixed reset', async () => { + const repo = await trackRepo(); + await writeAndAdd(repo, 'tracked.ts', 'v1\n'); + await simpleGitCommit(repo, 'initial'); + await fs.writeFile(path.join(repo, 'tracked.ts'), 'v2\n', 'utf8'); + + const watcher = await createGitStateWatcher(repo, { debounceMs: 75 }); + expect(watcher.getFileState('tracked.ts')).toMatchObject({ + path: 'tracked.ts', + status: 'modified', + staged: false, + unstaged: true, + }); + + const stagedChangesPromise = waitForChanges(watcher); + await simpleGitAdd(repo, 'tracked.ts'); + const stagedChanges = await stagedChangesPromise; + + expect(stagedChanges).toHaveLength(1); + expect(stagedChanges[0]).toMatchObject({ + path: 'tracked.ts', + previous: { staged: false, unstaged: true }, + current: { status: 'modified', staged: true, unstaged: false }, + }); + + const resetChangesPromise = waitForChanges(watcher); + await simpleGitReset(repo, 'mixed'); + const resetChanges = await resetChangesPromise; + + expect(resetChanges).toHaveLength(1); + expect(resetChanges[0]).toMatchObject({ + path: 'tracked.ts', + previous: { staged: true, unstaged: false }, + current: { status: 'modified', staged: false, unstaged: true }, + }); + + await watcher.close(); + }); + it('does not emit when filesystem noise leaves git state unchanged', async () => { const repo = await trackRepo(); await writeAndAdd(repo, 'stable.ts', 'same\n');