mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 10:27:33 +00:00
test: remove low-value browser, image, and ACP suites (#41329)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
import { createElement } from 'react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { renderImageParagraph } from './mobile-markdown-image-paragraph'
|
||||
import { mobileMarkdownParagraphImages } from './mobile-markdown-image-placement'
|
||||
import { parseMobileMarkdownTree } from './mobile-markdown-tree'
|
||||
import { MARKDOWN_TONES } from './mobile-markdown-styles'
|
||||
import type { MarkdownBlockContext } from './mobile-markdown-blocks'
|
||||
|
||||
vi.mock('react-native', () => ({
|
||||
Linking: { openURL: () => Promise.resolve() },
|
||||
Platform: { OS: 'ios' },
|
||||
StyleSheet: { create: (styles: unknown) => styles, hairlineWidth: 1 },
|
||||
Text: 'Text',
|
||||
View: 'View'
|
||||
}))
|
||||
|
||||
describe('phone Markdown image paragraphs', () => {
|
||||
it.each([100, 1000])('draws %i images with linear eligibility reads', (count) => {
|
||||
const root = parseMobileMarkdownTree(
|
||||
Array(count).fill('').join(' '),
|
||||
false,
|
||||
true
|
||||
)
|
||||
const paragraph = root.children[0]!
|
||||
if (paragraph.type !== 'paragraph') {
|
||||
throw new Error('expected an image paragraph')
|
||||
}
|
||||
let reads = 0
|
||||
const images = mobileMarkdownParagraphImages(paragraph, 0)
|
||||
images.forEach((image, index) => {
|
||||
Object.defineProperty(images, index, {
|
||||
get() {
|
||||
reads += 1
|
||||
return image
|
||||
}
|
||||
})
|
||||
})
|
||||
const drawn: string[] = []
|
||||
const ctx: MarkdownBlockContext = {
|
||||
onOpenLink: () => {},
|
||||
tone: MARKDOWN_TONES.default,
|
||||
textScale: 1,
|
||||
chatMath: true,
|
||||
growing: false,
|
||||
listText: {},
|
||||
listMarker: {},
|
||||
directives: [],
|
||||
mermaidOccurrences: new Map(),
|
||||
renderImage: (href) => {
|
||||
drawn.push(href)
|
||||
return createElement('Image', { href })
|
||||
}
|
||||
}
|
||||
expect(
|
||||
renderImageParagraph(paragraph.children, images, 0, ctx, {
|
||||
style: {},
|
||||
selectable: true
|
||||
})
|
||||
).not.toBeNull()
|
||||
expect(drawn).toEqual(Array(count).fill('/tmp/p.png'))
|
||||
// Each eligible image needs one read to index and one to draw, independent of paragraph width.
|
||||
expect(reads).toBeLessThanOrEqual(2 * count)
|
||||
})
|
||||
})
|
||||
@@ -1,32 +0,0 @@
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
import { acpLaunchSpecFor } from './acp-launch-registry'
|
||||
import { resolveAcpLaunchInvocation } from './acp-structured-launch-resolution'
|
||||
|
||||
afterEach(() => vi.unstubAllGlobals())
|
||||
|
||||
it('composes configured Windows values before ACP command lookup and account pinning', async () => {
|
||||
vi.stubGlobal('process', { ...process, platform: 'win32' })
|
||||
const spec = acpLaunchSpecFor('grok')
|
||||
if (!spec) {
|
||||
throw new Error('Missing Grok spec')
|
||||
}
|
||||
const launch = await resolveAcpLaunchInvocation(
|
||||
{ ...spec, installDirectories: () => [] },
|
||||
{ variable: 'GROK_HOME', path: '/pinned' },
|
||||
{
|
||||
dataDirectory: '/isolated',
|
||||
inheritedEnv: {},
|
||||
resolveEnvironment: async () => ({ PATH: '/inherited/bin', TOKEN: 'inherited' }),
|
||||
resolveLaunchEnv: () => ({
|
||||
path: '/configured/bin',
|
||||
tOKEN: 'configured',
|
||||
grok_home: '/configured/home'
|
||||
}),
|
||||
resolveCommand: (_command, options) => {
|
||||
expect(options?.pathEnv).toBe('/configured/bin')
|
||||
return '/configured/bin/grok.exe'
|
||||
}
|
||||
}
|
||||
)
|
||||
expect(launch.env).toEqual({ PATH: '/configured/bin', TOKEN: 'configured', GROK_HOME: '/pinned' })
|
||||
})
|
||||
@@ -1,55 +0,0 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import type { AgentJournalRenderItem } from '../../../shared/agent-session/journal/agent-session-journal-types'
|
||||
import { closeProviderTimelineRigs } from '../../native-chat/agent-session-timeline/provider-timeline-assembler-test-support'
|
||||
import { OPENCODE_ACP_DIALECT } from '../acp-dialects/opencode-dialect'
|
||||
|
||||
import { openAcpFixtureRig } from './testing/acp-timeline-fixture.test-support'
|
||||
|
||||
afterEach(closeProviderTimelineRigs)
|
||||
|
||||
function texts(rows: AgentJournalRenderItem[], agentId: string) {
|
||||
return rows.flatMap((row) =>
|
||||
row.agentId === agentId && row.body.kind === 'message'
|
||||
? row.body.blocks.flatMap((block) => (block.type === 'text' ? [block.text] : []))
|
||||
: []
|
||||
)
|
||||
}
|
||||
|
||||
const opened = () => openAcpFixtureRig(OPENCODE_ACP_DIALECT, { journalOwnership: true })
|
||||
|
||||
describe('OpenCode subagents through the shared timeline', () => {
|
||||
it('a reply that resumes after the subagent thinks or runs a tool keeps all of its text', async () => {
|
||||
const fixture = await opened()
|
||||
const lane = fixture.lane()
|
||||
const report = (body: Record<string, unknown>) =>
|
||||
fixture.apply(lane.notification('opencode/session/child_update', { ...CHILD, ...body }, 1000))
|
||||
report({ type: 'status', status: 'created', title: 'Helper' })
|
||||
report(chunk('agent_message_chunk', 'msg-1', 'A'))
|
||||
report(chunk('agent_thought_chunk', 'msg-1:reasoning:0', 'R'))
|
||||
report({
|
||||
type: 'update',
|
||||
update: {
|
||||
sessionUpdate: 'tool_call',
|
||||
toolCallId: 'session-2:t1',
|
||||
title: 'shell',
|
||||
status: 'pending'
|
||||
}
|
||||
})
|
||||
report(chunk('agent_message_chunk', 'msg-1', 'B'))
|
||||
report({ type: 'status', status: 'completed' })
|
||||
expect(texts(await fixture.rig.rows(), 'session-2')).toEqual(['AB', 'R'])
|
||||
})
|
||||
})
|
||||
|
||||
const CHILD = {
|
||||
rootSessionId: 'session-1',
|
||||
childSessionId: 'session-2',
|
||||
parentSessionId: 'session-1'
|
||||
}
|
||||
|
||||
function chunk(sessionUpdate: string, messageId: string, text: string) {
|
||||
return {
|
||||
type: 'update',
|
||||
update: { sessionUpdate, messageId, content: { type: 'text', text } }
|
||||
}
|
||||
}
|
||||
@@ -71,28 +71,6 @@ function fakeHost(
|
||||
}
|
||||
|
||||
describe('runWithActionEffects', () => {
|
||||
it('lists the lines an action added and the console errors it logged', async () => {
|
||||
const guest = fakeGuest()
|
||||
const { host } = fakeHost(guest, [UNCHANGED, INVALID_LOGIN])
|
||||
|
||||
const result = await runWithActionEffects(host, async () => {
|
||||
guest.emit('console-message', { level: 'error', message: 'Uncaught TypeError: x' })
|
||||
guest.emit('console-message', { level: 'info', message: 'booted' })
|
||||
return { clicked: '@e6' }
|
||||
})
|
||||
|
||||
expect(readBrowserActionEffects(result)).toEqual({
|
||||
settled: true,
|
||||
consoleErrors: ['Uncaught TypeError: x'],
|
||||
page: {
|
||||
lines: [' - StaticText "Invalid username or password"'],
|
||||
removedLines: 0,
|
||||
full: false,
|
||||
truncated: false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('waits for a navigation the action started and reports where it landed', async () => {
|
||||
const guest = fakeGuest()
|
||||
const appTree = '- heading "Welcome ada" [level=1, ref=e9]\n- button "Submit ticket" [ref=e10]'
|
||||
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
vi.mock('electron', async () => {
|
||||
const { EventEmitter } = await import('node:events')
|
||||
return {
|
||||
BrowserWindow: class {
|
||||
webContents = new (class extends EventEmitter {
|
||||
send = vi.fn()
|
||||
})()
|
||||
},
|
||||
screen: { getCursorScreenPoint: vi.fn(() => ({ x: 0, y: 0 })) },
|
||||
webContents: { fromId: vi.fn() }
|
||||
}
|
||||
})
|
||||
|
||||
import { BrowserWindow } from 'electron'
|
||||
import { setupGuestShortcutForwarding } from './browser-guest-shortcut-forwarding'
|
||||
|
||||
function pressDictationInPage(isComposing: boolean) {
|
||||
const guest = new BrowserWindow().webContents
|
||||
const renderer = new BrowserWindow().webContents
|
||||
const cleanup = setupGuestShortcutForwarding({
|
||||
browserTabId: 'tab-1',
|
||||
guest,
|
||||
resolveRenderer: () => renderer,
|
||||
shouldForwardDictationShortcut: () => true,
|
||||
getKeybindings: () => ({})
|
||||
})
|
||||
const isMac = process.platform === 'darwin'
|
||||
const event: Electron.Event = { preventDefault: vi.fn(), defaultPrevented: false }
|
||||
const input: Electron.Input = {
|
||||
type: 'keyDown',
|
||||
code: 'KeyE',
|
||||
key: 'e',
|
||||
meta: isMac,
|
||||
control: !isMac,
|
||||
alt: false,
|
||||
shift: false,
|
||||
isAutoRepeat: false,
|
||||
isComposing,
|
||||
location: 0,
|
||||
modifiers: []
|
||||
}
|
||||
guest.emit('before-input-event', event, input)
|
||||
cleanup()
|
||||
return { prevented: vi.mocked(event.preventDefault).mock.calls.length > 0, renderer }
|
||||
}
|
||||
|
||||
describe('dictation shortcut from a focused browser page', () => {
|
||||
it('leaves the chord to the page while an IME composition owns it', () => {
|
||||
const composing = pressDictationInPage(true)
|
||||
expect(composing.prevented).toBe(false)
|
||||
expect(composing.renderer.send).not.toHaveBeenCalledWith('ui:dictationKeyDown')
|
||||
|
||||
const typed = pressDictationInPage(false)
|
||||
expect(typed.prevented).toBe(true)
|
||||
expect(typed.renderer.send).toHaveBeenCalledWith('ui:dictationKeyDown')
|
||||
})
|
||||
})
|
||||
@@ -2,11 +2,7 @@ import { EventEmitter } from 'node:events'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { BrowserGuestMetadata } from '../../../../shared/browser/guest-lifecycle/browser-guest-metadata'
|
||||
import type { BrowserLoadError } from '../../../../shared/browser-workspace-types'
|
||||
import {
|
||||
installBrowserGuestMetadata,
|
||||
publishBrowserGuestMetadata,
|
||||
readBrowserGuestMetadata
|
||||
} from './browser-guest-metadata'
|
||||
import { installBrowserGuestMetadata, publishBrowserGuestMetadata } from './browser-guest-metadata'
|
||||
|
||||
function fixture() {
|
||||
let url = 'https://example.test/start'
|
||||
@@ -59,24 +55,6 @@ function fixture() {
|
||||
}
|
||||
|
||||
describe('native guest metadata', () => {
|
||||
it('samples native loading before navigation-start and keeps subsequent title reports current', () => {
|
||||
const f = fixture()
|
||||
f.setLoading(true)
|
||||
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: fixture supplies the native metadata methods.
|
||||
const state = readBrowserGuestMetadata(f.guest as unknown as Electron.WebContents)
|
||||
expect(state).toMatchObject({
|
||||
url: 'https://example.test/start',
|
||||
loading: true,
|
||||
navigationRevision: 0
|
||||
})
|
||||
f.guest.emit('page-title-updated', {}, 'Current title')
|
||||
expect(f.reports.at(-1)).toMatchObject({ title: 'Current title', loading: true })
|
||||
f.setLoading(false)
|
||||
f.guest.emit('did-stop-loading')
|
||||
expect(f.reports.at(-1)).toMatchObject({ url: 'https://example.test/start', loading: false })
|
||||
f.dispose()
|
||||
})
|
||||
|
||||
it('projects same-URL native history and retains it through a failed destination without publishing Chromium internals', () => {
|
||||
const f = fixture()
|
||||
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: fixture supplies the production publisher native methods.
|
||||
|
||||
@@ -24,24 +24,6 @@ afterEach(async () => {
|
||||
})
|
||||
|
||||
describe('browser tunnel destination policy', () => {
|
||||
it.each([
|
||||
['localhost', 3000],
|
||||
['127.0.0.1', 5173],
|
||||
['::1', 8080],
|
||||
['0.0.0.0', 8000],
|
||||
['192.168.1.20', 80],
|
||||
['10.0.0.5', 443],
|
||||
['172.16.4.2', 8443],
|
||||
['100.75.218.44', 3000],
|
||||
['fd12:3456::1', 80],
|
||||
['example.com', 443],
|
||||
['2130706433', 3000],
|
||||
['1.2.3', 80],
|
||||
['v1.2.3.4', 80]
|
||||
])('allows %s:%i', (host, port) => {
|
||||
expect(browserTunnelTargetBlockReason(host, port)).toBeNull()
|
||||
})
|
||||
|
||||
it.each([
|
||||
['169.254.169.254', 80],
|
||||
['169.254.170.2', 80],
|
||||
@@ -181,22 +163,6 @@ describe('native browser tunnel dial', () => {
|
||||
).resolves.toBe('connected')
|
||||
})
|
||||
|
||||
it("refuses metadata and the host's own Orca listener before dialing", async () => {
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
const port = await startServer()
|
||||
cleanups.push(reserveBrowserTunnelOrcaListenerPort(port))
|
||||
|
||||
expect(() => connectNativeBrowserNetworkTarget({ host: '127.0.0.1', port }, {})).toThrow(
|
||||
BrowserTunnelDestinationBlockedError
|
||||
)
|
||||
expect(() =>
|
||||
connectNativeBrowserNetworkTarget({ host: '169.254.169.254', port: 80 }, {})
|
||||
).toThrow(BrowserTunnelDestinationBlockedError)
|
||||
expect(() => connectNativeBrowserNetworkTarget({ host: 'localhost', port }, {})).toThrow(
|
||||
BrowserTunnelDestinationBlockedError
|
||||
)
|
||||
})
|
||||
|
||||
it('restores unrestricted dialing when the host opts out', async () => {
|
||||
const port = await startServer()
|
||||
cleanups.push(reserveBrowserTunnelOrcaListenerPort(port))
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
import type * as HtmlParser from 'hast-util-from-html-isomorphic'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
const traversal = vi.hoisted(() => ({ fail: false }))
|
||||
vi.mock('hast-util-from-html-isomorphic', async (load) => {
|
||||
const actual = await load<typeof HtmlParser>()
|
||||
return {
|
||||
...actual,
|
||||
fromHtmlIsomorphic: (...args: Parameters<typeof actual.fromHtmlIsomorphic>) => {
|
||||
if (traversal.fail) {
|
||||
throw new Error('Optional image HTML could not be parsed')
|
||||
}
|
||||
return actual.fromHtmlIsomorphic(...args)
|
||||
}
|
||||
}
|
||||
})
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { githubBodyImageUrls } from './body-image-urls'
|
||||
|
||||
const original = 'https://github.com/user-attachments/assets/ce11040a-fb66-4289-927f-547b16dfc488'
|
||||
@@ -20,15 +6,6 @@ const signed =
|
||||
'https://private-user-images.githubusercontent.com/1/2-ce11040a-fb66-4289-927f-547b16dfc488.png?jwt=TEST&download=1'
|
||||
|
||||
describe('GitHub body image sources', () => {
|
||||
it('leaves the optional map absent if HTML extraction fails', () => {
|
||||
traversal.fail = true
|
||||
try {
|
||||
expect(githubBodyImageUrls(``, `<img src="${signed}">`)).toBeUndefined()
|
||||
} finally {
|
||||
traversal.fail = false
|
||||
}
|
||||
})
|
||||
|
||||
it('matches rendered images to canonical assets without changing editable Markdown', () => {
|
||||
const body = `\n<img src="https://github.enterprise/team/repo/assets/42/ab11040a-fb66-4289-927f-547b16dfc488">\n\n\`https://github.com/user-attachments/assets/dd11040a-fb66-4289-927f-547b16dfc488\``
|
||||
const html = `<img src="https://private-user-images.githubusercontent.com/1/2-ce11040a-fb66-4289-927f-547b16dfc488.png?jwt=TEST&download=1"><img src="https://github.enterprise/storage/ab11040a-fb66-4289-927f-547b16dfc488.png?jwt=TEST"><code>https://private-user-images.githubusercontent.com/1/dd11040a-fb66-4289-927f-547b16dfc488.png</code>`
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const {
|
||||
acquireMock,
|
||||
ghExecFileAsyncMock,
|
||||
noteRepositoryRateLimitSpendMock,
|
||||
projectHostAuthenticationErrorMock,
|
||||
repositoryRateLimitGuardMock,
|
||||
releaseMock,
|
||||
runGraphqlMock,
|
||||
runRestMock
|
||||
} = vi.hoisted(() => ({
|
||||
acquireMock: vi.fn(),
|
||||
ghExecFileAsyncMock: vi.fn(),
|
||||
noteRepositoryRateLimitSpendMock: vi.fn(),
|
||||
projectHostAuthenticationErrorMock: vi.fn(),
|
||||
repositoryRateLimitGuardMock: vi.fn(),
|
||||
releaseMock: vi.fn(),
|
||||
runGraphqlMock: vi.fn(),
|
||||
runRestMock: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('./internals', () => ({
|
||||
acquire: acquireMock,
|
||||
release: releaseMock,
|
||||
extractExecError: (err: unknown) => ({
|
||||
stderr: err instanceof Error ? err.message : String(err),
|
||||
stdout: ''
|
||||
}),
|
||||
ghExecFileAsync: ghExecFileAsyncMock,
|
||||
rateLimitGuard: () => ({ blocked: false }),
|
||||
noteRateLimitSpend: vi.fn(),
|
||||
repositoryRateLimitGuard: repositoryRateLimitGuardMock,
|
||||
noteRepositoryRateLimitSpend: noteRepositoryRateLimitSpendMock,
|
||||
projectHostAuthenticationError: projectHostAuthenticationErrorMock,
|
||||
projectGhExecOptions: (host?: string) => ({ host: host ?? 'github.com' }),
|
||||
classifyProjectError: (stderr: string) => ({ type: 'unknown', message: stderr }),
|
||||
rateLimitedError: () => ({ type: 'rate_limited', message: 'rate limited' }),
|
||||
runGraphql: runGraphqlMock,
|
||||
runRest: runRestMock,
|
||||
validateSlugArgs: (owner: string, repo: string) =>
|
||||
owner && repo ? { ok: true } : { ok: false, error: { type: 'validation_error' } },
|
||||
assertPositiveInt: (value: number, name: string) =>
|
||||
Number.isInteger(value) && value > 0
|
||||
? { ok: true, value }
|
||||
: { ok: false, error: { type: 'validation_error', message: `${name} invalid` } }
|
||||
}))
|
||||
|
||||
import { updateIssueBySlug } from './mutations'
|
||||
|
||||
describe('Project accepted body representations', () => {
|
||||
beforeEach(() => {
|
||||
acquireMock.mockReset().mockResolvedValue(undefined)
|
||||
ghExecFileAsyncMock.mockReset().mockResolvedValue({ stdout: '', stderr: '' })
|
||||
noteRepositoryRateLimitSpendMock.mockReset()
|
||||
projectHostAuthenticationErrorMock.mockReset().mockResolvedValue(null)
|
||||
repositoryRateLimitGuardMock.mockReset().mockReturnValue({ blocked: false })
|
||||
releaseMock.mockReset()
|
||||
runRestMock.mockReset().mockResolvedValue({ ok: true, data: {} })
|
||||
})
|
||||
|
||||
it('does not attach a Project issue map from a different accepted body snapshot', async () => {
|
||||
const body =
|
||||
''
|
||||
runRestMock.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
data: {
|
||||
body: `${body}\nchanged elsewhere`,
|
||||
body_html:
|
||||
'<img src="https://private-user-images.githubusercontent.com/1/ce11040a-fb66-4289-927f-547b16dfc488.png?jwt=TEST">'
|
||||
}
|
||||
})
|
||||
await expect(
|
||||
updateIssueBySlug({ owner: 'acme', repo: 'widgets', number: 12, updates: { body } })
|
||||
).resolves.toEqual({ ok: true, bodyImageUrls: undefined })
|
||||
})
|
||||
|
||||
it.each([null, true])(
|
||||
'finishes a Project compound save with unusable optional HTML (%s)',
|
||||
async (html) => {
|
||||
const body =
|
||||
''
|
||||
runRestMock.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
data: html === null ? null : { body, body_html: html }
|
||||
})
|
||||
await expect(
|
||||
updateIssueBySlug({
|
||||
owner: 'acme',
|
||||
repo: 'widgets',
|
||||
number: 12,
|
||||
updates: { body, addLabels: ['saved-label'] }
|
||||
})
|
||||
).resolves.toEqual({ ok: true, bodyImageUrls: undefined })
|
||||
expect(runRestMock).toHaveBeenCalledWith(
|
||||
[
|
||||
'-X',
|
||||
'POST',
|
||||
'repos/acme/widgets/issues/12/labels',
|
||||
'--raw-field',
|
||||
'labels[]=saved-label'
|
||||
],
|
||||
undefined,
|
||||
'core',
|
||||
{ host: 'github.com' }
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
@@ -14,24 +14,14 @@ import {
|
||||
} from '@/lib/workspace/creation/project-host-setup-options'
|
||||
import { NewWorkspaceComposerProjectSection } from '@/components/new-workspace/NewWorkspaceComposerProjectSection'
|
||||
import { SidebarHeaderActions } from '../../sidebar-header-actions'
|
||||
import AddRepoDialog from '../dialog/AddRepoDialog'
|
||||
import type { AddRepoDialogEntryRequest } from '../dialog/add-repo-dialog-types'
|
||||
|
||||
const browseRuntimeServerDirectoryMock = vi.fn()
|
||||
const callRuntimeRpcMock = vi.fn()
|
||||
|
||||
vi.mock('@/components/new-workspace/use-recent-project-ids', () => ({
|
||||
useRecentProjectIds: () => []
|
||||
}))
|
||||
vi.mock('@/components/sidebar/host-admission/ssh/AddRemoteHostDialog', () => ({
|
||||
AddRemoteHostDialog: () => null
|
||||
}))
|
||||
vi.mock('@/runtime/files/reads/runtime-server-directory-browser', () => ({
|
||||
browseRuntimeServerDirectory: (...args: unknown[]) => browseRuntimeServerDirectoryMock(...args)
|
||||
}))
|
||||
vi.mock('@/runtime/rpc/calls/runtime-rpc-call', () => ({
|
||||
callRuntimeRpc: (...args: unknown[]) => callRuntimeRpcMock(...args)
|
||||
}))
|
||||
|
||||
const UBUNTU_RUNTIME: PublicKnownRuntimeEnvironment = {
|
||||
id: 'wsl-ubuntu',
|
||||
@@ -57,8 +47,6 @@ const pickFoldersMock = vi.fn<() => Promise<string[]>>()
|
||||
|
||||
beforeEach(() => {
|
||||
pickFoldersMock.mockReset()
|
||||
browseRuntimeServerDirectoryMock.mockReset()
|
||||
callRuntimeRpcMock.mockReset()
|
||||
Object.defineProperty(window, 'api', {
|
||||
configurable: true,
|
||||
value: {
|
||||
@@ -289,33 +277,3 @@ describe('AddProjectMenu default host sync in worktree composer', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('AddRepoDialog direct menu entry', () => {
|
||||
it('opens directly on Create new project for the requested host without a Back button or cancelled host defaults', async () => {
|
||||
browseRuntimeServerDirectoryMock.mockResolvedValue({
|
||||
resolvedPath: '/home/alice',
|
||||
parentPath: '/home',
|
||||
entries: []
|
||||
})
|
||||
callRuntimeRpcMock.mockResolvedValue({ available: true })
|
||||
|
||||
render(
|
||||
<TooltipProvider>
|
||||
<AddRepoDialog />
|
||||
</TooltipProvider>
|
||||
)
|
||||
|
||||
useAppStore.getState().openModal('add-repo', {
|
||||
entryRequest: {
|
||||
id: 1,
|
||||
kind: 'create',
|
||||
hostId: 'runtime:wsl-ubuntu'
|
||||
}
|
||||
})
|
||||
|
||||
expect(await screen.findByRole('dialog', { name: 'Create a new project' })).not.toBeNull()
|
||||
expect(screen.queryByRole('button', { name: /Back/i })).toBeNull()
|
||||
expect(await screen.findByText('Git repository in /home/alice/orca/projects')).not.toBeNull()
|
||||
expect(browseRuntimeServerDirectoryMock).toHaveBeenCalledWith('wsl-ubuntu', '~')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user