AkurAI Build
Menu

Public repository / 275d4fa11a39ecc30e2caf604d5a0d499910e8db

AkurAI-Mail / src/framework/sync-state.test.js

Latest change ecdd82c68dc11022c41dbf1ff22cac68e002a3e1 - OLI-247: wave 2 — signal-badge view model and signals-based sync state on framework runtime by Ólafur Búi Ólafsson

// @ts-nocheck
import { afterEach, describe, expect, jest, test } from "bun:test";
import { createSyncState } from "./sync-state.js";

describe("framework sync state (signals)", () => {
  test("starts idle, never synced, no error", () => {
    const s = createSyncState();
    expect([s.status(), s.lastSyncAt(), s.errorKind(), s.dismissed(), s.retryCount()]).toEqual(["idle", null, null, false, 0]);
  });
  test("reportSuccess clears error, resets retries, stamps time", () => {
    const s = createSyncState(() => 1234);
    s.reportError("offline");
    s.reportSuccess();
    expect([s.errorKind(), s.retryCount(), s.lastSyncAt(), s.status()]).toEqual([null, 0, 1234, "idle"]);
  });
  test("reportError schedules backoff retry, except auth-expired", () => {
    const timers = [];
    const s = createSyncState(Date.now, (fn, ms) => { timers.push(ms); return timers.length; }, () => {});
    s.reportError("offline", () => {});
    s.reportError("server-error", () => {});
    s.reportError("auth-expired", () => {});
    expect(timers).toEqual([2000, 4000]);
    expect(s.errorKind()).toBe("auth-expired");
  });
  test("dismiss hides until the next error", () => {
    const s = createSyncState();
    s.reportError("offline");
    s.dismiss();
    expect(s.dismissed()).toBe(true);
    s.reportError("offline");
    expect(s.dismissed()).toBe(false);
  });
  test("retryNow cancels the pending timer and runs", () => {
    const cleared = [];
    const s = createSyncState(Date.now, () => 7, (id) => cleared.push(id));
    s.reportError("offline", () => {});
    let ran = false;
    s.retryNow(() => { ran = true; });
    expect(cleared).toEqual([7]);
    expect(ran).toBe(true);
  });
});