| 1 | import { test } from "node:test"; |
| 2 | import assert from "node:assert/strict"; |
| 3 | |
| 4 | import { ACTIVE, decayed, raised } from "./activity.ts"; |
| 5 | |
| 6 | const DAY = 24 * 60 * 60 * 1000; |
| 7 | const at = (days: number) => new Date(Date.UTC(2026, 9, 1) + days * DAY).toISOString(); |
| 8 | |
| 9 | test("a first piece of activity scores one", () => { |
| 10 | assert.deepEqual(raised(0, null, at(0)), { score: 1, at: at(0) }); |
| 11 | }); |
| 12 | |
| 13 | test("activity counts half as much a week later", () => { |
| 14 | assert.equal(decayed(4, at(0), at(7)), 2); |
| 15 | assert.equal(decayed(4, at(0), at(14)), 1); |
| 16 | assert.equal(raised(4, at(0), at(7)).score, 3); |
| 17 | }); |
| 18 | |
| 19 | test("a busy project outranks one busy long ago", () => { |
| 20 | let busyThen = { score: 0, at: null as string | null }; |
| 21 | for (let i = 0; i < 20; i++) busyThen = raised(busyThen.score, busyThen.at, at(0)); |
| 22 | let busyNow = { score: 0, at: null as string | null }; |
| 23 | for (let i = 0; i < 5; i++) busyNow = raised(busyNow.score, busyNow.at, at(40)); |
| 24 | assert.ok(decayed(busyNow.score, busyNow.at, at(41)) > decayed(busyThen.score, busyThen.at, at(41))); |
| 25 | }); |
| 26 | |
| 27 | test("an event delivered late never moves the time back", () => { |
| 28 | const next = raised(2, at(5), at(3)); |
| 29 | assert.equal(next.at, at(5)); |
| 30 | assert.equal(next.score, 3); |
| 31 | }); |
| 32 | |
| 33 | test("nonsense counts as nothing", () => { |
| 34 | assert.equal(decayed(3, "not a time", at(0)), 0); |
| 35 | assert.equal(decayed(-1, at(0), at(1)), 0); |
| 36 | }); |
| 37 | |
| 38 | test("pushes, work and deployments count; housekeeping does not", () => { |
| 39 | assert.ok(ACTIVE.has("git.push")); |
| 40 | assert.ok(ACTIVE.has("pull.merged")); |
| 41 | assert.ok(!ACTIVE.has("repo.created")); |
| 42 | }); |