mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 10:27:33 +00:00
test: trim redundant browser cleanup and preview coverage (#42167)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
+3
-53
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import type { BrowserClientHostCommandEvent } from '../../../../shared/browser/client-hosting/browser-client-host-protocol'
|
||||
import { BrowserClientPageCommandExecutor } from '../execution/browser-client-page-command-executor'
|
||||
import {
|
||||
@@ -11,21 +11,17 @@ import type { BrowserRouteElectronSession } from '../../routing/sessions/browser
|
||||
import type { BrowserRoutePageGuestIdentity } from '../../routing/guest-authority/browser-route-page-authority'
|
||||
|
||||
const SSH_HOST_STORAGE = 'storage-ssh-target-a'
|
||||
const OTHER_HOST_STORAGE = 'storage-ssh-target-b'
|
||||
const GENERATION_1 = 'execution-host-ssh-a-gen-1'
|
||||
const GENERATION_2 = 'execution-host-ssh-a-gen-2'
|
||||
const OTHER_HOST = 'execution-host-ssh-b-gen-1'
|
||||
|
||||
const proxyPortByKey: Record<string, number> = {
|
||||
[GENERATION_1]: 43123,
|
||||
[GENERATION_2]: 43124,
|
||||
[OTHER_HOST]: 43125
|
||||
[GENERATION_2]: 43124
|
||||
}
|
||||
|
||||
const storageIdentityByKey: Record<string, string> = {
|
||||
[GENERATION_1]: SSH_HOST_STORAGE,
|
||||
[GENERATION_2]: SSH_HOST_STORAGE,
|
||||
[OTHER_HOST]: OTHER_HOST_STORAGE
|
||||
[GENERATION_2]: SSH_HOST_STORAGE
|
||||
}
|
||||
|
||||
function createHarness(options: { failedRouteRelease?: string } = {}) {
|
||||
@@ -142,52 +138,6 @@ function createPage(
|
||||
)
|
||||
}
|
||||
|
||||
describe('client-hosted pages across an execution host generation change', () => {
|
||||
it('retires the superseded pages so the reconnected route can bind the partition', async () => {
|
||||
const harness = createHarness()
|
||||
|
||||
expect(await createPage(harness.executor, 'page-a', GENERATION_1)).toEqual({
|
||||
status: 'completed'
|
||||
})
|
||||
expect(await createPage(harness.executor, 'page-b', GENERATION_2)).toEqual({
|
||||
status: 'completed'
|
||||
})
|
||||
|
||||
expect(harness.executor.hasPage('page-a', 7)).toBe(false)
|
||||
expect(harness.executor.hasPage('page-b', 7)).toBe(true)
|
||||
expect(harness.releasedRoutes).toEqual([GENERATION_1])
|
||||
expect(harness.proxyRulesFor(SSH_HOST_STORAGE)).toBe('socks5://127.0.0.1:43124')
|
||||
})
|
||||
|
||||
it('keeps the sibling pages that share the current route key', async () => {
|
||||
const harness = createHarness()
|
||||
|
||||
await createPage(harness.executor, 'page-a', GENERATION_1)
|
||||
expect(await createPage(harness.executor, 'page-b', GENERATION_1)).toEqual({
|
||||
status: 'completed'
|
||||
})
|
||||
|
||||
expect(harness.executor.hasPage('page-a', 7)).toBe(true)
|
||||
expect(harness.executor.hasPage('page-b', 7)).toBe(true)
|
||||
expect(harness.releasedRoutes).toEqual([])
|
||||
})
|
||||
|
||||
it('keeps the pages held on a different execution host', async () => {
|
||||
const harness = createHarness()
|
||||
|
||||
await createPage(harness.executor, 'page-a', OTHER_HOST)
|
||||
expect(await createPage(harness.executor, 'page-b', GENERATION_2)).toEqual({
|
||||
status: 'completed'
|
||||
})
|
||||
|
||||
expect(harness.executor.hasPage('page-a', 7)).toBe(true)
|
||||
expect(harness.executor.hasPage('page-b', 7)).toBe(true)
|
||||
expect(harness.releasedRoutes).toEqual([])
|
||||
expect(harness.proxyRulesFor(OTHER_HOST_STORAGE)).toBe('socks5://127.0.0.1:43125')
|
||||
expect(harness.proxyRulesFor(SSH_HOST_STORAGE)).toBe('socks5://127.0.0.1:43124')
|
||||
})
|
||||
})
|
||||
|
||||
it('allows a different legacy page to retarget only after exact native and network retirement despite a missing renderer acknowledgement', async () => {
|
||||
const h = createHarness()
|
||||
const destroyed = Promise.withResolvers<void>()
|
||||
|
||||
@@ -51,26 +51,6 @@ async function fixture(
|
||||
}
|
||||
|
||||
describe('staged client page profile switching', () => {
|
||||
it('finishes failed old-generation renderer cleanup on teardown without repeating its releases', async () => {
|
||||
const h = await fixture()
|
||||
h.renderer.retirePage.mockRejectedValueOnce(new Error('old-retirement-reply-lost'))
|
||||
const warning = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
try {
|
||||
expect(await h.executor.handle(switchCommand(), new AbortController().signal)).toMatchObject({
|
||||
status: 'completed'
|
||||
})
|
||||
expect(h.executor.snapshotPageInventory()).toMatchObject([
|
||||
{ pageHostGeneration: 8, state: 'active' }
|
||||
])
|
||||
expect(h.routeSession.release).toHaveBeenCalledTimes(1)
|
||||
await h.executor.close()
|
||||
expect(h.renderer.retirePage).toHaveBeenCalledTimes(3)
|
||||
expect(h.routeSession.release).toHaveBeenCalledTimes(1)
|
||||
} finally {
|
||||
warning.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
it('finishes independent pages, retained profile cleanup and uploads after one initializer cleanup fails', async () => {
|
||||
const h = await fixture()
|
||||
const signal = new AbortController().signal
|
||||
|
||||
@@ -81,33 +81,4 @@ describe('readDocPreviewFile — paired runtime owner', () => {
|
||||
status: 404
|
||||
})
|
||||
})
|
||||
|
||||
it('requires approval for a sibling directory before touching the runtime', async () => {
|
||||
const grant = mintDocPreviewGrant({
|
||||
owner: {
|
||||
kind: 'runtime',
|
||||
environmentId: 'env-1',
|
||||
worktreeSelector: 'id:wt-1',
|
||||
worktreeRoot: '/srv/repo'
|
||||
},
|
||||
requestBase: '/srv/repo',
|
||||
root: '/srv/repo/docs',
|
||||
entryRelativePath: 'docs/index.html',
|
||||
browserPageId: 'page-1'
|
||||
})
|
||||
|
||||
await expect(readDocPreviewFile(grant, 'assets/app.js')).resolves.toMatchObject({
|
||||
ok: false,
|
||||
status: 403,
|
||||
reason: 'authorization-required'
|
||||
})
|
||||
|
||||
authorizeDocPreviewDirectory(grant.id, 'assets/app.js')
|
||||
mocks.callRuntimeEnvironment.mockResolvedValue({
|
||||
ok: true,
|
||||
result: { content: 'console.log(1)', isBinary: false }
|
||||
})
|
||||
|
||||
await expect(readDocPreviewFile(grant, 'assets/app.js')).resolves.toMatchObject({ ok: true })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { readDocPreviewFile } from './doc-preview-file-reader'
|
||||
import {
|
||||
authorizeDocPreviewDirectory,
|
||||
mintDocPreviewGrant,
|
||||
revokeAllDocPreviewGrants
|
||||
} from './doc-preview-grant-registry'
|
||||
|
||||
const mocks = vi.hoisted(() => ({ call: vi.fn() }))
|
||||
vi.mock('../../ipc/runtime-environments/requests/runtime-environment-transport-routing', () => ({
|
||||
callRuntimeEnvironment: mocks.call
|
||||
}))
|
||||
vi.mock('../../ipc/runtime-environments/catalog/runtime-environment-registry-root', () => ({
|
||||
getRuntimeEnvironmentRegistryRoot: () => '/user-data'
|
||||
}))
|
||||
vi.mock('../../../shared/remote-runtime/host-store/runtime-environment-store', () => ({
|
||||
resolveEnvironment: () => ({ id: 'vps', createdAt: 1, pairingRevision: 12 })
|
||||
}))
|
||||
|
||||
function grant(root = '/tmp/reports'): ReturnType<typeof mintDocPreviewGrant> {
|
||||
return mintDocPreviewGrant({
|
||||
owner: {
|
||||
kind: 'runtime',
|
||||
environmentId: 'vps',
|
||||
worktreeSelector: 'id:source-workspace',
|
||||
worktreeRoot: '/srv/repo',
|
||||
fileAccess: 'terminal-artifact'
|
||||
},
|
||||
requestBase: root,
|
||||
root,
|
||||
entryRelativePath: 'report.html',
|
||||
browserPageId: 'page-1'
|
||||
})
|
||||
}
|
||||
|
||||
type HostEntry = { canonical?: string; openTarget?: Record<string, unknown> }
|
||||
|
||||
/** The paired host: resolveTerminalPath answers per path, reads answer with `read`. */
|
||||
function host(entries: Record<string, HostEntry>, read?: unknown): void {
|
||||
mocks.call.mockImplementation(
|
||||
async (_root: string, _env: string, method: string, params: { pathText?: string }) => {
|
||||
if (method !== 'files.resolveTerminalPath') {
|
||||
return read
|
||||
}
|
||||
const path = params.pathText ?? ''
|
||||
const entry = entries[path] ?? {}
|
||||
const canonical = entry.canonical ?? path
|
||||
return {
|
||||
ok: true,
|
||||
result: {
|
||||
absolutePath: canonical,
|
||||
openTarget: entry.openTarget ?? {
|
||||
kind: 'absolute-file',
|
||||
absolutePath: canonical,
|
||||
grantId: 'host-grant'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks()
|
||||
revokeAllDocPreviewGrants()
|
||||
})
|
||||
|
||||
describe('outside-workspace HTML preview', () => {
|
||||
it('does not resolve or read neighboring assets until their directory is approved', async () => {
|
||||
const page = grant()
|
||||
await expect(readDocPreviewFile(page, 'secret.json')).resolves.toMatchObject({
|
||||
ok: false,
|
||||
status: 403,
|
||||
reason: 'authorization-required'
|
||||
})
|
||||
|
||||
authorizeDocPreviewDirectory(page.id, 'assets/logo.png')
|
||||
host(
|
||||
{},
|
||||
{
|
||||
ok: true,
|
||||
result: {
|
||||
content: Buffer.from([137, 80, 78, 71]).toString('base64'),
|
||||
isBinary: true,
|
||||
mimeType: 'image/png'
|
||||
}
|
||||
}
|
||||
)
|
||||
await expect(readDocPreviewFile(page, 'assets/logo.png')).resolves.toMatchObject({
|
||||
ok: true,
|
||||
bytes: Buffer.from([137, 80, 78, 71]),
|
||||
contentType: 'image/png'
|
||||
})
|
||||
})
|
||||
|
||||
it('refuses symlink redirection outside an approved asset directory', async () => {
|
||||
const page = grant()
|
||||
authorizeDocPreviewDirectory(page.id, 'assets/data.json')
|
||||
host({ '/tmp/reports/assets/data.json': { canonical: '/home/dev/.config/credentials.json' } })
|
||||
|
||||
await expect(readDocPreviewFile(page, 'assets/data.json')).resolves.toMatchObject({
|
||||
ok: false
|
||||
})
|
||||
})
|
||||
|
||||
// The host canonicalizes these roots, so a nested symlink cannot leave the approved folder.
|
||||
})
|
||||
Reference in New Issue
Block a user