Kulcare Docs
UhiTesting

UHI Patient Stages 2, 3 & 4 — Manual Test Plan

Use this plan to verify the end-to-end UHI booking implementation before pushing to CI. Each stage has: prerequisites, test steps, expected results, and pass/fail criteria.


🧪 Stage 0 — ABHA in Sign-In Response

Goal: Verify abha_address and abha_number are returned in the sign-in payload.

Prerequisites

  • Backend running at http://localhost:3000
  • A patient account that has an ABHA address linked (identity_patients.abha_address not null)
  • A patient account with NO ABHA address linked (null)
  • Chrome DevTools or Postman

Test Steps

T0-1: Patient with ABHA — regular phone/password sign-in

  1. Open browser DevTools → Network tab → filter by POST /identity/sessions
  2. Sign in as a regular patient (phone + password) who has abha_address in identity_patients table
  3. In the Network response, find the JSON body under data.user
  4. Verify: abha_address field is present with a non-null value (e.g., "rahul.k001@sbx")
  5. Verify: abha_number field is present with a non-null value (14-digit string)
  6. Verify: abha_address is also present in localStorage['auth-storage'] under state.user.abha_address

T0-2: Patient with ABHA — PHR sign-in (ABHA OTP flow)

  1. Sign in via the PHR/ABHA OTP flow (mobile OTP → verify_user → KulcareSession)
  2. In the stored localStorage['auth-storage'], find the user object
  3. Verify: abha_address and abha_number are present from session.patient
  4. Verify: Both sign-in methods (regular + PHR) result in the same user.abha_address shape

T0-2: Patient without ABHA — both sign-in methods

  1. Sign in as a patient whose identity_patients.abha_address is NULL via phone/password
  2. Find the same JSON response under data.user
  3. Verify: abha_address is null
  4. Verify: abha_number is null
  5. Repeat for PHR sign-in (ABHA OTP flow)
  6. Verify: abha_address and abha_number are absent from localStorage user object
  7. Verify: The UHI sidebar tab is hidden for this patient (Stage 1 verification)

T0-3: Practitioner sign-in — ABHA fields absent

  1. Sign in as a practitioner (doctor) user
  2. Find the JSON response under data.user
  3. Verify: abha_address is absent from the response (not returned at all for practitioners)
  4. Verify: abha_number is absent from the response
  5. Verify: Practitioner does not see the UHI Network tab (even if they somehow reach it)

Pass Criteria

  • ABHA fields present in patient sign-in, absent for practitioners
  • Fields never exposed in non-patient user types

🧪 Stage 1 — ABHA-Gated UHI Tab

Goal: The "UHI Network" sidebar tab is hidden when no ABHA address is linked, visible when linked.

Prerequisites

  • Patient app running at http://localhost:5173 (or port from pnpm dev)
  • Browser with DevTools open

Test Steps

T1-1: No ABHA — tab hidden

  1. Log in as a patient with no abha_address
  2. Observe the left sidebar navigation
  3. Verify: "UHI Network" tab is not visible in the sidebar
  4. Verify: No broken layout or empty space where the tab should be

T1-2: ABHA linked — tab visible

  1. Log in as a patient with an abha_address linked
  2. Observe the left sidebar navigation
  3. Verify: "UHI Network" tab appears with a globe icon
  4. Verify: Tab is clickable and navigates to /uhi/search

T1-3: URL direct access without ABHA

  1. Log in without ABHA
  2. Navigate directly to http://localhost:5173/uhi/search
  3. Verify: Page either redirects or shows an appropriate "link your ABHA first" message
  4. (Check that the route is protected — unauthenticated direct access to /uhi/search should redirect to login)

Pass Criteria

  • No ABHA patient: tab hidden, direct URL blocked
  • ABHA patient: tab visible and navigable

🧪 Stage 2 — P2P Slot Discovery

Goal: "View Slots" navigates to slot selection, P2P search is sent to the correct HSPA, slots render in a date-grouped grid.

Prerequisites

  • Stage 1 complete (UHI tab accessible)
  • HSPA sandbox environment reachable (or mock HSPA)
  • Network tab open in DevTools

Test Steps

T2-1: View Slots navigation

  1. From the UHI Search page, enter a search (city: "Delhi", specialty: any)
  2. Wait for search results to appear (Ably on_search events)
  3. On any provider card, click "View Slots"
  4. Verify: URL changes to /uhi/provider/<providerId>/slots
  5. Verify: Provider name appears in the slot selection page header

T2-2: P2P search API call

  1. Open DevTools → Network tab → filter by /uhi/eua/search/p2p
  2. Click "View Slots" on a provider card
  3. Verify: A POST /uhi/eua/search/p2p request is fired
  4. Verify: Request body includes:
    • provider_uri matching the HSPA URL from the provider card
    • transaction_id (UUID)
    • service_type: "physical"
  5. Verify: The request is sent directly to the HSPA URL, not through a gateway

T2-3: Slot grid — date grouping

  1. Wait for slot results to appear (via Ably or polling fallback)
  2. Verify: Slots are grouped by date (day selector at the top with prev/next arrows)
  3. Verify: Each day shows a list of slot cards
  4. Verify: Each slot card shows: time range, doctor name, mode badge ("Physical"), fee

T2-4: Slot selection → booking page

  1. Click any available slot card
  2. Verify: URL changes to /uhi/book/<providerId>/<slotId>
  3. Verify: Booking page loads with provider name and selected slot time in a summary card
  4. Verify: "Your Booking" summary card shows correct date, time, and fee

T2-5: No slots available

  1. Search with a date range that has no slots
  2. Verify: "No slots available on this date" message appears
  3. Verify: Day selector still works for adjacent dates

Pass Criteria

  • "View Slots" navigates correctly with provider context
  • P2P search sent to correct HSPA provider_uri
  • Slots grouped by date with day selector
  • Slot selection navigates to booking form

🧪 Stage 3 — Booking Init, T&C Acceptance, Confirm, PIN Display

Goal: Patient details → initiate → wait for on_init → accept 5 terms → confirm → PIN displayed.

Prerequisites

  • A slot selected from Stage 2 (booking page loaded)
  • HSPA sandbox reachable
  • Ably real-time connection active
  • DevTools open for console + network monitoring

Test Steps

T3-1: Patient details form — pre-fill

  1. On the booking page (/uhi/book/...), observe the form
  2. Verify: Name field is pre-filled from the logged-in user's name
  3. Verify: Phone field is pre-filled
  4. Verify: Email field is pre-filled (if available)
  5. Fill remaining required fields (city, state, area code)
  6. Verify: All NHA-required billing fields are present:
    • Name, Phone, Email
    • Locality, City, State, Country (pre-filled "INDIA"), Area Code

T3-2: Initiate booking — loading state

  1. Click "Continue to Terms" on the form
  2. Verify: Form disappears; a loading spinner appears
  3. Verify: Text reads "Connecting to healthcare provider..." or similar
  4. Verify: A POST /uhi/eua/bookings/init request appears in Network tab
  5. Verify: Request body includes:
    • customer.id = patient's abha_address (from auth store — populated by either regular sign-in or PHR sign-in)
    • fulfillment.id = selected slot ID
    • fulfillment.type = "Physical" (not "Teleconsultation")
    • billing with all address fields
  6. Verify: transaction_id is a UUID in the request
  7. Test both sign-in methods:
    • Sign in via regular phone/password → initiate booking → verify customer.id is user.abha_address
    • Sign in via PHR ABHA OTP → initiate booking → verify customer.id is session.patient.abha_address
    • Both paths must produce the same customer.id shape in the init request

T3-3: on_init arrival — terms displayed

  1. Wait for the Ably on_init event to arrive (check browser console for on_init log if available, or wait up to 60s)
  2. Verify: After on_init, the view switches to the T&C step
  3. Verify: All 5 terms are displayed in order: Commercial, Settlement, Cancellation, Refund, Payment
  4. Verify: Each term has a checkbox
  5. Verify: "Confirm Booking" button is disabled until all 5 terms are checked
  6. Verify: Cancellation term shows a warning about reason-required (if reasonRequired: true)

T3-4: Session expiry warning

  1. On the T&C step, observe the page
  2. Verify: Text mentions "15 minutes" session expiry
  3. Test: (If you can wait 15+ minutes or manipulate the clock) — after 15 minutes of no on_init, an error appears

T3-5: All terms checked → confirm enabled

  1. Check all 5 term checkboxes
  2. Verify: "Confirm Booking" button becomes enabled
  3. Click "Confirm Booking"
  4. Verify: POST /uhi/eua/bookings/confirm fires in Network tab
  5. Verify: Confirm request body includes every term with termsState: "AGREED"
  6. Verify: Cancellation term includes reason: "Patient agreed to cancellation policy"
  7. Verify: Each term carries the timePeriod from on_init

T3-6: on_confirm arrival — PIN displayed

  1. Wait for the Ably on_confirm event
  2. Verify: Page navigates to /uhi/book/confirmation/<transactionId> (or similar confirmation route)
  3. Verify: A "Booking Confirmed!" success header appears
  4. Verify: A large, monospace PIN is displayed (e.g., 7342)
  5. Verify: PIN validity window (valid from / valid to) is shown
  6. Verify: Booking details (provider name, date, time) are shown

T3-7: PIN security — no persistence

  1. Open DevTools → Application tab → Local Storage for localhost:5173
  2. Search for the PIN value in localStorage
  3. Verify: PIN is not stored in localStorage
  4. Verify: PIN is not in URL query parameters or hash
  5. Verify: PIN is not in the browser console logs
  6. Refresh the confirmation page
  7. Verify: PIN is cleared from memory (page still loads but PIN may not re-display since it came from in-memory state — acceptable fallback is to show "PIN not yet available" or fetch from API)
  8. Open DevTools → Session Storage — PIN is not stored there either

T3-8: Error — HSPA init rejection

  1. (With sandbox/QA HSPA) Send an init request that the HSPA rejects
  2. Verify: Error message appears: "Booking initiation failed" or similar
  3. Verify: "Try Again" button is present and returns to the details form

T3-9: Error — HSPA confirm rejection

  1. Send a confirm that the HSPA rejects (e.g., terms mismatch)
  2. Verify: Error message appears: "Booking confirmation failed"
  3. Verify: User is returned to the terms screen or booking page with error visible

Pass Criteria

  • Billing form pre-fills from auth context
  • Init fires with correct customer.id (abha_address) and billing
  • on_init shows 5 terms in correct order with all checkboxes
  • Confirm button only enables when all 5 terms checked
  • Confirm fires with all terms AGREED + cancellation reason
  • on_confirm shows PIN in large monospace font
  • PIN never persisted to localStorage/sessionStorage/URL/console

🧪 Stage 4 — Appointment Status Tracking & No-Show Reporting

Goal: UHI appointments list shows all bookings with status; patient can report doctor no-show.

Prerequisites

  • At least one confirmed UHI booking exists (from Stage 3)
  • UHI appointments page accessible

Test Steps

T4-1: UHI appointments page — empty state

  1. Navigate directly to /uhi/appointments (or click "View My Appointments" from confirmation page)
  2. If no bookings exist: Verify: "No UHI appointments yet." message appears
  3. Verify: "Find a Provider" button navigates to /uhi/search

T4-2: Appointments list — with bookings

  1. (With confirmed booking(s) from Stage 3)
  2. Open /uhi/appointments
  3. Verify: Each UHI booking appears as a card with:
    • Provider name
    • Appointment date and time
    • PIN (shown if available — e.g., ••42)
    • Status badge: "Initiated", "Confirmed", "Completed", "Cancelled", etc.
    • Mode: "Physical"
    • Order/Booking reference number

T4-3: Status tracker — confirmed booking

  1. Click on a "Confirmed" booking card
  2. Verify: A status panel appears on the right (or below on mobile)
  3. Verify: Status tracker shows a vertical timeline: Initiated → Confirmed → Fulfilled
  4. Verify: The "Confirmed" step is highlighted (current state)
  5. Verify: Completed steps have checkmarks
  6. Verify: PIN status badge shows "GENERATED" or "VERIFIED"

T4-4: Status tracker — completed booking

  1. Find a completed booking (if available in sandbox)
  2. Verify: All timeline steps show checkmarks
  3. Verify: PIN status shows "VERIFIED"

T4-5: Doctor no-show — button visibility

  1. Click on a "Confirmed" booking card
  2. Verify: "Report Doctor No-Show" button appears in the detail panel
  3. Verify: Button is styled as a warning (amber/orange)

T4-6: Doctor no-show — confirmation dialog

  1. Click "Report Doctor No-Show"
  2. Verify: A confirmation dialog appears with clear warning text
  3. Verify: "Confirm" and "Cancel" buttons present
  4. Click "Cancel" — Verify: Dialog closes, no API call fired

T4-7: Doctor no-show — report submission

  1. Click "Report Doctor No-Show"
  2. Click "Confirm" (or equivalent confirm action)
  3. Verify: POST /uhi/eua/bookings/<orderId>/update fires in Network tab
  4. Verify: Request includes state: "DOCTOR_NO_SHOW" or equivalent
  5. Verify: Booking card updates to show "No-Show" status
  6. Verify: "Report Doctor No-Show" button disappears (already reported)

T4-8: Non-confirmed booking — no no-show button

  1. Click on an "Initiated" or "Cancelled" booking
  2. Verify: "Report Doctor No-Show" button does not appear
  3. (Only CONFIRMED state should allow no-show reporting)

Pass Criteria

  • Appointments list shows all UHI bookings with PIN (masked), status, date
  • Status tracker shows correct timeline for each state
  • No-show button only visible for CONFIRMED bookings
  • No-show reporting fires correct API call with proper state

🧪 Stage 5 — Real-Time Ably Integration

Goal: All Ably events fire correctly; fallback to polling when Ably is unavailable.

Test Steps

T5-1: Ably connection — on_init

  1. Open DevTools → Console tab (or a dedicated Ably logger if added)
  2. Initiate a booking (submit patient details form)
  3. Verify: Ably channel private:user:<userId> is subscribed
  4. Verify: on_init event arrives on that channel within 60 seconds

T5-2: Ably connection — on_confirm

  1. Accept all 5 terms and confirm
  2. Verify: on_confirm event arrives on the same channel

T5-3: Ably unavailable — polling fallback

  1. Disconnect the Ably connection (e.g., block rest.ably.io in Network tab filters, or disconnect internet briefly)
  2. Initiate a booking
  3. Verify: System does not hang — polling fallback activates or a clear error appears
  4. Verify: "Failed to connect to real-time updates" message (or similar) if Ably is unavailable

T5-4: Ably reconnection

  1. Re-enable Ably connection
  2. Verify: New Ably subscription reconnects automatically

Pass Criteria

  • on_init and on_confirm arrive via Ably
  • System handles Ably unavailability gracefully

🧪 Edge Cases & Error Handling

E1: Network timeout on init

  1. Throttle network to "Slow 3G" or use DevTools to add a 30s delay to /uhi/eua/bookings/init
  2. Initiate a booking
  3. Verify: "Failed to initiate booking" error appears after timeout
  4. Verify: User can retry from the booking page

E2: HSPA offline during init

  1. (With sandbox HSPA) Stop the HSPA service
  2. Initiate a booking
  3. Verify: "Booking initiation failed" error appears (not a crash)
  4. Verify: "Try Again" button returns to the form

E3: Terms mismatch on confirm

  1. Modify a term's termsState to something other than AGREED before sending confirm
  2. Verify: HSPA rejects the confirm; error displayed; user can retry

E4: Session expiry — on_init never arrives

  1. Initiate a booking, then wait 15+ minutes without receiving on_init
  2. Verify: "Your booking session expired. Please try again." error
  3. Verify: User is returned to slot selection

E5: Local storage cleared mid-flow

  1. Fill patient details, initiate booking
  2. Before on_init arrives, clear localStorage (DevTools → Application → Clear)
  3. Verify: App still loads (graceful handling of auth token loss)
  4. Verify: On reconnect, auth state is restored from the token in localStorage

📋 Test Data Requirements

EntityRequired forHow to create
Patient with ABHA (regular sign-in)T0-1, T1-2, T2–T5Seed identity_patients with abha_address: 'test.k001@sbx', create a phone/password account. Sign in with phone + password
Patient with ABHA (PHR sign-in)T0-2, T1-2, T2–T5Same patient record; sign in via ABHA OTP flow (mobile OTP → verify_user → KulcareSession)
Patient without ABHAT0-2, T1-1, T1-3Seed identity_patients with abha_address: NULL
Practitioner userT0-3Seed a practitioner without patient record
HSPA provider (sandbox)T2–T5Use NHA sandbox HSPA URL from config
Confirmed bookingT4-2 onwardsComplete Stage 3 flow end-to-end

✅ Sign-Off Checklist

Before pushing to CI, verify all items:

  • Backend sign-in returns ABHA fields for patients only (regular phone/password login)
  • PHR sign-in (ABHA OTP flow) also surfaces abha_address in the auth store and localStorage
  • Both sign-in methods (signIn phone/password + phrSignIn ABHA OTP) produce the same user.abha_address shape for UHI customer.id
  • Sidebar hides UHI tab when no ABHA; shows when linked
  • Slot discovery navigates to P2P search, slots render in date grid
  • Booking form pre-fills from auth context, sends correct customer.id
  • 5 T&C terms displayed in order with checkboxes; confirm disabled until all checked
  • Cancel reason added to cancellation term in confirm request
  • PIN displayed in monospace, never in localStorage
  • 15-min expiry warning shown on terms page
  • Appointments list shows all UHI bookings with status badges
  • Status tracker shows correct timeline for each state
  • Doctor no-show button only for CONFIRMED bookings
  • TypeScript compiles with zero errors
  • Ably events on_init, on_confirm, on_status, on_update all wired

On this page

🧪 Stage 0 — ABHA in Sign-In ResponsePrerequisitesTest StepsT0-1: Patient with ABHA — regular phone/password sign-inT0-2: Patient with ABHA — PHR sign-in (ABHA OTP flow)T0-2: Patient without ABHA — both sign-in methodsT0-3: Practitioner sign-in — ABHA fields absentPass Criteria🧪 Stage 1 — ABHA-Gated UHI TabPrerequisitesTest StepsT1-1: No ABHA — tab hiddenT1-2: ABHA linked — tab visibleT1-3: URL direct access without ABHAPass Criteria🧪 Stage 2 — P2P Slot DiscoveryPrerequisitesTest StepsT2-1: View Slots navigationT2-2: P2P search API callT2-3: Slot grid — date groupingT2-4: Slot selection → booking pageT2-5: No slots availablePass Criteria🧪 Stage 3 — Booking Init, T&C Acceptance, Confirm, PIN DisplayPrerequisitesTest StepsT3-1: Patient details form — pre-fillT3-2: Initiate booking — loading stateT3-3: on_init arrival — terms displayedT3-4: Session expiry warningT3-5: All terms checked → confirm enabledT3-6: on_confirm arrival — PIN displayedT3-7: PIN security — no persistenceT3-8: Error — HSPA init rejectionT3-9: Error — HSPA confirm rejectionPass Criteria🧪 Stage 4 — Appointment Status Tracking & No-Show ReportingPrerequisitesTest StepsT4-1: UHI appointments page — empty stateT4-2: Appointments list — with bookingsT4-3: Status tracker — confirmed bookingT4-4: Status tracker — completed bookingT4-5: Doctor no-show — button visibilityT4-6: Doctor no-show — confirmation dialogT4-7: Doctor no-show — report submissionT4-8: Non-confirmed booking — no no-show buttonPass Criteria🧪 Stage 5 — Real-Time Ably IntegrationTest StepsT5-1: Ably connection — on_initT5-2: Ably connection — on_confirmT5-3: Ably unavailable — polling fallbackT5-4: Ably reconnectionPass Criteria🧪 Edge Cases & Error HandlingE1: Network timeout on initE2: HSPA offline during initE3: Terms mismatch on confirmE4: Session expiry — on_init never arrivesE5: Local storage cleared mid-flow📋 Test Data Requirements✅ Sign-Off Checklist