Files
zeekay 2e333bdcbe fix(webui): pin vitest to 3.x to match vite 5; set window.APIUrl in tests
Two compounding issues blocked the upstream image build:

1. An incomplete dep bump moved `vitest: ^3.2.4` → `^4.0.3` and added
   `@vitest/web-worker: ^4.0.2`, but left `vite: ^5.4.19` and
   `@vitest/coverage-v8: ^3.2.4`. Vitest 4 needs Vite 6+, so vitest's
   internal `vite/module-runner` import threw ERR_PACKAGE_PATH_NOT_EXPORTED
   on every test run. Pin vitest + @vitest/web-worker back to ^3.2.4 to
   match the rest of the trio. (Forward-port to vitest 4 is an explicit
   step that should also bump vite to ^6 and coverage-v8 to ^4.)

2. The webui test suite has rebrand-era request mocks at /v1/ingress/*
   but `BASE_PATH` (src/libs/utils.ts) reads `window.APIUrl` at
   module-load and falls back to ''. With BASE_PATH='', SWR fetched
   /http/routers/<x> and missed every msw handler — 4 tests timed out
   on `waitFor(...not.toBeUndefined)`. Set `window.APIUrl=/v1/ingress`
   at the top of test/setup.ts (before the mock server import) to
   match production.

Result: 28 test files, 125/125 pass. The Build experimental image
workflow can now produce ghcr.io/hanzoai/ingress:<branch>; the v1.7.x
branch and v1.7.37 tag both unblock.
2026-05-06 15:50:45 -07:00

91 lines
2.1 KiB
TypeScript

// Match the production API mount point. `BASE_PATH` (from
// src/libs/utils.ts) reads window.APIUrl on first import; without
// this, fetches resolve to '/http/routers/<x>' instead of
// '/v1/ingress/http/routers/<x>' and miss every msw handler.
//
// Must run BEFORE the imports below — Vitest's setupFiles are
// processed in source order and the mock server captures BASE_PATH
// at module load.
;(globalThis as unknown as { window: { APIUrl: string } }).window =
(globalThis as unknown as { window?: { APIUrl?: string } }).window || ({} as { APIUrl: string })
;(globalThis as unknown as { window: { APIUrl: string } }).window.APIUrl = '/v1/ingress'
import '@testing-library/jest-dom'
import 'vitest-canvas-mock'
import '@vitest/web-worker'
import * as matchers from 'jest-extended'
import { expect } from 'vitest'
import { server } from '../src/mocks/server'
expect.extend(matchers)
export class IntersectionObserver {
root = null
rootMargin = ''
thresholds = []
scrollMargin = ''
disconnect() {
return null
}
observe() {
return null
}
takeRecords() {
return []
}
unobserve() {
return null
}
}
class ResizeObserver {
observe() {
return null
}
unobserve() {
return null
}
disconnect() {
return null
}
}
beforeAll(() => {
globalThis.IntersectionObserver = IntersectionObserver
window.IntersectionObserver = IntersectionObserver
globalThis.ResizeObserver = ResizeObserver
window.ResizeObserver = ResizeObserver
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(), // deprecated
removeListener: vi.fn(), // deprecated
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
})),
})
Object.defineProperty(window, 'scrollTo', {
writable: true,
value: vi.fn(),
})
server.listen({ onUnhandledRequest: 'error' })
})
afterEach(() => server.resetHandlers())
afterAll(() => server.close())