← back to Govarbitrage
TK-11464 test: regression guard for sort orderBy nullability classification
6531e6f27385f57974da6616e4814886f60af27e · 2026-09-12 07:23:45 -0700 · Steve Abrams
DB-free vitest guard (reads Prisma DMMF) asserting a native sort column is
classified nullable iff its schema field is optional — catches the exact
recurrence vector of the title-sort 500 (the {sort,nulls} object form applied
to a required field). Verified: passes on current schema; proven to fail when
a required column (title) is misclassified as nullable. Does not touch
listings.ts (keeps the single-file deploy diff-guard intact).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UYTNq3N4J57Gcna8XdPJ18
Files touched
A src/lib/listings-sort.test.ts
Diff
commit 6531e6f27385f57974da6616e4814886f60af27e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Sep 12 07:23:45 2026 -0700
TK-11464 test: regression guard for sort orderBy nullability classification
DB-free vitest guard (reads Prisma DMMF) asserting a native sort column is
classified nullable iff its schema field is optional — catches the exact
recurrence vector of the title-sort 500 (the {sort,nulls} object form applied
to a required field). Verified: passes on current schema; proven to fail when
a required column (title) is misclassified as nullable. Does not touch
listings.ts (keeps the single-file deploy diff-guard intact).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UYTNq3N4J57Gcna8XdPJ18
---
src/lib/listings-sort.test.ts | 57 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/src/lib/listings-sort.test.ts b/src/lib/listings-sort.test.ts
new file mode 100644
index 0000000..38b4553
--- /dev/null
+++ b/src/lib/listings-sort.test.ts
@@ -0,0 +1,57 @@
+import { describe, it, expect } from "vitest";
+import { Prisma } from "@prisma/client";
+
+// Regression guard for TK-11464: sorting the listings grid by a non-nullable
+// native column (title, source, condition, …) returned HTTP 500 because the
+// DB-side orderBy applied Prisma's { sort, nulls } object form to EVERY native
+// column. Prisma only accepts that object form on OPTIONAL (nullable) fields;
+// a required field must use the bare SortOrder string, else it throws
+// PrismaClientValidationError ("Expected SortOrder, provided Object.").
+//
+// listings.ts gates the object form behind NULLABLE_NATIVE_SORT_COLUMNS. This
+// test keeps that gate honest against the schema with no DB needed: a native
+// column is classified nullable iff the Prisma field is optional. It fails if
+// a field's nullability changes without updating the set, or a new native sort
+// column is added unclassified.
+
+// Mirror of the sets in src/lib/listings.ts (this test is their sync-check).
+const NATIVE_SORT_COLUMNS = [
+ "currentBid",
+ "closingAt",
+ "title",
+ "source",
+ "sourceAuctionId",
+ "category",
+ "manufacturer",
+ "model",
+ "condition",
+ "quantity",
+ "researchStatus",
+] as const;
+
+const NULLABLE_NATIVE_SORT_COLUMNS = new Set<string>([
+ "closingAt",
+ "category",
+ "manufacturer",
+ "model",
+]);
+
+describe("listings native sort classification (TK-11464)", () => {
+ const listing = Prisma.dmmf.datamodel.models.find((m) => m.name === "Listing");
+
+ it("resolves the Listing model from the Prisma DMMF", () => {
+ expect(listing).toBeDefined();
+ });
+
+ it("classifies a native sort column as nullable iff the schema field is optional", () => {
+ for (const name of NATIVE_SORT_COLUMNS) {
+ const field = listing!.fields.find((f) => f.name === name);
+ expect(field, `${name} is not a scalar field on Listing`).toBeDefined();
+ // Prisma: optional field => isRequired === false => may carry { sort, nulls }.
+ expect(
+ NULLABLE_NATIVE_SORT_COLUMNS.has(name),
+ `${name}: orderBy nullability classification must match schema (schema optional=${!field!.isRequired})`,
+ ).toBe(!field!.isRequired);
+ }
+ });
+});
← 0442a97 TK-11466 FIX 2: decouple ADMIN mint from wall-disabled state
·
back to Govarbitrage
·
TK-11464 fix (re-commit): gate orderBy nulls-ordering to nul c62e153 →