import type { IncomingMessage, ServerResponse } from 'node:http' import type { ProjectBrowser } from './project' import type { ParentBrowserProject } from './projectParent' import { stringify } from 'flatted' import { replacer } from './utils' export async function resolveOrchestrator( globalServer: ParentBrowserProject, url: URL, res: ServerResponse, ): Promise { const sessionId = url.searchParams.get('sessionId') const session = sessionId && globalServer.vitest._browserSessions.getSession(sessionId) if (!session) { return } const browserProject = session.project.browser as ProjectBrowser | undefined if (!browserProject) { return } const injectorJs = typeof globalServer.injectorJs === 'string' ? globalServer.injectorJs : await globalServer.injectorJs const injector = replacer(injectorJs, { __VITEST_PROVIDER__: JSON.stringify(browserProject.config.browser.provider?.name || 'preview'), __VITEST_CONFIG__: JSON.stringify(browserProject.wrapSerializedConfig()), __VITEST_VITE_CONFIG__: JSON.stringify({ root: browserProject.vite.config.root, }), __VITEST_METHOD__: JSON.stringify('orchestrate'), __VITEST_TYPE__: '"orchestrator"', __VITEST_SESSION_ID__: JSON.stringify(sessionId), __VITEST_TESTER_ID__: '"none"', __VITEST_OTEL_CARRIER__: JSON.stringify(session?.otelCarrier ?? null), __VITEST_PROVIDED_CONTEXT__: JSON.stringify( stringify(browserProject.project.getProvidedContext()), ), __VITEST_API_TOKEN__: JSON.stringify(globalServer.vitest.config.api.token), }) // disable CSP for the orchestrator as we are the ones controlling it res.removeHeader('Content-Security-Policy') if (!globalServer.orchestratorScripts) { globalServer.orchestratorScripts = ( await globalServer.formatScripts(globalServer.config.browser.orchestratorScripts) ) .map((script) => { let html = '` return html }) .join('\n') } let baseHtml = typeof globalServer.orchestratorHtml === 'string' ? globalServer.orchestratorHtml : await globalServer.orchestratorHtml // if UI is enabled, use UI HTML and inject the orchestrator script if (globalServer.config.browser.ui) { const manifestContent = globalServer.manifest instanceof Promise ? await globalServer.manifest : globalServer.manifest const jsEntry = manifestContent['orchestrator.html'].file const base = browserProject.parent.vite.config.base || '/' baseHtml = baseHtml .replace('href="./favicon.ico"', `href="${base}__vitest__/favicon.ico"`) .replace('href="./favicon.svg"', `href="${base}__vitest__/favicon.svg"`) .replaceAll('./assets/', `${base}__vitest__/assets/`) .replace( '', [ ``, '{__VITEST_INJECTOR__}', '{__VITEST_ERROR_CATCHER__}', '{__VITEST_SCRIPTS__}', ``, ].join('\n'), ) } return replacer(baseHtml, { __VITEST_FAVICON__: globalServer.faviconUrl, __VITEST_TITLE__: 'Vitest Browser Runner', __VITEST_SCRIPTS__: globalServer.orchestratorScripts, __VITEST_INJECTOR__: ``, __VITEST_ERROR_CATCHER__: ``, __VITEST_SESSION_ID__: JSON.stringify(sessionId), }) } function escapeInlineScript(content: string): string { return content.replace(/