mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
fix(labs): name a merge in the owner's activity feed and toast it through the outcome module
A merge by a record manager now reads as its own sentence in the owner's activity feed, the merged toast goes through the written-outcome toast, and the export test doubles carry the alias and merge tables.
This commit is contained in:
1 parent
e65ada2961
commit
e112e05a58
13 files changed
+52
-25
No files matched your search
+2
-1
@@ -12061,7 +12061,8 @@
|
||||
"customVaccineDelete": "{name} hat einen eigenen Impfstoff entfernt",
|
||||
"lifeEventCreate": "{name} hat ein Lebensereignis hinzugefügt",
|
||||
"lifeEventUpdate": "{name} hat ein Lebensereignis geändert",
|
||||
"lifeEventDelete": "{name} hat ein Lebensereignis entfernt"
|
||||
"lifeEventDelete": "{name} hat ein Lebensereignis entfernt",
|
||||
"biomarkerMerge": "{name} hat Biomarker zusammengeführt"
|
||||
},
|
||||
"section": {
|
||||
"measurements": {
|
||||
|
||||
+2
-1
@@ -12061,7 +12061,8 @@
|
||||
"customVaccineDelete": "{name} removed an own vaccine",
|
||||
"lifeEventCreate": "{name} added a life event",
|
||||
"lifeEventUpdate": "{name} changed a life event",
|
||||
"lifeEventDelete": "{name} removed a life event"
|
||||
"lifeEventDelete": "{name} removed a life event",
|
||||
"biomarkerMerge": "{name} merged biomarkers"
|
||||
},
|
||||
"section": {
|
||||
"measurements": {
|
||||
|
||||
+2
-1
@@ -12061,7 +12061,8 @@
|
||||
"customVaccineDelete": "{name} quitó una vacuna propia",
|
||||
"lifeEventCreate": "{name} añadió un acontecimiento vital",
|
||||
"lifeEventUpdate": "{name} cambió un acontecimiento vital",
|
||||
"lifeEventDelete": "{name} eliminó un acontecimiento vital"
|
||||
"lifeEventDelete": "{name} eliminó un acontecimiento vital",
|
||||
"biomarkerMerge": "{name} combinó biomarcadores"
|
||||
},
|
||||
"section": {
|
||||
"measurements": {
|
||||
|
||||
+2
-1
@@ -12061,7 +12061,8 @@
|
||||
"customVaccineDelete": "{name} a retiré un vaccin personnel",
|
||||
"lifeEventCreate": "{name} a ajouté un événement de vie",
|
||||
"lifeEventUpdate": "{name} a modifié un événement de vie",
|
||||
"lifeEventDelete": "{name} a supprimé un événement de vie"
|
||||
"lifeEventDelete": "{name} a supprimé un événement de vie",
|
||||
"biomarkerMerge": "{name} a fusionné des biomarqueurs"
|
||||
},
|
||||
"section": {
|
||||
"measurements": {
|
||||
|
||||
+2
-1
@@ -12061,7 +12061,8 @@
|
||||
"customVaccineDelete": "{name} ha rimosso un vaccino personale",
|
||||
"lifeEventCreate": "{name} ha aggiunto un evento della vita",
|
||||
"lifeEventUpdate": "{name} ha modificato un evento della vita",
|
||||
"lifeEventDelete": "{name} ha rimosso un evento della vita"
|
||||
"lifeEventDelete": "{name} ha rimosso un evento della vita",
|
||||
"biomarkerMerge": "{name} ha unito dei biomarcatori"
|
||||
},
|
||||
"section": {
|
||||
"measurements": {
|
||||
|
||||
+2
-1
@@ -12061,7 +12061,8 @@
|
||||
"customVaccineDelete": "{name} 님이 직접 추가한 백신을 삭제했어요",
|
||||
"lifeEventCreate": "{name} 님이 삶의 사건을 추가했어요",
|
||||
"lifeEventUpdate": "{name} 님이 삶의 사건을 수정했어요",
|
||||
"lifeEventDelete": "{name} 님이 삶의 사건을 삭제했어요"
|
||||
"lifeEventDelete": "{name} 님이 삶의 사건을 삭제했어요",
|
||||
"biomarkerMerge": "{name} 님이 바이오마커를 합쳤어요"
|
||||
},
|
||||
"section": {
|
||||
"measurements": {
|
||||
|
||||
+2
-1
@@ -12061,7 +12061,8 @@
|
||||
"customVaccineDelete": "{name} usunął własną szczepionkę",
|
||||
"lifeEventCreate": "{name} dodał wydarzenie życiowe",
|
||||
"lifeEventUpdate": "{name} zmienił wydarzenie życiowe",
|
||||
"lifeEventDelete": "{name} usunął wydarzenie życiowe"
|
||||
"lifeEventDelete": "{name} usunął wydarzenie życiowe",
|
||||
"biomarkerMerge": "{name} scalił biomarkery"
|
||||
},
|
||||
"section": {
|
||||
"measurements": {
|
||||
|
||||
@@ -86,6 +86,8 @@ vi.mock("@/lib/db", () => ({
|
||||
// helper now also reads (`buildRecordsBackupSection`).
|
||||
labResult: { findMany: vi.fn() },
|
||||
biomarker: { findMany: vi.fn() },
|
||||
biomarkerAlias: { findMany: vi.fn() },
|
||||
biomarkerMerge: { findMany: vi.fn() },
|
||||
illnessEpisode: { findMany: vi.fn() },
|
||||
allergy: { findMany: vi.fn() },
|
||||
familyHistoryEntry: { findMany: vi.fn() },
|
||||
@@ -135,6 +137,8 @@ beforeEach(() => {
|
||||
// `resetAllMocks` clears the inline defaults, and the full-backup payload
|
||||
// builder reads these unconditionally.
|
||||
vi.mocked(prisma.nutrientIntakeDay.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.biomarkerAlias.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.biomarkerMerge.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.medicationCategoryLabel.findMany).mockResolvedValue(
|
||||
[] as never,
|
||||
);
|
||||
|
||||
@@ -67,6 +67,8 @@ vi.mock("@/lib/db", () => ({
|
||||
cycleDayLog: { findMany: vi.fn() },
|
||||
labResult: { findMany: vi.fn() },
|
||||
biomarker: { findMany: vi.fn() },
|
||||
biomarkerAlias: { findMany: vi.fn() },
|
||||
biomarkerMerge: { findMany: vi.fn() },
|
||||
allergy: { findMany: vi.fn() },
|
||||
familyHistoryEntry: { findMany: vi.fn() },
|
||||
workout: { findMany: vi.fn() },
|
||||
@@ -205,6 +207,8 @@ beforeEach(() => {
|
||||
vi.mocked(prisma.cycleDayLog.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.labResult.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.biomarker.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.biomarkerAlias.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.biomarkerMerge.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.allergy.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.familyHistoryEntry.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.workout.findMany).mockResolvedValue([] as never);
|
||||
|
||||
@@ -77,6 +77,8 @@ vi.mock("@/lib/db", () => ({
|
||||
// builder now also reads (`buildRecordsBackupSection`).
|
||||
labResult: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
biomarker: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
biomarkerAlias: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
biomarkerMerge: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
illnessEpisode: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
allergy: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
familyHistoryEntry: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { Loader2 } from "lucide-react";
|
||||
|
||||
import { toastWrittenOutcome } from "@/components/outcome/outcome-toast";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Label } from "@/components/ui/label";
|
||||
@@ -71,7 +72,8 @@ export function BiomarkerMergeSheet({
|
||||
setPreview(result);
|
||||
return;
|
||||
}
|
||||
toast.success(
|
||||
toastWrittenOutcome(
|
||||
"success",
|
||||
tCount("labs.merge.doneToast", result.movedReadings, {
|
||||
name: result.target.name,
|
||||
}),
|
||||
|
||||
@@ -179,6 +179,8 @@ export function recordActivityVerbLine(
|
||||
return t("recordSharing.activityVerb.biomarkerUpdate", { name });
|
||||
case "biomarker.delete":
|
||||
return t("recordSharing.activityVerb.biomarkerDelete", { name });
|
||||
case "labs.biomarker.merge":
|
||||
return t("recordSharing.activityVerb.biomarkerMerge", { name });
|
||||
|
||||
case "allergy.update":
|
||||
return t("recordSharing.activityVerb.allergyUpdate", { name });
|
||||
|
||||
@@ -97,10 +97,9 @@ async function merge(
|
||||
body: { sourceIds: string[]; dryRun?: boolean },
|
||||
) {
|
||||
const { POST } = await import("@/app/api/biomarkers/[id]/merge/route");
|
||||
return POST(
|
||||
json(body, `http://localhost/api/biomarkers/${targetId}/merge`),
|
||||
{ params: Promise.resolve({ id: targetId }) },
|
||||
);
|
||||
return POST(json(body, `http://localhost/api/biomarkers/${targetId}/merge`), {
|
||||
params: Promise.resolve({ id: targetId }),
|
||||
});
|
||||
}
|
||||
|
||||
async function tableCounts() {
|
||||
@@ -172,9 +171,8 @@ describe("POST /api/biomarkers/{id}/merge", () => {
|
||||
expect(detail.data.meta.total).toBe(42);
|
||||
|
||||
// The doctor report: one line, counted 42, under the marker's name.
|
||||
const { loadLabResults } = await import(
|
||||
"@/lib/doctor-report/clinical-records"
|
||||
);
|
||||
const { loadLabResults } =
|
||||
await import("@/lib/doctor-report/clinical-records");
|
||||
const report = await loadLabResults(USER_ID, daysAgo(1000), new Date());
|
||||
expect(report).toHaveLength(1);
|
||||
expect(report![0]).toMatchObject({
|
||||
@@ -206,14 +204,18 @@ describe("POST /api/biomarkers/{id}/merge", () => {
|
||||
if (!page.nextCursor) break;
|
||||
offset += page.readings!.length;
|
||||
}
|
||||
expect(total.reduce((a, b) => a + b, 0), analyte).toBe(42);
|
||||
expect(
|
||||
total.reduce((a, b) => a + b, 0),
|
||||
analyte,
|
||||
).toBe(42);
|
||||
}
|
||||
|
||||
// The source is gone, its old id leads to the target, and the reading's
|
||||
// printed name survived.
|
||||
const prisma = getPrismaClient();
|
||||
expect(await prisma.biomarker.findUnique({ where: { id: source.id } }))
|
||||
.toBeNull();
|
||||
expect(
|
||||
await prisma.biomarker.findUnique({ where: { id: source.id } }),
|
||||
).toBeNull();
|
||||
const { GET: getMarker } = await import("@/app/api/biomarkers/[id]/route");
|
||||
const stale = await getMarker(
|
||||
new NextRequest(`http://localhost/api/biomarkers/${source.id}`),
|
||||
@@ -442,9 +444,11 @@ describe("POST /api/biomarkers/{id}/merge", () => {
|
||||
"Ferr",
|
||||
"Ferritin (Serum)",
|
||||
]);
|
||||
expect(await getPrismaClient().labResult.count({
|
||||
where: { biomarkerId: c.id },
|
||||
})).toBe(3);
|
||||
expect(
|
||||
await getPrismaClient().labResult.count({
|
||||
where: { biomarkerId: c.id },
|
||||
}),
|
||||
).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -469,7 +473,9 @@ describe("aliases on the marker", () => {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await put(alp.id, { aliases: ["Alk.P", "AP", "alkaline phosphatase"] });
|
||||
const res = await put(alp.id, {
|
||||
aliases: ["Alk.P", "AP", "alkaline phosphatase"],
|
||||
});
|
||||
expect(res.status).toBe(200);
|
||||
expect((await res.json()).data.aliases).toEqual(["Alk.P", "AP"]);
|
||||
const rows = await prisma.biomarkerAlias.findMany({
|
||||
@@ -712,9 +718,9 @@ describe("a spelling resolves on its own once chosen", () => {
|
||||
where: { id: ref.recordId },
|
||||
});
|
||||
expect(reading.biomarkerId).toBe(alp.id);
|
||||
expect(
|
||||
(await prisma.biomarkerAlias.findFirstOrThrow({})).name,
|
||||
).toBe("Alk. Phosph.");
|
||||
expect((await prisma.biomarkerAlias.findFirstOrThrow({})).name).toBe(
|
||||
"Alk. Phosph.",
|
||||
);
|
||||
|
||||
const again = serialiseFact(fact, await loadMarkerIndex(prisma, USER_ID));
|
||||
expect(again).toMatchObject({ biomarkerId: alp.id, matchKind: "alias" });
|
||||
|
||||
Reference in new issue
Block a user