Ctrl K
ComunidadGuías…

frontend/test/route-chunk.test.ts

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/* 低频页 chunk 的装载(ADR-0118):打开页面时装不上而服务还在,说明旧入口指着已删除的 chunk,整页重载一次;
 * 同一会话 30 秒内不重载第二次,服务连不上不重载,空闲预热失败不重载。 */
import { afterEach, beforeEach, expect, it, vi } from 'vitest';

let reload: ReturnType<typeof vi.fn>;
beforeEach(() => {
  vi.resetModules();
  sessionStorage.clear();
  reload = vi.fn();
  vi.stubGlobal('location', { ...window.location, reload });
});
afterEach(() => { vi.unstubAllGlobals(); vi.useRealTimers() });

const missing = () => Promise.reject(new TypeError('Failed to fetch dynamically imported module'));

it('装上之前 get() 抛错,装上之后同步拿到模块,第二次打开不再装载', async () => {
  const { routeChunk } = await import('../src/react/router/route-chunk');
  const load = vi.fn(async () => ({ Page: 'page' }));
  const chunk = routeChunk(load);
  expect(() => chunk.get()).toThrow('页面代码还没装载');
  await chunk.preload();
  await chunk.preload();
  expect(chunk.get()).toEqual({ Page: 'page' });
  expect(load).toHaveBeenCalledTimes(1);
});

it('打开时装不上而服务可达就重载一次,30 秒内再失败不重载,失败的那次不记住、下次重试', async () => {
  vi.stubGlobal('fetch', vi.fn(async () => ({ ok: true })));
  const { routeChunk } = await import('../src/react/router/route-chunk');
  const load = vi.fn(missing);
  const chunk = routeChunk(load);
  await expect(chunk.preload()).rejects.toThrow('dynamically imported module');
  expect(reload).toHaveBeenCalledTimes(1);
  expect(vi.mocked(fetch).mock.calls[0]?.[0]).toBe('/healthz');
  await expect(chunk.preload()).rejects.toThrow('dynamically imported module');
  expect(load).toHaveBeenCalledTimes(2);
  expect(reload).toHaveBeenCalledTimes(1);
});

it('服务连不上时不重载,错误交给页面', async () => {
  vi.stubGlobal('fetch', vi.fn(async () => { throw new TypeError('offline') }));
  const { routeChunk } = await import('../src/react/router/route-chunk');
  await expect(routeChunk(missing).preload()).rejects.toThrow('dynamically imported module');
  expect(reload).not.toHaveBeenCalled();
});

it('空闲预热逐个装载,失败不重载,留到打开时再试', async () => {
  vi.stubGlobal('fetch', vi.fn(async () => ({ ok: true })));
  vi.stubGlobal('requestIdleCallback', (callback: () => void) => { queueMicrotask(callback); return 0 });
  const { routeChunk, warmRouteChunks } = await import('../src/react/router/route-chunk');
  const broken = vi.fn(missing);
  const fine = vi.fn(async () => ({ ok: 1 }));
  routeChunk(broken);
  const chunk = routeChunk(fine);
  warmRouteChunks();
  await vi.waitFor(() => expect(fine).toHaveBeenCalledTimes(1));
  expect(broken).toHaveBeenCalledTimes(1);
  expect(chunk.get()).toEqual({ ok: 1 });
  expect(reload).not.toHaveBeenCalled();
  expect(fetch).not.toHaveBeenCalled();
});