1import { describe, expect, it } from "vite-plus/test";
2
3import {
4 INITIAL_WEBVIEW_CRASH_RECOVERY_STATE,
5 planWebviewCrashRecovery,
6 WEBVIEW_CRASH_RECOVERY_WINDOW_MS,
7} from "./webviewCrashRecovery";
8
9describe("planWebviewCrashRecovery", () => {
10 it("backs off and stops after a bounded number of rapid crashes", () => {
11 const first = planWebviewCrashRecovery(INITIAL_WEBVIEW_CRASH_RECOVERY_STATE, 1_000);
12 expect(first).not.toBeNull();
13 expect(first?.delayMs).toBe(250);
14
15 const second = planWebviewCrashRecovery(first!.state, 1_100);
16 expect(second).not.toBeNull();
17 expect(second?.delayMs).toBe(500);
18
19 const third = planWebviewCrashRecovery(second!.state, 1_200);
20 expect(third).not.toBeNull();
21 expect(third?.delayMs).toBe(1_000);
22
23 expect(planWebviewCrashRecovery(third!.state, 1_300)).toBeNull();
24 });
25
26 it("allows recovery again after the crash window expires", () => {
27 const first = planWebviewCrashRecovery(INITIAL_WEBVIEW_CRASH_RECOVERY_STATE, 1_000)!;
28 const second = planWebviewCrashRecovery(first.state, 1_100)!;
29 const third = planWebviewCrashRecovery(second.state, 1_200)!;
30
31 expect(planWebviewCrashRecovery(third.state, 1_000 + WEBVIEW_CRASH_RECOVERY_WINDOW_MS)).toEqual(
32 {
33 delayMs: 250,
34 state: {
35 attempts: 1,
36 windowStartedAt: 1_000 + WEBVIEW_CRASH_RECOVERY_WINDOW_MS,
37 },
38 },
39 );
40 });
41});