one
Version:
One is a new React Framework that makes Vite serve both native and web.
84 lines (69 loc) • 2.96 kB
text/typescript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
type RouteHmrModule = typeof import('./routeHmr.native')
describe('routeHmr.native', () => {
let routeHmr: RouteHmrModule
const realWindow = (globalThis as any).window
const realModuleUpdatedHook = globalThis.__VXRN_ON_MODULE_UPDATED__
beforeEach(async () => {
// the __VXRN_ON_MODULE_UPDATED__ registration is dev-gated and runs at module
// load, so stub NODE_ENV then re-import to exercise it
vi.stubEnv('NODE_ENV', 'development')
vi.resetModules()
routeHmr = await import('./routeHmr.native')
})
afterEach(() => {
vi.unstubAllEnvs()
globalThis.__VXRN_ON_MODULE_UPDATED__ = realModuleUpdatedHook
;(globalThis as any).window = realWindow
})
it('registers globalThis.__VXRN_ON_MODULE_UPDATED__ in development', () => {
expect(typeof globalThis.__VXRN_ON_MODULE_UPDATED__).toBe('function')
})
it('does not bump the epoch, so Fast Refresh can keep the mounted route', () => {
const before = routeHmr.getRouteHmrEpoch()
const listener = vi.fn()
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')
expect(routeHmr.getRouteHmrEpoch()).toBe(before)
expect(listener).not.toHaveBeenCalled()
unsubscribe()
})
it('evicts the route cache for the updated file when window.__oneRouteCache is present', () => {
const clearFile = vi.fn(() => true)
;(globalThis as any).window = { __oneRouteCache: { clearFile } }
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/_layout.tsx')
expect(clearFile).toHaveBeenCalledWith('app/_layout.tsx')
})
it('does not bump the epoch for a non-route module either', () => {
const before = routeHmr.getRouteHmrEpoch()
const listener = vi.fn()
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
;(globalThis as any).window = {
__oneRouteCache: { clearFile: () => false },
}
globalThis.__VXRN_ON_MODULE_UPDATED__!('features/onboarding/HmrProbeChild.tsx')
expect(routeHmr.getRouteHmrEpoch()).toBe(before)
expect(listener).not.toHaveBeenCalled()
unsubscribe()
})
it('does not throw when window / route cache is absent', () => {
;(globalThis as any).window = undefined
expect(() => globalThis.__VXRN_ON_MODULE_UPDATED__!('x.tsx')).not.toThrow()
})
it('does not throw or bump the epoch when route-cache eviction throws', () => {
const listener = vi.fn()
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
const before = routeHmr.getRouteHmrEpoch()
;(globalThis as any).window = {
__oneRouteCache: {
clearFile() {
throw new Error('cache eviction failed')
},
},
}
expect(() => globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')).not.toThrow()
expect(routeHmr.getRouteHmrEpoch()).toBe(before)
expect(listener).not.toHaveBeenCalled()
unsubscribe()
})
})