756 lines
21 KiB
TypeScript
756 lines
21 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const callMock = vi.fn()
|
|
|
|
vi.mock('./runtime-client', () => {
|
|
class RuntimeClient {
|
|
call = callMock
|
|
getCliStatus = vi.fn()
|
|
openOrca = vi.fn()
|
|
}
|
|
|
|
class RuntimeClientError extends Error {
|
|
readonly code: string
|
|
|
|
constructor(code: string, message: string) {
|
|
super(message)
|
|
this.code = code
|
|
}
|
|
}
|
|
|
|
class RuntimeRpcFailureError extends RuntimeClientError {
|
|
readonly response: unknown
|
|
|
|
constructor(response: unknown) {
|
|
super('runtime_error', 'runtime_error')
|
|
this.response = response
|
|
}
|
|
}
|
|
|
|
return {
|
|
RuntimeClient,
|
|
RuntimeClientError,
|
|
RuntimeRpcFailureError
|
|
}
|
|
})
|
|
|
|
import { main } from './index'
|
|
import { RuntimeClientError } from './runtime-client'
|
|
import { buildWorktree, okFixture, queueFixtures, worktreeListFixture } from './test-fixtures'
|
|
|
|
describe('orca cli browser page targeting', () => {
|
|
beforeEach(() => {
|
|
callMock.mockReset()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('passes explicit page ids to snapshot without resolving the current worktree', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_snapshot', {
|
|
browserPageId: 'page-1',
|
|
snapshot: 'tree',
|
|
refs: [],
|
|
url: 'https://example.com',
|
|
title: 'Example'
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['snapshot', '--page', 'page-1', '--json'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.snapshot', { page: 'page-1' })
|
|
})
|
|
|
|
it('resolves current worktree only when --page is combined with --worktree current', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
worktreeListFixture([buildWorktree('/tmp/repo/feature', 'feature/foo')]),
|
|
okFixture('req_snapshot', {
|
|
browserPageId: 'page-1',
|
|
snapshot: 'tree',
|
|
refs: [],
|
|
url: 'https://example.com',
|
|
title: 'Example'
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['snapshot', '--page', 'page-1', '--worktree', 'current', '--json'],
|
|
'/tmp/repo/feature/src'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenNthCalledWith(1, 'worktree.list', { limit: 10_000 })
|
|
expect(callMock).toHaveBeenNthCalledWith(2, 'browser.snapshot', {
|
|
page: 'page-1',
|
|
worktree: 'id:repo::/tmp/repo/feature'
|
|
})
|
|
})
|
|
|
|
it('passes page-targeted tab switches through without auto-scoping to the current worktree', async () => {
|
|
queueFixtures(callMock, okFixture('req_switch', { switched: 2, browserPageId: 'page-2' }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'switch', '--page', 'page-2', '--json'], '/tmp/repo/feature/src')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabSwitch', {
|
|
index: undefined,
|
|
page: 'page-2'
|
|
})
|
|
})
|
|
|
|
it('still resolves the current worktree when tab switch --page is combined with --worktree current', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
worktreeListFixture([buildWorktree('/tmp/repo/feature', 'feature/foo')]),
|
|
okFixture('req_switch', { switched: 2, browserPageId: 'page-2' })
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'switch', '--page', 'page-2', '--worktree', 'current', '--json'],
|
|
'/tmp/repo/feature/src'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenNthCalledWith(1, 'worktree.list', { limit: 10_000 })
|
|
expect(callMock).toHaveBeenNthCalledWith(2, 'browser.tabSwitch', {
|
|
index: undefined,
|
|
page: 'page-2',
|
|
worktree: 'id:repo::/tmp/repo/feature'
|
|
})
|
|
})
|
|
|
|
it('passes focus: true through to browser.tabSwitch when --focus is set', async () => {
|
|
queueFixtures(callMock, okFixture('req_switch', { switched: 1, browserPageId: 'page-1' }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'switch', '--page', 'page-1', '--focus', '--json'], '/tmp/repo/feature/src')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabSwitch', {
|
|
index: undefined,
|
|
page: 'page-1',
|
|
focus: true
|
|
})
|
|
})
|
|
|
|
it('omits focus from the payload when --focus is absent', async () => {
|
|
queueFixtures(callMock, okFixture('req_switch', { switched: 1, browserPageId: 'page-1' }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'switch', '--page', 'page-1', '--json'], '/tmp/repo/feature/src')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
const call = callMock.mock.calls[0]
|
|
expect(call[0]).toBe('browser.tabSwitch')
|
|
expect(call[1]).not.toHaveProperty('focus')
|
|
})
|
|
|
|
it('passes explicit profile ids to tab create', async () => {
|
|
queueFixtures(callMock, okFixture('req_create', { browserPageId: 'page-3' }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
[
|
|
'tab',
|
|
'create',
|
|
'--url',
|
|
'https://example.com',
|
|
'--profile',
|
|
'work',
|
|
'--worktree',
|
|
'all',
|
|
'--json'
|
|
],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith(
|
|
'browser.tabCreate',
|
|
{
|
|
url: 'https://example.com',
|
|
worktree: undefined,
|
|
profileId: 'work'
|
|
},
|
|
{ timeoutMs: 60_000 }
|
|
)
|
|
})
|
|
|
|
it('passes tab profile updates through by page id', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_set_profile', {
|
|
browserPageId: 'page-2',
|
|
profileId: 'work',
|
|
profileLabel: 'Work'
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'set', '--page', 'page-2', '--profile', 'work', '--json'],
|
|
'/tmp/repo/feature/src'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabSetProfile', {
|
|
page: 'page-2',
|
|
profileId: 'work'
|
|
})
|
|
})
|
|
|
|
it('shows tab profile labels in text mode when requested', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_list', {
|
|
tabs: [
|
|
{
|
|
browserPageId: 'page-1',
|
|
index: 0,
|
|
url: 'https://example.com',
|
|
title: 'Example',
|
|
active: true,
|
|
profileId: 'default',
|
|
profileLabel: 'Default'
|
|
},
|
|
{
|
|
browserPageId: 'page-2',
|
|
index: 1,
|
|
url: 'https://mail.example.com',
|
|
title: 'Mail',
|
|
active: false,
|
|
profileId: 'work',
|
|
profileLabel: 'Work'
|
|
}
|
|
]
|
|
})
|
|
)
|
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'list', '--show-profile', '--worktree', 'all'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabList', { worktree: undefined })
|
|
expect(logSpy).toHaveBeenCalledWith(
|
|
'* [0] page-1 Example — https://example.com [Default]\n' +
|
|
' [1] page-2 Mail — https://mail.example.com [Work]'
|
|
)
|
|
})
|
|
|
|
it('shows a single tab by page id', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_tab_show', {
|
|
tab: {
|
|
browserPageId: 'page-1',
|
|
index: 0,
|
|
url: 'https://example.com',
|
|
title: 'Example',
|
|
active: true,
|
|
worktreeId: 'repo::/tmp/repo/feature',
|
|
profileId: 'work',
|
|
profileLabel: 'Work'
|
|
}
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'show', '--page', 'page-1', '--json'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabShow', { page: 'page-1' })
|
|
})
|
|
|
|
it('resolves the current tab in a worktree', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_tab_current', {
|
|
tab: {
|
|
browserPageId: 'page-2',
|
|
index: 1,
|
|
url: 'https://mail.example.com',
|
|
title: 'Mail',
|
|
active: true,
|
|
worktreeId: 'repo::/tmp/repo/feature',
|
|
profileId: 'default',
|
|
profileLabel: 'Default'
|
|
}
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'current', '--worktree', 'all', '--json'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabCurrent', { worktree: undefined })
|
|
})
|
|
})
|
|
|
|
describe('orca cli browser profile management', () => {
|
|
beforeEach(() => {
|
|
callMock.mockReset()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('shows the profile bound to a tab', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profile_show', {
|
|
browserPageId: 'page-2',
|
|
worktreeId: 'repo::/tmp/repo/feature',
|
|
profileId: 'work',
|
|
profileLabel: 'Work'
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'show', '--page', 'page-2', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabProfileShow', { page: 'page-2' })
|
|
})
|
|
|
|
it('switches a tab back to the default profile', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profile_default', {
|
|
browserPageId: 'page-2',
|
|
profileId: 'default',
|
|
profileLabel: 'Default'
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'use-default', '--page', 'page-2', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabSetProfile', {
|
|
page: 'page-2',
|
|
profileId: 'default'
|
|
})
|
|
})
|
|
|
|
it('clones a tab into a different profile', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profile_clone', {
|
|
browserPageId: 'page-9',
|
|
sourceBrowserPageId: 'page-2',
|
|
profileId: 'work',
|
|
profileLabel: 'Work'
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'clone', '--page', 'page-2', '--profile', 'work', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.tabProfileClone', {
|
|
page: 'page-2',
|
|
profileId: 'work'
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('orca cli browser tab profiles', () => {
|
|
beforeEach(() => {
|
|
callMock.mockReset()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('lists browser tab profiles', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profiles', {
|
|
profiles: [
|
|
{ id: 'default', scope: 'default', label: 'Default', partition: 'persist:orca-browser' },
|
|
{
|
|
id: 'work',
|
|
scope: 'isolated',
|
|
label: 'Work',
|
|
partition: 'persist:orca-browser-session-work'
|
|
}
|
|
]
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'profile', 'list', '--json'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.profileList')
|
|
})
|
|
|
|
it('reports an empty browser tab profile list with a friendly message', async () => {
|
|
queueFixtures(callMock, okFixture('req_profiles', { profiles: [] }))
|
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'profile', 'list'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.profileList')
|
|
expect(logSpy).toHaveBeenCalledWith('No browser profiles found.')
|
|
})
|
|
|
|
it('marks native-UA profiles in text output', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profiles_native_ua', {
|
|
profiles: [
|
|
{
|
|
id: 'google',
|
|
scope: 'isolated',
|
|
label: 'Google',
|
|
partition: 'persist:orca-browser-session-google',
|
|
source: null,
|
|
userAgentMode: 'native'
|
|
}
|
|
]
|
|
})
|
|
)
|
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'profile', 'list'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('ua:native'))
|
|
})
|
|
|
|
it('creates isolated browser tab profiles by default', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profile_create', {
|
|
profile: {
|
|
id: 'work',
|
|
scope: 'isolated',
|
|
label: 'Work',
|
|
partition: 'persist:orca-browser-session-work'
|
|
}
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'create', '--label', 'Work', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.profileCreate', {
|
|
label: 'Work',
|
|
scope: 'isolated'
|
|
})
|
|
})
|
|
|
|
it('forwards --scope imported through to the runtime', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profile_create', {
|
|
profile: {
|
|
id: 'imp',
|
|
scope: 'imported',
|
|
label: 'From Chrome',
|
|
partition: 'persist:orca-browser-session-imp'
|
|
}
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'create', '--label', 'From Chrome', '--scope', 'imported', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledWith('browser.profileCreate', {
|
|
label: 'From Chrome',
|
|
scope: 'imported'
|
|
})
|
|
})
|
|
|
|
it('creates a profile with the native user agent when requested', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profile_native_ua', {
|
|
profile: {
|
|
id: 'google',
|
|
scope: 'isolated',
|
|
label: 'Google',
|
|
partition: 'persist:orca-browser-session-google',
|
|
userAgentMode: 'native'
|
|
}
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'create', '--label', 'Google', '--no-ua-spoof', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledWith('browser.profileCreate', {
|
|
label: 'Google',
|
|
scope: 'isolated',
|
|
userAgentMode: 'native'
|
|
})
|
|
})
|
|
|
|
it('rejects unknown --scope values instead of silently defaulting to isolated', async () => {
|
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'create', '--label', 'Work', '--scope', 'isloated'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).not.toHaveBeenCalled()
|
|
expect(errorSpy).toHaveBeenCalledWith('--scope must be "isolated" or "imported"')
|
|
})
|
|
|
|
it('surfaces a runtime error if the registry refuses to create a profile', async () => {
|
|
queueFixtures(callMock, okFixture('req_profile_create', { profile: null }))
|
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'profile', 'create', '--label', 'Bogus'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(errorSpy).toHaveBeenCalledWith(
|
|
'Failed to create browser profile (label=Bogus, scope=isolated)'
|
|
)
|
|
})
|
|
|
|
it('deletes browser tab profiles by id', async () => {
|
|
queueFixtures(callMock, okFixture('req_profile_delete', { deleted: true, profileId: 'work' }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['tab', 'profile', 'delete', '--profile', 'work', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledTimes(1)
|
|
expect(callMock).toHaveBeenCalledWith('browser.profileDelete', { profileId: 'work' })
|
|
})
|
|
|
|
it('reports a not-deleted profile in text mode without throwing', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_profile_delete', { deleted: false, profileId: 'default' })
|
|
)
|
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(['tab', 'profile', 'delete', '--profile', 'default'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(callMock).toHaveBeenCalledWith('browser.profileDelete', { profileId: 'default' })
|
|
expect(logSpy).toHaveBeenCalledWith('Profile default was not deleted')
|
|
})
|
|
})
|
|
|
|
describe('orca cli browser cookies', () => {
|
|
beforeEach(() => {
|
|
callMock.mockReset()
|
|
process.exitCode = undefined
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('passes a finite non-negative cookie expiry through as a number', async () => {
|
|
queueFixtures(callMock, okFixture('req_cookie', { success: true }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
[
|
|
'cookie',
|
|
'set',
|
|
'--name',
|
|
'sid',
|
|
'--value',
|
|
'x',
|
|
'--expires',
|
|
'0',
|
|
'--worktree',
|
|
'all',
|
|
'--json'
|
|
],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledWith('browser.cookie.set', {
|
|
name: 'sid',
|
|
value: 'x',
|
|
expires: 0,
|
|
worktree: undefined
|
|
})
|
|
})
|
|
|
|
it.each(['not-a-number', 'Infinity', '-1'])(
|
|
'rejects invalid cookie expiry value %s before RPC dispatch',
|
|
async (expires) => {
|
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
const priorExitCode = process.exitCode
|
|
|
|
await main(
|
|
['cookie', 'set', '--name', 'sid', '--value', 'x', '--expires', expires],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).not.toHaveBeenCalled()
|
|
expect(errorSpy.mock.calls.flat().join('\n')).toContain(`Invalid --expires value: ${expires}`)
|
|
expect(process.exitCode).toBe(1)
|
|
|
|
process.exitCode = priorExitCode
|
|
}
|
|
)
|
|
|
|
it('rejects --expires without a value before RPC dispatch', async () => {
|
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
const priorExitCode = process.exitCode
|
|
|
|
await main(
|
|
['cookie', 'set', '--name', 'sid', '--value', 'x', '--expires'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).not.toHaveBeenCalled()
|
|
expect(errorSpy.mock.calls.flat().join('\n')).toContain('Missing value for --expires.')
|
|
expect(process.exitCode).toBe(1)
|
|
|
|
process.exitCode = priorExitCode
|
|
})
|
|
})
|
|
|
|
describe('orca cli browser waits and viewport flags', () => {
|
|
beforeEach(() => {
|
|
callMock.mockReset()
|
|
process.exitCode = undefined
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('gives selector waits an explicit RPC timeout budget', async () => {
|
|
queueFixtures(callMock, okFixture('req_wait', { ok: true }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['wait', '--selector', '#ready', '--worktree', 'all', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledWith(
|
|
'browser.wait',
|
|
{
|
|
selector: '#ready',
|
|
timeout: undefined,
|
|
text: undefined,
|
|
url: undefined,
|
|
load: undefined,
|
|
fn: undefined,
|
|
state: undefined,
|
|
worktree: undefined
|
|
},
|
|
{ timeoutMs: 60_000 }
|
|
)
|
|
})
|
|
|
|
it('extends selector wait RPC timeout when the user passes --timeout', async () => {
|
|
queueFixtures(callMock, okFixture('req_wait', { ok: true }))
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
['wait', '--selector', '#ready', '--timeout', '12000', '--worktree', 'all', '--json'],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledWith(
|
|
'browser.wait',
|
|
{
|
|
selector: '#ready',
|
|
timeout: 12000,
|
|
text: undefined,
|
|
url: undefined,
|
|
load: undefined,
|
|
fn: undefined,
|
|
state: undefined,
|
|
worktree: undefined
|
|
},
|
|
{ timeoutMs: 17000 }
|
|
)
|
|
})
|
|
|
|
it('does not tell users Orca is down for a generic runtime timeout', async () => {
|
|
callMock.mockRejectedValueOnce(
|
|
new RuntimeClientError(
|
|
'runtime_timeout',
|
|
'Timed out waiting for the Orca runtime to respond.'
|
|
)
|
|
)
|
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
|
|
await main(['wait', '--selector', '#ready', '--worktree', 'all'], '/tmp/not-an-orca-worktree')
|
|
|
|
expect(errorSpy).toHaveBeenCalledWith('Timed out waiting for the Orca runtime to respond.')
|
|
})
|
|
|
|
it('passes the mobile viewport flag through to browser.viewport', async () => {
|
|
queueFixtures(
|
|
callMock,
|
|
okFixture('req_viewport', {
|
|
width: 375,
|
|
height: 812,
|
|
deviceScaleFactor: 2,
|
|
mobile: true
|
|
})
|
|
)
|
|
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
await main(
|
|
[
|
|
'viewport',
|
|
'--width',
|
|
'375',
|
|
'--height',
|
|
'812',
|
|
'--scale',
|
|
'2',
|
|
'--mobile',
|
|
'--worktree',
|
|
'all',
|
|
'--json'
|
|
],
|
|
'/tmp/not-an-orca-worktree'
|
|
)
|
|
|
|
expect(callMock).toHaveBeenCalledWith('browser.viewport', {
|
|
width: 375,
|
|
height: 812,
|
|
deviceScaleFactor: 2,
|
|
mobile: true,
|
|
worktree: undefined
|
|
})
|
|
})
|
|
})
|