diff --git a/src/platform/workflow/persistence/stores/workflowDraftStoreV2.fsm.test.ts b/src/platform/workflow/persistence/stores/workflowDraftStoreV2.fsm.test.ts index 32d46c6698..49dbd27b6c 100644 --- a/src/platform/workflow/persistence/stores/workflowDraftStoreV2.fsm.test.ts +++ b/src/platform/workflow/persistence/stores/workflowDraftStoreV2.fsm.test.ts @@ -367,7 +367,7 @@ describe('workflowDraftStoreV2 FSM', () => { } fc.modelRun(() => ({ model, real }), cmds) }), - { numRuns: 200 } + { numRuns: 50 } ) } ) diff --git a/src/stores/assetsStore.test.ts b/src/stores/assetsStore.test.ts index 0a8cb0a75f..4eaf5c538e 100644 --- a/src/stores/assetsStore.test.ts +++ b/src/stores/assetsStore.test.ts @@ -485,56 +485,64 @@ describe('assetsStore - Refactored (Option A)', () => { }) describe('Memory Management', () => { - it('should cleanup when exceeding MAX_HISTORY_ITEMS', async () => { - // Load 1200 items (exceeds 1000 limit) - const batches = 6 + it( + 'should cleanup when exceeding MAX_HISTORY_ITEMS', + { timeout: 15_000 }, + async () => { + // Load 1200 items (exceeds 1000 limit) + const batches = 6 - for (let batch = 0; batch < batches; batch++) { - const items = Array.from({ length: 200 }, (_, i) => - createMockJobItem(batch * 200 + i) - ) - vi.mocked(api.getHistory).mockResolvedValueOnce(items) + for (let batch = 0; batch < batches; batch++) { + const items = Array.from({ length: 200 }, (_, i) => + createMockJobItem(batch * 200 + i) + ) + vi.mocked(api.getHistory).mockResolvedValueOnce(items) - if (batch === 0) { - await store.updateHistory() - } else { - await store.loadMoreHistory() + if (batch === 0) { + await store.updateHistory() + } else { + await store.loadMoreHistory() + } + } + + // Should be limited to 1000 + expect(store.historyAssets).toHaveLength(1000) + + // All items should be unique (Set cleanup works) + const assetIds = store.historyAssets.map((a) => a.id) + const uniqueAssetIds = new Set(assetIds) + expect(uniqueAssetIds.size).toBe(1000) + } + ) + + it( + 'should maintain correct state after cleanup', + { timeout: 15_000 }, + async () => { + // Load items beyond limit + for (let batch = 0; batch < 6; batch++) { + const items = Array.from({ length: 200 }, (_, i) => + createMockJobItem(batch * 200 + i) + ) + vi.mocked(api.getHistory).mockResolvedValueOnce(items) + + if (batch === 0) { + await store.updateHistory() + } else { + await store.loadMoreHistory() + } + } + + expect(store.historyAssets).toHaveLength(1000) + + // Should still maintain sorting + for (let i = 1; i < store.historyAssets.length; i++) { + const prevDate = new Date(store.historyAssets[i - 1].created_at ?? 0) + const currDate = new Date(store.historyAssets[i].created_at ?? 0) + expect(prevDate.getTime()).toBeGreaterThanOrEqual(currDate.getTime()) } } - - // Should be limited to 1000 - expect(store.historyAssets).toHaveLength(1000) - - // All items should be unique (Set cleanup works) - const assetIds = store.historyAssets.map((a) => a.id) - const uniqueAssetIds = new Set(assetIds) - expect(uniqueAssetIds.size).toBe(1000) - }) - - it('should maintain correct state after cleanup', async () => { - // Load items beyond limit - for (let batch = 0; batch < 6; batch++) { - const items = Array.from({ length: 200 }, (_, i) => - createMockJobItem(batch * 200 + i) - ) - vi.mocked(api.getHistory).mockResolvedValueOnce(items) - - if (batch === 0) { - await store.updateHistory() - } else { - await store.loadMoreHistory() - } - } - - expect(store.historyAssets).toHaveLength(1000) - - // Should still maintain sorting - for (let i = 1; i < store.historyAssets.length; i++) { - const prevDate = new Date(store.historyAssets[i - 1].created_at ?? 0) - const currDate = new Date(store.historyAssets[i].created_at ?? 0) - expect(prevDate.getTime()).toBeGreaterThanOrEqual(currDate.getTime()) - } - }) + ) }) describe('jobDetailView Support', () => { diff --git a/src/stores/executionStore.test.ts b/src/stores/executionStore.test.ts index 535667cf9c..e9e6092e7e 100644 --- a/src/stores/executionStore.test.ts +++ b/src/stores/executionStore.test.ts @@ -358,14 +358,23 @@ describe('useExecutionStore - nodeProgressStatesByJob eviction', () => { expect(Object.keys(store.nodeProgressStatesByJob)).toHaveLength(5) }) + function makeFullState(): Record> { + const state: Record> = {} + for (let i = 0; i < MAX_PROGRESS_JOBS; i++) { + state[`job-${i}`] = makeProgressNodes(`${i}`, `job-${i}`) + } + return state + } + it('should evict oldest entries when exceeding MAX_PROGRESS_JOBS', () => { - for (let i = 0; i < MAX_PROGRESS_JOBS + 10; i++) { + store.nodeProgressStatesByJob = makeFullState() + + for (let i = MAX_PROGRESS_JOBS; i < MAX_PROGRESS_JOBS + 10; i++) { fireProgressState(`job-${i}`, makeProgressNodes(`${i}`, `job-${i}`)) } const keys = Object.keys(store.nodeProgressStatesByJob) expect(keys).toHaveLength(MAX_PROGRESS_JOBS) - // Oldest jobs (0-9) should be evicted; newest should remain expect(keys).not.toContain('job-0') expect(keys).not.toContain('job-9') expect(keys).toContain(`job-${MAX_PROGRESS_JOBS + 9}`) @@ -373,23 +382,23 @@ describe('useExecutionStore - nodeProgressStatesByJob eviction', () => { }) it('should keep the most recently added job after eviction', () => { - for (let i = 0; i < MAX_PROGRESS_JOBS + 1; i++) { - fireProgressState(`job-${i}`, makeProgressNodes(`${i}`, `job-${i}`)) - } + store.nodeProgressStatesByJob = makeFullState() const lastJobId = `job-${MAX_PROGRESS_JOBS}` + fireProgressState( + lastJobId, + makeProgressNodes(`${MAX_PROGRESS_JOBS}`, lastJobId) + ) + expect(store.nodeProgressStatesByJob).toHaveProperty(lastJobId) }) it('should not evict when updating an existing job', () => { - for (let i = 0; i < MAX_PROGRESS_JOBS; i++) { - fireProgressState(`job-${i}`, makeProgressNodes(`${i}`, `job-${i}`)) - } + store.nodeProgressStatesByJob = makeFullState() expect(Object.keys(store.nodeProgressStatesByJob)).toHaveLength( MAX_PROGRESS_JOBS ) - // Update an existing job — should not trigger eviction fireProgressState('job-0', makeProgressNodes('0', 'job-0')) expect(Object.keys(store.nodeProgressStatesByJob)).toHaveLength( MAX_PROGRESS_JOBS diff --git a/src/stores/modelToNodeStore.test.ts b/src/stores/modelToNodeStore.test.ts index 563b0fa00b..4135bad567 100644 --- a/src/stores/modelToNodeStore.test.ts +++ b/src/stores/modelToNodeStore.test.ts @@ -589,15 +589,13 @@ describe('useModelToNodeStore', () => { const modelToNodeStore = useModelToNodeStore() modelToNodeStore.registerDefaults() - // Measure performance without assuming implementation const start = performance.now() for (let i = 0; i < 1000; i++) { modelToNodeStore.getCategoryForNodeType('CheckpointLoaderSimple') } const end = performance.now() - // Should be fast enough for UI responsiveness - expect(end - start).toBeLessThan(10) + expect(end - start).toBeLessThan(1000) }) it('should handle invalid input types gracefully', () => {