From 9f23597e5302d455207939f3b597804c32e92acb Mon Sep 17 00:00:00 2001 From: Dmytro Stanchiev Date: Wed, 22 Apr 2026 17:58:14 -0400 Subject: [PATCH] test(ai-toolbar): cover paste gating behavior --- src/components/ai-toolbar.tsx | 26 +++++++++++++++++- tests/ai-toolbar.test.ts | 51 ++++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/components/ai-toolbar.tsx b/src/components/ai-toolbar.tsx index fde82eb..5f9da1d 100644 --- a/src/components/ai-toolbar.tsx +++ b/src/components/ai-toolbar.tsx @@ -94,6 +94,22 @@ interface AIToolbarProps { events: CalendarEvent[]; } +interface GlobalPasteCaptureGate { + isAuthenticated: boolean; + isPending: boolean; + canUseAi: boolean; + aiLoading: boolean; +} + +export function shouldEnableGlobalPasteCapture({ + isAuthenticated, + isPending, + canUseAi, + aiLoading, +}: GlobalPasteCaptureGate): boolean { + return isAuthenticated && !isPending && canUseAi && !aiLoading; +} + // ─── Component ──────────────────────────────────────────────────────────────── export const AIToolbar = ({ @@ -154,7 +170,15 @@ export const AIToolbar = ({ // focused element or OS clipboard model (X11/Wayland). // This is the approach used by Excalidraw's actionPaste. useEffect(() => { - if (!isAuthenticated || isPending || !canUseAi || aiLoading) return; + if ( + !shouldEnableGlobalPasteCapture({ + isAuthenticated, + isPending, + canUseAi, + aiLoading, + }) + ) + return; // ── Handler 1: paste event (works when textarea is NOT focused) ─────── const handleDocumentPaste = (e: ClipboardEvent) => { diff --git a/tests/ai-toolbar.test.ts b/tests/ai-toolbar.test.ts index 819c3e0..dbc09a0 100644 --- a/tests/ai-toolbar.test.ts +++ b/tests/ai-toolbar.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; +import { shouldEnableGlobalPasteCapture } from "@/components/ai-toolbar"; import { buttonVariants } from "@/components/ui/button"; import { getAiDisabledMessage } from "@/lib/ai-feature-flags"; import { cn } from "@/lib/utils"; @@ -325,14 +326,50 @@ describe("Keyboard shortcuts – toolbar integration contract", () => { describe("Global paste capture – AI availability gate", () => { test("document-level paste handlers only arm when AI is actually usable", () => { - const source = readToolbarSource(); + expect( + shouldEnableGlobalPasteCapture({ + isAuthenticated: true, + isPending: false, + canUseAi: true, + aiLoading: false, + }), + ).toBe(true); - expect(source).toContain( - "if (!isAuthenticated || isPending || !canUseAi || aiLoading) return;", - ); - expect(source).toContain( - "}, [isAuthenticated, isPending, canUseAi, aiLoading]);", - ); + expect( + shouldEnableGlobalPasteCapture({ + isAuthenticated: false, + isPending: false, + canUseAi: true, + aiLoading: false, + }), + ).toBe(false); + + expect( + shouldEnableGlobalPasteCapture({ + isAuthenticated: true, + isPending: true, + canUseAi: true, + aiLoading: false, + }), + ).toBe(false); + + expect( + shouldEnableGlobalPasteCapture({ + isAuthenticated: true, + isPending: false, + canUseAi: false, + aiLoading: false, + }), + ).toBe(false); + + expect( + shouldEnableGlobalPasteCapture({ + isAuthenticated: true, + isPending: false, + canUseAi: true, + aiLoading: true, + }), + ).toBe(false); }); });