Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556import { db, eq } from "@openstatus/db";import { monitor, pageComponent } from "@openstatus/db/src/schema";import { allPlans } from "@openstatus/db/src/schema/plan/config";import type { Limits } from "@openstatus/db/src/schema/plan/schema";import type { ImportSummary } from "@openstatus/importers";import { expect } from "@std/expect";import { beforeAll, describe, test } from "@std/testing/bdd";
import { addLimitWarnings, clampPeriodicity, computePhaseStatus } from "../";import { withTestTransaction } from "../../../test/helpers";
function makeSummary(overrides?: Partial<ImportSummary>): ImportSummary { return { provider: "statuspage", status: "completed", startedAt: new Date(), completedAt: new Date(), phases: [], errors: [], ...overrides, };}
function makeLimits(overrides?: Partial<Limits>): Limits { return { ...allPlans.free.limits, ...overrides };}
// `addLimitWarnings` issues real `count(*)` queries against// `pageComponent` and `monitor`. The expectations below assume an empty// workspace, so wipe rows other suites' `beforeAll` blocks may have// committed in workspace 2 once before any test runs. Per-test writes// from this file all live inside `withTestTransaction` and roll back.const TEST_WORKSPACE_ID = 2;
describe("addLimitWarnings", () => { beforeAll(async () => { await db .delete(pageComponent) .where(eq(pageComponent.workspaceId, TEST_WORKSPACE_ID)); await db.delete(monitor).where(eq(monitor.workspaceId, TEST_WORKSPACE_ID)); });
// ------------------------------------------------------------------------- // Component limits // ------------------------------------------------------------------------- describe("component limits", () => { test("no warning when under limit", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "components", status: "completed", resources: [ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "created" }, ], }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "page-components": 20 }), workspaceId: 2, db: tx, });
expect(summary.errors).toEqual([]); }); });
test("no warning when exactly at limit", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "components", status: "completed", resources: [ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "created" }, { sourceId: "3", name: "C", status: "created" }, ], }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "page-components": 3 }), workspaceId: 2, db: tx, });
expect(summary.errors).toEqual([]); }); });
test("warns when import exceeds limit (no existing components)", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "components", status: "completed", resources: [ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "created" }, { sourceId: "3", name: "C", status: "created" }, { sourceId: "4", name: "D", status: "created" }, ], }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "page-components": 3 }), workspaceId: 2, db: tx, });
expect(summary.errors.length).toBe(1); // Wording: "Only 3 new components may be created โฆ 4 in the import". // Both numbers land in the message โ assert on the salient // fragments instead of the exact string so future phrasing tweaks // don't churn the assertion. expect(summary.errors[0]).toContain("3 new component"); expect(summary.errors[0]).toContain("4 in the import"); }); });
test("no warning when components phase is empty", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [{ phase: "components", status: "completed", resources: [] }], });
await addLimitWarnings(summary, { limits: makeLimits({ "page-components": 3 }), workspaceId: 2, db: tx, });
expect(summary.errors).toEqual([]); }); });
test("no warning when components phase is missing", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [{ phase: "page", status: "completed", resources: [] }], });
await addLimitWarnings(summary, { limits: makeLimits({ "page-components": 3 }), workspaceId: 2, db: tx, });
expect(summary.errors).toEqual([]); }); }); });
// ------------------------------------------------------------------------- // Custom domain // ------------------------------------------------------------------------- describe("custom domain", () => { test("warns when custom domain present on free plan", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "page", status: "completed", resources: [ { sourceId: "p1", name: "My Page", status: "created", data: { customDomain: "status.example.com" }, }, ], }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "custom-domain": false }), workspaceId: 2, db: tx, });
expect(summary.errors.length).toBe(1); expect(summary.errors[0]).toContain("Custom domain"); }); });
test("no warning when custom domain is empty", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "page", status: "completed", resources: [ { sourceId: "p1", name: "My Page", status: "created", data: { customDomain: "" }, }, ], }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "custom-domain": false }), workspaceId: 2, db: tx, });
expect(summary.errors).toEqual([]); }); });
test("no warning on paid plan with custom domain", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "page", status: "completed", resources: [ { sourceId: "p1", name: "My Page", status: "created", data: { customDomain: "status.example.com" }, }, ], }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "custom-domain": true }), workspaceId: 2, db: tx, });
expect(summary.errors).toEqual([]); }); }); });
// ------------------------------------------------------------------------- // Subscribers // ------------------------------------------------------------------------- describe("subscribers", () => { test("warns when subscribers present on free plan", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "subscribers", status: "completed", resources: [ { sourceId: "s1", name: "alice@test.com", status: "created" }, { sourceId: "s2", name: "bob@test.com", status: "created" }, ], }, ], });
// `addLimitWarnings` gates subscribers warnings on // `options.includeSubscribers` (Cubic P2 โ otherwise users who // aren't importing subscribers get a noise warning). Default // matches `ImportOptions` (`false`), so the warning only fires // when the caller explicitly opts in. Tests that want to exercise // the warning pass `options.includeSubscribers: true`. await addLimitWarnings(summary, { limits: makeLimits({ "status-subscribers": false }), workspaceId: 2, db: tx, options: { includeSubscribers: true }, });
expect(summary.errors.length).toBe(1); expect(summary.errors[0]).toContain("Subscribers"); }); });
test("no warning when subscribers phase is empty", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "subscribers", status: "completed", resources: [] }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "status-subscribers": false }), workspaceId: 2, db: tx, options: { includeSubscribers: true }, });
expect(summary.errors).toEqual([]); }); });
test("no warning on paid plan with subscribers", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "subscribers", status: "completed", resources: [ { sourceId: "s1", name: "alice@test.com", status: "created" }, ], }, ], });
await addLimitWarnings(summary, { limits: makeLimits({ "status-subscribers": true }), workspaceId: 2, db: tx, options: { includeSubscribers: true }, });
expect(summary.errors).toEqual([]); }); }); });
// ------------------------------------------------------------------------- // Combined // ------------------------------------------------------------------------- test("reports multiple warnings at once", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "page", status: "completed", resources: [ { sourceId: "p1", name: "Page", status: "created", data: { customDomain: "status.example.com" }, }, ], }, { phase: "components", status: "completed", resources: [ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "created" }, { sourceId: "3", name: "C", status: "created" }, { sourceId: "4", name: "D", status: "created" }, ], }, { phase: "subscribers", status: "completed", resources: [ { sourceId: "s1", name: "alice@test.com", status: "created" }, ], }, ], });
// Free plan: page-components=3, custom-domain=false, status-subscribers=false // Opt in to subscribers so the subscribers-disallowed warning fires // (default `includeSubscribers` is `false` โ warning silent). await addLimitWarnings(summary, { limits: makeLimits(), workspaceId: 2, db: tx, options: { includeSubscribers: true }, });
expect(summary.errors.length).toBe(3); expect(summary.errors.some((e) => e.includes("3 new component"))).toBe( true, ); expect(summary.errors.some((e) => e.includes("Custom domain"))).toBe( true, ); expect(summary.errors.some((e) => e.includes("Subscribers"))).toBe(true); }); });
test("no warnings on starter plan within limits", async () => { await withTestTransaction(async (tx) => { const summary = makeSummary({ phases: [ { phase: "page", status: "completed", resources: [ { sourceId: "p1", name: "Page", status: "created", data: { customDomain: "status.example.com" }, }, ], }, { phase: "components", status: "completed", resources: [ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "created" }, { sourceId: "3", name: "C", status: "created" }, { sourceId: "4", name: "D", status: "created" }, ], }, { phase: "subscribers", status: "completed", resources: [ { sourceId: "s1", name: "alice@test.com", status: "created" }, ], }, ], });
await addLimitWarnings(summary, { limits: { ...allPlans.starter.limits }, workspaceId: 2, db: tx, });
expect(summary.errors).toEqual([]); }); });});
describe("computePhaseStatus", () => { test("returns completed for empty resources", () => { expect(computePhaseStatus([])).toBe("completed"); });
test("returns completed when all resources are created", () => { expect( computePhaseStatus([ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "created" }, ]), ).toBe("completed"); });
test("returns completed when all resources are skipped", () => { expect( computePhaseStatus([ { sourceId: "1", name: "A", status: "skipped" }, { sourceId: "2", name: "B", status: "skipped" }, ]), ).toBe("completed"); });
test("returns partial when some resources are skipped", () => { expect( computePhaseStatus([ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "skipped" }, ]), ).toBe("partial"); });
test("returns partial when some resources fail", () => { expect( computePhaseStatus([ { sourceId: "1", name: "A", status: "created" }, { sourceId: "2", name: "B", status: "failed" }, ]), ).toBe("partial"); });
test("returns failed when all resources fail", () => { expect( computePhaseStatus([ { sourceId: "1", name: "A", status: "failed" }, { sourceId: "2", name: "B", status: "failed" }, ]), ).toBe("failed"); });});
describe("clampPeriodicity", () => { const freePlan = allPlans.free.limits.periodicity as string[]; const starterPlan = allPlans.starter.limits.periodicity as string[];
describe("free plan", () => { test("allows 10m (already in plan)", () => { expect(clampPeriodicity("10m", freePlan)).toBe("10m"); });
test("allows 30m (already in plan)", () => { expect(clampPeriodicity("30m", freePlan)).toBe("30m"); });
test("allows 1h (already in plan)", () => { expect(clampPeriodicity("1h", freePlan)).toBe("1h"); });
test("clamps 1m to 10m", () => { expect(clampPeriodicity("1m", freePlan)).toBe("10m"); });
test("clamps 30s to 10m", () => { expect(clampPeriodicity("30s", freePlan)).toBe("10m"); });
test("clamps 5m to 10m", () => { expect(clampPeriodicity("5m", freePlan)).toBe("10m"); }); });
describe("starter plan", () => { test("allows 1m (in plan)", () => { expect(clampPeriodicity("1m", starterPlan)).toBe("1m"); });
test("allows 5m (in plan)", () => { expect(clampPeriodicity("5m", starterPlan)).toBe("5m"); });
test("clamps 30s to 1m", () => { expect(clampPeriodicity("30s", starterPlan)).toBe("1m"); }); });
describe("unknown requested periodicity", () => { // An unknown periodicity string (e.g. `"2m"` โ not in // `PERIODICITY_ORDER`) previously clamped from index 0 (the // fastest tier), which could pick a *faster* interval than // requested. It should fall back to the slowest allowed instead, // erring toward the "never faster than requested" invariant. test("falls back to slowest allowed on unknown value", () => { expect(clampPeriodicity("2m", ["5m", "10m", "30m"])).toBe("30m"); });
test("falls back to 10m when `allowed` is empty", () => { expect(clampPeriodicity("2m", [])).toBe("10m"); }); });});