import { renderToStaticMarkup } from 'react-dom/server'; import { describe, expect, it, vi } from 'vitest'; import { FileWorkspace, scrollWorkspaceTabsWithWheel } from '../../src/components/FileWorkspace'; import { projectSplitClassName } from '../../src/components/ProjectView'; describe('FileWorkspace upload input', () => { it('keeps the Design Files picker aligned with drag-and-drop file support', () => { const markup = renderToStaticMarkup( , ); expect(markup).toContain('data-testid="design-files-upload-input"'); expect(markup).not.toContain('accept='); }); it('keeps focus mode controls in the workspace tab bar', () => { const markup = renderToStaticMarkup( , ); expect(markup).toContain('data-testid="workspace-focus-toggle"'); expect(markup).toContain('Focus workspace'); }); it('keeps the focus mode action outside the horizontally scrollable tablist', () => { const markup = renderToStaticMarkup( , ); expect(markup).toContain('class="ws-tabs-shell"'); expect(markup).toContain('class="ws-tabs-actions"'); expect(markup).toMatch( /
]*>[\s\S]*?<\/div>
/, ); }); it('labels the same workspace control as chat restore while focused', () => { const markup = renderToStaticMarkup( , ); expect(markup).toContain('Show chat'); }); }); describe('projectSplitClassName', () => { it('marks the project split as focused so the chat pane can collapse globally', () => { expect(projectSplitClassName(false)).toBe('split'); expect(projectSplitClassName(true)).toBe('split split-focus'); }); }); describe('scrollWorkspaceTabsWithWheel', () => { function makeTabBar(scrollLeft: number, scrollWidth = 400, clientWidth = 200) { return { scrollLeft, scrollWidth, clientWidth } as HTMLDivElement; } function makeClampedTabBar(scrollLeft: number, scrollWidth = 400, clientWidth = 200) { let value = scrollLeft; return { scrollWidth, clientWidth, get scrollLeft() { return value; }, set scrollLeft(next: number) { value = Math.min(Math.max(next, 0), scrollWidth - clientWidth); }, } as HTMLDivElement; } it('maps vertical mouse wheel movement to horizontal tab scrolling', () => { const preventDefault = vi.fn(); const currentTarget = makeTabBar(12); const event = { ctrlKey: false, deltaMode: 0, deltaX: 0, deltaY: 40, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(52); expect(preventDefault).toHaveBeenCalledTimes(1); }); it('supports reverse vertical wheel movement', () => { const preventDefault = vi.fn(); const currentTarget = makeTabBar(52); const event = { ctrlKey: false, deltaMode: 0, deltaX: 0, deltaY: -40, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(12); expect(preventDefault).toHaveBeenCalledTimes(1); }); it('normalizes line-based wheel deltas to useful pixel movement', () => { const preventDefault = vi.fn(); const currentTarget = makeTabBar(12); const event = { ctrlKey: false, deltaMode: 1, deltaX: 0, deltaY: 3, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(60); expect(preventDefault).toHaveBeenCalledTimes(1); }); it('normalizes page-based wheel deltas to useful pixel movement', () => { const preventDefault = vi.fn(); const currentTarget = makeTabBar(12, 600, 200); const event = { ctrlKey: false, deltaMode: 2, deltaX: 0, deltaY: 1, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(172); expect(preventDefault).toHaveBeenCalledTimes(1); }); it('leaves native horizontal wheel gestures alone', () => { const preventDefault = vi.fn(); const currentTarget = makeTabBar(12); const event = { ctrlKey: false, deltaMode: 0, deltaX: 50, deltaY: 10, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(12); expect(preventDefault).not.toHaveBeenCalled(); }); it('leaves ctrl-wheel zoom gestures alone', () => { const preventDefault = vi.fn(); const currentTarget = makeTabBar(12); const event = { ctrlKey: true, deltaMode: 0, deltaX: 0, deltaY: 40, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(12); expect(preventDefault).not.toHaveBeenCalled(); }); it('does not intercept vertical wheel movement when tabs do not overflow', () => { const preventDefault = vi.fn(); const currentTarget = makeTabBar(12, 200, 200); const event = { ctrlKey: false, deltaMode: 0, deltaX: 0, deltaY: 40, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(12); expect(preventDefault).not.toHaveBeenCalled(); }); it('lets page scrolling continue when the tab bar is already at the wheel boundary', () => { const preventDefault = vi.fn(); const currentTarget = makeClampedTabBar(200, 400, 200); const event = { ctrlKey: false, deltaMode: 0, deltaX: 0, deltaY: 40, preventDefault, } as unknown as WheelEvent; scrollWorkspaceTabsWithWheel(currentTarget, event); expect(currentTarget.scrollLeft).toBe(200); expect(preventDefault).not.toHaveBeenCalled(); }); });