Split runtime file watcher tests

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
brennanb2025
2026-05-28 16:36:34 -07:00
co-authored by Orca
parent a24e3694d5
commit 808f705fa3
2 changed files with 151 additions and 91 deletions
@@ -0,0 +1,151 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type * as Fs from 'fs'
import type * as FsPromises from 'fs/promises'
import type * as FilesystemAuth from '../ipc/filesystem-auth'
const { resolveAuthorizedPathMock, statMock, subscribeParcelWatcherMock, watchMock } = vi.hoisted(
() => ({
resolveAuthorizedPathMock: vi.fn(),
statMock: vi.fn(),
subscribeParcelWatcherMock: vi.fn(),
watchMock: vi.fn()
})
)
vi.mock('fs', async () => {
const actual = await vi.importActual<typeof Fs>('fs')
return {
...actual,
watch: watchMock
}
})
vi.mock('fs/promises', async () => {
const actual = await vi.importActual<typeof FsPromises>('fs/promises')
return {
...actual,
stat: statMock
}
})
vi.mock('@parcel/watcher', () => ({
subscribe: subscribeParcelWatcherMock
}))
vi.mock('../ipc/filesystem-auth', async () => {
const actual = await vi.importActual<typeof FilesystemAuth>('../ipc/filesystem-auth')
return {
...actual,
resolveAuthorizedPath: resolveAuthorizedPathMock
}
})
import { awaitRuntimeFileWatcherUnsubscribes, RuntimeFileCommands } from './orca-runtime-files'
function createRuntimeFileCommands(rootPath: string) {
const store = { getRepo: vi.fn(() => undefined) }
const commands = new RuntimeFileCommands({
getRuntimeId: () => 'runtime-1',
requireStore: () => store,
resolveWorktreeSelector: vi.fn(async () => ({
id: 'wt-1',
repoId: 'repo-1',
path: rootPath
})),
resolveRuntimeGitTarget: vi.fn(),
openFile: vi.fn()
} as never)
return { commands, store }
}
describe('RuntimeFileCommands file watching', () => {
const originalPlatform = process.platform
beforeEach(() => {
vi.useFakeTimers()
resolveAuthorizedPathMock.mockReset()
statMock.mockReset()
subscribeParcelWatcherMock.mockReset()
watchMock.mockReset()
Object.defineProperty(process, 'platform', {
configurable: true,
value: originalPlatform
})
})
afterEach(async () => {
await awaitRuntimeFileWatcherUnsubscribes()
Object.defineProperty(process, 'platform', {
configurable: true,
value: originalPlatform
})
vi.useRealTimers()
})
it('uses a conservative Node watcher for Windows runtime file watches', async () => {
Object.defineProperty(process, 'platform', {
configurable: true,
value: 'win32'
})
const close = vi.fn()
const on = vi.fn()
let listener: (() => void) | null = null
watchMock.mockImplementation((_rootPath, _options, callback) => {
listener = callback
return { close, on }
})
resolveAuthorizedPathMock.mockResolvedValue('C:\\repo')
statMock.mockResolvedValue({ isDirectory: () => true })
const { commands } = createRuntimeFileCommands('C:\\repo')
const onEvents = vi.fn()
const unsubscribe = await commands.watchFileExplorer('id:wt-1', onEvents)
expect(watchMock).toHaveBeenCalledWith('C:\\repo', { recursive: true }, expect.any(Function))
const emit = listener as (() => void) | null
expect(emit).not.toBeNull()
emit?.()
emit?.()
await vi.advanceTimersByTimeAsync(149)
expect(onEvents).not.toHaveBeenCalled()
await vi.advanceTimersByTimeAsync(1)
expect(onEvents).toHaveBeenCalledTimes(1)
expect(onEvents).toHaveBeenCalledWith([{ kind: 'overflow', absolutePath: 'C:\\repo' }])
unsubscribe()
expect(close).toHaveBeenCalledTimes(1)
})
it('tracks native Parcel watcher unsubscribe work so shutdown can await it', async () => {
resolveAuthorizedPathMock.mockResolvedValue('/repo')
statMock.mockResolvedValue({ isDirectory: () => true })
let resolveUnsubscribe: () => void = () => {}
const unsubscribeMock = vi.fn(
() =>
new Promise<void>((resolve) => {
resolveUnsubscribe = resolve
})
)
subscribeParcelWatcherMock.mockResolvedValue({ unsubscribe: unsubscribeMock })
const { commands } = createRuntimeFileCommands('/repo')
const unsubscribe = await commands.watchFileExplorer('id:wt-1', vi.fn())
unsubscribe()
let drained = false
const drainPromise = awaitRuntimeFileWatcherUnsubscribes().then(() => {
drained = true
})
await Promise.resolve()
expect(unsubscribeMock).toHaveBeenCalledTimes(1)
expect(drained).toBe(false)
resolveUnsubscribe()
await drainPromise
expect(drained).toBe(true)
})
})
@@ -239,95 +239,4 @@ describe('RuntimeFileCommands', () => {
)
expect(renameMock).not.toHaveBeenCalled()
})
it('uses a conservative Node watcher for Windows runtime file watches', async () => {
Object.defineProperty(process, 'platform', {
configurable: true,
value: 'win32'
})
const store = { getRepo: vi.fn(() => undefined) }
const close = vi.fn()
const on = vi.fn()
let listener: (() => void) | null = null
watchMock.mockImplementation((_rootPath, _options, callback) => {
listener = callback
return { close, on }
})
resolveAuthorizedPathMock.mockResolvedValue('C:\\repo')
statMock.mockResolvedValue({ isDirectory: () => true })
const commands = new RuntimeFileCommands({
getRuntimeId: () => 'runtime-1',
requireStore: () => store,
resolveWorktreeSelector: vi.fn(async () => ({
id: 'wt-1',
repoId: 'repo-1',
path: 'C:\\repo'
})),
resolveRuntimeGitTarget: vi.fn(),
openFile: vi.fn()
} as never)
const onEvents = vi.fn()
const unsubscribe = await commands.watchFileExplorer('id:wt-1', onEvents)
expect(watchMock).toHaveBeenCalledWith('C:\\repo', { recursive: true }, expect.any(Function))
const emit = listener as (() => void) | null
expect(emit).not.toBeNull()
emit?.()
emit?.()
await vi.advanceTimersByTimeAsync(149)
expect(onEvents).not.toHaveBeenCalled()
await vi.advanceTimersByTimeAsync(1)
expect(onEvents).toHaveBeenCalledTimes(1)
expect(onEvents).toHaveBeenCalledWith([{ kind: 'overflow', absolutePath: 'C:\\repo' }])
unsubscribe()
expect(close).toHaveBeenCalledTimes(1)
})
it('tracks native Parcel watcher unsubscribe work so shutdown can await it', async () => {
const store = { getRepo: vi.fn(() => undefined) }
resolveAuthorizedPathMock.mockResolvedValue('/repo')
statMock.mockResolvedValue({ isDirectory: () => true })
let resolveUnsubscribe: () => void = () => {}
const unsubscribeMock = vi.fn(
() =>
new Promise<void>((resolve) => {
resolveUnsubscribe = resolve
})
)
subscribeParcelWatcherMock.mockResolvedValue({ unsubscribe: unsubscribeMock })
const commands = new RuntimeFileCommands({
getRuntimeId: () => 'runtime-1',
requireStore: () => store,
resolveWorktreeSelector: vi.fn(async () => ({
id: 'wt-1',
repoId: 'repo-1',
path: '/repo'
})),
resolveRuntimeGitTarget: vi.fn(),
openFile: vi.fn()
} as never)
const unsubscribe = await commands.watchFileExplorer('id:wt-1', vi.fn())
unsubscribe()
let drained = false
const drainPromise = awaitRuntimeFileWatcherUnsubscribes().then(() => {
drained = true
})
await Promise.resolve()
expect(unsubscribeMock).toHaveBeenCalledTimes(1)
expect(drained).toBe(false)
resolveUnsubscribe()
await drainPromise
expect(drained).toBe(true)
})
})