diff --git a/src/renderer/src/lib/pane-manager/mobile-fit-overrides.test.ts b/src/renderer/src/lib/pane-manager/mobile-fit-overrides.test.ts index a284b6b19b1..66a4cf4cf28 100644 --- a/src/renderer/src/lib/pane-manager/mobile-fit-overrides.test.ts +++ b/src/renderer/src/lib/pane-manager/mobile-fit-overrides.test.ts @@ -301,3 +301,109 @@ describe('getAllOverrides', () => { expect(getFitOverrideForPty('pty-1')).not.toBeNull() }) }) + +// --------------------------------------------------------------------------- +// Scenario tests (from design doc verification matrix) +// --------------------------------------------------------------------------- + +describe('scenario: desktop window resize while mobile is viewing', () => { + it('override persists across setFitOverride calls — desktop safeFit will see it', () => { + setFitOverride('pty-1', 'mobile-fit', 49, 20) + bindPanePtyId(1, 'pty-1', 'tab-0') + + // Simulate desktop resize triggering a re-check — override should still be there + expect(getFitOverrideForPty('pty-1')).toEqual({ mode: 'mobile-fit', cols: 49, rows: 20 }) + expect(getFitOverrideForPane(1, 'tab-0')).toEqual({ mode: 'mobile-fit', cols: 49, rows: 20 }) + }) +}) + +describe('scenario: mobile disconnect restores all terminals', () => { + it('clearing all overrides for a disconnected client removes all traces', () => { + setFitOverride('pty-1', 'mobile-fit', 49, 20) + setFitOverride('pty-2', 'mobile-fit', 49, 20) + bindPanePtyId(1, 'pty-1', 'tab-0') + bindPanePtyId(2, 'pty-2', 'tab-0') + + // Simulate runtime clearing overrides on disconnect + setFitOverride('pty-1', 'desktop-fit', 120, 40) + setFitOverride('pty-2', 'desktop-fit', 120, 40) + + expect(getFitOverrideForPty('pty-1')).toBeNull() + expect(getFitOverrideForPty('pty-2')).toBeNull() + expect(getFitOverrideForPane(1, 'tab-0')).toBeNull() + expect(getFitOverrideForPane(2, 'tab-0')).toBeNull() + }) +}) + +describe('scenario: PTY exits while phone-fitted', () => { + it('clearing override for exited PTY leaves no stale state', () => { + setFitOverride('pty-1', 'mobile-fit', 49, 20) + bindPanePtyId(1, 'pty-1', 'tab-0') + + // Runtime clears override on PTY exit + setFitOverride('pty-1', 'desktop-fit', 0, 0) + unbindPane(1, 'tab-0') + + expect(getFitOverrideForPty('pty-1')).toBeNull() + expect(getFitOverrideForPane(1, 'tab-0')).toBeNull() + expect(getPaneIdsForPty('pty-1')).toEqual([]) + expect(getAllOverrides().size).toBe(0) + }) +}) + +describe('scenario: mobile reconnects after disconnect', () => { + it('new override after clear works correctly', () => { + // First session + setFitOverride('pty-1', 'mobile-fit', 49, 20) + bindPanePtyId(1, 'pty-1', 'tab-0') + + // Disconnect + setFitOverride('pty-1', 'desktop-fit', 120, 40) + + // Reconnect — new session sets override again + setFitOverride('pty-1', 'mobile-fit', 55, 22) + + expect(getFitOverrideForPty('pty-1')).toEqual({ mode: 'mobile-fit', cols: 55, rows: 22 }) + expect(getFitOverrideForPane(1, 'tab-0')).toEqual({ mode: 'mobile-fit', cols: 55, rows: 22 }) + }) +}) + +describe('scenario: multiple tabs with same pane IDs', () => { + it('override on one tab does not affect the other', () => { + bindPanePtyId(1, 'pty-A', 'tab-0') + bindPanePtyId(1, 'pty-B', 'tab-1') + + setFitOverride('pty-A', 'mobile-fit', 49, 20) + + expect(getFitOverrideForPane(1, 'tab-0')?.cols).toBe(49) + expect(getFitOverrideForPane(1, 'tab-1')).toBeNull() + }) + + it('clearing override for one tab does not affect the other', () => { + bindPanePtyId(1, 'pty-A', 'tab-0') + bindPanePtyId(1, 'pty-B', 'tab-1') + + setFitOverride('pty-A', 'mobile-fit', 49, 20) + setFitOverride('pty-B', 'mobile-fit', 60, 25) + + // Clear only tab-0's PTY + setFitOverride('pty-A', 'desktop-fit', 120, 40) + + expect(getFitOverrideForPane(1, 'tab-0')).toBeNull() + expect(getFitOverrideForPane(1, 'tab-1')?.cols).toBe(60) + }) +}) + +describe('scenario: change listener fires for both override and restore', () => { + it('tracks full lifecycle: mobile-fit → desktop-fit', () => { + const events: { mode: string }[] = [] + const unsub = onOverrideChange((e) => events.push({ mode: e.mode })) + + setFitOverride('pty-1', 'mobile-fit', 49, 20) + setFitOverride('pty-1', 'desktop-fit', 120, 40) + + expect(events).toEqual([{ mode: 'mobile-fit' }, { mode: 'desktop-fit' }]) + + unsub() + }) +})