From df7daeb41dba2b610edee4c85571826318449406 Mon Sep 17 00:00:00 2001 From: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Date: Thu, 12 Nov 2026 16:54:05 -0800 Subject: [PATCH] test: remove low-value sidebar and prompt disclosure suites --- .../AutomationPromptDisclosure.test.tsx | 144 ------------------ .../sidebar-delete-repeat.perf.test.tsx | 72 --------- .../rows/folder-row-selection.perf.test.tsx | 136 ----------------- 3 files changed, 352 deletions(-) delete mode 100644 src/renderer/src/components/automations/details/AutomationPromptDisclosure.test.tsx delete mode 100644 src/renderer/src/components/sidebar/worktree-list/navigation/sidebar-delete-repeat.perf.test.tsx delete mode 100644 src/renderer/src/components/sidebar/worktree-list/rows/folder-row-selection.perf.test.tsx diff --git a/src/renderer/src/components/automations/details/AutomationPromptDisclosure.test.tsx b/src/renderer/src/components/automations/details/AutomationPromptDisclosure.test.tsx deleted file mode 100644 index 8f84b63df4e..00000000000 --- a/src/renderer/src/components/automations/details/AutomationPromptDisclosure.test.tsx +++ /dev/null @@ -1,144 +0,0 @@ -// @vitest-environment happy-dom -import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { TooltipProvider } from '@/components/ui/tooltip' -import { AutomationPromptDisclosure } from './AutomationPromptDisclosure' - -const END_MARKER = 'SYNTHETIC-END-MARKER' -const LONG_PROMPT = [ - 'Synthetic prompt preview validation only.', - '', - ...Array.from( - { length: 20 }, - (_, index) => - `Synthetic step ${index + 1}: inspect placeholder input and summarize placeholder output.` - ), - '', - END_MARKER -].join('\n') - -// Why: happy-dom has no layout, so the clamped paragraph's overflow is driven by these values. -const layout = { scrollHeight: 0, clientHeight: 0 } -const resizeCallbacks = new Set<() => void>() - -class ResizeObserverStub { - private readonly callback: () => void - constructor(callback: () => void) { - this.callback = callback - } - observe(): void { - resizeCallbacks.add(this.callback) - } - unobserve(): void {} - disconnect(): void { - resizeCallbacks.delete(this.callback) - } -} - -const writeClipboardText = vi.fn<(text: string) => Promise>() - -beforeEach(() => { - layout.scrollHeight = 0 - layout.clientHeight = 0 - vi.spyOn(HTMLElement.prototype, 'scrollHeight', 'get').mockImplementation( - () => layout.scrollHeight - ) - vi.spyOn(HTMLElement.prototype, 'clientHeight', 'get').mockImplementation( - () => layout.clientHeight - ) - vi.stubGlobal('ResizeObserver', ResizeObserverStub) - writeClipboardText.mockReset().mockResolvedValue(undefined) - Object.assign(window, { api: { ui: { writeClipboardText } } }) -}) - -afterEach(() => { - cleanup() - resizeCallbacks.clear() - vi.restoreAllMocks() - vi.unstubAllGlobals() -}) - -function renderPrompt(prompt: string): void { - render( - - - - ) -} - -function promptFor(toggle: HTMLElement): HTMLElement { - const id = toggle.getAttribute('aria-controls') - const element = id ? document.getElementById(id) : null - if (!element) { - throw new Error('Toggle does not control a prompt element') - } - return element -} - -describe('AutomationPromptDisclosure', () => { - it('shows a short prompt in full without an expand control', () => { - layout.scrollHeight = 40 - layout.clientHeight = 40 - renderPrompt('Synthetic short prompt.') - - expect(screen.getByText('Synthetic short prompt.')).toBeTruthy() - expect(screen.queryByRole('button', { name: 'Show more' })).toBeNull() - }) - - it('collapses a long prompt behind Show more and reveals all of it on expand', () => { - layout.scrollHeight = 600 - layout.clientHeight = 160 - renderPrompt(LONG_PROMPT) - - const showMore = screen.getByRole('button', { name: 'Show more' }) - expect(showMore.getAttribute('aria-expanded')).toBe('false') - const prompt = promptFor(showMore) - expect(prompt.textContent).toBe(LONG_PROMPT) - - showMore.focus() - fireEvent.click(showMore) - - const showLess = screen.getByRole('button', { name: 'Show less' }) - expect(showLess.getAttribute('aria-expanded')).toBe('true') - expect(document.activeElement).toBe(showLess) - expect(promptFor(showLess)).toBe(prompt) - expect(prompt.textContent).toContain(END_MARKER) - - fireEvent.click(showLess) - expect(screen.getByRole('button', { name: 'Show more' }).getAttribute('aria-expanded')).toBe( - 'false' - ) - }) - - it('drops the expand control and keeps focus on the prompt when it stops overflowing', () => { - layout.scrollHeight = 300 - layout.clientHeight = 160 - renderPrompt(`Synthetic resize focus validation. ${'placeholder '.repeat(48)}`) - - const showMore = screen.getByRole('button', { name: 'Show more' }) - const prompt = promptFor(showMore) - showMore.focus() - - layout.scrollHeight = 160 - act(() => { - for (const callback of resizeCallbacks) { - callback() - } - }) - - expect(screen.queryByRole('button', { name: 'Show more' })).toBeNull() - expect(document.activeElement).toBe(prompt) - }) - - it('copies the full prompt text', async () => { - layout.scrollHeight = 600 - layout.clientHeight = 160 - renderPrompt(LONG_PROMPT) - - fireEvent.click(screen.getByRole('button', { name: 'Copy prompt' })) - - expect(writeClipboardText).toHaveBeenCalledTimes(1) - expect(writeClipboardText).toHaveBeenCalledWith(LONG_PROMPT) - await waitFor(() => expect(screen.getByRole('button', { name: 'Copied' })).toBeTruthy()) - }) -}) diff --git a/src/renderer/src/components/sidebar/worktree-list/navigation/sidebar-delete-repeat.perf.test.tsx b/src/renderer/src/components/sidebar/worktree-list/navigation/sidebar-delete-repeat.perf.test.tsx deleted file mode 100644 index 62891b3514b..00000000000 --- a/src/renderer/src/components/sidebar/worktree-list/navigation/sidebar-delete-repeat.perf.test.tsx +++ /dev/null @@ -1,72 +0,0 @@ -// @vitest-environment happy-dom -import { act } from 'react' -import { createRoot } from 'react-dom/client' -import { expect, it, vi } from 'vitest' -import { createUIStore } from '@/store/slices/ui/ui-slice-test-harness' -import { useSidebarWorkspaceDeleteKeyboard } from './use-sidebar-workspace-delete-keyboard' -import { resolveSidebarWorkspaceDeleteIntent } from './sidebar-workspace-delete' -import { repo, worktree } from '../grouping/worktree-list-groups-test-fixtures' - -const store = createUIStore() -vi.mock('@/store', () => ({ useAppStore: { getState: () => store.getState() } })) -vi.mock('../../workspace-actions/deletion/delete-worktree-flow', () => ({ - runWorktreeDelete: vi.fn(), - runWorktreeBatchDelete: vi.fn() -})) -vi.mock('../../workspace-actions/deletion/folder-workspace-delete', () => ({ - deleteFolderWorkspaceUnlessUnsaved: vi.fn() -})) -Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true }) - -it('resolves the initial delete gesture once and never resolves held repeats at fleet scale', () => { - store.setState({ repos: [repo], deleteStateByWorktreeId: {} }) - for (const size of [750, 7500]) { - const selectedWorktrees = Array.from({ length: size }, (_, index) => ({ - ...worktree, - id: `primary-${index}`, - isMainWorktree: true - })) - const resolve = vi.fn(() => - resolveSidebarWorkspaceDeleteIntent({ - selectedWorktrees, - focusedWorktree: selectedWorktrees[0], - repoMap: new Map([[repo.id, repo]]) - }) - ) - function Probe() { - const keyboard = useSidebarWorkspaceDeleteKeyboard({ - keybindings: {}, - resolveDeleteIntent: resolve, - dropPreview: () => {} - }) - return
- } - const container = document.createElement('div') - document.body.append(container) - const root = createRoot(container) - try { - act(() => root.render()) - const target = container.firstElementChild! - for (let index = 0; index < 21; index++) { - act(() => - target.dispatchEvent( - new KeyboardEvent('keydown', { - bubbles: true, - cancelable: true, - key: 'Backspace', - code: 'Backspace', - shiftKey: true, - metaKey: navigator.userAgent.includes('Mac'), - ctrlKey: !navigator.userAgent.includes('Mac'), - repeat: index > 0 - }) - ) - ) - } - expect(resolve).toHaveBeenCalledTimes(1) - } finally { - act(() => root.unmount()) - container.remove() - } - } -}) diff --git a/src/renderer/src/components/sidebar/worktree-list/rows/folder-row-selection.perf.test.tsx b/src/renderer/src/components/sidebar/worktree-list/rows/folder-row-selection.perf.test.tsx deleted file mode 100644 index afadbc9e815..00000000000 --- a/src/renderer/src/components/sidebar/worktree-list/rows/folder-row-selection.perf.test.tsx +++ /dev/null @@ -1,136 +0,0 @@ -// @vitest-environment happy-dom -import type { ComponentProps } from 'react' -import { act, cleanup, fireEvent, render } from '@testing-library/react' -import { afterEach, expect, it, vi } from 'vitest' -import { useAppStore } from '@/store' -import { TooltipProvider } from '@/components/ui/tooltip' -import WorktreeContextMenu from '../../workspace-actions/context-menu/WorktreeContextMenu' -import type WorktreeCard from '../../workspace-card/surface/WorktreeCard' -import { renderFolderWorkspaceOption, type FolderWorkspaceRowContext } from './folder-row' -import type { FolderWorkspaceItemRow } from '../listing/renderable-rows' -import { WORKTREE_ROW_DRAG_INITIAL_STATE } from '../drag/row-state' -import { folderWorkspaceToWorktree } from '../../../../../../shared/folder-workspaces/folder-workspace-worktree' -import type { Worktree } from '../../../../../../shared/worktree/types' -import { worktree } from '../grouping/worktree-list-groups-test-fixtures' - -// Keep the real menu model/view at the card prop seam; omit unrelated card presentation. -vi.mock('../../workspace-card/surface/WorktreeCard', () => ({ - default: (props: ComponentProps) => ( - - props.onContextMenuSelect?.(event, props.worktree) ?? [props.worktree] - } - > - {props.worktree.displayName} - - ) -})) - -afterEach(() => { - cleanup() - useAppStore.setState(useAppStore.getInitialState(), true) -}) -it.each([750, 7500])( - 'does no aggregate selection work for closed folder menus at %i selected rows', - (size) => { - const folders: FolderWorkspaceItemRow[] = Array.from({ length: 10 }, (_, index) => ({ - type: 'folder-workspace', - key: `folder-${index}`, - depth: 0, - groupDepth: 0, - projectGroup: { - id: 'group', - name: 'Folders', - parentPath: null, - parentGroupId: null, - createdFrom: 'manual', - tabOrder: 0, - isCollapsed: false, - color: null, - createdAt: 0, - updatedAt: 0 - }, - folderWorkspace: { - id: `folder-${index}`, - projectGroupId: 'group', - name: `Folder ${index}`, - folderPath: `/tmp/tri35-folder-${index}`, - linkedTask: null, - comment: '', - isArchived: false, - isUnread: false, - isPinned: false, - sortOrder: index, - lastActivityAt: 0, - createdAt: 0, - updatedAt: 0 - } - })) - let selectedOwnerReads = 0 - const selection = Array.from({ length: size }, (_, index): Worktree => { - const item = - index < folders.length - ? folderWorkspaceToWorktree(folders[index].folderWorkspace) - : { ...worktree, id: `worktree-${index}` } - Object.defineProperty(item, 'runtimeOwnerEnvironmentId', { - get: () => { - selectedOwnerReads += 1 - return undefined - } - }) - return item - }) - // The list owns this collection; unopened folder menus must not traverse it. - const ctx: FolderWorkspaceRowContext & { selectedWorktrees: readonly Worktree[] } = { - groupBy: 'none', - newCardStyle: false, - settings: null, - activeWorktreeId: null, - activeWorkspaceExecutionHostId: null, - currentWorktreeId: null, - selectedWorktreeIds: new Set(folders.map((row) => `local|folder:${row.folderWorkspace.id}`)), - selectedWorktrees: selection, - repoMap: new Map(), - worktreeMap: new Map(), - worktreeLineageById: {}, - workspaceLineageByChildKey: {}, - crossStoreChildrenByFolderId: new Map(), - prCache: null, - hostedReviewCache: null, - getCachedFolderWorkspacePathStatus: () => null, - onSelectionGesture: () => false, - onContextMenuSelect: () => selection, - onImmediateActivate: () => {}, - onRowClickCapture: () => {}, - onRowPointerDown: () => {}, - worktreeDragState: WORKTREE_ROW_DRAG_INITIAL_STATE, - nativeLineageDropTargetIdentity: null - } - const view = render( - - {folders.map((row) => renderFolderWorkspaceOption({ ctx, row }))} - - ) - expect(selectedOwnerReads).toBe(0) - view.rerender( - - {folders.map((row) => - renderFolderWorkspaceOption({ - ctx: { ...ctx, selectedWorktreeIds: new Set(ctx.selectedWorktreeIds) }, - row - }) - )} - - ) - // Ten mounted folders require zero selected-row owner lookups until a menu opens, at either fleet size. - expect(selectedOwnerReads).toBe(0) - const first = view.container.querySelector('[data-worktree-context-menu-scope]') - if (!(first instanceof HTMLElement)) { - throw new Error('Missing folder menu scope') - } - act(() => fireEvent.contextMenu(first)) - expect(selectedOwnerReads).toBeGreaterThan(0) - } -)