Kulcare Docs
Test plansClinic app

Test Plan: Patient Management (List, View, Edit, Create)

Module: Clinic App - Patient Management Code Audit Date: 2026-06-17 Status: 🔄 In Progress


Code Audit Summary

Backend APIs (patients_controller.rb)

ActionEndpointDescription
indexGET /clinical/patientsList patients with filters
searchGET /clinical/patients/searchSearch patients
showGET /clinical/patients/:idGet patient details
createPOST /clinical/patientsCreate patient
updatePATCH /clinical/patients/:idUpdate patient
destroyDELETE /clinical/patients/:idDelete patient
generate_reportPOST /clinical/patients/generate_reportExport patients

Frontend Pages

PageURLRoute
PatientsPage/cms/patientsList view
PatientFormPage/cms/patients/add-patientCreate mode
PatientFormPage/cms/patients/add-patient?edit={id}Edit mode
PatientDetailPage/cms/patient/{id}/{facility_id}View details

SECTION 1: Patient List Page

Component: PatientsPage.tsx URL: /cms/patients

1.1 List Display

#Test CasePriorityAPI/UIExpectedStatus
LIST-01View patient listP0GET /clinical/patientsShows paginated list✅ PASS
LIST-02View stats cardsP0Same APIShows Total, New, Active, Avg Visits✅ PASS
LIST-03Empty state - no patientsP0API returns emptyShows "No patients" message✅ PASS
LIST-04Loading stateP1API loadingShows loading spinner✅ PASS
LIST-05Error stateP1API errorShows error message with retry✅ PASS

1.2 Search & Filter

#Test CasePriorityAPI ParamExpectedStatus
LIST-10Search by nameP0search=nameReturns matching patients✅ PASS
LIST-11Search by partial nameP0search=mohReturns matching patientsBug #31 ❌
LIST-12Search by phoneP0search=phoneReturns matching patientsBug #36 ❌
LIST-13Search by MRNP0search=mrnReturns matching patientsPending
LIST-14Clear searchP0Clear paramShows all patients✅ PASS
LIST-15No resultsP0Invalid searchShows "No results" message✅ PASS
LIST-16Debounce searchP1300ms delayPrevents excessive API calls✅ PASS

1.3 Date Range Filter

#Test CasePriorityAPI ParamExpectedStatus
LIST-20Filter by birth date rangeP0birth_date_from, birth_date_toFiltered resultsBug #35 ❌
LIST-21Clear date filterP0No paramsShows all patients⏭️ Skipped

1.4 Pagination

#Test CasePriorityUI ActionExpectedStatus
LIST-30Next pageP0Click NextShows page 2✅ PASS
LIST-31Previous pageP0Click PreviousReturns to page 1✅ PASS
LIST-32Jump to pageP0Enter page numberShows that page✅ PASS
LIST-33Change page sizeP0Select 10/25/50/100Updates results✅ PASS
LIST-34Total count displayedP1-Shows "Showing X of Y"✅ PASS

1.5 Table Actions

#Test CasePriorityUI ActionExpectedStatus
LIST-40Click Edit (pencil)P0NavigateOpens /cms/patients/add-patient?edit={id}✅ PASS
LIST-41Click Print (printer)P0ModalOpens PatientPreviewModal✅ PASS
LIST-42Click View (eye)P0NavigateOpens /cms/patient/{id}/{facility_id}✅ PASS

1.6 Header Actions

#Test CasePriorityUI ActionExpectedStatus
LIST-50Click ExportP0ModalOpens ExportReportsModal✅ PASS
LIST-51Confirm exportP0API callGenerates report, sends emailBug #37 ❌
LIST-52Click UploadP0ModalOpens PatientUploadModal✅ PASS
LIST-53Upload valid fileP0API callUploads successfullyPending
LIST-54Upload invalid fileP0ValidationShows errorPending
LIST-55Click Add PatientP0ModalOpens AddPatientModal✅ PASS

1.7 Table Density

#Test CasePriorityUI ActionExpectedStatus
LIST-60Compact viewP2ToggleShows more rows✅ PASS
LIST-61Comfortable viewP2ToggleShows less rows, more space✅ PASS

SECTION 2: Patient View Page

Component: PatientDetailPage.tsx URL: /cms/patient/{patientId}/{patientFacilityId}

2.1 Page Load

#Test CasePriorityAPIExpectedStatus
VIEW-01Load patient detailP0GET /clinical/patients/:idShows header with patient infoPending
VIEW-02Loading stateP0API loadingShows loading skeletonPending
VIEW-03Error state - not foundP0404 responseShows error messagePending
VIEW-04Error state - no accessP0403 responseShows "Not authorized"Pending

2.2 Header Display

#Test CasePriorityExpectedStatus
VIEW-10Display patient nameP0Shows full namePending
VIEW-11Display patient photoP0Shows avatar or placeholderPending
VIEW-12Display MRNP0Shows medical record numberPending
VIEW-13Display phoneP0Shows phone with country codePending
VIEW-14Display emailP0Shows email addressPending
VIEW-15Display DOB/AgeP0Shows date and calculated agePending
VIEW-16Display genderP0Shows gender (Male/Female/Other)Pending
VIEW-17Display blood groupP0Shows blood group if setPending

2.3 Tabs Navigation

#Test CasePriorityTabExpectedStatus
VIEW-20Services tab defaultP0ServicesSelected by defaultPending
VIEW-21Switch to PaymentsP0PaymentsShows payment historyPending
VIEW-22Switch to BillsP0BillsShows billing historyPending
VIEW-23Switch to PackagesP0PackagesShows package subscriptionsPending
VIEW-24Switch to ActivityP0ActivityShows audit feedPending
VIEW-25Switch to LHRP0LHRShows longitudinal recordsPending

2.4 Services Tab

#Test CasePriorityExpectedStatus
VIEW-30List patient servicesP0Shows all servicesPending
VIEW-31Select servicesP0Checkbox selectionPending
VIEW-32Generate billP0Creates invoicePending
VIEW-33Empty servicesP0Shows "No services"Pending

2.5 Header Actions

#Test CasePriorityActionExpectedStatus
VIEW-40Click BackP0navigate(-1)Returns to previous pagePending
VIEW-41View Care PlanP1NavigateOpens care plan pagePending
VIEW-42View EpisodesP1NavigateOpens episodes pagePending
VIEW-43Refer PatientP1NavigateOpens referral pagePending
VIEW-44Associate PackageP1ModalOpens package modalPending

2.6 Activity Tab

#Test CasePriorityExpectedStatus
VIEW-50Show audit logP0Shows all changesPending
VIEW-51Filter by dateP1Shows filtered resultsPending

SECTION 3: Patient Edit Page

Component: PatientFormPage.tsx (edit mode) URL: /cms/patients/add-patient?edit={id} Form library: react-hook-form + Zod (createPatientSchemaRefined)

Form Structure (from code audit)

SectionTypeFields (9)
Basic InformationCard, always expandedPhoto upload, first_name*, last_name*, DOB* (date, max=today), gender* (select), blood_group (select), marital_status (select), deceased (checkbox), deceased_date (date, disabled when not deceased)
Contact InformationCard, always expandedphone_country_code (select), phone_number* (tel), email (email)
AddressCollapsible Accordionline1, line2, city, state, postal_code, country
Emergency ContactCollapsible Accordionname, relationship, phone_number, email
CommunicationCollapsible Accordionemail_enabled (checkbox), sms_enabled (checkbox), language (select)

3.1 Page Load (Edit Mode — patient fetch)

#Test CasePriorityExpectedStatus
EDIT-01Navigate to edit pageP0URL contains ?edit={patientId}, form loads with LoadingSpinner brieflyPending
EDIT-02Form pre-filled with all fieldsP0All 5 sections populated from API (usePatient hook → form.reset())Pending
EDIT-03Patient not found (bad ID in URL)P0EmptyState with AlertCircle icon, "Not Found" message, Back to List buttonPending
EDIT-04Loading stateP0LoadingSpinner shown while isLoadingPatient is truePending
EDIT-05API error stateP1Network/server error → EmptyState error view (handled by isPatientError)Pending

3.2 Section 1: Basic Information (always expanded)

#Test CasePriorityFieldExpectedStatus
EDIT-10Pre-fill first_nameP0first_nameShows value from APIPending
EDIT-11Pre-fill last_nameP0last_nameShows value from APIPending
EDIT-12Pre-fill DOBP0birth_dateShows formatted date, max=today on date pickerPending
EDIT-13Pre-fill genderP0genderShows selected value (male/female/other/unknown)Pending
EDIT-14Pre-fill blood_groupP0blood_groupShows selected value (A+ to O-) or emptyPending
EDIT-15Pre-fill marital_statusP0marital_statusShows selected value or emptyPending
EDIT-16Pre-fill deceased checkboxP0deceasedChecked if patient is deceasedPending
EDIT-17Pre-fill deceased_dateP0deceased_dateShows date if deceased=true, field disabled if deceased=falsePending
EDIT-18Photo — show existingP0photo_urlPhoto displayed in avatar circlePending
EDIT-19Photo — no photoP1photo_url nullShows placeholder (ImageIcon + "Upload Photo" button)Pending

3.3 Photo Upload & Remove

#Test CasePriorityActionExpectedStatus
EDIT-20Upload photo — valid fileP0Select JPEG/PNG < 5MBUploads to S3, preview shown, "Change" + "Remove" buttons appearPending
EDIT-21Upload photo — invalid typeP1Select PDF or non-imageToast error: "Please select a valid image"Pending
EDIT-22Upload photo — file too largeP1Select image > 5MBToast error: "Image must be less than 5MB"Pending
EDIT-23Upload photo — loading stateP1During uploadLoadingSpinner shown in avatar circlePending
EDIT-24Change photoP1Click "Change" → select new photoNew photo replaces old, preview updatesPending
EDIT-25Remove photoP0Click "Remove" (X button)Photo cleared, placeholder returns, photo_url set to ""Pending

3.4 Section 2: Contact Information (always expanded)

#Test CasePriorityFieldExpectedStatus
EDIT-30Pre-fill country codeP0phone_country_codeShows value from API (default +91)Pending
EDIT-31Pre-fill phoneP0phone_numberShows value from APIPending
EDIT-32Pre-fill emailP0emailShows value from API or emptyPending

3.5 Section 3: Address (collapsible accordion)

#Test CasePriorityExpectedStatus
EDIT-35Accordion — collapsed by defaultP0Address section starts collapsed, click to expandPending
EDIT-36Pre-fill address fieldsP0All 6 fields (line1, line2, city, state, postal_code, country) show API valuesPending
EDIT-37Address — all fields emptyP1Empty state when patient has no addressPending
EDIT-38Accordion — expand/collapse toggleP1Click header toggles section open/closedPending

3.6 Section 4: Emergency Contact (collapsible accordion)

#Test CasePriorityExpectedStatus
EDIT-40Accordion — collapsed by defaultP0Section starts collapsedPending
EDIT-41Pre-fill emergency contactP0Name, relationship, phone, email show API values (handles JSON string or object)Pending
EDIT-42Emergency contact — all fields emptyP1Empty state when patient has no emergency contactPending

3.7 Section 5: Communication Preferences (collapsible accordion)

#Test CasePriorityExpectedStatus
EDIT-45Accordion — collapsed by defaultP0Section starts collapsedPending
EDIT-46Pre-fill email_enabled checkboxP0Checked/unchecked per API (default: true)Pending
EDIT-47Pre-fill sms_enabled checkboxP0Checked/unchecked per API (default: true)Pending
EDIT-48Pre-fill preferred languageP0Shows English/Spanish/Hindi per API (default: en)Pending

3.8 Update Patient — Successful Updates

#Test CasePriorityActionExpectedStatus
EDIT-50Update first_nameP0Change name → SaveSuccess toast, redirect to /cms/patients-v2Pending
EDIT-51Update last_nameP0Change name → SaveSuccess toast, redirectPending
EDIT-52Update phoneP0Change number → SaveSuccess toast, redirectPending
EDIT-53Update emailP0Change email → SaveSuccess toast, redirectPending
EDIT-54Update DOBP0Change date → SaveSuccess toast, redirectPending
EDIT-55Update genderP0Change gender → SaveSuccess toast, redirectPending
EDIT-56Update blood_groupP1Change group → SaveSuccess toast, redirectPending
EDIT-57Update marital_statusP1Change status → SaveSuccess toast, redirectPending
EDIT-58Mark as deceasedP0Check deceased → set date → SaveSuccess toast, deceased_date savedPending
EDIT-59Update addressP1Fill address section → SaveSuccess toast, address savedPending
EDIT-60Update emergency contactP1Fill EC section → SaveSuccess toast, EC savedPending
EDIT-61Update communication prefsP1Toggle checkboxes, change language → SaveSuccess toast, prefs savedPending
EDIT-62Update multiple fields at onceP0Change name + phone + DOB → SaveAll changes persistedPending

3.9 Deceased Checkbox Behavior

#Test CasePriorityActionExpectedStatus
EDIT-65Check deceased → date field enablesP0Check the Deceased checkboxdeceased_date field becomes enabled (not greyed out)Pending
EDIT-66Uncheck deceased → date field disablesP0Uncheck the Deceased checkboxdeceased_date field becomes disabled (greyed out)Pending
EDIT-67Save deceased without dateP0Check deceased, leave date empty → SaveValidation error: "Deceased date is required when deceased is checked" (Zod refinement)Pending
EDIT-68Deceased date before DOBP0Set deceased_date < birth_date → SaveValidation error: "Deceased date must be after birth date" (Zod refinement)Pending

3.10 Validation — Edit Mode ⚠️ Known Bug #34 area

#Test CasePriorityInputExpectedStatus
EDIT-70Empty first_nameP0Clear field → SaveZod error: "First name is required" (client-side, never reaches API)Pending
EDIT-71Empty last_nameP0Clear field → SaveZod error: "Last name is required"Pending
EDIT-72First name < 2 charsP0"A" → SaveZod error: "First name must be at least 2 characters"Pending
EDIT-73Last name < 2 charsP0"B" → SaveZod error: "Last name must be at least 2 characters"Pending
EDIT-74Empty phoneP0Clear phone → SaveZod error: "Phone number is required"Pending
EDIT-75Invalid phone (letters)P0"abc123" → Save⚠️ Zod schema has no phone format validation — may pass client-side, check if backend rejects (Bug #34)Pending
EDIT-76Phone with whitespace onlyP0" " → Save⚠️ Zod doesn't strip whitespace — may pass (Bug #34c)Pending
EDIT-77Future DOBP0Tomorrow's date⚠️ Zod has no future-date check — may pass client-side, check if backend rejects (Bug #34)Pending
EDIT-78Long name (100+ chars)P0120 char string⚠️ No max-length in Zod — may pass (Bug #34)Pending
EDIT-79Invalid email formatP1"notanemail" → SaveZod error: "Invalid email address"Pending
EDIT-80Empty DOBP0Clear date → SaveZod error: "Date of birth is required"Pending

3.11 Form Actions

#Test CasePriorityActionExpectedStatus
EDIT-85Submit — success flowP0Make changes → SaveButton shows "Updating" spinner, success toast, navigate to /cms/patients-v2Pending
EDIT-86Submit — API errorP1Trigger API failureError toast: "Failed to update patient", stays on form (no navigation)Pending
EDIT-87Cancel — back buttonP0Click Back or browser backNavigates to previous page, no changes savedPending
EDIT-88Save button — disabled during submitP1Click SaveButton disabled while isPending is truePending
EDIT-89Save button — enabled when form dirtyP1Make a changeButton is enabled (react-hook-form dirty state)Pending
EDIT-90Save button — no changesP2Open form, click Save without changesForm submits with existing values (no diff check) — should succeedPending

SECTION 4: Patient Preview Modal

Component: PatientPreviewModal.tsx Trigger: Print button in patient list

4.1 Modal Display

#Test CasePriorityExpectedStatus
PREVIEW-01Open modalP0Shows patient summary✅ PASS
PREVIEW-02Loading stateP0Shows spinner✅ PASS
PREVIEW-03Error stateP0Shows error✅ PASS
PREVIEW-04Close modalP0Modal closes✅ PASS

4.2 Patient Info Display

#Test CasePrioritySectionExpectedStatus
PREVIEW-10Header sectionP0Photo, Name, MRNDisplayedPending
PREVIEW-11Basic InfoP0DOB, Gender, Phone, EmailDisplayedPending
PREVIEW-12AddressP0Full addressDisplayedPending
PREVIEW-13Emergency ContactP0Contact detailsDisplayedPending
PREVIEW-14Status (Deceased)P0Deceased badgeDisplayed if applicablePending

4.3 Print Function

#Test CasePriorityActionExpectedStatus
PREVIEW-20Print patientP0Click PrintOpens print dialog✅ PASS
PREVIEW-21Print stylesP1Print CSSClean print output✅ PASS

Known Bugs

Bug #Test IDDescriptionSeverity
#31LIST-11Partial name works, full name with space returns no results (LIKE query issue)🟡 High
#34EDIT-75, EDIT-78Validation gaps — no max-length in Zod, no phone format, no future DOB check🟠 Medium
#34bEDIT-71Backend accepts empty/whitespace for last_name🟠 Medium
#34cEDIT-76Backend accepts whitespace for phone_number🟠 Medium
#35LIST-20Date range filter UI not wired to API params🟠 Medium
#36LIST-12Phone search returns no results — search only queries name fields🟡 High
#38LIST-42Cross-clinic patients missing patient_facility_id — View link broken🟡 High
#39EDIT-20Photo upload → S3 403 Forbidden on staging (kulcare-stag-profile-images bucket)🟡 High
#40EDIT-18Broken image after save — S3 object returns AllAccessDisabled🟡 High
#41LIST-01Patient list API doesn't include photo_url — no image in list view🟡 High
#42EDIT-30Country code pre-fill broken — API returns "91", form expects "+91"🟠 Medium
#43EDIT-88Save button always enabled — no dirty state check or disabled-during-submit🟢 Low

Test Summary

SectionTest CasesTestedPassedFailedSkipped
1. Patient List Page30272151
2. Patient View Page210000
3. Patient Edit Page51514272
4. Patient Preview Modal86600
Total1108469123

Test Execution Order

  1. Phase 1: Patient List (LIST-01 to LIST-61) - 30 tests ✅ Complete
  2. Phase 2: Patient View (VIEW-01 to VIEW-51) - 21 tests ⏸️ Deferred
  3. Phase 3: Patient Edit (EDIT-01 to EDIT-90) - 51 tests ✅ Complete
  4. Phase 4: Patient Preview (PREVIEW-01 to PREVIEW-21) - 8 tests ✅ Complete

Phase 4 skipped: The standalone /cms/patients/add-patient page has no user flow — patients are always created via AddPatientModal (tested in Session 08).


Status: ✅ Complete (Phases 1, 3, 4 done; Phase 2 deferred) Last Updated: 2026-06-17 Next: Patient App Booking Flow OR Doctor App testing

On this page