@@ -15,7 +15,7 @@ import { withTestRenderer } from "./harness";
1515import type { PaletteCommand } from "./command-catalog" ;
1616import { openCommandSurface , type CommandSurfaceDeps } from "./command-surfaces" ;
1717import { wireGates } from "./gate-wire" ;
18- import { openPermissionsOverlay } from "./overlays" ;
18+ import { openAddProviderOverlay , openPermissionsOverlay } from "./overlays" ;
1919import {
2020 acceptOverlaySelection ,
2121 closeInsetOverlay ,
@@ -29,6 +29,7 @@ import {
2929 openHelpOverlay ,
3030 openListOverlay ,
3131 openPalette ,
32+ reserveOverlayHost ,
3233 type AppShell ,
3334} from "./shell" ;
3435
@@ -882,6 +883,7 @@ describe("overlay host occupancy and opt-in deferral", () => {
882883 press ( "Escape" ) ;
883884 await render ( ) ;
884885 await Bun . sleep ( 60 ) ;
886+ expect ( isOverlayHostIdle ( shell ) ) . toBe ( true ) ;
885887 hanging . resolve ( ) ;
886888 await Promise . resolve ( ) ;
887889 await Promise . resolve ( ) ;
@@ -1017,4 +1019,68 @@ describe("overlay host occupancy and opt-in deferral", () => {
10171019 { onCommand : settingsOnCommand ( hanging . list ) } ,
10181020 ) ;
10191021 } ) ;
1022+
1023+ test ( "palette stacked over help then Enter /help leaves a single help overlay" , async ( ) => {
1024+ await withShell ( async ( { shell } ) => {
1025+ openHelpOverlay ( shell ) ;
1026+ expect ( shell . overlayKind ) . toBe ( "help" ) ;
1027+
1028+ openPalette ( shell , { catalog : CATALOG } ) ;
1029+ expect ( shell . overlayKind ) . toBe ( "palette" ) ;
1030+
1031+ acceptOverlaySelection ( shell ) ;
1032+ expect ( shell . overlayKind ) . toBe ( "help" ) ;
1033+ expect (
1034+ shell . streamLog . filter ( ( row ) => row . role === "system" && / w i l l o p e n / i. test ( row . text ) ) ,
1035+ ) . toHaveLength ( 0 ) ;
1036+
1037+ closeInsetOverlay ( shell ) ;
1038+ await Promise . resolve ( ) ;
1039+ expect ( shell . overlayList ) . toBeNull ( ) ;
1040+ } ) ;
1041+ } ) ;
1042+
1043+ test ( "add-provider while a live gate is up defers instead of denying the gate" , async ( ) => {
1044+ await withShell ( async ( { shell } ) => {
1045+ const emitter = new EventEmitter ( ) ;
1046+ const dispose = wireGates ( emitter , shell ) ;
1047+ try {
1048+ let resolved : unknown ;
1049+ emitPermissionGate ( emitter , ( outcome ) => {
1050+ resolved = outcome ;
1051+ } ) ;
1052+ expect ( shell . overlayKind ) . toBe ( "permissions" ) ;
1053+
1054+ openAddProviderOverlay ( shell , { items : [ "custom" ] , itemIds : [ "custom" ] } ) ;
1055+ expect ( shell . overlayKind ) . toBe ( "permissions" ) ;
1056+ expect ( resolved ) . toBeUndefined ( ) ;
1057+ expect (
1058+ shell . streamLog . some ( ( row ) => row . role === "system" && / w i l l o p e n / i. test ( row . text ) ) ,
1059+ ) . toBe ( true ) ;
1060+
1061+ closeInsetOverlay ( shell ) ;
1062+ await Promise . resolve ( ) ;
1063+ expect ( shell . overlayKind ) . toBe ( "add_provider" ) ;
1064+ expect ( resolved ) . not . toBeUndefined ( ) ;
1065+ } finally {
1066+ dispose ( ) ;
1067+ }
1068+ } ) ;
1069+ } ) ;
1070+
1071+ test ( "Esc during a host reservation idles the host" , async ( ) => {
1072+ await withShell ( async ( { shell, press, render } ) => {
1073+ const release = reserveOverlayHost ( shell ) ;
1074+ expect ( shell . overlayList ) . toBeNull ( ) ;
1075+ expect ( isOverlayHostIdle ( shell ) ) . toBe ( false ) ;
1076+
1077+ press ( "Escape" ) ;
1078+ await render ( ) ;
1079+ await Bun . sleep ( 60 ) ;
1080+ expect ( isOverlayHostIdle ( shell ) ) . toBe ( true ) ;
1081+
1082+ release ( ) ;
1083+ expect ( isOverlayHostIdle ( shell ) ) . toBe ( true ) ;
1084+ } ) ;
1085+ } ) ;
10201086} ) ;
0 commit comments