| 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; |
| 3 | |
| 4 | import { VISIT_GAP_MS, lastVisit, markVisit, visitWorkspace } from "./visits.ts"; |
| 5 | |
| 6 | const NOW = Date.parse("2026-10-10T12:00:00Z"); |
| 7 | const MIN = 60_000; |
| 8 | const HOUR = 60 * MIN; |
| 9 | const DAY = 24 * HOUR; |
| 10 | |
| 11 | test("a workspace slug is lowercased and checked", () => { |
| 12 | assert.equal(visitWorkspace(" Acme "), "acme"); |
| 13 | assert.equal(visitWorkspace("flagon-io"), "flagon-io"); |
| 14 | assert.equal(visitWorkspace(""), null); |
| 15 | assert.equal(visitWorkspace("a/b"), null); |
| 16 | assert.equal(visitWorkspace(7), null); |
| 17 | assert.equal(visitWorkspace("x".repeat(65)), null); |
| 18 | }); |
| 19 | |
| 20 | test("the first mark starts a visit with nothing before it", () => { |
| 21 | assert.deepEqual(markVisit(null, new Date(NOW - HOUR).toISOString(), NOW), { seen_at: NOW - HOUR, previous_at: null }); |
| 22 | }); |
| 23 | |
| 24 | test("marks close together are one visit; a gap starts the next", () => { |
| 25 | const first = { seen_at: NOW - 3 * DAY, previous_at: null }; |
| 26 | // Back after three days: the new visit counts from the old one's last mark. |
| 27 | const back = markVisit(first, NOW - 10 * MIN, NOW)!; |
| 28 | assert.deepEqual(back, { seen_at: NOW - 10 * MIN, previous_at: NOW - 3 * DAY }); |
| 29 | // A refresh a few minutes later is the same visit. |
| 30 | assert.deepEqual(markVisit(back, NOW, NOW), { seen_at: NOW, previous_at: NOW - 3 * DAY }); |
| 31 | }); |
| 32 | |
| 33 | test("a mark never moves the visit back", () => { |
| 34 | const kept = { seen_at: NOW - HOUR, previous_at: null }; |
| 35 | assert.equal(markVisit(kept, NOW - 2 * HOUR, NOW), null); |
| 36 | assert.equal(markVisit(kept, NOW - HOUR, NOW), null); |
| 37 | }); |
| 38 | |
| 39 | test("a mark is never in the future, nor more than a day behind", () => { |
| 40 | assert.equal(markVisit(null, NOW + HOUR, NOW)!.seen_at, NOW); |
| 41 | assert.equal(markVisit(null, NOW - 72 * HOUR, NOW)!.seen_at, NOW - DAY); |
| 42 | assert.equal(markVisit(null, "not a time", NOW), null); |
| 43 | assert.equal(markVisit(null, undefined, NOW), null); |
| 44 | }); |
| 45 | |
| 46 | test("last here: the visit before during one, its last mark after", () => { |
| 47 | assert.equal(lastVisit(null, NOW), null); |
| 48 | const during = { seen_at: NOW - 5 * MIN, previous_at: NOW - 3 * DAY }; |
| 49 | assert.equal(lastVisit(during, NOW), NOW - 3 * DAY); |
| 50 | assert.equal(lastVisit({ seen_at: NOW - 5 * MIN, previous_at: null }, NOW), null); |
| 51 | assert.equal(lastVisit(during, NOW - 5 * MIN + VISIT_GAP_MS), NOW - 5 * MIN); |
| 52 | }); |