@@ -78,6 +78,7 @@ import {
7878 resolveSessionOptionGroups ,
7979 resolveSessionDisplayName ,
8080 switchChatSession ,
81+ switchChatSessionAndWait ,
8182} from "./app-render.helpers.ts" ;
8283import type { AppViewState } from "./app-view-state.ts" ;
8384import type { SessionsListResult } from "./types.ts" ;
@@ -964,6 +965,80 @@ describe("createChatSession", () => {
964965} ) ;
965966
966967describe ( "switchChatSession" , ( ) => {
968+ it ( "waits for the initial history and message subscription when requested" , async ( ) => {
969+ let resolveHistory ! : ( ) => void ;
970+ let resolveSubscription ! : ( ) => void ;
971+ const historyLoaded = new Promise < void > ( ( resolve ) => {
972+ resolveHistory = resolve ;
973+ } ) ;
974+ const subscriptionSynced = new Promise < void > ( ( resolve ) => {
975+ resolveSubscription = resolve ;
976+ } ) ;
977+ const settings = createSettings ( ) ;
978+ const state = {
979+ sessionKey : "main" ,
980+ chatMessage : "" ,
981+ chatAttachments : [ ] ,
982+ chatMessages : [ ] ,
983+ chatToolMessages : [ ] ,
984+ chatStreamSegments : [ ] ,
985+ chatThinkingLevel : null ,
986+ chatStream : null ,
987+ chatSideResult : null ,
988+ lastError : null ,
989+ compactionStatus : null ,
990+ fallbackStatus : null ,
991+ chatAvatarUrl : null ,
992+ chatQueue : [ ] ,
993+ chatQueueBySession : { } ,
994+ chatRunId : null ,
995+ sessionsShowArchived : false ,
996+ chatSideResultTerminalRuns : new Set < string > ( ) ,
997+ chatStreamStartedAt : null ,
998+ sessionsResult : {
999+ ts : 0 ,
1000+ path : "" ,
1001+ count : 2 ,
1002+ defaults : { modelProvider : "openai" , model : "gpt-5" , contextTokens : null } ,
1003+ sessions : [ row ( { key : "main" } ) , row ( { key : "agent:main:review" } ) ] ,
1004+ } ,
1005+ settings,
1006+ announceSessionSwitch : vi . fn ( ) ,
1007+ applySettings ( next : typeof settings ) {
1008+ state . settings = next ;
1009+ } ,
1010+ loadAssistantIdentity : vi . fn ( ) ,
1011+ resetToolStream : vi . fn ( ) ,
1012+ resetChatScroll : vi . fn ( ) ,
1013+ resetChatInputHistoryNavigation : vi . fn ( ) ,
1014+ } as unknown as AppViewState ;
1015+
1016+ refreshChatAvatarMock . mockResolvedValue ( undefined ) ;
1017+ refreshSlashCommandsMock . mockResolvedValue ( undefined ) ;
1018+ loadChatHistoryMock . mockReturnValue ( historyLoaded ) ;
1019+ syncSelectedSessionMessageSubscriptionMock . mockReturnValue ( subscriptionSynced ) ;
1020+ loadSessionsMock . mockResolvedValue ( undefined ) ;
1021+
1022+ const switched = switchChatSessionAndWait ( state , "agent:main:review" ) ;
1023+ let settled = false ;
1024+ void switched . then ( ( ) => {
1025+ settled = true ;
1026+ } ) ;
1027+
1028+ await Promise . resolve ( ) ;
1029+ expect ( settled ) . toBe ( false ) ;
1030+
1031+ resolveHistory ( ) ;
1032+ await Promise . resolve ( ) ;
1033+ expect ( settled ) . toBe ( false ) ;
1034+
1035+ resolveSubscription ( ) ;
1036+ await switched ;
1037+
1038+ expect ( settled ) . toBe ( true ) ;
1039+ expect ( state . sessionKey ) . toBe ( "agent:main:review" ) ;
1040+ } ) ;
1041+
9671042 it ( "refreshes the chat avatar after clearing session-scoped state" , async ( ) => {
9681043 const settings = createSettings ( ) ;
9691044 const state = {
0 commit comments