Compare commits

...

2 Commits

Author SHA1 Message Date
Flea Flicker 707e74e6e1 fix: add missing 'short'/'medium'/'silky' to coat_type enum (GRO-1971)
CI / Test (pull_request) Successful in 12s
CI / Lint & Typecheck (pull_request) Successful in 16s
CI / Build & Push Docker Images (pull_request) Successful in 1m2s
Migration 0031_buffer_rules.sql created coat_type enum with values
('smooth', 'double', 'wire', 'curly', 'long', 'hairless') but omitted
'short', 'medium', and 'silky' which are defined in schema.ts and
required by seed.ts.

Added 0035_add_missing_coat_type_values.sql to add the missing values
using ALTER TYPE ... ADD VALUE IF NOT EXISTS.

This resolves the UAT seed failure:
  PostgresError: invalid input value for enum coat_type: "short"
  code: '22P02' routine: 'enum_in' (packages/db/src/seed.ts)

Dev→UAT SDLC: QA (Lint Roller) review, then CTO review.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-31 23:08:38 +00:00
Scrubs McBarkley bec7b014be fix(seed): remove stale uc.petName closure ref, correct medicalAlerts distribution to 30% (#115)
CI / Test (push) Successful in 11s
CI / Lint & Typecheck (push) Successful in 18s
CI / Build & Push Docker Images (push) Successful in 1m4s
CI / Test (pull_request) Successful in 12s
CI / Lint & Typecheck (pull_request) Successful in 14s
CI / Build & Push Docker Images (pull_request) Successful in 1m4s
2026-05-31 22:14:30 +00:00
4 changed files with 29 additions and 10 deletions
+3
View File
@@ -114,6 +114,9 @@ GroomBook API is a Hono-based REST service (TypeScript/Node.js) powering the pet
| TC-API-3.22 | Verify medicalAlerts shape | GET /api/pets/{id} for any pet with non-empty medicalAlerts | medicalAlerts is an array; each entry has type, description, severity |
| TC-API-3.23 | Verify UAT test pet Charlie has behavioral alert | GET /api/pets/{id} where name = "TestCooper" (pet for uat-charlie@groombook.dev) | medicalAlerts includes an entry with type: "behavioral", severity: "low" or "high" |
| TC-API-3.24 | Verify UAT test pet Delta has skin alert | GET /api/pets/{id} where name = "TestRocky" (pet for uat-delta@groombook.dev) | medicalAlerts includes an entry with type: "skin" |
| TC-API-3.25 | Verify 30+ total pets in UAT DB | GET /api/pets then count total | 30+ pets returned (UAT seed creates 500 random-pool + 5 UAT test clients + 2 UAT customer = 507 total) |
| TC-API-3.26 | Verify 25-35% medicalAlerts distribution | GET /api/pets (first 30 pets), count how many have non-empty medicalAlerts | Ratio is 25-35% (seed uses rand() < 0.3 for ~30% distribution) |
| TC-API-3.27 | Verify coat_type enum has all seed values | After UAT seed completes, inspect the coat_type enum on the UAT DB — it must contain: short, medium, long, double, wire, silky, curly, hairless | UAT seed jobs (`reset-demo-data`, `seed-test-data`) complete 1/1 with no `enum_in` error; coat_type includes all 8 values used by seed.ts `coatTypePool` |
### 4.4 Appointment Scheduling
@@ -0,0 +1,9 @@
-- Migration: 0035_add_missing_coat_type_values.sql
-- Adds missing values to coat_type enum that seed.ts requires but which were
-- omitted from the 0031_buffer_rules.sql CREATE TYPE statement (migration drift).
-- 0031 created: 'smooth', 'double', 'wire', 'curly', 'long', 'hairless'
-- Missing (from schema.ts coatTypeEnum): 'short', 'medium', 'silky'
ALTER TYPE "coat_type" ADD VALUE IF NOT EXISTS 'short';
ALTER TYPE "coat_type" ADD VALUE IF NOT EXISTS 'medium';
ALTER TYPE "coat_type" ADD VALUE IF NOT EXISTS 'silky';
+2 -2
View File
@@ -250,8 +250,8 @@
{
"idx": 35,
"version": "7",
"when": 1751140800000,
"tag": "0035_add_short_to_coat_type_enum",
"when": 1751480000000,
"tag": "0035_add_missing_coat_type_values",
"breakpoints": true
}
]
+15 -8
View File
@@ -1009,6 +1009,7 @@ async function seed() {
temperamentScore: randInt(1, 5),
temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)),
medicalAlerts: (() => {
// ~30% of random-pool pets have alerts — lands squarely in the 2535% AC band
if (rand() < 0.3) {
const count = rand() < 0.7 ? 1 : 2;
return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() }));
@@ -1105,15 +1106,14 @@ async function seed() {
temperamentScore: randInt(1, 5),
temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)),
medicalAlerts: (() => {
// Deterministic alerts for UAT AC pets
if (uc.petName === "TestCooper") {
return pickN(medicalAlertPool.filter((a) => a.type === "behavioral"), 1).map((a) => ({ ...a, id: uuid() }));
}
if (uc.petName === "TestRocky") {
return pickN(medicalAlertPool.filter((a) => a.type === "skin"), 1).map((a) => ({ ...a, id: uuid() }));
}
// Other UAT pets: random
// ~30% of pets get alerts; TestCooper/TestRocky get deterministic types
if (rand() < 0.3) {
if (uc.petName === "TestCooper") {
return pickN(medicalAlertPool.filter((a) => a.type === "behavioral"), 1).map((a) => ({ ...a, id: uuid() }));
}
if (uc.petName === "TestRocky") {
return pickN(medicalAlertPool.filter((a) => a.type === "skin"), 1).map((a) => ({ ...a, id: uuid() }));
}
const count = rand() < 0.7 ? 1 : 2;
return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() }));
}
@@ -1136,7 +1136,14 @@ async function seed() {
temperamentScore: randInt(1, 5),
temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)),
medicalAlerts: (() => {
// ~30% of pets get alerts; TestCooper/TestRocky get deterministic types
if (rand() < 0.3) {
if (uc.petName === "TestCooper") {
return pickN(medicalAlertPool.filter((a) => a.type === "behavioral"), 1).map((a) => ({ ...a, id: uuid() }));
}
if (uc.petName === "TestRocky") {
return pickN(medicalAlertPool.filter((a) => a.type === "skin"), 1).map((a) => ({ ...a, id: uuid() }));
}
const count = rand() < 0.7 ? 1 : 2;
return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() }));
}