From 42d1c5cf34eaa6a1fe598989f7fe280fa2505865 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Wed, 20 May 2026 05:01:36 +0000 Subject: [PATCH] Fix QA review 2719: optional coatType/petSizeCategory, CoatType union, null guards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Make coatType and petSizeCategory optional on Pet (?:) — they may not be set - Remove "single" and "short" from COAT_TYPES (not in CoatType union) - Use { name: "Add" } instead of /add/i to target the + button specifically - Add optional chaining to puppyCutSpans[0]?.closest() (noUncheckedIndexedAccess) - Add optional chaining to petsData[0]?.id ?? "" in PetProfiles Co-Authored-By: Claude Opus 4.7 --- packages/types/src/index.ts | 4 ++-- src/__tests__/PetForm.test.tsx | 4 ++-- src/portal/sections/PetForm.tsx | 2 +- src/portal/sections/PetProfiles.tsx | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index d53138e..ea46cc2 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -39,8 +39,8 @@ export interface Pet { cutStyle: string | null; shampooPreference: string | null; specialCareNotes: string | null; - coatType: string | null; - petSizeCategory: string | null; + coatType?: string | null; + petSizeCategory?: string | null; preferredCuts: string[]; medicalAlerts: MedicalAlert[]; temperamentScore?: number; diff --git a/src/__tests__/PetForm.test.tsx b/src/__tests__/PetForm.test.tsx index 802e851..6553089 100644 --- a/src/__tests__/PetForm.test.tsx +++ b/src/__tests__/PetForm.test.tsx @@ -65,7 +65,7 @@ describe("PetForm", () => { render(); const input = screen.getByPlaceholderText(/type a cut name/i); fireEvent.change(input, { target: { value: "Teddy Bear" } }); - fireEvent.click(screen.getByRole("button", { name: /add/i })); + fireEvent.click(screen.getByRole("button", { name: "Add" })); expect(screen.getByText("Teddy Bear")).toBeTruthy(); }); @@ -76,7 +76,7 @@ describe("PetForm", () => { }; render(); const puppyCutSpans = screen.getAllByText("Puppy Cut"); - const puppyCutTag = puppyCutSpans[0].closest("span"); + const puppyCutTag = puppyCutSpans[0]?.closest("span"); if (!puppyCutTag) return; const removeBtn = puppyCutTag.querySelector("button"); if (!removeBtn) return; diff --git a/src/portal/sections/PetForm.tsx b/src/portal/sections/PetForm.tsx index 16c4476..4dc0dd4 100644 --- a/src/portal/sections/PetForm.tsx +++ b/src/portal/sections/PetForm.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { X, Save, Plus, Star } from "lucide-react"; import type { Pet, MedicalAlert, CoatType, AlertSeverity } from "@groombook/types"; -const COAT_TYPES: CoatType[] = ["double", "single", "wire", "curly", "smooth", "long", "short", "hairless"]; +const COAT_TYPES: CoatType[] = ["double", "wire", "curly", "smooth", "long", "hairless"]; const SEVERITY_OPTIONS: AlertSeverity[] = ["low", "medium", "high"]; interface Props { diff --git a/src/portal/sections/PetProfiles.tsx b/src/portal/sections/PetProfiles.tsx index 2820326..787eeb3 100644 --- a/src/portal/sections/PetProfiles.tsx +++ b/src/portal/sections/PetProfiles.tsx @@ -67,7 +67,7 @@ export function PetProfiles({ sessionId, readOnly }: Props) { setAppointments(apptsData); if (petsData.length > 0 && !selectedPetId) { - setSelectedPetId(petsData[0].id); + setSelectedPetId(petsData[0]?.id ?? ""); } } catch (e) { setError(e instanceof Error ? e.message : "Failed to load data");