11// @vitest -environment jsdom
2- import { createElement , useCallback , useState } from "react" ;
2+ import { createElement } from "react" ;
33import { createRoot , type Root } from "react-dom/client" ;
44import { act } from "react-dom/test-utils" ;
55import { afterEach , describe , expect , it } from "vitest" ;
6- import { initialAgentMode , type DashboardAgentMode } from "./panel-layout" ;
6+ import { initialAgentMode , useAgentPanelMode , type DashboardAgentMode } from "./panel-layout" ;
77
88describe ( "initialAgentMode" , ( ) => {
99 it ( "opens in the account preference when one is set" , ( ) => {
@@ -16,13 +16,6 @@ describe("initialAgentMode", () => {
1616 } ) ;
1717} ) ;
1818
19- type HarnessHandle = {
20- mode : DashboardAgentMode ;
21- changeMode : ( mode : DashboardAgentMode ) => void ;
22- close : ( ) => void ;
23- reopen : ( ) => void ;
24- } ;
25-
2619let container : HTMLDivElement | undefined ;
2720let root : Root | undefined ;
2821
@@ -33,20 +26,13 @@ afterEach(() => {
3326 root = undefined ;
3427} ) ;
3528
36- // Mirrors DashboardAgent.tsx's own state shape: mode starts from the preference, an
37- // in-chat switch is transient (setMode only), and closing reverts to the preference —
38- // so the next open starts clean regardless of what the last session left it on.
39- function renderHarness ( preference : DashboardAgentMode | undefined ) {
40- let latest ! : HarnessHandle ;
29+ // Renders the real hook DashboardAgent.tsx uses for its mode state — not a re-implementation
30+ // — so a regression in the actual reset wiring fails this test.
31+ function renderAgentPanelMode ( preference : DashboardAgentMode | undefined ) {
32+ let latest ! : ReturnType < typeof useAgentPanelMode > ;
4133 function Harness ( ) {
42- const [ mode , setMode ] = useState < DashboardAgentMode > ( ( ) => initialAgentMode ( preference ) ) ;
43-
44- const changeMode = useCallback ( ( next : DashboardAgentMode ) => setMode ( next ) , [ ] ) ;
45- const close = useCallback ( ( ) => setMode ( initialAgentMode ( preference ) ) , [ ] ) ;
46- const reopen = useCallback ( ( ) => { } , [ ] ) ;
47-
48- // oxlint-disable-next-line react/globals -- test harness capturing the latest state/handlers.
49- latest = { mode, changeMode, close, reopen } ;
34+ // oxlint-disable-next-line react/globals -- test harness capturing the hook's return value.
35+ latest = useAgentPanelMode ( preference ) ;
5036 return null ;
5137 }
5238 container = document . createElement ( "div" ) ;
@@ -62,18 +48,37 @@ function renderHarness(preference: DashboardAgentMode | undefined) {
6248 } ;
6349}
6450
65- describe ( "a transient in-chat mode switch reverts on close" , ( ) => {
66- it ( "switching mode while open, then closing and reopening, lands back on the preference" , ( ) => {
67- const harness = renderHarness ( "rightPanel" ) ;
51+ describe ( "useAgentPanelMode" , ( ) => {
52+ it ( "starts from the account preference" , ( ) => {
53+ const hook = renderAgentPanelMode ( "rightPanel" ) ;
54+ expect ( hook . current . mode ) . toBe ( "rightPanel" ) ;
55+ } ) ;
56+
57+ it ( "defaults to floating when there is no preference" , ( ) => {
58+ const hook = renderAgentPanelMode ( undefined ) ;
59+ expect ( hook . current . mode ) . toBe ( "floating" ) ;
60+ } ) ;
61+
62+ it ( "a transient changeMode applies immediately but resetToPreference (the close path) reverts it" , ( ) => {
63+ const hook = renderAgentPanelMode ( "rightPanel" ) ;
6864
69- expect ( harness . current . mode ) . toBe ( "rightPanel" ) ;
65+ act ( ( ) => hook . current . changeMode ( "fullscreen" ) ) ;
66+ expect ( hook . current . mode ) . toBe ( "fullscreen" ) ;
67+
68+ // This is exactly what DashboardAgent.tsx's setPanelOpen calls on close.
69+ act ( ( ) => hook . current . resetToPreference ( ) ) ;
70+ expect ( hook . current . mode ) . toBe ( "rightPanel" ) ;
71+ } ) ;
7072
71- act ( ( ) => harness . current . changeMode ( " fullscreen" ) ) ;
72- expect ( harness . current . mode ) . toBe ( "fullscreen ") ;
73+ it ( "revertFullscreen (the pathname-change path) drops fullscreen but leaves other transient modes alone" , ( ) => {
74+ const hook = renderAgentPanelMode ( "floating ") ;
7375
74- act ( ( ) => harness . current . close ( ) ) ;
75- act ( ( ) => harness . current . reopen ( ) ) ;
76+ act ( ( ) => hook . current . changeMode ( "fullscreen" ) ) ;
77+ act ( ( ) => hook . current . revertFullscreen ( ) ) ;
78+ expect ( hook . current . mode ) . toBe ( "floating" ) ;
7679
77- expect ( harness . current . mode ) . toBe ( "rightPanel" ) ;
80+ act ( ( ) => hook . current . changeMode ( "rightPanel" ) ) ;
81+ act ( ( ) => hook . current . revertFullscreen ( ) ) ;
82+ expect ( hook . current . mode ) . toBe ( "rightPanel" ) ;
7883 } ) ;
7984} ) ;
0 commit comments