@@ -11,12 +11,15 @@ import { ChatDatabase, EMPTY_CONVERSATION_LIST_ID } from './tools/chatDb/chatDb'
1111import { Tab } from './tools/chatDb/util'
1212import { ConversationItemGroup , OpenTabParams , OpenTabResult } from '@aws/language-server-runtimes-types'
1313import { InitializeParams } from '@aws/language-server-runtimes/protocol'
14+ import { ChatHistoryActionType } from '../../shared/telemetry/types'
15+ import { TelemetryService } from '../../shared/telemetry/telemetryService'
1416
1517describe ( 'TabBarController' , ( ) => {
1618 let testFeatures : TestFeatures
1719 let chatHistoryDb : ChatDatabase
1820 let tabBarController : TabBarController
1921 let clock : sinon . SinonFakeTimers
22+ let telemetryService : TelemetryService
2023
2124 beforeEach ( ( ) => {
2225 testFeatures = new TestFeatures ( )
@@ -29,9 +32,17 @@ describe('TabBarController', () => {
2932 setHistoryIdMapping : sinon . stub ( ) ,
3033 getOpenTabs : sinon . stub ( ) . returns ( [ ] ) ,
3134 updateTabOpenState : sinon . stub ( ) ,
35+ getDatabaseFileSize : sinon . stub ( ) ,
36+ getLoadTime : sinon . stub ( ) ,
3237 } as unknown as ChatDatabase
3338
34- tabBarController = new TabBarController ( testFeatures , chatHistoryDb )
39+ telemetryService = {
40+ emitChatHistoryAction : sinon . stub ( ) ,
41+ emitExportTab : sinon . stub ( ) ,
42+ emitLoadHistory : sinon . stub ( ) ,
43+ } as any
44+
45+ tabBarController = new TabBarController ( testFeatures , chatHistoryDb , telemetryService )
3546 clock = sinon . useFakeTimers ( )
3647 } )
3748
@@ -56,7 +67,7 @@ describe('TabBarController', () => {
5667
5768 it ( 'should perform debounced search when search filter is provided' , async ( ) => {
5869 const mockSearchResults = [ { id : 'result1' } ]
59- ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( mockSearchResults )
70+ ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( { results : mockSearchResults , searchTime : 100 } )
6071
6172 const promise = tabBarController . onListConversations ( { filter : { search : 'test query' } } )
6273
@@ -67,11 +78,26 @@ describe('TabBarController', () => {
6778
6879 assert . deepStrictEqual ( result . list , mockSearchResults )
6980 sinon . assert . calledWith ( chatHistoryDb . searchMessages as sinon . SinonStub , 'test query' )
81+ sinon . assert . calledWith ( telemetryService . emitChatHistoryAction as sinon . SinonStub , {
82+ action : ChatHistoryActionType . Search ,
83+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
84+ amazonQHistoryFileSize : undefined ,
85+ amazonqTimeToSearchHistory : 100 ,
86+ } )
7087 } )
7188
7289 it ( 'should clear previous timeout when multiple search requests are made' , async ( ) => {
7390 const clearTimeoutSpy = sinon . spy ( global , 'clearTimeout' )
7491
92+ // Setup mock return values for searchMessages
93+ const mockSearchResults1 = [ { id : 'result1' } ]
94+ const mockSearchResults2 = [ { id : 'result2' } ]
95+ ; ( chatHistoryDb . searchMessages as sinon . SinonStub )
96+ . onFirstCall ( )
97+ . returns ( { results : mockSearchResults1 , searchTime : 100 } )
98+ . onSecondCall ( )
99+ . returns ( { results : mockSearchResults2 , searchTime : 100 } )
100+
75101 // First search request
76102 const promise1 = tabBarController . onListConversations ( { filter : { search : 'first query' } } )
77103
@@ -158,7 +184,7 @@ describe('TabBarController', () => {
158184 items : [ { id : 'history1' } , { id : 'history2' } ] ,
159185 } ,
160186 ]
161- ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( mockSearchResults )
187+ ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( { results : mockSearchResults , searchTime : 100 } )
162188
163189 const promise = tabBarController . onListConversations ( {
164190 filter : {
@@ -186,7 +212,7 @@ describe('TabBarController', () => {
186212 const mockSearchResults : ConversationItemGroup [ ] = [
187213 { items : [ { id : 'empty' , description : 'No matches found' } ] } ,
188214 ]
189- ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( mockSearchResults )
215+ ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( { results : mockSearchResults , searchTime : 100 } )
190216
191217 const promise = tabBarController . onListConversations ( {
192218 filter : {
@@ -218,6 +244,10 @@ describe('TabBarController', () => {
218244 await tabBarController . onConversationClick ( { id : historyId } )
219245
220246 sinon . assert . calledWith ( openTabStub , { tabId : openTabId } )
247+ sinon . assert . calledWith ( telemetryService . emitChatHistoryAction as sinon . SinonStub , {
248+ action : ChatHistoryActionType . Open ,
249+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
250+ } )
221251 } )
222252
223253 it ( 'should restore tab when conversation is not already open' , async ( ) => {
@@ -242,6 +272,10 @@ describe('TabBarController', () => {
242272 const result = await tabBarController . onConversationClick ( { id : historyId , action : 'delete' } )
243273
244274 sinon . assert . calledWith ( chatHistoryDb . deleteHistory as sinon . SinonStub , historyId )
275+ sinon . assert . calledWith ( telemetryService . emitChatHistoryAction as sinon . SinonStub , {
276+ action : ChatHistoryActionType . Delete ,
277+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
278+ } )
245279 assert . strictEqual ( result . success , true )
246280 } )
247281
@@ -313,6 +347,12 @@ describe('TabBarController', () => {
313347 // Write serialized content to file
314348 sinon . assert . calledWith ( fsWriteFileStub , '/testworkspace/test.md' , 'Test Serialized Content' )
315349
350+ sinon . assert . calledWith ( telemetryService . emitChatHistoryAction as sinon . SinonStub , {
351+ action : ChatHistoryActionType . Export ,
352+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
353+ filenameExt : 'markdown' ,
354+ } )
355+
316356 assert . strictEqual ( result . success , true )
317357 } )
318358
@@ -381,6 +421,11 @@ describe('TabBarController', () => {
381421 // Write serialized content to file
382422 sinon . assert . calledWith ( fsWriteFileStub , '/testworkspace/test.md' , 'Test Serialized Content' )
383423
424+ sinon . assert . calledWith ( telemetryService . emitExportTab as sinon . SinonStub , {
425+ filenameExt : 'markdown' ,
426+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
427+ } )
428+
384429 assert . strictEqual ( result . success , true )
385430 } )
386431 } )
@@ -436,6 +481,12 @@ describe('TabBarController', () => {
436481 sinon . assert . calledTwice ( restoreTabStub )
437482 sinon . assert . calledWith ( restoreTabStub . firstCall , mockTabs [ 0 ] )
438483 sinon . assert . calledWith ( restoreTabStub . secondCall , mockTabs [ 1 ] )
484+ sinon . assert . calledWith ( telemetryService . emitLoadHistory as sinon . SinonStub , {
485+ openTabCount : 2 ,
486+ amazonqTimeToLoadHistory : - 1 ,
487+ amazonQHistoryFileSize : - 1 ,
488+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
489+ } )
439490 } )
440491
441492 it ( 'should only load chats once' , async ( ) => {
@@ -448,6 +499,13 @@ describe('TabBarController', () => {
448499 await tabBarController . loadChats ( ) // Second call should be ignored
449500
450501 sinon . assert . calledOnce ( restoreTabStub )
502+ sinon . assert . calledOnce ( telemetryService . emitLoadHistory as sinon . SinonStub )
503+ sinon . assert . calledWith ( telemetryService . emitLoadHistory as sinon . SinonStub , {
504+ openTabCount : 1 ,
505+ amazonqTimeToLoadHistory : - 1 ,
506+ amazonQHistoryFileSize : - 1 ,
507+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
508+ } )
451509 } )
452510
453511 it ( 'should not restore tabs with empty conversations' , async ( ) => {
0 commit comments