import { describe, expect, it } from 'vitest' import { slaReport, toReport, formatSla, type Check } from '../src/index.js' import { overall, validateReport } from '@extant2000/evidence-record' const FROM = '2026-07-01T00:00:00.000Z' const TO = '2026-08-01T00:00:00.000Z' /** n samples 5 minutes apart from `start`, `okAt` decides pass/fail. */ function series(start: string, n: number, okAt: (i: number) => boolean): Check[] { const t0 = new Date(start).getTime() return Array.from({ length: n }, (_, i) => ({ ts: new Date(t0 + i * 300_000).toISOString(), ok: okAt(i), })) } describe('slaReport — refusing flattering answers', () => { it('reports uptime_pct as NULL with no samples, not 100', () => { // An availability report that answers "100%" when nothing was measured is // worse than one that abstains. const r = slaReport([], { from: FROM, to: TO, target: 99.9 }) expect(r.uptime_pct).toBeNull() expect(r.total_checks).toBe(0) }) it('reports met as NULL with no target, not false', () => { // "no SLA target" and "SLA missed" are different claims. A free plan must // not produce a statement that reads as a failure. expect(slaReport(series(FROM, 10, () => true), { from: FROM, to: TO }).met).toBeNull() }) it('cannot report met=true from zero evidence', () => { const r = slaReport([], { from: FROM, to: TO, target: 99.9 }) expect(r.met).toBe(false) }) }) describe('slaReport — window semantics', () => { it('is half-open [from, to) so adjacent months never double-count', () => { const boundary: Check[] = [ { ts: FROM, ok: true }, // included { ts: TO, ok: true }, // excluded — belongs to the NEXT statement ] expect(slaReport(boundary, { from: FROM, to: TO }).total_checks).toBe(1) }) it('drops samples outside the window entirely', () => { const r = slaReport([ { ts: '2026-06-30T23:59:59.000Z', ok: false }, { ts: '2026-07-15T00:00:00.000Z', ok: true }, ], { from: FROM, to: TO }) expect(r.total_checks).toBe(1) expect(r.uptime_pct).toBe(100) }) it('ignores malformed samples rather than counting them', () => { const r = slaReport( [{ ts: 'not-a-date', ok: false }, { ts: FROM, ok: true }] as Check[], { from: FROM, to: TO }, ) expect(r.total_checks).toBe(1) }) }) describe('slaReport — availability and downtime', () => { it('computes uptime to one decimal', () => { // 999 up, 1 down out of 1000 → 99.9 const r = slaReport(series(FROM, 1000, i => i !== 500), { from: FROM, to: TO, target: 99.9 }) expect(r.uptime_pct).toBe(99.9) expect(r.up_checks).toBe(999) expect(r.down_checks).toBe(1) expect(r.met).toBe(true) }) it('misses the target just below it', () => { // 998/1000 = 99.8 < 99.9 const r = slaReport(series(FROM, 1000, i => i !== 500 && i !== 600), { from: FROM, to: TO, target: 99.9, }) expect(r.uptime_pct).toBe(99.8) expect(r.met).toBe(false) }) it('charges a failing sample the gap to its successor, capped at one interval', () => { // Two failures 5 min apart at a 300s cadence → 5 min each = 10 min. const r = slaReport(series(FROM, 3, i => i === 2), { from: FROM, to: TO, intervalSeconds: 300, }) expect(r.downtime_minutes).toBe(10) }) it('caps a long reporting gap at one interval', () => { // A single failure followed by a sample a DAY later must not charge a day. const r = slaReport([ { ts: '2026-07-01T00:00:00.000Z', ok: false }, { ts: '2026-07-02T00:00:00.000Z', ok: true }, ], { from: FROM, to: TO, intervalSeconds: 300 }) expect(r.downtime_minutes).toBe(5) }) it('charges the final sample exactly one interval when it has no successor', () => { const r = slaReport([{ ts: FROM, ok: false }], { from: FROM, to: TO, intervalSeconds: 600, }) expect(r.downtime_minutes).toBe(10) }) }) describe('slaReport — scheduled maintenance', () => { const win = [{ starts_at: '2026-07-10T00:00:00.000Z', ends_at: '2026-07-10T01:00:00.000Z' }] it('removes samples inside a window from the math entirely', () => { const r = slaReport([ { ts: '2026-07-10T00:30:00.000Z', ok: false }, // planned downtime { ts: '2026-07-11T00:00:00.000Z', ok: true }, ], { from: FROM, to: TO, excludeWindows: win, target: 99.9 }) expect(r.excluded_checks).toBe(1) expect(r.total_checks).toBe(1) expect(r.uptime_pct).toBe(100) // planned downtime never counts against it expect(r.excluded_minutes).toBe(60) }) it('ignores a cancelled window — it did not happen', () => { const r = slaReport([{ ts: '2026-07-10T00:30:00.000Z', ok: false }], { from: FROM, to: TO, excludeWindows: [{ ...win[0]!, status: 'cancelled' }], }) expect(r.excluded_checks).toBe(0) expect(r.uptime_pct).toBe(0) }) it('does NOT double-count overlapping windows', () => { const r = slaReport([], { from: FROM, to: TO, excludeWindows: [ { starts_at: '2026-07-10T00:00:00.000Z', ends_at: '2026-07-10T02:00:00.000Z' }, { starts_at: '2026-07-10T01:00:00.000Z', ends_at: '2026-07-10T03:00:00.000Z' }, ], }) expect(r.excluded_minutes).toBe(180) // union, not 120 + 120 }) it('clips a window to the report period', () => { const r = slaReport([], { from: FROM, to: TO, excludeWindows: [{ starts_at: '2026-06-01T00:00:00.000Z', ends_at: '2026-07-01T01:00:00.000Z' }], }) expect(r.excluded_minutes).toBe(60) // only the hour inside July }) it('drops a zero-length or inverted window', () => { const r = slaReport([], { from: FROM, to: TO, excludeWindows: [ { starts_at: '2026-07-10T01:00:00.000Z', ends_at: '2026-07-10T01:00:00.000Z' }, { starts_at: '2026-07-10T05:00:00.000Z', ends_at: '2026-07-10T04:00:00.000Z' }, ], }) expect(r.excluded_minutes).toBe(0) }) it('accepts start/end aliases', () => { const r = slaReport([], { from: FROM, to: TO, excludeWindows: [{ start: '2026-07-10T00:00:00.000Z', end: '2026-07-10T00:30:00.000Z' }], }) expect(r.excluded_minutes).toBe(30) }) }) describe('slaReport — reproducibility', () => { it('same input, identical output', () => { const checks = series(FROM, 200, i => i % 17 !== 0) const a = slaReport(checks, { from: FROM, to: TO, target: 99 }) const b = slaReport(checks, { from: FROM, to: TO, target: 99 }) expect(a).toEqual(b) }) it('is order-independent — unsorted input gives the same answer', () => { const checks = series(FROM, 50, i => i !== 10) const shuffled = [...checks].reverse() expect(slaReport(shuffled, { from: FROM, to: TO, intervalSeconds: 300 })) .toEqual(slaReport(checks, { from: FROM, to: TO, intervalSeconds: 300 })) }) }) describe('report — the null cases said out loud', () => { const period = { from: '2026-07-01T00:00:00Z', to: '2026-08-01T00:00:00Z' } it('reads zero samples as uncomputable, not as a missed SLA', () => { // `uptime null, met=false` is correct arithmetic and an overclaim to // print: nothing was measured, so nothing was missed. const r = slaReport([], { ...period, target: 99.9 }) expect(r.uptime_pct).toBeNull() expect(r.met).toBe(false) // ported behaviour, unchanged expect(overall(toReport(r))).toBe('not-assessed') // what a reader is told const text = formatSla(r) expect(text).toContain('No samples in this period; availability cannot be computed.') expect(text).toContain('neither met nor missed') expect(text).not.toContain('100%') }) it('says plainly when no SLA target applies', () => { const r = slaReport([{ ts: '2026-07-02T00:00:00Z', ok: true }], period) expect(r.met).toBeNull() expect(formatSla(r)).toContain('No SLA target applies to this plan.') }) it('carries the sample count into the citation', () => { const checks = Array.from({ length: 100 }, (_, i) => ({ ts: new Date(Date.parse(period.from) + i * 300_000).toISOString(), ok: i !== 3, })) const r = slaReport(checks, { ...period, target: 99.9 }) const text = formatSla(r, { subject: 'app.example.com', evidence: 'inline' }) expect(text).toContain('100 samples') expect(text).toContain('app.example.com') expect(overall(toReport(r))).toBe('fail') expect(text).toContain('was NOT met') }) it('reports excluded maintenance as not-applicable, with its own measurement', () => { const checks = Array.from({ length: 20 }, (_, i) => ({ ts: new Date(Date.parse(period.from) + i * 300_000).toISOString(), ok: true, })) const r = slaReport(checks, { ...period, target: 99.9, excludeWindows: [{ start: period.from, end: new Date(Date.parse(period.from) + 3600_000).toISOString() }], }) expect(r.excluded_checks).toBeGreaterThan(0) const f = toReport(r).findings.find(x => x.id === 'maintenance')! expect(f.determination).toBe('not-applicable') expect(formatSla(r)).toContain('scheduled maintenance excluded') }) it('every conclusion carries a citation', () => { const r = slaReport([{ ts: '2026-07-02T00:00:00Z', ok: true }], { ...period, target: 99.9 }) expect(validateReport(toReport(r))).toEqual([]) }) })