Openstatus www.openstatus.dev
at main 98 lines 3.2 kB view raw
1import { describe, expect, it } from "bun:test"; 2import type { Incident } from "@openstatus/db/src/schema"; 3import { getIncidentDuration } from "./incident"; 4 5// Helper to create a partial incident object for testing 6function createIncident(overrides: Partial<Incident>): Incident { 7 return { 8 id: 1, 9 monitorId: 1, 10 workspaceId: 1, 11 startedAt: null, 12 resolvedAt: null, 13 autoResolved: false, 14 acknowledgedAt: null, 15 acknowledgedBy: null, 16 ...overrides, 17 } as Incident; 18} 19 20describe("getIncidentDuration", () => { 21 it("returns null when incident.startedAt is missing", () => { 22 const incident = createIncident({ 23 startedAt: null, 24 resolvedAt: new Date("2026-01-22T12:00:00Z"), 25 }); 26 expect(getIncidentDuration(incident)).toBe(null); 27 }); 28 29 it("returns null when incident.resolvedAt is null (ongoing incident)", () => { 30 const incident = createIncident({ 31 startedAt: new Date("2026-01-22T10:00:00Z"), 32 resolvedAt: null, 33 }); 34 expect(getIncidentDuration(incident)).toBe(null); 35 }); 36 37 it("calculates correct duration for resolved incident", () => { 38 // 2h 15m 30s = 8130000ms 39 const incident = createIncident({ 40 startedAt: new Date("2026-01-22T10:00:00Z"), 41 resolvedAt: new Date("2026-01-22T12:15:30Z"), 42 }); 43 expect(getIncidentDuration(incident)).toBe("2h 15m 30s"); 44 }); 45 46 it("calculates duration with Date objects", () => { 47 const incident = createIncident({ 48 startedAt: new Date("2026-01-22T10:00:00Z"), 49 resolvedAt: new Date("2026-01-22T10:30:00Z"), 50 }); 51 expect(getIncidentDuration(incident)).toBe("30m"); 52 }); 53 54 it("calculates duration with timestamp numbers", () => { 55 // 5 minutes = 300000ms 56 const startTime = new Date("2026-01-22T10:00:00Z").getTime(); 57 const endTime = new Date("2026-01-22T10:05:00Z").getTime(); 58 const incident = createIncident({ 59 startedAt: startTime as unknown as Date, 60 resolvedAt: endTime as unknown as Date, 61 }); 62 expect(getIncidentDuration(incident)).toBe("5m"); 63 }); 64 65 it("handles very short durations (less than a minute)", () => { 66 const incident = createIncident({ 67 startedAt: new Date("2026-01-22T10:00:00Z"), 68 resolvedAt: new Date("2026-01-22T10:00:45Z"), 69 }); 70 expect(getIncidentDuration(incident)).toBe("45s"); 71 }); 72 73 it("handles very long durations (over a day)", () => { 74 // 1 day, 2 hours = 26 hours = 93600000ms 75 const incident = createIncident({ 76 startedAt: new Date("2026-01-21T10:00:00Z"), 77 resolvedAt: new Date("2026-01-22T12:00:00Z"), 78 }); 79 expect(getIncidentDuration(incident)).toBe("1d 2h"); 80 }); 81 82 it("handles same start and end time (0 duration)", () => { 83 const timestamp = new Date("2026-01-22T10:00:00Z"); 84 const incident = createIncident({ 85 startedAt: timestamp, 86 resolvedAt: timestamp, 87 }); 88 expect(getIncidentDuration(incident)).toBe("0s"); 89 }); 90 91 it("returns null when resolvedAt is before startedAt (negative duration)", () => { 92 const incident = createIncident({ 93 startedAt: new Date("2026-01-22T12:00:00Z"), 94 resolvedAt: new Date("2026-01-22T10:00:00Z"), 95 }); 96 expect(getIncidentDuration(incident)).toBe(null); 97 }); 98});