diff --git a/tests/integration/log-work.test.ts b/tests/integration/log-work.test.ts index ee48fae..4959231 100644 --- a/tests/integration/log-work.test.ts +++ b/tests/integration/log-work.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeAll, afterAll } from "vitest"; import PocketBase from "pocketbase"; -import { DEMO, adminPb, requireServices } from "./helpers"; +import { APP_URL, DEMO, adminPb, requireServices, signIn } from "./helpers"; let admin: PocketBase; let projectId: string; @@ -53,15 +53,13 @@ describe("computeProjectMetrics via recomputeMetrics", () => { afterAll(async () => { if (commitId) await admin.collection("commits").delete(commitId).catch(() => {}); + const { recomputeMetrics } = await import("@/lib/metrics/store"); + await recomputeMetrics(projectId).catch(() => {}); }); it("adds a manual entry's declared minutes to estimatedMinutes", async () => { - const before = await admin - .collection("project_metrics") - .getFirstListItem(`project = "${projectId}"`) - .catch(() => null); - const beforeMinutes = (before?.payload as { estimatedMinutes?: number } | undefined) - ?.estimatedMinutes ?? 0; + const { recomputeMetrics } = await import("@/lib/metrics/store"); + const base = await recomputeMetrics(projectId); // fresh baseline, not a possibly-stale cache const commit = await admin.collection("commits").create({ project: projectId, @@ -76,7 +74,7 @@ describe("computeProjectMetrics via recomputeMetrics", () => { additions: 0, deletions: 0, card: "", - link_source: "none", + link_source: "manual", url: "", summary: "Integration test entry", summary_version: 0, @@ -86,10 +84,27 @@ describe("computeProjectMetrics via recomputeMetrics", () => { }); commitId = commit.id; - const { recomputeMetrics } = await import("@/lib/metrics/store"); - const metrics = await recomputeMetrics(projectId); + const after = await recomputeMetrics(projectId); - expect(metrics.manualMinutes).toBeGreaterThanOrEqual(90); - expect(metrics.estimatedMinutes).toBeGreaterThanOrEqual(beforeMinutes + 90); + expect(after.manualMinutes).toBe(base.manualMinutes + 90); + expect(after.estimatedMinutes).toBe(base.estimatedMinutes + 90); // flat, not clustered + }); +}); + +describe("the Log work UI is owner-only", () => { + it("shows the button to the owner but not to a client manager", async () => { + const ownerCookie = await signIn(DEMO.ownerEmail, DEMO.ownerPassword); + const ownerHtml = await fetch( + `${APP_URL}/p/${DEMO.clientSlug}/${DEMO.projectSlug}/dashboard`, + { headers: { cookie: ownerCookie } } + ).then((r) => r.text()); + expect(ownerHtml).toContain("Log work"); + + const managerCookie = await signIn(DEMO.managerEmail, DEMO.managerPassword); + const managerHtml = await fetch( + `${APP_URL}/p/${DEMO.clientSlug}/${DEMO.projectSlug}/dashboard`, + { headers: { cookie: managerCookie } } + ).then((r) => r.text()); + expect(managerHtml).not.toContain("Log work"); }); }); diff --git a/tests/integration/summarise.test.ts b/tests/integration/summarise.test.ts index 694b131..29c9555 100644 --- a/tests/integration/summarise.test.ts +++ b/tests/integration/summarise.test.ts @@ -24,7 +24,6 @@ afterAll(async () => { describe("merge commits are never summarised", () => { it("excludes them from the pending set", async () => { const { summaryStatus } = await import("@/lib/ai/summarise"); - const status = await summaryStatus(projectId); const merges = ( await admin @@ -38,9 +37,40 @@ describe("merge commits are never summarised", () => { .getList(1, 1, { filter: `project = "${projectId}"`, fields: "id" }) ).totalItems; - // status.total counts non-merge commits only. - expect(status.total).toBe(all - merges); + const before = await summaryStatus(projectId); + // status.total counts non-merge, non-manual commits only. + expect(before.total).toBe(all - merges); expect(merges).toBeGreaterThan(0); + + // A manual entry must not move this count at all. + const manual = await admin.collection("commits").create({ + project: projectId, + sha: `manual-summarise-test-${Date.now()}`, + short_sha: "manual", + message: "Summarise-exclusion probe", + subject: "Summarise-exclusion probe", + type: "", + scope: "", + authored_at: "2026-09-19 12:00:00.000Z", + is_merge: false, + additions: 0, + deletions: 0, + card: "", + link_source: "manual", + url: "", + summary: "Summarise-exclusion probe", + summary_version: 0, + summary_attempts: 0, + source: "manual", + manual_minutes: 30, + }); + + try { + const after = await summaryStatus(projectId); + expect(after.total).toBe(before.total); + } finally { + await admin.collection("commits").delete(manual.id).catch(() => {}); + } }); });