test: remove low-value workspace wrapper and notice cases (#41938)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-11-13 01:31:41 -08:00
committed by GitHub
co-authored by OrcaWin
parent 96d2c0b0b6
commit e4eecd847c
7 changed files with 1 additions and 357 deletions
@@ -4755,9 +4755,6 @@
"src/renderer/src/components/native-chat/pane/actions/use-structured-native-chat-submit-reveal.test.ts": 2304,
"src/renderer/src/components/network/CustomAddressDialog.test.tsx": 568,
"src/renderer/src/components/new-workspace/branch-selection/ComposerParentWorktreePicker.test.tsx": 870,
"src/renderer/src/components/new-workspace/setup/DirectWorkItemSetupDialog.test.tsx": 5296,
"src/renderer/src/components/new-workspace/composer/NewWorkspaceComposerNameSection.test.tsx": 2493,
"src/renderer/src/components/new-workspace/project-selection/ProjectCombobox.dialog-handoff.test.tsx": 1043,
"src/renderer/src/components/new-workspace/RunTargetCombobox.host-identity.test.tsx": 856,
"src/renderer/src/components/new-workspace/SetProjectLocationDialog.host-identity.test.tsx": 1094,
"src/renderer/src/components/new-workspace/project-location/SetProjectLocationDialog.test.tsx": 1387,
@@ -1,8 +1,6 @@
import { readFileSync } from 'node:fs'
import { describe, expect, it } from 'vitest'
import { hexToRgb, rgbaToHex, type Rgba } from '../../../../shared/color/rgba-contrast'
import { hexToRgb, type Rgba } from '../../../../shared/color/rgba-contrast'
import { noticeSurfaceTokens } from './notice-surface-tokens'
import { safePluginThemeTokens } from './plugin-theme-tokens'
const DARK_BUILT_INS = {
'--foreground': '#f0f0f0',
@@ -71,16 +69,6 @@ function expectReadable(themeTokens: Record<string, string>): void {
}
describe('noticeSurfaceTokens', () => {
it("paints Orca's dark notice colors for the built-in palette", () => {
expect(noticeSurfaceTokens({}, 'dark', DARK_BUILT_INS, probe)).toEqual({
'--notice-surface': '#262626',
'--notice-secondary': '#3a3a3a',
'--notice-secondary-edge': 'transparent',
'--notice-muted': '#3a3a3a',
'--notice-muted-foreground': '#acacac'
})
})
// Popovers the theme validator accepts that once painted notice text under 4.5:1: #5a5a5a
// through Chromium's color-mix rounding and an over-lifted 80% description, #383838 through hex
// rounding, white-on-dark-base through dark muted panels, the rest unlifted.
@@ -94,18 +82,6 @@ describe('noticeSurfaceTokens', () => {
expectReadable(themeTokens)
})
it('keeps notice text 4.5:1 for every gray popover the validator accepts', () => {
const accepted = Array.from({ length: 256 }, (_, gray) => ({
'--popover': rgbaToHex([gray, gray, gray, 1])
})).filter(
(tokens) => safePluginThemeTokens(tokens, 'dark', DARK_BUILT_INS, probe)['--popover']
)
expect(accepted.length).toBeGreaterThan(50)
for (const tokens of accepted) {
expectReadable(tokens)
}
})
it('outlines secondary buttons only when their fill is gone', () => {
const tokensFor = (popoverForeground: string): Record<string, string> =>
noticeSurfaceTokens(
@@ -121,25 +97,4 @@ describe('noticeSurfaceTokens', () => {
expect(filled['--notice-secondary']).not.toBe(filled['--notice-surface'])
expect(filled['--notice-secondary-edge']).toBe('transparent')
})
it('remaps the surface paired with every foreground the notice scope remaps', () => {
const css = readFileSync(new URL('../../assets/main.css', import.meta.url), 'utf8')
const scope = css.match(
/\[data-sonner-toaster\],\s*\.notification-card-stack\s*\{([^}]*)\}/
)?.[1]
expect(scope).toBeDefined()
const remapped = new Set([...(scope ?? '').matchAll(/(--[\w-]+):/g)].map(([, name]) => name))
// Why: a foreground remapped onto the popover's polarity over an unremapped surface (outline
// buttons: text-foreground on bg-background) paints light-on-light or dark-on-dark.
const pairs = [
['--foreground', '--background'],
['--card-foreground', '--card'],
['--secondary-foreground', '--secondary'],
['--muted-foreground', '--muted']
]
for (const [foreground, surface] of pairs) {
expect(remapped.has(foreground), foreground).toBe(true)
expect(remapped.has(surface), `${surface} pairs with ${foreground}`).toBe(true)
}
})
})
@@ -107,7 +107,6 @@ describe('FullDiskAccessSetupPrompt state helpers', () => {
expect(container.textContent).not.toContain('Full Disk Access')
expect(getStatus).not.toHaveBeenCalled()
expect(window.api.developerPermissions.request).not.toHaveBeenCalled()
root.unmount()
})
})
@@ -1,104 +0,0 @@
// @vitest-environment happy-dom
import React from 'react'
import { cleanup, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { NewWorkspaceComposerNameSection } from './NewWorkspaceComposerNameSection'
vi.mock('@/components/new-workspace/SmartWorkspaceNameField', () => ({
default: ({ value, selectedSource }: { value: string; selectedSource?: { label: string } }) => (
<div>
<span>{selectedSource?.label}</span>
<input aria-label="Workspace name" value={value} readOnly />
</div>
)
}))
function branchProps(): React.ComponentProps<typeof NewWorkspaceComposerNameSection> {
return {
eligibleRepos: [],
repoId: 'repo',
onRepoChange: vi.fn(),
name: 'Payments review',
onNameValueChange: vi.fn(),
onSmartGitHubItemSelect: vi.fn(),
onSmartGitLabItemSelect: vi.fn(),
onSmartBranchSelect: vi.fn(),
onSmartLinearIssueSelect: vi.fn(),
smartNameSelection: { kind: 'branch', label: 'origin/feature/payments' },
onClearSmartNameSelection: vi.fn(),
selectedRepoRequiresConnection: false,
selectedRepoIsGit: true,
branchesEnabled: true,
forkPushWarning: null,
canReuseSelectedBranch: true,
reuseEligibleBranch: 'feature/payments',
branchNameOverride: undefined,
onBranchNameOverrideChange: vi.fn(),
reuseSelectedBranch: true,
onReuseSelectedBranchChange: vi.fn(),
baseBranch: 'refs/remotes/origin/feature/payments',
onNamePlainEnter: vi.fn()
}
}
afterEach(cleanup)
describe('NewWorkspaceComposerNameSection branch reuse', () => {
it('chooses a new branch by pointer and the existing branch by keyboard without changing the source', async () => {
const user = userEvent.setup()
const props = branchProps()
const { rerender } = render(<NewWorkspaceComposerNameSection {...props} />)
expect(screen.getByText('origin/feature/payments')).toBeTruthy()
expect(screen.getByText('feature/payments')).toBeTruthy()
expect(screen.queryByRole('textbox', { name: 'New branch name' })).toBeNull()
expect(
screen.getByRole('radio', { name: 'Existing branch' }).getAttribute('aria-checked')
).toBe('true')
await user.click(screen.getByRole('radio', { name: 'New branch' }))
expect(props.onReuseSelectedBranchChange).toHaveBeenLastCalledWith(false)
rerender(<NewWorkspaceComposerNameSection {...props} reuseSelectedBranch={false} />)
expect(
screen.getByRole('radio', { name: 'Existing branch' }).getAttribute('aria-checked')
).toBe('false')
expect(document.activeElement).toBe(screen.getByRole('textbox', { name: 'New branch name' }))
await user.paste('review/payments')
expect(props.onBranchNameOverrideChange).toHaveBeenLastCalledWith('review/payments')
await user.click(screen.getByRole('radio', { name: 'New branch' }))
expect(document.activeElement).toBe(screen.getByRole('textbox', { name: 'New branch name' }))
screen.getByRole('radio', { name: 'New branch' }).focus()
await user.keyboard('{ArrowUp>}')
await waitFor(() => expect(props.onReuseSelectedBranchChange).toHaveBeenLastCalledWith(true))
await user.keyboard('{/ArrowUp}')
expect(props.onNameValueChange).not.toHaveBeenCalled()
expect(props.onClearSmartNameSelection).not.toHaveBeenCalled()
})
it('opens the existing workspace with the keyboard without submitting or changing branch intent', async () => {
const user = userEvent.setup()
const props = branchProps()
const openWorkspace = vi.fn()
const submit = vi.fn((event: React.FormEvent) => event.preventDefault())
render(
<form onSubmit={submit}>
<NewWorkspaceComposerNameSection {...props} onOpenSelectedBranchWorkspace={openWorkspace} />
</form>
)
const openButton = screen.getByRole('button', { name: 'Open existing workspace' })
await user.tab()
await user.tab()
await user.tab()
expect(document.activeElement).toBe(openButton)
await user.keyboard('{Enter}')
expect(openWorkspace).toHaveBeenCalledOnce()
expect(submit).not.toHaveBeenCalled()
expect(props.onReuseSelectedBranchChange).not.toHaveBeenCalled()
expect(props.onNameValueChange).not.toHaveBeenCalled()
expect(props.onClearSmartNameSelection).not.toHaveBeenCalled()
})
})
@@ -1,120 +0,0 @@
// @vitest-environment happy-dom
import React, { act, Suspense, useEffect, useRef, useState } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog'
import ProjectCombobox from './ProjectCombobox'
import { TooltipProvider } from '@/components/ui/tooltip'
vi.mock('./use-recent-project-ids', () => ({ useRecentProjectIds: () => [] }))
// Mirrors a lazily loaded creation dialog that focuses its primary action from a mount effect.
let resolveLateDialog: () => void = () => {}
const LateAddDialogBody = React.lazy(
() =>
new Promise<{ default: () => React.JSX.Element }>((resolve) => {
resolveLateDialog = () =>
resolve({
default: function Body(): React.JSX.Element {
const browseRef = useRef<HTMLButtonElement>(null)
useEffect(() => browseRef.current?.focus(), [])
return <button ref={browseRef}>Browse</button>
}
})
})
)
function LateDialogComposer(): React.JSX.Element {
const [adding, setAdding] = useState(false)
return (
<Dialog open>
<DialogContent aria-describedby={undefined}>
<DialogTitle>New workspace</DialogTitle>
<ProjectCombobox
options={[]}
value={null}
onValueChange={vi.fn()}
onAddProject={() => setAdding(true)}
/>
{adding ? (
<Suspense fallback={null}>
<Dialog open onOpenChange={setAdding}>
<DialogContent aria-describedby={undefined}>
<DialogTitle>Add a project</DialogTitle>
<LateAddDialogBody />
</DialogContent>
</Dialog>
</Suspense>
) : null}
</DialogContent>
</Dialog>
)
}
let container: HTMLDivElement
let root: Root
beforeEach(() => {
// Radix Presence retains closing content when the production exit animation runs.
const getStyle = window.getComputedStyle.bind(window)
vi.spyOn(window, 'getComputedStyle').mockImplementation((element, ...args) => {
const style = getStyle(element, ...args)
if (element.getAttribute('data-slot') === 'popover-content') {
return new Proxy(style, {
get: (target, property) =>
property === 'animationName'
? element.getAttribute('data-state') === 'closed'
? 'exit'
: 'enter'
: // oxlint-disable-next-line anti-slop/no-reflect-get -- Proxy `get` trap: raw string|symbol pass-through; the receiver stays the target on purpose.
Reflect.get(target, property)
})
}
return style
})
container = document.createElement('div')
document.body.appendChild(container)
root = createRoot(container)
})
afterEach(async () => {
await act(async () => root.unmount())
container.remove()
vi.restoreAllMocks()
})
function projectField(): HTMLInputElement {
return document.querySelector<HTMLInputElement>('[role="combobox"][aria-label="Project"]')!
}
function addOption(): HTMLElement {
return Array.from(document.querySelectorAll<HTMLElement>('[role="option"]')).find((option) =>
option.textContent?.includes('Add project')
)!
}
it('keeps the selector closed when a late creation dialog focuses before its trap mounts', async () => {
await act(async () =>
root.render(
<TooltipProvider>
<LateDialogComposer />
</TooltipProvider>
)
)
// Dialog autofocus lands on the field, so the composer trap records it as last focused.
expect(document.activeElement).toBe(projectField())
expect(document.querySelector('[role="listbox"]')).not.toBeNull()
await act(async () => {
addOption().dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true }))
addOption().click()
})
expect(document.querySelector('[role="listbox"]')).toBeNull()
// Let the closed selector release its focus scope before the lazy dialog arrives.
await act(async () => new Promise((resolve) => setTimeout(resolve, 0)))
await act(async () => resolveLateDialog())
expect(document.querySelector('[role="listbox"]')).toBeNull()
expect(projectField().getAttribute('aria-expanded')).toBe('false')
})
@@ -1,36 +0,0 @@
// @vitest-environment happy-dom
import { readDirectSetupRequest } from '@/lib/workspace/creation/work-item/direct-work-item-setup-test-fixture'
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, expect, it } from 'vitest'
import { i18n } from '@/i18n/i18n'
import { useAppStore } from '@/store'
import {
requestDirectWorkItemSetup,
type DirectWorkItemSetupRequest
} from '@/lib/workspace/creation/work-item/direct-work-item-setup'
import { DirectWorkItemSetupDialog } from './DirectWorkItemSetupDialog'
import type { WorkspaceSetupInspection as DirectSetupInspection } from '@/lib/workspace/creation/setup/workspace-setup-preparation'
const initial = useAppStore.getState()
afterEach(async () => {
cleanup()
await i18n.changeLanguage('en')
useAppStore.getState().closeModal()
useAppStore.setState(initial, true)
})
function request(): DirectWorkItemSetupRequest {
return readDirectSetupRequest(useAppStore.getState().modalData.directSetup)
}
it('ignores recovery after cancellation without closing the replacement modal', async () => {
const retry = Promise.withResolvers<DirectSetupInspection>()
const result = requestDirectWorkItemSetup('Repo', { kind: 'unavailable' }, () => retry.promise)
const old = request()
render(<DirectWorkItemSetupDialog request={old} />)
fireEvent.click(screen.getByRole('button', { name: 'Retry' }))
useAppStore.getState().openModal('quick-open', { section: 'appearance' })
await expect(result).resolves.toBe('cancelled')
await act(async () => retry.resolve({ kind: 'decided', decision: 'run' }))
expect(old.isPending()).toBe(false)
expect(useAppStore.getState().modalData).toEqual({ section: 'appearance' })
})
@@ -1,47 +0,0 @@
import { describe, expect, it } from 'vitest'
import { resolveLocalGitlabAvailable } from './use-smart-workspace-field-availability'
describe('resolveLocalGitlabAvailable', () => {
const lastKnown = new Map([['host', true]])
it('uses the current preflight answer when it is for this context', () => {
expect(
resolveLocalGitlabAvailable({
preflightStatusCurrent: true,
glabInstalled: false,
contextKey: 'host',
lastKnown
})
).toBe(false)
expect(
resolveLocalGitlabAvailable({
preflightStatusCurrent: true,
glabInstalled: true,
contextKey: 'wsl:Ubuntu',
lastKnown
})
).toBe(true)
})
it('keeps the last known answer while this context is being re-checked', () => {
expect(
resolveLocalGitlabAvailable({
preflightStatusCurrent: false,
glabInstalled: undefined,
contextKey: 'host',
lastKnown
})
).toBe(true)
})
it('stays hidden for a context that was never checked', () => {
expect(
resolveLocalGitlabAvailable({
preflightStatusCurrent: false,
glabInstalled: undefined,
contextKey: 'wsl:Debian',
lastKnown
})
).toBe(false)
})
})