Luigit
repositories / will

will

owned by admin

src/shared/wake.test.ts

Raw
import assert from 'node:assert/strict'
import { test } from 'node:test'
import fc from 'fast-check'
import {
  claimHeartbeatHour,
  hasPendingHeartbeat,
  orderWakes,
  type Wake,
  type WakeKind,
  wakePriority,
} from './wake.ts'

function wake(kind: WakeKind, seq: number, deferredUntil?: string): Wake {
  return {
    id: `w${seq}`,
    seq,
    kind,
    createdAt: new Date(seq).toISOString(),
    payload: null,
    attempts: 0,
    deferredUntil,
  }
}

test('failure wakes outrank chat which outranks heartbeat', () => {
  const ordered = orderWakes([wake('heartbeat', 1), wake('chat', 2), wake('deploy_failure', 3)], 0)
  assert.deepEqual(
    ordered.map((w) => w.kind),
    ['deploy_failure', 'chat', 'heartbeat'],
  )
})

test('FIFO inside a class', () => {
  const ordered = orderWakes([wake('chat', 5), wake('chat', 4), wake('chat', 6)], 0)
  assert.deepEqual(
    ordered.map((w) => w.seq),
    [4, 5, 6],
  )
})

test('deferred wakes are skipped until their time', () => {
  const now = 1_000_000
  const ordered = orderWakes(
    [wake('chat', 1, new Date(now + 1000).toISOString()), wake('chat', 2)],
    now,
  )
  assert.deepEqual(
    ordered.map((w) => w.seq),
    [2],
  )
})

test('heartbeat coalescing predicate', () => {
  assert.equal(hasPendingHeartbeat([wake('chat', 1)]), false)
  assert.equal(hasPendingHeartbeat([wake('chat', 1), wake('heartbeat', 2)]), true)
})

test('heartbeat hour is claimed at most once and never replayed', () => {
  const first = claimHeartbeatHour({}, '2026-09-12T03')
  assert.equal(first.claimed, true)
  const second = claimHeartbeatHour(first.state, '2026-09-12T03')
  assert.equal(second.claimed, false)
  const older = claimHeartbeatHour(second.state, '2026-09-12T02')
  assert.equal(older.claimed, false)
  const next = claimHeartbeatHour(second.state, '2026-09-12T04')
  assert.equal(next.claimed, true)
})

test('property: ordering is stable sort by (priority, seq)', () => {
  const kinds: WakeKind[] = ['deploy_failure', 'ci_failure', 'recovery', 'chat', 'heartbeat']
  const arbWake = fc
    .record({ kind: fc.constantFrom(...kinds), seq: fc.nat({ max: 500 }) })
    .map((r) => wake(r.kind, r.seq))
  fc.assert(
    fc.property(fc.array(arbWake, { maxLength: 50 }), (wakes) => {
      const ordered = orderWakes(wakes, 0)
      for (let i = 1; i < ordered.length; i++) {
        const a = ordered[i - 1] as Wake
        const b = ordered[i] as Wake
        if (a.kind === b.kind) assert.ok(a.seq <= b.seq)
        else assert.ok(wakePriority(a.kind) <= wakePriority(b.kind))
      }
    }),
  )
})