@@ -6,7 +6,8 @@ import { DEVFRAME_EVENTS } from 'devframe/constants'
66import { createEventEmitter } from 'devframe/utils/events'
77import { createSharedState } from 'devframe/utils/shared-state'
88import { describe , expect , it , vi } from 'vitest'
9- import { nextTick , ref } from 'vue'
9+ import { createRenderer , nextTick , ref , ssrContextKey } from 'vue'
10+ import DockStandalone from '../components/dock/DockStandalone.vue'
1011import { createDocksContext } from './context'
1112import { executeSetupScript } from './setup-script'
1213
@@ -430,3 +431,88 @@ describe('dock group command activation', () => {
430431 ] )
431432 } )
432433} )
434+
435+ describe ( 'standalone initial dock' , ( ) => {
436+ /** Mount the real component setup without rendering its unrelated dock panels or creating browser iframes. */
437+ const renderer = createRenderer < object , object > ( {
438+ createElement : ( ) => ( { } ) ,
439+ createText : ( ) => ( { } ) ,
440+ createComment : ( ) => ( { } ) ,
441+ insert : vi . fn ( ) ,
442+ remove : vi . fn ( ) ,
443+ setText : vi . fn ( ) ,
444+ setElementText : vi . fn ( ) ,
445+ parentNode : ( ) => null ,
446+ nextSibling : ( ) => null ,
447+ patchProp : vi . fn ( ) ,
448+ } )
449+
450+ async function fixture ( entries : DevframeDockEntry [ ] ) {
451+ const { rpc, sharedStates, trust } = createStubRpc ( )
452+ const context = await createDocksContext ( 'standalone' , rpc )
453+ sharedStates . get ( HUB_EVENTS . sharedState . docks ) ! . push ( entries )
454+ const switchEntry = vi . spyOn ( context . docks , 'switchEntry' )
455+ const component = renderer . createApp ( { ...DockStandalone , render : ( ) => null } , { context } )
456+ component . provide ( ssrContextKey , { } )
457+ component . mount ( { } )
458+ return {
459+ context,
460+ stop : ( ) => component . unmount ( ) ,
461+ switchEntry,
462+ async connect ( ) {
463+ trust ( )
464+ await flushRestore ( )
465+ } ,
466+ async publish ( next : DevframeDockEntry [ ] ) {
467+ sharedStates . get ( HUB_EVENTS . sharedState . docks ) ! . push ( next )
468+ await flushRestore ( )
469+ } ,
470+ }
471+ }
472+
473+ it ( 'skips a hidden wrapper and activates the first visible dock through its client script' , async ( ) => {
474+ expect . assertions ( 4 )
475+ const { context, connect, stop, switchEntry } = await fixture ( [
476+ { id : 'wrapper' , title : 'Wrapper' , icon : 'ph:box' , type : 'iframe' , url : '/devframe/' , when : 'false' } ,
477+ gitEntry ,
478+ ] )
479+ expect ( context . docks . selectedId ) . toBeNull ( )
480+ await connect ( )
481+ expect ( context . docks . selectedId ) . toBe ( 'git' )
482+ expect ( switchEntry ) . toHaveBeenCalledWith ( 'git' )
483+ expect ( executeSetupScript ) . toHaveBeenCalledWith ( gitEntry , expect . anything ( ) )
484+ stop ( )
485+ } )
486+
487+ it ( 'waits for an eligible entry without running actions or selecting a built-in fallback' , async ( ) => {
488+ expect . assertions ( 2 )
489+ const { context, connect, publish, stop } = await fixture ( [
490+ { id : 'command' , title : 'Command' , icon : 'ph:play' , type : 'action' , action : { importFrom : '/command.js' } } ,
491+ ] )
492+ await connect ( )
493+ expect ( context . docks . selectedId ) . toBeNull ( )
494+ await publish ( [ gitEntry ] )
495+ expect ( context . docks . selectedId ) . toBe ( 'git' )
496+ stop ( )
497+ } )
498+
499+ it ( 'keeps an existing selection when the catalog changes' , async ( ) => {
500+ expect . assertions ( 1 )
501+ const { context, connect, publish, stop } = await fixture ( [ gitEntry ] )
502+ await connect ( )
503+ await publish ( [ { ...gitEntry , id : 'new-first' } , gitEntry ] )
504+ expect ( context . docks . selectedId ) . toBe ( 'git' )
505+ stop ( )
506+ } )
507+
508+ it ( 'uses normal group routing to open a visible member' , async ( ) => {
509+ expect . assertions ( 1 )
510+ const { context, connect, stop } = await fixture ( [
511+ { id : 'tools' , title : 'Tools' , icon : 'ph:folder' , type : 'group' } ,
512+ { ...gitEntry , groupId : 'tools' } ,
513+ ] )
514+ await connect ( )
515+ expect ( context . docks . selectedId ) . toBe ( 'git' )
516+ stop ( )
517+ } )
518+ } )
0 commit comments