Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.laportenard.com/llms.txt

Use this file to discover all available pages before exploring further.

The sync system has 575 tests across three packages, all using Vitest.
PackageTest filesTestsWhat’s covered
nu_pos_sync_protocol155Zod validators for all 15 message types
nu_pos_hub12129Storage, leasing, handlers, server, forwarder, adapter
nu_pos_react24391State machines, transports, reconcile, outbox, and existing POS tests

Running tests

Always run from the correct package directory. Running from the repo root picks up test files from all packages, causing path alias resolution failures.
cd nu_pos_sync_protocol
npx vitest run

Single test file

cd nu_pos_react && npx vitest run src/state/machines/__tests__/syncMachine.test.ts
cd nu_pos_hub && npx vitest run src/handlers/__tests__/orderHandler.test.ts

Watch mode

cd nu_pos_react && npm test
cd nu_pos_hub && npm test

Test architecture

Protocol tests

nu_pos_sync_protocol/src/__tests__/validators.test.ts (55 tests)
  • Round-trip validation for all terminal and hub message types
  • Rejection of malformed messages (missing fields, wrong types)
  • parseTerminalMessage(), parseHubMessage(), parseProtocolMessage() helpers

Hub tests

Storage layer (41 tests)

FileTestsCoverage
orderStore.test.ts11Upsert with version auto-increment, get, getByTable, count
leaseStore.test.ts11Grant, renew, release, getExpired, getByTerminal
eventLog.test.ts11Append, getPending, markForwarded, getRecent, count
tableStore.test.ts8Upsert, get, getAll, status transitions
All storage tests use in-memory SQLite (:memory:) for speed and isolation.

Lease manager (25 tests)

  • Acquire: new lease, re-entrant, denied (held by other), force override
  • Release: by holder, by non-holder (rejected), with final snapshot
  • Heartbeat: renewal, rejected for non-holder
  • Tick: expired lease revocation, callback invocation
  • Disconnect: grace period extension

Handlers (14 tests)

FileTestsCoverage
orderHandler.test.ts7Snapshot without lease, with lease, version conflict, broadcast, event log, table status
leaseHandler.test.ts7Acquire, release, heartbeat, force override, event logging

Server (25 tests)

FileTestsCoverage
wsServer.test.ts3WebSocket connection, auth flow, message routing
messageRouter.test.ts9JSON parsing, schema validation, auth gating, message dispatch
httpServer.test.ts13Health, status, events, dashboard, OPTIONS, 404, CORS

Upstream (24 tests)

FileTestsCoverage
forwarder.test.ts9Drain pending events, mark forwarded, skip non-order events, handle failure
odooAdapter.test.ts15Auth, forward create/update, payload transformation, voided line filtering

Frontend tests

Sync-specific (67 tests)

FileTestsCoverage
syncMachine.test.ts35All 4 states, all 14 events, context updates, state transitions
hubTransport.test.ts24Lease acquire/deny/timeout/revoke, message routing, offline fallback
reconcile.test.ts8All reconcile strategies: accept_remote, merge, default fallback

Transport infrastructure (31 tests)

FileTestsCoverage
directTransport.test.ts18Local locks, outbox integration, state lifecycle
createTransport.test.ts4Factory: returns direct when hub disabled, hub when enabled
hubDiscovery.test.ts9Config extraction, URL resolution

Testing patterns

Hub: in-memory SQLite

beforeEach(() => {
  db = initDb(":memory:");
  orderStore = createOrderStore(db);
});

Hub: mock WebSocket

function makeMockWs() {
  return {
    send: vi.fn(),
    readyState: 1,
    OPEN: 1,
  } as unknown as import("ws").WebSocket;
}

Frontend: module mocking

vi.mock("../sync/outbox", () => ({
  queueOutbound: vi.fn(),
  flushOutbound: vi.fn().mockResolvedValue({ sent: 0, failed: 0 }),
  listOutbound: vi.fn().mockReturnValue([]),
}));

Frontend: XState actor testing

const actor = createActor(syncMachine);
actor.start();
actor.send({ type: "TRANSPORT_RECONNECTING" });
expect(actor.getSnapshot().value).toBe("reconnecting");

What’s not tested

The following are intentionally untested (React components requiring DOM/render context):
  • SyncStatusIndicator — Read-only badge, tested visually
  • ConflictDialog — Radix UI dialog, tested visually
  • SyncOverlay — Toast integration, tested visually
  • SyncUIProvider — Simple React context with useState
  • RealtimeProvider — Tested indirectly through transport and machine tests