diff --git a/apps/server/src/routes/v1/incidents/get_all.test.ts b/apps/server/src/routes/v1/incidents/get_all.test.ts index 77de0cd441..1d298e8d6a 100644 --- a/apps/server/src/routes/v1/incidents/get_all.test.ts +++ b/apps/server/src/routes/v1/incidents/get_all.test.ts @@ -1,8 +1,58 @@ -import { expect, test } from "bun:test"; +import { afterAll, beforeAll, expect, test } from "bun:test"; +import { db, eq } from "@openstatus/db"; +import { incidentTable, monitor } from "@openstatus/db/src/schema"; import { app } from "@/index"; import { IncidentSchema } from "./schema"; +const TEST_PREFIX = "v1-incident-getall-test"; +let testMonitorId: number; +let testIncidentId: number; + +beforeAll(async () => { + await db + .delete(incidentTable) + .where(eq(incidentTable.title, `${TEST_PREFIX}-incident`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); + + const mon = await db + .insert(monitor) + .values({ + workspaceId: 1, + name: `${TEST_PREFIX}-monitor`, + url: "https://test.example.com", + periodicity: "1m", + active: true, + regions: "ams", + jobType: "http", + method: "GET", + timeout: 30000, + }) + .returning() + .get(); + testMonitorId = mon.id; + + const incident = await db + .insert(incidentTable) + .values({ + workspaceId: 1, + monitorId: testMonitorId, + title: `${TEST_PREFIX}-incident`, + status: "investigating", + startedAt: new Date("2099-01-01T00:00:00Z"), + }) + .returning() + .get(); + testIncidentId = incident.id; +}); + +afterAll(async () => { + await db + .delete(incidentTable) + .where(eq(incidentTable.title, `${TEST_PREFIX}-incident`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); +}); + test("return all incidents", async () => { const res = await app.request("/v1/incident", { method: "GET", @@ -15,14 +65,14 @@ test("return all incidents", async () => { expect(res.status).toBe(200); expect(result.success).toBe(true); - expect(result.data?.length).toBeGreaterThan(0); + expect(result.data?.some((i) => i.id === testIncidentId)).toBe(true); }); test("return empty incidents", async () => { const res = await app.request("/v1/incident", { method: "GET", headers: { - "x-openstatus-key": "2", + "x-openstatus-key": "3", }, }); diff --git a/apps/server/src/routes/v1/maintenances/get_all.test.ts b/apps/server/src/routes/v1/maintenances/get_all.test.ts index c905b5d59e..2841437c06 100644 --- a/apps/server/src/routes/v1/maintenances/get_all.test.ts +++ b/apps/server/src/routes/v1/maintenances/get_all.test.ts @@ -1,7 +1,93 @@ -import { expect, test } from "bun:test"; +import { afterAll, beforeAll, expect, test } from "bun:test"; +import { db, eq } from "@openstatus/db"; +import { + maintenance, + maintenancesToPageComponents, + monitor, + pageComponent, +} from "@openstatus/db/src/schema"; + import { app } from "@/index"; import { MaintenanceSchema } from "./schema"; +const TEST_PREFIX = "v1-maint-getall-test"; +let testMonitorId: number; +let testPageComponentId: number; +let testMaintenanceId: number; + +beforeAll(async () => { + await db + .delete(maintenance) + .where(eq(maintenance.title, `${TEST_PREFIX}-maint`)); + await db + .delete(pageComponent) + .where(eq(pageComponent.name, `${TEST_PREFIX}-component`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); + + const mon = await db + .insert(monitor) + .values({ + workspaceId: 1, + name: `${TEST_PREFIX}-monitor`, + url: "https://test.example.com", + periodicity: "1m", + active: true, + regions: "ams", + jobType: "http", + method: "GET", + timeout: 30000, + }) + .returning() + .get(); + testMonitorId = mon.id; + + const comp = await db + .insert(pageComponent) + .values({ + workspaceId: 1, + pageId: 1, + monitorId: testMonitorId, + type: "monitor", + name: `${TEST_PREFIX}-component`, + order: 200, + }) + .returning() + .get(); + testPageComponentId = comp.id; + + const maint = await db + .insert(maintenance) + .values({ + workspaceId: 1, + pageId: 1, + title: `${TEST_PREFIX}-maint`, + message: "Test maintenance", + from: new Date("2099-01-01T00:00:00Z"), + to: new Date("2099-01-02T00:00:00Z"), + }) + .returning() + .get(); + testMaintenanceId = maint.id; + + await db.insert(maintenancesToPageComponents).values({ + maintenanceId: testMaintenanceId, + pageComponentId: testPageComponentId, + }); +}); + +afterAll(async () => { + await db + .delete(maintenancesToPageComponents) + .where(eq(maintenancesToPageComponents.maintenanceId, testMaintenanceId)); + await db + .delete(maintenance) + .where(eq(maintenance.title, `${TEST_PREFIX}-maint`)); + await db + .delete(pageComponent) + .where(eq(pageComponent.name, `${TEST_PREFIX}-component`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); +}); + test("return all maintenances", async () => { const res = await app.request("/v1/maintenance", { method: "GET", @@ -11,10 +97,10 @@ test("return all maintenances", async () => { }); const result = MaintenanceSchema.array().safeParse(await res.json()); - console.log(result); + expect(res.status).toBe(200); expect(result.success).toBe(true); - expect(result.data?.length).toBeGreaterThan(0); + expect(result.data?.some((m) => m.id === testMaintenanceId)).toBe(true); }); test("return all maintenances with monitorIds", async () => { @@ -29,19 +115,19 @@ test("return all maintenances with monitorIds", async () => { expect(res.status).toBe(200); expect(result.success).toBe(true); - expect(result.data?.length).toBeGreaterThan(0); - // Each maintenance should have monitorIds defined - for (const maintenance of result.data || []) { - expect(maintenance.monitorIds).toBeDefined(); - expect(Array.isArray(maintenance.monitorIds)).toBe(true); - } + + const testMaint = result.data?.find((m) => m.id === testMaintenanceId); + expect(testMaint).toBeDefined(); + expect(testMaint?.monitorIds).toBeDefined(); + expect(Array.isArray(testMaint?.monitorIds)).toBe(true); + expect(testMaint?.monitorIds).toContain(testMonitorId); }); test("return empty maintenances", async () => { const res = await app.request("/v1/maintenance", { method: "GET", headers: { - "x-openstatus-key": "2", + "x-openstatus-key": "3", }, }); diff --git a/apps/server/src/routes/v1/notifications/get_all.test.ts b/apps/server/src/routes/v1/notifications/get_all.test.ts index fd584c8729..4b88ec4312 100644 --- a/apps/server/src/routes/v1/notifications/get_all.test.ts +++ b/apps/server/src/routes/v1/notifications/get_all.test.ts @@ -1,8 +1,37 @@ -import { expect, test } from "bun:test"; +import { afterAll, beforeAll, expect, test } from "bun:test"; +import { db, eq } from "@openstatus/db"; +import { notification } from "@openstatus/db/src/schema"; import { app } from "@/index"; import { NotificationSchema } from "./schema"; +const TEST_PREFIX = "v1-notif-getall-test"; +let testNotificationId: number; + +beforeAll(async () => { + await db + .delete(notification) + .where(eq(notification.name, `${TEST_PREFIX}-email`)); + + const notif = await db + .insert(notification) + .values({ + workspaceId: 1, + name: `${TEST_PREFIX}-email`, + provider: "email", + data: '{"email":"test@test.com"}', + }) + .returning() + .get(); + testNotificationId = notif.id; +}); + +afterAll(async () => { + await db + .delete(notification) + .where(eq(notification.name, `${TEST_PREFIX}-email`)); +}); + test("return all notifications", async () => { const res = await app.request("/v1/notification", { method: "GET", @@ -15,14 +44,14 @@ test("return all notifications", async () => { expect(res.status).toBe(200); expect(result.success).toBe(true); - expect(result.data?.length).toBeGreaterThan(0); + expect(result.data?.some((n) => n.id === testNotificationId)).toBe(true); }); test("return empty notifications", async () => { const res = await app.request("/v1/notification", { method: "GET", headers: { - "x-openstatus-key": "2", + "x-openstatus-key": "3", }, }); diff --git a/apps/server/src/routes/v1/pages/get_all.test.ts b/apps/server/src/routes/v1/pages/get_all.test.ts index 836e0bbd12..8427558229 100644 --- a/apps/server/src/routes/v1/pages/get_all.test.ts +++ b/apps/server/src/routes/v1/pages/get_all.test.ts @@ -1,8 +1,69 @@ -import { expect, test } from "bun:test"; +import { afterAll, beforeAll, expect, test } from "bun:test"; +import { db, eq } from "@openstatus/db"; +import { monitor, page, pageComponent } from "@openstatus/db/src/schema"; import { app } from "@/index"; import { PageSchema } from "./schema"; +const TEST_PREFIX = "v1-page-getall-test"; +let testMonitorId: number; +let testPageId: number; + +beforeAll(async () => { + await db + .delete(pageComponent) + .where(eq(pageComponent.name, `${TEST_PREFIX}-component`)); + await db.delete(page).where(eq(page.slug, `${TEST_PREFIX}-slug`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); + + const mon = await db + .insert(monitor) + .values({ + workspaceId: 1, + name: `${TEST_PREFIX}-monitor`, + url: "https://test.example.com", + periodicity: "1m", + active: true, + regions: "ams", + jobType: "http", + method: "GET", + timeout: 30000, + }) + .returning() + .get(); + testMonitorId = mon.id; + + const p = await db + .insert(page) + .values({ + workspaceId: 1, + title: `${TEST_PREFIX}-page`, + slug: `${TEST_PREFIX}-slug`, + description: "Test page", + customDomain: "", + }) + .returning() + .get(); + testPageId = p.id; + + await db.insert(pageComponent).values({ + workspaceId: 1, + pageId: testPageId, + monitorId: testMonitorId, + type: "monitor", + name: `${TEST_PREFIX}-component`, + order: 0, + }); +}); + +afterAll(async () => { + await db + .delete(pageComponent) + .where(eq(pageComponent.name, `${TEST_PREFIX}-component`)); + await db.delete(page).where(eq(page.slug, `${TEST_PREFIX}-slug`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); +}); + test("return all pages", async () => { const res = await app.request("/v1/page", { method: "GET", @@ -15,14 +76,14 @@ test("return all pages", async () => { expect(res.status).toBe(200); expect(result.success).toBe(true); - expect(result.data?.length).toBeGreaterThan(0); + expect(result.data?.some((p) => p.id === testPageId)).toBe(true); }); test("return empty pages", async () => { const res = await app.request("/v1/page", { method: "GET", headers: { - "x-openstatus-key": "2", + "x-openstatus-key": "3", }, }); diff --git a/apps/server/src/routes/v1/pages/post.ts b/apps/server/src/routes/v1/pages/post.ts index 4ba09dc5ef..c4e01cb78a 100644 --- a/apps/server/src/routes/v1/pages/post.ts +++ b/apps/server/src/routes/v1/pages/post.ts @@ -65,21 +65,6 @@ export function registerPostPage(api: typeof pagesApi) { }); } - const count = ( - await db - .select({ count: sql`count(*)` }) - .from(page) - .where(eq(page.workspaceId, workspaceId)) - .all() - )[0].count; - - if (count >= limits["status-pages"]) { - throw new OpenStatusApiError({ - code: "PAYMENT_REQUIRED", - message: "Upgrade for more status pages", - }); - } - if ( !limits["password-protection"] && (input?.passwordProtected || input?.password) @@ -110,6 +95,21 @@ export function registerPostPage(api: typeof pagesApi) { }); } + const count = ( + await db + .select({ count: sql`count(*)` }) + .from(page) + .where(eq(page.workspaceId, workspaceId)) + .all() + )[0].count; + + if (count >= limits["status-pages"]) { + throw new OpenStatusApiError({ + code: "PAYMENT_REQUIRED", + message: "Upgrade for more status pages", + }); + } + if (subdomainSafeList.includes(input.slug)) { throw new OpenStatusApiError({ code: "BAD_REQUEST", diff --git a/apps/server/src/routes/v1/statusReports/get_all.test.ts b/apps/server/src/routes/v1/statusReports/get_all.test.ts index 77c81e8018..daa698ce38 100644 --- a/apps/server/src/routes/v1/statusReports/get_all.test.ts +++ b/apps/server/src/routes/v1/statusReports/get_all.test.ts @@ -1,8 +1,104 @@ -import { expect, test } from "bun:test"; +import { afterAll, beforeAll, expect, test } from "bun:test"; +import { db, eq } from "@openstatus/db"; +import { + monitor, + pageComponent, + statusReport, + statusReportUpdate, + statusReportsToPageComponents, +} from "@openstatus/db/src/schema"; import { app } from "@/index"; import { StatusReportSchema } from "./schema"; +const TEST_PREFIX = "v1-sr-getall-test"; +let testMonitorId: number; +let testPageComponentId: number; +let testStatusReportId: number; + +beforeAll(async () => { + await db + .delete(statusReport) + .where(eq(statusReport.title, `${TEST_PREFIX}-report`)); + await db + .delete(pageComponent) + .where(eq(pageComponent.name, `${TEST_PREFIX}-component`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); + + const mon = await db + .insert(monitor) + .values({ + workspaceId: 1, + name: `${TEST_PREFIX}-monitor`, + url: "https://test.example.com", + periodicity: "1m", + active: true, + regions: "ams", + jobType: "http", + method: "GET", + timeout: 30000, + }) + .returning() + .get(); + testMonitorId = mon.id; + + const comp = await db + .insert(pageComponent) + .values({ + workspaceId: 1, + pageId: 1, + monitorId: testMonitorId, + type: "monitor", + name: `${TEST_PREFIX}-component`, + order: 200, + }) + .returning() + .get(); + testPageComponentId = comp.id; + + const report = await db + .insert(statusReport) + .values({ + workspaceId: 1, + pageId: 1, + title: `${TEST_PREFIX}-report`, + status: "investigating", + }) + .returning() + .get(); + testStatusReportId = report.id; + + await db.insert(statusReportUpdate).values({ + statusReportId: testStatusReportId, + status: "investigating", + message: "Test investigating", + date: new Date("2099-01-01T00:00:00Z"), + }); + + await db.insert(statusReportsToPageComponents).values({ + statusReportId: testStatusReportId, + pageComponentId: testPageComponentId, + }); +}); + +afterAll(async () => { + await db + .delete(statusReportsToPageComponents) + .where( + eq(statusReportsToPageComponents.statusReportId, testStatusReportId), + ); + await db + .delete(statusReportUpdate) + .where(eq(statusReportUpdate.statusReportId, testStatusReportId)); + await db + .delete(statusReport) + .where(eq(statusReport.title, `${TEST_PREFIX}-report`)); + await db + .delete(pageComponent) + .where(eq(pageComponent.name, `${TEST_PREFIX}-component`)); + await db.delete(monitor).where(eq(monitor.name, `${TEST_PREFIX}-monitor`)); +}); + test("return all status reports", async () => { const res = await app.request("/v1/status_report", { method: "GET", @@ -15,7 +111,7 @@ test("return all status reports", async () => { expect(res.status).toBe(200); expect(result.success).toBe(true); - expect(result.data?.length).toBeGreaterThan(0); + expect(result.data?.some((r) => r.id === testStatusReportId)).toBe(true); }); test("return all status reports with monitorIds", async () => { @@ -30,23 +126,19 @@ test("return all status reports with monitorIds", async () => { expect(res.status).toBe(200); expect(result.success).toBe(true); - expect(result.data?.length).toBeGreaterThan(0); - // Each status report should have monitorIds defined - for (const statusReport of result.data || []) { - expect(statusReport.monitorIds).toBeDefined(); - expect(Array.isArray(statusReport.monitorIds)).toBe(true); - // Ensure each monitorId is a number - for (const monitorId of statusReport.monitorIds || []) { - expect(typeof monitorId).toBe("number"); - } - } + + const testReport = result.data?.find((r) => r.id === testStatusReportId); + expect(testReport).toBeDefined(); + expect(testReport?.monitorIds).toBeDefined(); + expect(Array.isArray(testReport?.monitorIds)).toBe(true); + expect(testReport?.monitorIds).toContain(testMonitorId); }); test("return empty status reports", async () => { const res = await app.request("/v1/status_report", { method: "GET", headers: { - "x-openstatus-key": "2", + "x-openstatus-key": "3", }, });