Path: blob/main/extensions/copilot/src/extension/conversationStore/node/conversationStore.spec.ts
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';6import { IChatSessionService } from '../../../platform/chat/common/chatSessionService';7import { Emitter } from '../../../util/vs/base/common/event';8import { Conversation, Turn } from '../../prompt/common/conversation';9import { ConversationStore } from './conversationStore';1011function createConversation(sessionId: string): Conversation {12return new Conversation(sessionId, [new Turn('turn-1', { message: 'test', type: 'user' })]);13}1415describe('ConversationStore', () => {16let disposeChatSession: Emitter<string>;17let store: ConversationStore;1819beforeEach(() => {20vi.useFakeTimers();21disposeChatSession = new Emitter<string>();22const chatSessionService: IChatSessionService = {23_serviceBrand: undefined,24onDidDisposeChatSession: disposeChatSession.event,25};26store = new ConversationStore(chatSessionService);27});2829afterEach(() => {30store.dispose();31disposeChatSession.dispose();32vi.useRealTimers();33});3435test('basic add and get', () => {36const conv = createConversation('session-1');37store.addConversation('resp-1', conv);38expect(store.getConversation('resp-1')).toBe(conv);39expect(store.lastConversation).toBe(conv);40});4142test('cleans up session conversations after timeout', () => {43const conv = createConversation('session-1');44store.addConversation('resp-1', conv);4546disposeChatSession.fire('session-1');4748vi.advanceTimersByTime(10 * 60 * 1000);49expect(store.getConversation('resp-1')).toBeUndefined();50});5152test('accessing conversation cancels cleanup', () => {53const conv = createConversation('session-1');54store.addConversation('resp-1', conv);5556disposeChatSession.fire('session-1');5758// Access before timeout — cancels cleanup entirely59vi.advanceTimersByTime(7 * 60 * 1000);60expect(store.getConversation('resp-1')).toBe(conv);6162// Advance well past the original timeout — should still exist63vi.advanceTimersByTime(30 * 60 * 1000);64expect(store.getConversation('resp-1')).toBe(conv);65});6667test('accessing lastConversation cancels cleanup', () => {68const conv = createConversation('session-1');69store.addConversation('resp-1', conv);7071disposeChatSession.fire('session-1');7273vi.advanceTimersByTime(7 * 60 * 1000);74expect(store.lastConversation).toBe(conv);7576vi.advanceTimersByTime(30 * 60 * 1000);77expect(store.lastConversation).toBe(conv);78});7980test('adding conversation for pending-cleanup session cancels cleanup', () => {81const conv1 = createConversation('session-1');82store.addConversation('resp-1', conv1);8384disposeChatSession.fire('session-1');85vi.advanceTimersByTime(7 * 60 * 1000);8687// Late write for the same session — cancels cleanup88const conv2 = createConversation('session-1');89store.addConversation('resp-2', conv2);9091// Advance well past the original timeout — both should survive92vi.advanceTimersByTime(30 * 60 * 1000);93expect(store.getConversation('resp-1')).toBe(conv1);94expect(store.getConversation('resp-2')).toBe(conv2);95});9697test('does not clean up sessions that were not disposed', () => {98const conv = createConversation('session-1');99store.addConversation('resp-1', conv);100101vi.advanceTimersByTime(30 * 60 * 1000);102expect(store.getConversation('resp-1')).toBe(conv);103});104105test('only cleans up the disposed session, not others', () => {106const conv1 = createConversation('session-1');107const conv2 = createConversation('session-2');108store.addConversation('resp-1', conv1);109store.addConversation('resp-2', conv2);110111disposeChatSession.fire('session-1');112vi.advanceTimersByTime(10 * 60 * 1000);113114expect(store.getConversation('resp-1')).toBeUndefined();115expect(store.getConversation('resp-2')).toBe(conv2);116});117});118119120