@@ -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,27 @@ 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+ result : 'Succeeded' ,
87+ } )
7088 } )
7189
7290 it ( 'should clear previous timeout when multiple search requests are made' , async ( ) => {
7391 const clearTimeoutSpy = sinon . spy ( global , 'clearTimeout' )
7492
93+ // Setup mock return values for searchMessages
94+ const mockSearchResults1 = [ { id : 'result1' } ]
95+ const mockSearchResults2 = [ { id : 'result2' } ]
96+ ; ( chatHistoryDb . searchMessages as sinon . SinonStub )
97+ . onFirstCall ( )
98+ . returns ( { results : mockSearchResults1 , searchTime : 100 } )
99+ . onSecondCall ( )
100+ . returns ( { results : mockSearchResults2 , searchTime : 100 } )
101+
75102 // First search request
76103 const promise1 = tabBarController . onListConversations ( { filter : { search : 'first query' } } )
77104
@@ -158,7 +185,7 @@ describe('TabBarController', () => {
158185 items : [ { id : 'history1' } , { id : 'history2' } ] ,
159186 } ,
160187 ]
161- ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( mockSearchResults )
188+ ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( { results : mockSearchResults , searchTime : 100 } )
162189
163190 const promise = tabBarController . onListConversations ( {
164191 filter : {
@@ -186,7 +213,7 @@ describe('TabBarController', () => {
186213 const mockSearchResults : ConversationItemGroup [ ] = [
187214 { items : [ { id : 'empty' , description : 'No matches found' } ] } ,
188215 ]
189- ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( mockSearchResults )
216+ ; ( chatHistoryDb . searchMessages as sinon . SinonStub ) . returns ( { results : mockSearchResults , searchTime : 100 } )
190217
191218 const promise = tabBarController . onListConversations ( {
192219 filter : {
@@ -218,6 +245,11 @@ describe('TabBarController', () => {
218245 await tabBarController . onConversationClick ( { id : historyId } )
219246
220247 sinon . assert . calledWith ( openTabStub , { tabId : openTabId } )
248+ sinon . assert . calledWith ( telemetryService . emitChatHistoryAction as sinon . SinonStub , {
249+ action : ChatHistoryActionType . Open ,
250+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
251+ result : 'Succeeded' ,
252+ } )
221253 } )
222254
223255 it ( 'should restore tab when conversation is not already open' , async ( ) => {
@@ -242,6 +274,11 @@ describe('TabBarController', () => {
242274 const result = await tabBarController . onConversationClick ( { id : historyId , action : 'delete' } )
243275
244276 sinon . assert . calledWith ( chatHistoryDb . deleteHistory as sinon . SinonStub , historyId )
277+ sinon . assert . calledWith ( telemetryService . emitChatHistoryAction as sinon . SinonStub , {
278+ action : ChatHistoryActionType . Delete ,
279+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
280+ result : 'Succeeded' ,
281+ } )
245282 assert . strictEqual ( result . success , true )
246283 } )
247284
@@ -313,6 +350,13 @@ describe('TabBarController', () => {
313350 // Write serialized content to file
314351 sinon . assert . calledWith ( fsWriteFileStub , '/testworkspace/test.md' , 'Test Serialized Content' )
315352
353+ sinon . assert . calledWith ( telemetryService . emitChatHistoryAction as sinon . SinonStub , {
354+ action : ChatHistoryActionType . Export ,
355+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
356+ filenameExt : 'markdown' ,
357+ result : 'Succeeded' ,
358+ } )
359+
316360 assert . strictEqual ( result . success , true )
317361 } )
318362
@@ -381,6 +425,12 @@ describe('TabBarController', () => {
381425 // Write serialized content to file
382426 sinon . assert . calledWith ( fsWriteFileStub , '/testworkspace/test.md' , 'Test Serialized Content' )
383427
428+ sinon . assert . calledWith ( telemetryService . emitExportTab as sinon . SinonStub , {
429+ filenameExt : 'markdown' ,
430+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
431+ result : 'Succeeded' ,
432+ } )
433+
384434 assert . strictEqual ( result . success , true )
385435 } )
386436 } )
@@ -436,6 +486,13 @@ describe('TabBarController', () => {
436486 sinon . assert . calledTwice ( restoreTabStub )
437487 sinon . assert . calledWith ( restoreTabStub . firstCall , mockTabs [ 0 ] )
438488 sinon . assert . calledWith ( restoreTabStub . secondCall , mockTabs [ 1 ] )
489+ sinon . assert . calledWith ( telemetryService . emitLoadHistory as sinon . SinonStub , {
490+ openTabCount : 2 ,
491+ amazonqTimeToLoadHistory : - 1 ,
492+ amazonqHistoryFileSize : - 1 ,
493+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
494+ result : 'Succeeded' ,
495+ } )
439496 } )
440497
441498 it ( 'should only load chats once' , async ( ) => {
@@ -448,6 +505,14 @@ describe('TabBarController', () => {
448505 await tabBarController . loadChats ( ) // Second call should be ignored
449506
450507 sinon . assert . calledOnce ( restoreTabStub )
508+ sinon . assert . calledOnce ( telemetryService . emitLoadHistory as sinon . SinonStub )
509+ sinon . assert . calledWith ( telemetryService . emitLoadHistory as sinon . SinonStub , {
510+ openTabCount : 1 ,
511+ amazonqTimeToLoadHistory : - 1 ,
512+ amazonqHistoryFileSize : - 1 ,
513+ languageServerVersion : testFeatures . runtime . serverInfo . version ,
514+ result : 'Succeeded' ,
515+ } )
451516 } )
452517
453518 it ( 'should not restore tabs with empty conversations' , async ( ) => {
0 commit comments