mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
test(mood): read the patterns through the real aggregate, note days included
This commit is contained in:
1 parent
a0f6b89e92
commit
b7706d2ecc
1 file changed
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Mood patterns from the real aggregate read (ios #116 item 6).
|
||||
*
|
||||
* The note days come from their own projection (`noteEncrypted` or the legacy
|
||||
* `note` set, distinct by mood day), so the `notes` pattern is only as right
|
||||
* as that query. This seeds a year with a weekend effect and notes on low
|
||||
* days, runs `fetchMoodAggregates` against Postgres, and reads the patterns
|
||||
* the wire serves for the year and for thirty days.
|
||||
*/
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
import { getPrismaClient, truncateAllTables } from "./setup";
|
||||
|
||||
process.env.ENCRYPTION_KEY ??=
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
||||
|
||||
const USER_ID = "user-mood-patterns";
|
||||
|
||||
beforeEach(async () => {
|
||||
await truncateAllTables(getPrismaClient());
|
||||
await getPrismaClient().user.create({
|
||||
data: {
|
||||
id: USER_ID,
|
||||
username: "mood-patterns",
|
||||
email: "mood-patterns@example.test",
|
||||
timezone: "UTC",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe("mood patterns", () => {
|
||||
it("finds the weekend and the note days in a seeded year", async () => {
|
||||
const { encryptToBytes } = await import("@/lib/ai/coach/bytes-codec");
|
||||
const now = new Date();
|
||||
const rows = [];
|
||||
for (let back = 1; back <= 200; back += 1) {
|
||||
const at = new Date(now.getTime() - back * 86_400_000);
|
||||
const date = at.toISOString().slice(0, 10);
|
||||
const weekday = (at.getUTCDay() + 6) % 7;
|
||||
const low = back % 3 === 0;
|
||||
const jitter = ((back * 37) % 10) / 20;
|
||||
const score = Math.min(
|
||||
5,
|
||||
Math.max(
|
||||
1,
|
||||
Math.round((weekday >= 5 ? 4.4 : 3) - (low ? 1 : 0) + jitter),
|
||||
),
|
||||
);
|
||||
rows.push({
|
||||
userId: USER_ID,
|
||||
date,
|
||||
mood: "GUT" as const,
|
||||
score,
|
||||
source: "WEB" as const,
|
||||
moodLoggedAt: at,
|
||||
tz: "UTC",
|
||||
...(low ? { noteEncrypted: encryptToBytes("a hard day") } : {}),
|
||||
});
|
||||
}
|
||||
await getPrismaClient().moodEntry.createMany({ data: rows as never });
|
||||
|
||||
const { fetchMoodAggregates, moodInsightsWire } =
|
||||
await import("@/lib/insights/mood-aggregates");
|
||||
const aggregate = await fetchMoodAggregates(USER_ID, now);
|
||||
const year = moodInsightsWire(aggregate, 365, (k) => k).patterns;
|
||||
expect(year.map((p) => p.kind)).toContain("weekend");
|
||||
expect(year.find((p) => p.kind === "notes")).toMatchObject({
|
||||
direction: "lower",
|
||||
});
|
||||
const notes = year.find((p) => p.kind === "notes")!;
|
||||
expect(notes.sampleSize.subject).toBeGreaterThanOrEqual(60);
|
||||
const month = moodInsightsWire(aggregate, 30, (k) => k).patterns;
|
||||
for (const p of month) {
|
||||
expect(
|
||||
p.sampleSize.subject + p.sampleSize.comparison,
|
||||
).toBeLessThanOrEqual(30);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user