Files
fusion/packages/dashboard/app/utils/__tests__/mobileBarKeyboardFlags.test.ts
gsxdsm 869a4f77da FN-6329: prevent Quick Chat keyboard board shift
Keep the mobile board layout stable while Quick Chat owns the keyboard viewport.

- Treat fullscreen mobile overlays as suppressors for App-level footer hiding.
- Pass Quick Chat mobile open state into the shared keyboard flag helper.
- Cover iOS, Android, modal, and non-mobile keyboard flag behavior.
- Document the Quick Chat mobile keyboard board-shift root cause and fix.

Files changed:
 .../quick-chat-mobile-keyboard-board-shift.md      | 58 ++++++++++++++++++++++
 packages/dashboard/app/App.tsx                     |  4 +-
 .../utils/__tests__/mobileBarKeyboardFlags.test.ts | 57 ++++++++++++++++++++-
 .../dashboard/app/utils/mobileBarKeyboardFlags.ts  | 10 +++-
 4 files changed, 126 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-6329

Fusion-Task-Lineage: f7c37252-c0ea-44f0-b4e3-5aa2022cf7bc
2026-06-12 19:22:11 -07:00

129 lines
3.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { computeMobileBarKeyboardFlags } from "../mobileBarKeyboardFlags";
describe("computeMobileBarKeyboardFlags", () => {
it("keeps footer rendered and uncollapsed on Android when keyboard is open", () => {
const flags = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: true,
anyModalOpen: false,
overlayOpen: false,
isIOS: false,
});
expect(flags.footerKeyboardOpen).toBe(false);
expect(flags.footerHidden).toBe(false);
expect(flags.navKeyboardOpen).toBe(true);
});
it("hides and collapses footer on iOS when keyboard is open and no overlay is open", () => {
const flags = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: true,
anyModalOpen: false,
overlayOpen: false,
isIOS: true,
});
expect(flags.footerHidden).toBe(true);
expect(flags.navKeyboardOpen).toBe(true);
expect(flags.footerKeyboardOpen).toBe(true);
});
it("keeps footer visible when iOS keyboard is open over a modal", () => {
const flags = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: true,
anyModalOpen: true,
overlayOpen: false,
isIOS: true,
});
expect(flags.footerHidden).toBe(false);
expect(flags.footerKeyboardOpen).toBe(true);
expect(flags.navKeyboardOpen).toBe(true);
});
it("returns all false when keyboard is closed", () => {
const flags = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: false,
anyModalOpen: false,
overlayOpen: false,
isIOS: true,
});
expect(flags).toEqual({
footerHidden: false,
navKeyboardOpen: false,
footerKeyboardOpen: false,
});
});
it("returns all false when not mobile", () => {
const flags = computeMobileBarKeyboardFlags({
isMobile: false,
keyboardOpen: true,
anyModalOpen: false,
overlayOpen: false,
isIOS: true,
});
expect(flags).toEqual({
footerHidden: false,
navKeyboardOpen: false,
footerKeyboardOpen: false,
});
});
it("keeps the board footer visible on iOS when a fullscreen overlay owns the keyboard", () => {
const flags = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: true,
anyModalOpen: false,
overlayOpen: true,
isIOS: true,
});
expect(flags.footerHidden).toBe(false);
expect(flags.navKeyboardOpen).toBe(true);
expect(flags.footerKeyboardOpen).toBe(true);
});
it("keeps Android board-layout behavior unchanged when a fullscreen overlay owns the keyboard", () => {
const flags = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: true,
anyModalOpen: false,
overlayOpen: true,
isIOS: false,
});
expect(flags.footerHidden).toBe(false);
expect(flags.navKeyboardOpen).toBe(true);
expect(flags.footerKeyboardOpen).toBe(false);
});
it("suppresses the original iOS board-shift trigger only when the Quick Chat overlay flag is set", () => {
const originalBoardShiftTrigger = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: true,
anyModalOpen: false,
overlayOpen: false,
isIOS: true,
});
const quickChatOverlayKeyboard = computeMobileBarKeyboardFlags({
isMobile: true,
keyboardOpen: true,
anyModalOpen: false,
overlayOpen: true,
isIOS: true,
});
expect(originalBoardShiftTrigger.footerHidden).toBe(true);
expect(quickChatOverlayKeyboard.footerHidden).toBe(false);
expect(quickChatOverlayKeyboard.navKeyboardOpen).toBe(true);
expect(quickChatOverlayKeyboard.footerKeyboardOpen).toBe(true);
});
});