From 4afcc3810bdc483f8bd529a434035263c73882c6 Mon Sep 17 00:00:00 2001 From: creatixchu Date: Fri, 31 Jul 2026 17:57:10 +0800 Subject: [PATCH] test(ui-conversation): pin the settling exemption for summary-blank sessions The mount helper's 4th positional argument becomes an options object so a test can set the session list row's blank flag independently of the conversation snapshot's; the two new cases cover both branches of the settling condition. --- .../ui-conversation/tests/skeleton.spec.tsx | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/client/ui-conversation/tests/skeleton.spec.tsx b/packages/client/ui-conversation/tests/skeleton.spec.tsx index eeb8404fd5..1d98cfd6fa 100644 --- a/packages/client/ui-conversation/tests/skeleton.spec.tsx +++ b/packages/client/ui-conversation/tests/skeleton.spec.tsx @@ -80,15 +80,19 @@ function mount( snapshot: ConversationSnapshot, workspaceRows: WorkspaceView[] = [{ ...workspace('one'), sessionIds: [SID] }], retargetWorkspace = vi.fn(async (_workspaceId: WorkspaceId) => {}), - /** When true, mimic overlay:true chain siblings (hidden fallback + takeover). */ - overlayTakeover = false, + options: { + /** When true, mimic overlay:true chain siblings (hidden fallback + takeover). */ + overlayTakeover?: boolean + /** The session list summary's `blank` flag — independent of the snapshot's. */ + summaryBlank?: boolean + } = {}, ) { const root = sid('root') const sessions = createSnapshotStore({ ids: [root, SID], byId: { [root]: { id: root, displayTitle: 'Root', running: false, waitingApproval: false, blank: false, updatedAt: 1 }, - [SID]: { id: SID, displayTitle: 'Child', parentId: root, cwd: '/projects/one', running: false, waitingApproval: false, blank: false, updatedAt: 2 }, + [SID]: { id: SID, displayTitle: 'Child', parentId: root, cwd: '/projects/one', running: false, waitingApproval: false, blank: options.summaryBlank ?? false, updatedAt: 2 }, }, current: SID, phase: 'ready', @@ -167,7 +171,7 @@ function mount( return
}) as ConversationRootProps['renderSlot'] const renderSlotChain = ((_key, _owner, opts) => ( - overlayTakeover + options.overlayTakeover === true ? ( <>
@@ -229,7 +233,7 @@ describe('ConversationRoot resident composer', () => { }) it('sticky composer seat wraps the whole overlay chain, not only the fallback stack', () => { - const b = mount(conversationSnapshot(), undefined, undefined, true) + const b = mount(conversationSnapshot(), undefined, undefined, { overlayTakeover: true }) const seat = b.view.container.querySelector('[data-composer-seat]') const takeover = b.view.getByTestId('composer-takeover') const fallback = b.view.container.querySelector('[data-chain-overlay-fallback="conversation.composer"]') @@ -270,6 +274,28 @@ describe('ConversationRoot resident composer', () => { expect(b.view.getByText('Selected Folder')).toBeTruthy() }) + it('settling phase: a blank session with no list summary hides the composer while it opens', () => { + const b = mount(conversationSnapshot({ composerPhase: 'blank', blank: true, openState: 'loading' })) + const root = b.view.container.querySelector('[data-phase]') + expect(root?.getAttribute('data-phase')).toBe('settling') + expect(b.view.queryByText('开始构建吧')).toBeNull() + }) + + it('startup auto-selection: a summary-proven blank session opens straight into the hero', () => { + const b = mount( + conversationSnapshot({ composerPhase: 'blank', blank: true, openState: 'loading' }), + undefined, + undefined, + { summaryBlank: true }, + ) + // The summary already proves the outcome, so the settling hide would only + // blank the column for the history round-trip. + const root = b.view.container.querySelector('[data-phase]') + expect(root?.getAttribute('data-phase')).toBe('hero') + expect(b.view.getByText('开始构建吧')).toBeTruthy() + expect(b.view.getByRole('textbox')).toBeTruthy() + }) + it('same textarea DOM node survives the hero → active flip into the sticky scrollport', () => { const b = mount(conversationSnapshot({ composerPhase: 'blank', blank: true })) const before = b.view.getByRole('textbox')