// Shared scaffolding for the assembled-jsdom snapshots: the real built // workspace `lib/client.js` artifacts booted through AppWebEntry's // ModuleLoader path (loadBundle) against the keyless FixtureApiClient // transport. Every file that mounts this graph needs the same boot entry list, // the same bundle map, the same jsdom globals, and the same mount call, and // differs only in what it asserts afterwards, so the scaffolding lives here. // // Keyless and deterministic: the fixture is the fake server, so nothing here // reaches a model or the network. import { readFileSync } from 'node:fs' import { createRequire } from 'node:module' import { dirname, join, resolve } from 'node:path' import { pathToFileURL } from 'node:url' import { act, cleanup } from '@testing-library/react' import { afterEach, beforeEach, vi } from 'vitest' import { injectBootManifest, orderByModuleGraph } from '@deepseek-ai/dsh-client-modules' import type { ClientModuleLoaderTarget, WebBootEntry } from '@deepseek-ai/dsh-client-modules/client' import { AppWebEntry } from '@deepseek-ai/dsh-client-web' interface AssembledPlugin extends WebBootEntry { /** Absolute path to the built client artifact declared by this package. */ bundlePath: string } interface ClientPackageManifest { name?: string exports?: Record dsh?: { client?: { platform?: string inject?: string[] external?: string[] immediately?: boolean } } } interface ComposedEntry { name?: unknown disabled?: unknown } interface BootComposition { loadOverlayPatches(binName: string, file: string): unknown[] composeEntries(layers: readonly unknown[][]): ComposedEntry[] } const REPO_ROOT = process.cwd() const BUNDLE_LAYERS = [ { manifest: join(REPO_ROOT, 'packages/bundle/base/package.json'), patch: join(REPO_ROOT, 'packages/bundle/base/cordis.patch.yml'), }, { manifest: join(REPO_ROOT, 'packages/bundle/web-app/package.json'), patch: join(REPO_ROOT, 'packages/bundle/web-app/cordis.patch.yml'), }, ] as const const bundleResolvers = BUNDLE_LAYERS.map(layer => createRequire(layer.manifest)) const webBundleResolver = bundleResolvers[1] if (webBundleResolver === undefined) throw new Error('assembled boot: web bundle resolver missing') const appBoot = await import(pathToFileURL(webBundleResolver.resolve('@deepseek-ai/dsh-app-boot')).href) as unknown as BootComposition function resolvePackageManifest(specifier: string): string | undefined { for (const require of bundleResolvers) { try { return require.resolve(`${specifier}/package.json`) } catch { continue } } return undefined } function resolveClientExport(packagePath: string, pkg: ClientPackageManifest): string { const declared = pkg.exports?.['./client'] const relative = typeof declared === 'string' ? declared : declared?.default if (relative === undefined) { throw new Error(`assembled boot: ${pkg.name ?? packagePath} declares dsh.client without a ./client export`) } return resolve(dirname(packagePath), relative) } /** Derive the assembled browser graph from the same bundle patches and package declarations as `dsh web`. */ function loadAssembledPlugins(): readonly AssembledPlugin[] { const entries = appBoot.composeEntries(BUNDLE_LAYERS.map(layer => appBoot.loadOverlayPatches('assembled boot', layer.patch))) const plugins = new Map() for (const entry of entries) { if (entry.disabled === true || typeof entry.name !== 'string') continue const packagePath = resolvePackageManifest(entry.name) if (packagePath === undefined) continue const pkg = JSON.parse(readFileSync(packagePath, 'utf8')) as ClientPackageManifest const declaration = pkg.dsh?.client if (declaration?.platform !== 'web') continue if (pkg.name !== entry.name) { throw new Error(`assembled boot: ${entry.name} resolved package ${pkg.name ?? ''}`) } plugins.set(entry.name, { id: entry.name, bundlePath: resolveClientExport(packagePath, pkg), url: `/plugins/${entry.name}/client.js?rev=fx`, rev: 'fx', ...(declaration.inject === undefined ? {} : { inject: declaration.inject }), ...(declaration.external === undefined ? {} : { external: declaration.external }), ...(declaration.immediately === true ? { immediately: true } : {}), }) } return orderByModuleGraph([...plugins.values()]).map(({ id }) => { const plugin = plugins.get(id) /* v8 ignore next -- orderByModuleGraph returns the input row identities */ if (plugin === undefined) throw new Error(`assembled boot: ordered unknown client package ${id}`) return plugin }) } const PLUGINS = loadAssembledPlugins() const bundles = new Map(PLUGINS.map(plugin => [ plugin.url, readFileSync(plugin.bundlePath, 'utf8'), ])) interface FixtureWindow extends Window { __DSH_BOOT__?: { rev: string; entries: WebBootEntry[] } __ModuleLoader__?: ClientModuleLoaderTarget } class ResizeObserverStub { observe(): void {} disconnect(): void {} unobserve(): void {} } class EventSourceStub { addEventListener(): void {} close(): void {} } const win = window as FixtureWindow let unmount: (() => Promise) | undefined /** * Register the per-test jsdom setup and teardown the assembled boot needs: * English pinned before boot so role/text locators stay deterministic across * localized component migrations (the newEnglishPage e2e convention), the * observers and frame callbacks jsdom lacks, and a full reset of the document, * the boot globals, and the injected plugin styles afterwards. */ export function installAssembledBootEnv(): void { beforeEach(() => { localStorage.clear() // The locale service derives its provisional locale from the browser and // takes an explicit choice only from Host settings, which this lane's // fixture transport does not serve; pinning the navigator is what selects // English here. Object.defineProperty(navigator, 'languages', { value: ['en-US'], configurable: true }) Object.defineProperty(navigator, 'language', { value: 'en-US', configurable: true }) document.title = 'DeepSeek Harness' vi.stubGlobal('ResizeObserver', ResizeObserverStub) vi.stubGlobal('EventSource', EventSourceStub) vi.stubGlobal('requestAnimationFrame', (callback: FrameRequestCallback) => setTimeout(() => { callback(0) }, 0) as unknown as number) vi.stubGlobal('cancelAnimationFrame', (id: number) => { clearTimeout(id) }) }) afterEach(async () => { await act(async () => { await unmount?.() }) unmount = undefined cleanup() delete win.__DSH_BOOT__ delete win.__ModuleLoader__ document.body.innerHTML = '' document.head.querySelectorAll('style[data-plugin]').forEach((style) => { style.remove() }) document.title = '' history.replaceState(null, '', '/') // Deleting the own properties uncovers jsdom's own accessors again // (Navigator declares both readonly, hence the erased receiver). const ownNavigator = navigator as unknown as Record delete ownNavigator.languages delete ownNavigator.language vi.unstubAllGlobals() }) } /** * Mount the assembled application on the fixture transport; the teardown * registered by installAssembledBootEnv disposes it. * @param search - fixture query string used to select deterministic host behavior. */ export function mountAssembledApp(search = '?fixture'): void { history.replaceState(null, '', `/${search}`) const root = document.createElement('div') root.id = 'root' document.body.appendChild(root) win.__DSH_BOOT__ = { rev: 'fx', entries: PLUGINS.map(({ bundlePath: _bundlePath, ...plugin }) => plugin) } const html = injectBootManifest('', win.__DSH_BOOT__) const facadeSource = /