fix(web): recover pre-render boot failures

This commit is contained in:
lingniu
2026-07-16 06:04:30 +08:00
parent 4302fc8d45
commit 97fe1704a2
9 changed files with 196 additions and 20 deletions

View File

@@ -0,0 +1,49 @@
import { afterEach, expect, test, vi } from 'vitest';
import indexSource from '../../index.html?raw';
const bootScript = indexSource.match(/<script>\s*([\s\S]*?vehicle-platform:ready[\s\S]*?)<\/script>/)?.[1];
function mountBootShell() {
document.body.innerHTML = '<div id="root"><div id="platform-boot" role="status"><div><span class="platform-boot-mark">车</span><strong>车辆数据中台</strong><small>正在加载工作台…</small></div></div></div>';
expect(bootScript).toBeTruthy();
Function(bootScript!)();
}
afterEach(() => {
vi.useRealTimers();
document.body.innerHTML = '';
});
test('turns an entry resource error into an actionable static recovery screen', () => {
vi.useFakeTimers();
mountBootShell();
window.dispatchEvent(new Event('error'));
expect(document.getElementById('platform-boot')).toHaveClass('is-error');
expect(document.getElementById('platform-boot')).toHaveAttribute('role', 'alert');
expect(document.querySelector('#platform-boot strong')).toHaveTextContent('平台启动失败');
expect(document.querySelector('#platform-boot button')).toHaveTextContent('重新加载最新版本');
});
test('uses the timeout only before React readiness and never replaces a committed app', () => {
vi.useFakeTimers();
mountBootShell();
document.getElementById('root')!.innerHTML = '<main data-testid="committed-app">已启动</main>';
vi.advanceTimersByTime(10_000);
expect(document.querySelector('[data-testid="committed-app"]')).toHaveTextContent('已启动');
expect(document.querySelector('#platform-boot')).not.toBeInTheDocument();
});
test('cancels the watchdog after the React ready handshake', () => {
vi.useFakeTimers();
mountBootShell();
window.dispatchEvent(new Event('vehicle-platform:ready'));
vi.advanceTimersByTime(10_000);
expect(document.getElementById('platform-boot')).not.toHaveClass('is-error');
expect(document.querySelector('#platform-boot button')).not.toBeInTheDocument();
});