mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Merge pull request #198 from johndoe6345789/codex/add-unit-tests-for-autosyncmanager-ijr1r0
Export AutoSyncManager and add unit tests
This commit is contained in:
112
src/store/middleware/autoSyncMiddleware.test.ts
Normal file
112
src/store/middleware/autoSyncMiddleware.test.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { AutoSyncManager } from './autoSyncMiddleware'
|
||||
|
||||
const { syncToFlaskBulkMock } = vi.hoisted(() => ({
|
||||
syncToFlaskBulkMock: vi.fn(() => ({ type: 'sync/bulk' })),
|
||||
}))
|
||||
|
||||
vi.mock('../slices/syncSlice', () => ({
|
||||
syncToFlaskBulk: syncToFlaskBulkMock,
|
||||
checkFlaskConnection: vi.fn(() => ({ type: 'sync/check' })),
|
||||
}))
|
||||
|
||||
const nextTick = () => new Promise(resolve => setTimeout(resolve, 0))
|
||||
|
||||
const waitFor = async (assertion: () => void, attempts = 5) => {
|
||||
let lastError: unknown
|
||||
|
||||
for (let i = 0; i < attempts; i += 1) {
|
||||
await nextTick()
|
||||
|
||||
try {
|
||||
assertion()
|
||||
return
|
||||
} catch (error) {
|
||||
lastError = error
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError
|
||||
}
|
||||
|
||||
const createControlledPromise = () => {
|
||||
let resolve: () => void
|
||||
|
||||
const promise = new Promise<void>((resolvePromise) => {
|
||||
resolve = resolvePromise
|
||||
})
|
||||
|
||||
return {
|
||||
promise,
|
||||
resolve: resolve!,
|
||||
}
|
||||
}
|
||||
|
||||
describe('AutoSyncManager', () => {
|
||||
let manager: AutoSyncManager
|
||||
let dispatchMock: ReturnType<typeof vi.fn>
|
||||
|
||||
beforeEach(() => {
|
||||
manager = new AutoSyncManager()
|
||||
dispatchMock = vi.fn()
|
||||
manager.setDispatch(dispatchMock)
|
||||
syncToFlaskBulkMock.mockClear()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('serializes performSync calls', async () => {
|
||||
const firstSync = createControlledPromise()
|
||||
dispatchMock
|
||||
.mockReturnValueOnce(firstSync.promise)
|
||||
.mockResolvedValueOnce(undefined)
|
||||
|
||||
const firstRun = manager.syncNow()
|
||||
const secondRun = manager.syncNow()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(dispatchMock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
firstSync.resolve()
|
||||
await Promise.all([firstRun, secondRun])
|
||||
|
||||
expect(dispatchMock).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('resets changeCounter after a successful sync', async () => {
|
||||
dispatchMock.mockResolvedValue(undefined)
|
||||
|
||||
manager.trackChange()
|
||||
manager.trackChange()
|
||||
|
||||
await manager.syncNow()
|
||||
|
||||
expect(manager.getStatus().changeCounter).toBe(0)
|
||||
})
|
||||
|
||||
it('runs one pending sync after an in-flight sync finishes', async () => {
|
||||
const firstSync = createControlledPromise()
|
||||
dispatchMock
|
||||
.mockReturnValueOnce(firstSync.promise)
|
||||
.mockResolvedValueOnce(undefined)
|
||||
|
||||
const syncPromise = manager.syncNow()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(dispatchMock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
manager.trackChange()
|
||||
manager.trackChange()
|
||||
|
||||
firstSync.resolve()
|
||||
await syncPromise
|
||||
await waitFor(() => {
|
||||
expect(dispatchMock).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -10,7 +10,7 @@ interface AutoSyncConfig {
|
||||
maxQueueSize: number
|
||||
}
|
||||
|
||||
class AutoSyncManager {
|
||||
export class AutoSyncManager {
|
||||
private config: AutoSyncConfig = {
|
||||
enabled: false,
|
||||
intervalMs: 30000,
|
||||
|
||||
Reference in New Issue
Block a user