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
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175import { eq } from "@openstatus/db";import { incident, slackUser } from "@openstatus/db/src/schema";import { addUserToWorkspace, createPage, createSlackUser, createUser,} from "@openstatus/db/src/test/factories";import { expect } from "@std/expect";import { beforeAll, describe, test } from "@std/testing/bdd";
import { createWorkspaceFixture, expectAuditRow, makeUserCtx, withTestTransaction,} from "../../../test/helpers";import type { DB } from "../../context";import { removeMemberInWorkspace } from "../../member/internal";import { createStatusReport } from "../../status-report/create";import { deleteStatusReport } from "../../status-report/delete";import type { Workspace } from "../../types";import { deleteAccount } from "../../user/delete";import { closeIncident, declareIncident, listIncidentEvents, setIncidentStatus,} from "../index";
let workspace: Workspace;let ownerId: number;let pageId: number;
beforeAll(async () => { const fixture = await createWorkspaceFixture("team"); workspace = fixture.workspace; ownerId = fixture.userId; pageId = (await createPage(workspace.id)).id;});
const as = (userId: number, tx: DB) => ({ ...makeUserCtx(workspace, { userId }), db: tx,});
async function incidentRow(tx: DB, id: number) { return tx.select().from(incident).where(eq(incident.id, id)).get();}
describe("member removal", () => { test("clears the commander of open incidents, keeps closed ones, drops slack links", async () => { const leaver = await createUser(); await addUserToWorkspace(leaver.id, workspace.id, "member"); await withTestTransaction(async (tx) => { const ctx = as(ownerId, tx); const open = await declareIncident({ ctx, input: { title: "open", severity: "major", commanderId: leaver.id }, }); const closed = await declareIncident({ ctx, input: { title: "closed", severity: "minor", commanderId: leaver.id }, }); await setIncidentStatus({ ctx, input: { id: closed.id, status: "resolved" }, }); await closeIncident({ ctx, input: { id: closed.id, skipPostmortem: true }, }); const link = await createSlackUser(workspace.id, leaver.id, {}, tx);
await removeMemberInWorkspace({ tx, ctx, userId: leaver.id });
expect((await incidentRow(tx, open.id))?.commanderId).toBeNull(); expect((await incidentRow(tx, closed.id))?.commanderId).toBe(leaver.id); const events = await listIncidentEvents({ ctx, input: { id: open.id } }); expect(events[0].type).toBe("commander_changed"); expect(events[0].createdBy).toBe(ownerId); expect( await tx .select() .from(slackUser) .where(eq(slackUser.id, link.id)) .get(), ).toBeUndefined(); }); });});
describe("account deletion", () => { test("clears the deleted user's commands and slack links", async () => { const leaver = await createUser(); await addUserToWorkspace(leaver.id, workspace.id, "member"); await withTestTransaction(async (tx) => { const open = await declareIncident({ ctx: as(ownerId, tx), input: { title: "open", severity: "major", commanderId: leaver.id }, }); await createSlackUser(workspace.id, leaver.id, {}, tx); await deleteAccount({ ctx: as(leaver.id, tx) }); expect((await incidentRow(tx, open.id))?.commanderId).toBeNull(); expect( await tx .select() .from(slackUser) .where(eq(slackUser.userId, leaver.id)) .all(), ).toHaveLength(0); }); });});
describe("status reports", () => { test("creating a report for an incident links it in the same transaction", async () => { await withTestTransaction(async (tx) => { const ctx = as(ownerId, tx); const inc = await declareIncident({ ctx, input: { title: "API", severity: "major" }, }); const { statusReport } = await createStatusReport({ ctx, input: { title: "API degraded", status: "investigating", message: "Looking into it", date: new Date(), pageId, pageComponentIds: [], incidentId: inc.id, }, }); expect((await incidentRow(tx, inc.id))?.statusReportId).toBe( statusReport.id, ); }); });
test("deleting a linked report unlinks the incident, audited", async () => { await withTestTransaction(async (tx) => { const ctx = as(ownerId, tx); const inc = await declareIncident({ ctx, input: { title: "API", severity: "major" }, }); const { statusReport } = await createStatusReport({ ctx, input: { title: "API degraded", status: "investigating", message: "Looking into it", date: new Date(), pageId, pageComponentIds: [], incidentId: inc.id, }, }); await deleteStatusReport({ ctx, input: { id: statusReport.id } }); expect((await incidentRow(tx, inc.id))?.statusReportId).toBeNull(); const events = await listIncidentEvents({ ctx, input: { id: inc.id } }); expect(events[0].type).toBe("status_report_unlinked"); await expectAuditRow({ workspaceId: workspace.id, action: "incident.update", entityType: "incident", entityId: inc.id, db: tx, }); }); });});