-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Problem
OpenAlerts currently has zero test coverage. The core engine, all 8 alert rules, the evaluator, the JSONL store, the event bus, the formatter, and the bounded map are all untested. This makes it risky to accept contributions or refactor internals there's no safety net to catch regressions.
The publish CI workflow also has no test step, so broken code can ship to npm undetected.
Proposal
Add a comprehensive test suite using Vitest (fast, TypeScript-native, zero-config for ESM projects). The suite should cover the framework-agnostic src/core/ layer the part that every adapter depends on.
Proposed test files
| File | Covers |
|---|---|
tests/rules.test.ts |
All 8 alert rules in isolation |
tests/evaluator.test.ts |
processEvent(), warmFromHistory(), stats tracking, hourly cap |
tests/store.test.ts |
JSONL append, read, prune (age + size), atomic write |
tests/engine.test.ts |
OpenAlertsEngine lifecycle — start, stop, ingest → alert flow |
tests/formatter.test.ts |
/health and /alerts output formatting |
tests/bounded-map.test.ts |
LRU eviction, TTL expiry, hit/miss stats |
tests/event-bus.test.ts |
Pub/sub, listener error isolation |
Key test cases for rules (rules.test.ts)
llm-errors
- Fires after ≥1 error-outcome
llm.callevent in a 1-minute window - Does NOT fire for
llm.callwithoutcome: "success"orundefined - Fires for
llm.errorandagent.errorevent types (always treated as errors) - Respects configurable
thresholdoverride
gateway-down
- Only evaluates on
watchdog.tickevents (ignores all other types) - Returns
nullwhen no heartbeat has ever been received (lastHeartbeatTs === 0) - Fires when silence exceeds threshold (default 30s)
- Severity is
critical
high-error-rate
- Does NOT fire until at least 20 messages have been tracked
- Calculates rate over the last 20 messages only (sliding window)
- Fires at ≥50% error rate by default
- Counts
timeoutoutcomes as errors
queue-depth
- Updates
lastHeartbeatTsoninfra.heartbeatevents regardless of whether the rule itself is enabled (gateway-down depends on this) - Fires when
queueDepth≥ threshold
Cross-cutting (evaluator)
- Cooldown prevents the same fingerprint from firing twice within the cooldown window
- Hourly cap (default 5) blocks the 6th alert in the same hour
- Hourly cap resets after the hour expires
- Cooldown map is pruned when it exceeds
maxCooldownEntries(50) - 24h stats reset after 24 hours
warmFromHistory()restores cooldowns from persisted alert eventswarmFromHistory()does NOT replay diagnostic events through rules
Setup
npm install -D vitestAdd to package.json:
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest"
}
}Add to tsconfig.json (or a tsconfig.test.json):
I'd like to work on this , happy to submit a PR if this fits in. Thanks!
{ "exclude": ["tests"] // don't emit test files to dist/ }