@@ -1361,4 +1361,125 @@ describe('agent workspace runtime behavior', () => {
13611361 const messages = document . getElementById ( 'agent-workspace-messages' ) as HTMLElement ;
13621362 expect ( messages . textContent || '' ) . toContain ( 'read' ) ;
13631363 } ) ;
1364+
1365+ test ( 're-renders pane labels and capability cards on language change' , async ( ) => {
1366+ let language = 'en' ;
1367+ const languageListeners : Array < ( ) => void > = [ ] ;
1368+ const dictionaries : Record < string , Record < string , string > > = {
1369+ en : {
1370+ 'agentWorkspace.placeholders.input' : 'Ask in English' ,
1371+ 'agentWorkspace.actions.pathFullscreen' : 'Path Fullscreen EN' ,
1372+ 'agentWorkspace.actions.exitPathFullscreen' : 'Exit Path Fullscreen EN' ,
1373+ 'agentWorkspace.messages.clickPointToFocus' : 'Click to focus EN' ,
1374+ 'agentWorkspace.labels.score' : 'Score EN' ,
1375+ 'agentWorkspace.actions.openLearningPath' : 'Open Learning Path EN' ,
1376+ } ,
1377+ zh : {
1378+ 'agentWorkspace.placeholders.input' : '请用中文提问' ,
1379+ 'agentWorkspace.actions.pathFullscreen' : '路径全屏 ZH' ,
1380+ 'agentWorkspace.actions.exitPathFullscreen' : '退出路径全屏 ZH' ,
1381+ 'agentWorkspace.messages.clickPointToFocus' : '点击进入专注 ZH' ,
1382+ 'agentWorkspace.labels.score' : '分数 ZH' ,
1383+ 'agentWorkspace.actions.openLearningPath' : '打开学习路径 ZH' ,
1384+ } ,
1385+ } ;
1386+ const i18nMock = {
1387+ t : jest . fn ( ( key : string , params ?: Record < string , unknown > ) => {
1388+ const template = dictionaries [ language ] ?. [ key ] ;
1389+ if ( ! template ) {
1390+ return key ;
1391+ }
1392+ return template . replace ( / \{ ( \w + ) \} / g, ( _match , token ) => {
1393+ const value = params && Object . prototype . hasOwnProperty . call ( params , token )
1394+ ? params [ token ]
1395+ : '' ;
1396+ return value == null ? '' : String ( value ) ;
1397+ } ) ;
1398+ } ) ,
1399+ onLanguageChange : jest . fn ( ( listener : ( ) => void ) => {
1400+ languageListeners . push ( listener ) ;
1401+ } ) ,
1402+ } ;
1403+ ( global as unknown as Record < string , unknown > ) . i18n = i18nMock ;
1404+ ( ( global as unknown as { window : { i18n ?: unknown } } ) . window ) . i18n = i18nMock ;
1405+
1406+ const fetchMock = jest . fn ( ) . mockResolvedValue ( {
1407+ ok : true ,
1408+ status : 200 ,
1409+ json : async ( ) => ( {
1410+ success : true ,
1411+ result : {
1412+ userId : 'agent_user_default' ,
1413+ message : 'Found 1 local knowledge point(s).' ,
1414+ knowledgePoints : [
1415+ {
1416+ atomId : 'atom-i18n-1' ,
1417+ title : 'I18N Candidate' ,
1418+ snippet : 'Language rerender coverage.' ,
1419+ score : 0.905 ,
1420+ capabilities : [
1421+ {
1422+ actionId : 'open_learning_path' ,
1423+ label : 'Learning Path' ,
1424+ labelKey : 'agentWorkspace.actions.openLearningPath' ,
1425+ request : {
1426+ userId : 'agent_user_default' ,
1427+ atomId : 'atom-i18n-1' ,
1428+ } ,
1429+ execution : {
1430+ kind : 'knowledge_operation' ,
1431+ operationId : 'build_learning_path' ,
1432+ resultPresentation : 'learning_path_card' ,
1433+ } ,
1434+ } ,
1435+ ] ,
1436+ } ,
1437+ ] ,
1438+ } ,
1439+ } ) ,
1440+ } ) ;
1441+ ( global as unknown as Record < string , unknown > ) . fetch = fetchMock ;
1442+
1443+ const runtime = runtimeModule . createAgentWorkspaceRuntime ( { defaultUserId : 'agent_user_default' } ) ;
1444+ runtime . init ( ) ;
1445+ expect ( i18nMock . onLanguageChange ) . toHaveBeenCalledTimes ( 1 ) ;
1446+
1447+ const input = document . getElementById ( 'agent-workspace-input' ) as HTMLTextAreaElement ;
1448+ const form = document . getElementById ( 'agent-workspace-form' ) as HTMLFormElement ;
1449+ input . value = 'language rerender' ;
1450+ form . dispatchEvent ( new dom ! . window . Event ( 'submit' , { bubbles : true , cancelable : true } ) ) ;
1451+ await flushAsync ( ) ;
1452+
1453+ runtime . openLearningPathDock ( 'atom-i18n-1' ) ;
1454+ await flushAsync ( ) ;
1455+
1456+ const pathFullscreenButton = document . getElementById ( 'agent-workspace-path-fullscreen' ) as HTMLButtonElement ;
1457+ expect ( input . placeholder ) . toBe ( 'Ask in English' ) ;
1458+ expect ( pathFullscreenButton . textContent ) . toBe ( 'Path Fullscreen EN' ) ;
1459+ runtime . togglePathFullscreen ( ) ;
1460+ expect ( pathFullscreenButton . textContent ) . toBe ( 'Exit Path Fullscreen EN' ) ;
1461+
1462+ const pointCardEn = document . querySelector ( '.agent-workspace-point-card' ) as HTMLElement ;
1463+ const pointMetaEn = document . querySelector ( '.agent-workspace-point-meta' ) as HTMLElement ;
1464+ const actionButtonEn = document . querySelector ( '.agent-workspace-action-button' ) as HTMLButtonElement ;
1465+ expect ( pointCardEn . title ) . toBe ( 'Click to focus EN' ) ;
1466+ expect ( pointMetaEn . textContent || '' ) . toContain ( 'Score EN: 0.905' ) ;
1467+ expect ( actionButtonEn . textContent ) . toBe ( 'Open Learning Path EN' ) ;
1468+
1469+ language = 'zh' ;
1470+ languageListeners . forEach ( ( listener ) => listener ( ) ) ;
1471+ await flushAsync ( ) ;
1472+
1473+ const pointCardZh = document . querySelector ( '.agent-workspace-point-card' ) as HTMLElement ;
1474+ const pointMetaZh = document . querySelector ( '.agent-workspace-point-meta' ) as HTMLElement ;
1475+ const actionButtonZh = document . querySelector ( '.agent-workspace-action-button' ) as HTMLButtonElement ;
1476+ expect ( input . placeholder ) . toBe ( '请用中文提问' ) ;
1477+ expect ( pathFullscreenButton . textContent ) . toBe ( '退出路径全屏 ZH' ) ;
1478+ expect ( pointCardZh . title ) . toBe ( '点击进入专注 ZH' ) ;
1479+ expect ( pointMetaZh . textContent || '' ) . toContain ( '分数 ZH: 0.905' ) ;
1480+ expect ( actionButtonZh . textContent ) . toBe ( '打开学习路径 ZH' ) ;
1481+
1482+ runtime . togglePathFullscreen ( ) ;
1483+ expect ( pathFullscreenButton . textContent ) . toBe ( '路径全屏 ZH' ) ;
1484+ } ) ;
13641485} ) ;
0 commit comments