diff --git a/packages/core/src/client/inject/runtime.test.ts b/packages/core/src/client/inject/runtime.test.ts new file mode 100644 index 00000000..d653aaf5 --- /dev/null +++ b/packages/core/src/client/inject/runtime.test.ts @@ -0,0 +1,53 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { startDevTools } from './runtime' + +const mocks = vi.hoisted(() => ({ + getDevToolsRpcClient: vi.fn( + (_options: { baseURL: string[] }) => new Promise(() => {}), + ), +})) + +vi.mock('@vitejs/devtools-kit/client', () => ({ + CLIENT_CONTEXT_KEY: '__VITE_DEVTOOLS_CLIENT_CONTEXT__', + getDevToolsRpcClient: mocks.getDevToolsRpcClient, +})) + +vi.mock('@vueuse/core', () => ({ + useLocalStorage: vi.fn(), +})) + +vi.mock('../webcomponents/state/context', () => ({ + createDocksContext: vi.fn(), +})) + +describe('injected DevTools runtime', () => { + beforeEach(() => { + const hostWindow = { + addEventListener: vi.fn(), + } as unknown as Window + Object.defineProperty(hostWindow, 'parent', { value: hostWindow }) + vi.stubGlobal('window', hostWindow) + + startDevTools('normal') + }) + + afterEach(() => { + vi.unstubAllGlobals() + mocks.getDevToolsRpcClient.mockClear() + }) + + it('preserves the host-relative mount path as the primary base', () => { + const options = mocks.getDevToolsRpcClient.mock.calls[0]![0] + + expect(options.baseURL).toHaveLength(2) + expect(options.baseURL[0]).toBe('/__devtools/') + }) + + it('adds the Vite module origin as the fallback base', () => { + const options = mocks.getDevToolsRpcClient.mock.calls[0]![0] + + expect(options.baseURL[1]).toBe( + new URL('/__devtools/', import.meta.url).href, + ) + }) +}) diff --git a/packages/core/src/client/inject/runtime.ts b/packages/core/src/client/inject/runtime.ts index df483659..0a5d2c52 100644 --- a/packages/core/src/client/inject/runtime.ts +++ b/packages/core/src/client/inject/runtime.ts @@ -50,10 +50,15 @@ async function mountDock(): Promise { if (dockEl) return - // Inject runs in the user's host page, so `document.baseURI` points at - // the user's app — not at the Vite DevTools mount. Pass the mount path - // explicitly so the connection meta lookup hits `/__devtools/__connection.json`. - const rpc = await getDevToolsRpcClient({ baseURL: DEVTOOLS_MOUNT_PATH }) + // Prefer the host page's origin for backwards compatibility. When the page + // is served by another backend, fall back to the Vite origin that loaded + // this module. + const rpc = await getDevToolsRpcClient({ + baseURL: [ + DEVTOOLS_MOUNT_PATH, + new URL(DEVTOOLS_MOUNT_PATH, import.meta.url).href, + ], + }) const state = useLocalStorage( 'vite-devtools-dock-state',