Files
local-cal/tests/keyboard-shortcuts.test.ts
Dmytro Stanchiev 722c0f0f7d 🚸 feat: redesign AI toolbar with two-zone layout and HoverCard shortcuts popover
- Split composer into AI zone (primary accent) and data actions zone (neutral)
- Move Attach/Generate to labeled footer bar below textarea (left/right aligned)
- Add info icon with HoverCard (hover preview) + Popover (pinned click) showing identical keyboard shortcuts content using shadcn HoverCard to fix theme inconsistency vs Tooltip
- Expose imperative triggerRef on ImagePicker for keyboard shortcut access
- Wire TooltipProvider in root layout; install shadcn kbd and hover-card
- Unauthenticated state shows locked CTA with real sign-in button weight
- Add behavioral contract tests for footer bar, info trigger, and zone layout
2026-04-08 13:08:36 -04:00

138 lines
4.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, test } from "bun:test";
import {
SHORTCUT_DEFINITIONS,
resolveKeys,
} from "@/lib/keyboard-shortcuts";
// ---------------------------------------------------------------------------
// Keyboard shortcuts OS-aware key resolution
//
// Public interface under test: resolveKeys(modifiers, os) — a pure function
// that maps abstract modifier tokens to display glyphs based on the detected
// operating system.
//
// We test the pure function directly, no browser or DOM required.
// The React hook (useOs) is just a thin browser wrapper around the same
// detection logic and doesn't need separate unit tests.
// ---------------------------------------------------------------------------
describe("resolveKeys Mac", () => {
test("mod resolves to ⌘ on Mac", () => {
expect(resolveKeys(["mod"], "mac")).toEqual(["⌘"]);
});
test("shift resolves to ⇧ on Mac", () => {
expect(resolveKeys(["shift"], "mac")).toEqual(["⇧"]);
});
test("alt resolves to ⌥ on Mac", () => {
expect(resolveKeys(["alt"], "mac")).toEqual(["⌥"]);
});
test("enter resolves to ↵ on Mac", () => {
expect(resolveKeys(["enter"], "mac")).toEqual(["↵"]);
});
test("esc resolves to Esc on Mac", () => {
expect(resolveKeys(["esc"], "mac")).toEqual(["Esc"]);
});
test("combined mod+enter resolves correctly on Mac", () => {
expect(resolveKeys(["mod", "enter"], "mac")).toEqual(["⌘", "↵"]);
});
test("combined mod+shift+A resolves correctly on Mac", () => {
expect(resolveKeys(["mod", "shift", "A"], "mac")).toEqual(["⌘", "⇧", "A"]);
});
});
describe("resolveKeys Windows / Linux", () => {
test("mod resolves to Ctrl on non-Mac", () => {
expect(resolveKeys(["mod"], "other")).toEqual(["Ctrl"]);
});
test("shift resolves to Shift on non-Mac", () => {
expect(resolveKeys(["shift"], "other")).toEqual(["Shift"]);
});
test("alt resolves to Alt on non-Mac", () => {
expect(resolveKeys(["alt"], "other")).toEqual(["Alt"]);
});
test("enter resolves to Enter on non-Mac", () => {
expect(resolveKeys(["enter"], "other")).toEqual(["Enter"]);
});
test("esc resolves to Esc on non-Mac (same as Mac)", () => {
expect(resolveKeys(["esc"], "other")).toEqual(["Esc"]);
});
test("combined mod+enter resolves correctly on non-Mac", () => {
expect(resolveKeys(["mod", "enter"], "other")).toEqual(["Ctrl", "Enter"]);
});
test("combined mod+shift+A resolves correctly on non-Mac", () => {
expect(resolveKeys(["mod", "shift", "A"], "other")).toEqual(["Ctrl", "Shift", "A"]);
});
});
describe("resolveKeys unknown OS (SSR fallback)", () => {
test("unknown falls back to Mac glyphs (most users are Mac)", () => {
expect(resolveKeys(["mod"], "unknown")).toEqual(["⌘"]);
});
test("unknown enter fallback", () => {
expect(resolveKeys(["enter"], "unknown")).toEqual(["↵"]);
});
});
describe("resolveKeys passthrough for plain keys", () => {
test("plain letter A passes through unchanged on Mac", () => {
expect(resolveKeys(["A"], "mac")).toEqual(["A"]);
});
test("plain letter A passes through unchanged on non-Mac", () => {
expect(resolveKeys(["A"], "other")).toEqual(["A"]);
});
});
describe("SHORTCUT_DEFINITIONS schema contract", () => {
test("every definition has a non-empty modifiers array", () => {
for (const def of SHORTCUT_DEFINITIONS) {
expect(def.modifiers.length).toBeGreaterThan(0);
}
});
test("every definition has a non-empty label", () => {
for (const def of SHORTCUT_DEFINITIONS) {
expect(def.label.length).toBeGreaterThan(0);
}
});
test("Generate event shortcut exists and uses mod+enter", () => {
const gen = SHORTCUT_DEFINITIONS.find((d) =>
d.label.toLowerCase().includes("generate"),
);
expect(gen).toBeDefined();
expect(gen!.modifiers).toContain("mod");
expect(gen!.modifiers).toContain("enter");
});
test("Attach image shortcut exists and uses mod+shift", () => {
const attach = SHORTCUT_DEFINITIONS.find((d) =>
d.label.toLowerCase().includes("attach"),
);
expect(attach).toBeDefined();
expect(attach!.modifiers).toContain("mod");
expect(attach!.modifiers).toContain("shift");
});
test("Clear prompt shortcut exists and uses esc", () => {
const clear = SHORTCUT_DEFINITIONS.find((d) =>
d.label.toLowerCase().includes("clear"),
);
expect(clear).toBeDefined();
expect(clear!.modifiers).toContain("esc");
});
});