diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2a94ae9..a51ba8e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -131,6 +131,9 @@ jobs:
- name: Seed admin account
run: npx tsx prisma/seed.ts
+ - name: Seed e2e fixtures
+ run: npx tsx e2e/seed.ts
+
- name: Build
run: npm run build
diff --git a/e2e/seed.ts b/e2e/seed.ts
new file mode 100644
index 0000000..33168ba
--- /dev/null
+++ b/e2e/seed.ts
@@ -0,0 +1,36 @@
+import { PrismaClient } from "@prisma/client"
+import { PrismaPg } from "@prisma/adapter-pg"
+
+// E2E fixture: one employee so a fresh instance counts as set up
+// (the dashboard redirects empty workspaces to /setup). Run after
+// prisma/seed.ts; used by the CI e2e job only.
+const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL! })
+const prisma = new PrismaClient({ adapter })
+
+async function main() {
+ const company = await prisma.company.findUniqueOrThrow({
+ where: { domain: "datashield.dev" },
+ })
+
+ await prisma.employee.upsert({
+ where: {
+ email_companyId: { email: "jane.doe@datashield.dev", companyId: company.id },
+ },
+ update: {},
+ create: {
+ email: "jane.doe@datashield.dev",
+ firstName: "Jane",
+ lastName: "Doe",
+ department: "Engineering",
+ companyId: company.id,
+ },
+ })
+
+}
+
+main()
+ .then(() => prisma.$disconnect())
+ .catch((e) => {
+ console.error(e)
+ process.exit(1)
+ })
diff --git a/e2e/smoke.spec.ts b/e2e/smoke.spec.ts
index b49961f..e53b6a9 100644
--- a/e2e/smoke.spec.ts
+++ b/e2e/smoke.spec.ts
@@ -1,19 +1,25 @@
import { test, expect } from "@playwright/test"
let cspViolations: string[]
+let pageErrors: string[]
test.beforeEach(({ page }) => {
cspViolations = []
+ pageErrors = []
page.on("console", (msg) => {
const text = msg.text()
if (text.includes("Content Security Policy") || text.includes("Refused to")) {
cspViolations.push(text)
}
})
+ page.on("pageerror", (err) => {
+ pageErrors.push(err.message)
+ })
})
test.afterEach(() => {
expect(cspViolations).toEqual([])
+ expect(pageErrors).toEqual([])
})
test("admin signs in, sees dashboard and alerts", async ({ page }) => {
@@ -27,4 +33,8 @@ test("admin signs in, sees dashboard and alerts", async ({ page }) => {
await page.goto("/alerts")
await expect(page.getByRole("main")).toBeVisible()
+
+ await page.goto("/dashboard/widgets")
+ await expect(page.getByRole("heading", { name: "Widget Library" })).toBeVisible()
+ await expect(page.getByRole("heading", { name: "Alert Severity" })).toBeVisible()
})
diff --git a/src/app/(dashboard)/dashboard/widgets/page.tsx b/src/app/(dashboard)/dashboard/widgets/page.tsx
index d548ce8..40be2ba 100644
--- a/src/app/(dashboard)/dashboard/widgets/page.tsx
+++ b/src/app/(dashboard)/dashboard/widgets/page.tsx
@@ -3,6 +3,7 @@ import { getDashboardData } from "@/lib/dashboard"
import { prisma } from "@/lib/prisma"
import { WIDGETS } from "@/lib/widgetRegistry"
import { WidgetLibrary } from "@/components/dashboard/WidgetLibrary"
+import { DetailDrawerProvider } from "@/contexts/DetailDrawerContext"
import { StatsRow } from "@/components/dashboard/StatsRow"
import { TrendChart } from "@/components/dashboard/TrendChart"
import { DataTypeBreakdown } from "@/components/dashboard/DataTypeBreakdown"
@@ -86,10 +87,12 @@ export default async function WidgetsPage() {
}
return (
-
+
+
+
)
}