test(medications): close the gaps the mutation pass found

Three things the tests said were covered and were not.

A column flipped from honoured to ignored moved both sides of its own
assertion, because the check read the verdict off the table it was checking.
The verdicts are now written out as literals, so changing one is a decision
somebody states twice.

The preview block was unreachable from an SSR-only test, so nothing would
have noticed it rendering through the outcome view — which would classify
what a preview *would* write as a success and put a tick on a run that never
ran. It moves into its own component that takes the verdict as a prop, the way
the CSV result view already does, and the preview and the archived-row report
are asserted directly.

The account-wide import narrows its in-progress check to account-wide jobs, so
an import running on one medication's page does not refuse it. Nothing pinned
that; now something does.

Also correct two comments about the earlier replay-key fault. The repeated
value in the reported file was not a dose quantity — it was copied from the
example this dialog itself displays. The field never carried identity, and the
submission was never at fault.
This commit is contained in:
Marc-André Bombeck committed 2026-07-26 16:37:10 +02:00
1 parent 8a36117a0c
commit 36d589e11b
8 files changed
+274 -107

No files matched your search

@@ -28,12 +28,17 @@ import { isPlausibleEntryInstant } from "@/lib/validations/entry-instant";
// The entry shape carried a third field, `zaehler`, and the replay key was
// built from it whenever it was present. That reads as a per-row counter,
// which is what the documented example showed — but the field was optional,
// its uniqueness was never stated and never checked, and an export that puts
// the dose quantity there (1 tablet, on every row) collapsed a month of
// history onto one key: the first row imported, every later one lost the
// `(userId, idempotencyKey)` unique and came back reported as a duplicate of
// a dose it had nothing to do with.
// which is what the example beside this dialog showed — but the field was
// optional, its uniqueness was never stated and never checked, and nothing
// told anyone it carried identity. A submission that repeated one value down
// the column collapsed a month of history onto one key: the first row
// imported, every later one lost the `(userId, idempotencyKey)` unique and
// came back reported as a duplicate of a dose it had nothing to do with.
//
// The reported file repeated `1.0` because it was modelled on the example this
// dialog itself displayed, which counted upward and explained nothing. So the
// fault was never in the submission; it was in a field that decided identity
// while presenting itself as a quantity.
//
// `zaehler` is gone from the contract rather than accepted-and-ignored. A
// payload that still carries it imports unchanged — `z.object` drops
@@ -241,6 +241,30 @@ describe("POST /api/medications/intake/dose-history-import", () => {
expect(prisma.medicationIntakeImportJob.create).not.toHaveBeenCalled();
});
it("looks only at account-wide work when deciding whether one is already running", async () => {
await POST(postReq(CSV));
// The in-progress check and the stale sweep both narrow on
// `medicationId: null`. Without that narrowing, an import running on a
// single medication's own page would refuse this one — and the sweep would
// reach across and fail it.
expect(prisma.medicationIntakeImportJob.findFirst).toHaveBeenCalledWith({
where: {
userId: "user-1",
medicationId: null,
status: { in: ["queued", "running"] },
},
select: { id: true },
});
expect(prisma.medicationIntakeImportJob.updateMany).toHaveBeenCalledWith(
expect.objectContaining({
where: expect.objectContaining({
userId: "user-1",
medicationId: null,
}),
}),
);
});
it("fails the job and answers 503 when the worker cannot take it", async () => {
vi.mocked(getGlobalBoss).mockReturnValue(null as never);
const res = await POST(postReq(CSV));