UHI Stage 1 Discovery — Manual Test Plan
Scope: Physical consultation only (nic2004:85111). Booking deferred to Stage 2. Apps: CMS, Patient. Backend: Rails dev server + migrations.
Auth System — Phone + Password
Kulcare uses phone number + password for login (not email). The sign-in form accepts either:
phone_country_code: "91"
phone_number: "5555555558"
password: "FacilityAdmin123!"Or email + password:
email: "lisa.admin@cityhospital.com"
password: "FacilityAdmin123!"Both are supported by Identity::UserSignInForm. For testing, phone is recommended as all seeded users have verified phone numbers.
Test Credentials
All seeded users are in backend/db/seeds/identity/04_users.rb and already in your kulcare_dev database.
CMS (Owner/Admin for UHI Settings TC-1 to TC-5)
| Name | Phone | Password | Role | Tenant | |
|---|---|---|---|---|---|
| Lisa Anderson | lisa.admin@cityhospital.com | +91 5555555558 | FacilityAdmin123! | admin | Tenant 1 (City Hospital) |
| Sarah Johnson | sarah.johnson@cityhospital.com | +91 5551234567 | Admin123! | admin | Tenant 1 (City Hospital) |
| James Wilson | dr.james.wilson@smith.com | +91 5555555557 | Facility123! | owner | Tenant 3 (Smith Clinic) |
| Raj Kumar | dr.raj.kumar@example.com | +91 9876543210 | Doctor123! | practitioner | Tenant 1 (City Hospital) |
Recommended for TC-1 to TC-5:
+91 5555555558/FacilityAdmin123!(Lisa Anderson, admin role, City Hospital).
To log in via phone (recommended):
phone_country_code: 91
phone_number: 5555555558
password: FacilityAdmin123!To log in via email:
email: lisa.admin@cityhospital.com
password: FacilityAdmin123!Patient (for UHI Search TC-9 to TC-16)
| Name | Phone | Password | Notes | |
|---|---|---|---|---|
| John Doe | john.doe.patient@gmail.com | +91 9876543211 | Patient123! | Patient + practitioner. Has patient profile. |
To log in via phone (recommended):
phone_country_code: 91
phone_number: 9876543211
password: Patient123!CMS Staff (for TC-8 — limited access)
| Name | Phone | Password | Role | |
|---|---|---|---|---|
| Rani Singh | rani.nurse@cityhospital.com | +91 9876543212 | Nurse123! | staff |
Prerequisites
1. Run Migrations
cd backend
bundle exec rails db:migrate2. Verify Test Data
Confirm the test users exist in your database:
# In Rails console (cd backend && rails console):
Identity::User.find_by(phone_number: '5555555558')&.active # => true
Identity::User.find_by(phone_number: '9876543211')&.active # => true3. Start Services
# Backend (if not already running)
cd backend && bundle exec rails server -p 3000
# Typesense (if not already running)
# Check backend/config/initializers/typesense.rb for host/port
# Ably (if not already running)
# Check backend/config/initializers/ably.rbTest Cases
TC-1: CMS — UHI Settings Tab Exists
Route: /cms/settings/practiceSettings/uhi
Login: CMS owner/admin
- Sign in to CMS as facility owner
- Navigate to Settings → Practice Settings
- Confirm the UHI tab appears alongside Communication, Online Booking, Availability, AI Scribe
- Click the UHI tab
Expected: UHI tab renders without errors. Shows facility-level enable toggle and practitioner opt-in section.
TC-2: CMS — Enable UHI Discovery
Route: /cms/settings/practiceSettings/uhi
Login: CMS owner/admin
- On the UHI tab, find the Enable UHI Discovery toggle
- Toggle it ON
- Click Save
- Refresh the page
- Confirm the toggle is still ON
Expected:
- Success toast appears after save
- After refresh, toggle remains ON
- Stats cards (searches count, views count) appear below the form
TC-3: CMS — Set Default Fee
Route: /cms/settings/practiceSettings/uhi
Login: CMS owner/admin
- Ensure UHI is already enabled (from TC-2)
- In the Default Consultation Fee field, enter
500 - Click Save
- Refresh the page
- Confirm the fee is
500
Expected: Fee persists after page refresh.
TC-4: CMS — Per-Practitioner Opt-In
Route: /cms/settings/practiceSettings/uhi
Login: CMS owner/admin
- Ensure UHI is already enabled (from TC-2)
- Scroll to Practitioner Opt-In section
- Confirm at least one practitioner role is listed with a toggle
- Toggle a role OFF → Save
- Refresh → confirm the toggle is OFF
- Toggle the same role back ON → Save
- Refresh → confirm the toggle is ON
Expected: Per-role uhi_enabled flag persists independently.
TC-5: CMS — Disable UHI Discovery
Route: /cms/settings/practiceSettings/uhi
Login: CMS owner/admin
- Toggle Enable UHI Discovery OFF
- Click Save
- Refresh the page
- Confirm toggle is OFF and stats cards are hidden
Expected: Facility returns to non-UHI state.
TC-6: API — Read UHI Catalog
Prerequisite: CMS admin token via phone auth.
Generate a token via Rails console:
# cd backend && rails console
result = Identity::Sessions::AuthenticationOrganizer.call(
form: Identity::UserSignInForm.new(
phone_country_code: '91',
phone_number: '5555555558',
password: 'FacilityAdmin123!'
),
device_details: {}
)
puts result[:access_token] if result.success?Or via curl (phone auth):
TOKEN=$(curl -s -X POST http://localhost:3000/api/identity/session \
-H "Content-Type: application/json" \
-d '{"user_signin_form":{"phone_country_code":"91","phone_number":"5555555558","password":"FacilityAdmin123!"}}' \
| jq -r '.token')
echo "Token: $TOKEN"
# Then use the token:
curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/uhi/hspa/catalog | jqOr via email:
TOKEN=$(curl -s -X POST http://localhost:3000/api/identity/session \
-H "Content-Type: application/json" \
-d '{"user_signin_form":{"email":"lisa.admin@cityhospital.com","password":"FacilityAdmin123!"}}' \
| jq -r '.token')
curl -s -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/uhi/hspa/catalog | jqExpected Response:
{
"success": true,
"data": {
"facility": {
"id": 123,
"name": "ABC Clinic",
"uhi_enabled": false,
"uhi_default_fee": null,
"uhi_searches_count": 0,
"uhi_views_count": 0
},
"practitioner_roles": [
{
"id": 456,
"specialty": "Cardiology",
"role_type": "doctor",
"uhi_enabled": false,
"uhi_discoverable": false
}
]
}
}TC-7: API — Enable UHI via PUT
# Get token first
TOKEN=$(curl -s -X POST http://localhost:3000/api/identity/session \
-H "Content-Type: application/json" \
-d '{"user_signin_form":{"phone_country_code":"91","phone_number":"5555555558","password":"FacilityAdmin123!"}}' \
| jq -r '.token')
curl -s -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"facility":{"uhi_enabled":true,"uhi_default_fee":500}}' \
http://localhost:3000/api/uhi/hspa/catalog | jqExpected: Returns updated catalog with uhi_enabled: true, uhi_default_fee: 500.
TC-8: CMS — UHI Tab Only Visible to Staff
Route: /cms/settings/practiceSettings/uhi
Login: Non-admin CMS user
- Sign in as a staff member (not owner/admin)
- Navigate to Settings → Practice Settings
- Observe available tabs
Expected: UHI tab may or may not appear depending on role permissions. No errors.
TC-9: Patient — UHI Search Page Loads
Route: /uhi/search (patient app)
Login: Patient user
- Sign in to patient app
- Navigate to UHI Network in the sidebar
- Confirm the page renders with the search form
Expected:
- Page title: "UHI Network Search"
- Form has: City dropdown, Specialty dropdown, Doctor Name input, Search button
- Stage 1 notice visible
TC-10: Patient — Search Form Validation
Route: /uhi/search (patient app)
Login: Patient user
- Click Search UHI Network without selecting a city
Expected: Form submission is blocked. City field shows a validation error (red asterisk or similar).
TC-11: Patient — City Dropdown Options
Route: /uhi/search (patient app)
Login: Patient user
- Open the City dropdown
- Confirm it contains Indian cities (Delhi, Mumbai, Chennai, Bangalore, etc.)
Expected: At least 15 Indian cities present.
TC-12: Patient — Search Request Sent
Route: /uhi/search (patient app)
Login: Patient user
- Select a city (e.g., Chandigarh)
- Click Search UHI Network
- Open browser dev tools → Network tab
- Observe the POST request to
/api/uhi/eua/search
Expected:
- A POST request is sent with
{ intent: { city, fulfillment_type: "Physical" } } - A
transaction_idis returned or pending - Loading state appears
TC-13: Patient — No Booking in Stage 1
Route: /uhi/search (patient app)
Login: Patient user
- Perform a search and wait for results
- On a provider card, look for a Book button
Expected: No Book button. Only "View Profile" and "Contact" actions. Footer text says "Stage 1 — Physical consultation".
TC-14: Patient — Provider Card Displays Data
Route: /uhi/search (patient app)
Login: Patient user
- Perform a search (may be empty if no HSPAs are enrolled)
- If results appear, inspect a provider card
Expected:
- Provider name visible
- Specialty badge shown
- Location displayed (city/state)
- Fee shown or "Fee on request"
- "UHI Network" badge
- "Stage 1 — Physical consultation" label
TC-15: Patient — Empty Results State
Route: /uhi/search (patient app)
Login: Patient user
- Perform a search for a city unlikely to have UHI providers
- Wait for the 30-second polling timeout
Expected:
- Loading spinner appears during search
- After timeout, "No providers found" message with "Try a different search" button
TC-16: Patient — New Search Resets Results
Route: /uhi/search (patient app)
Login: Patient user
- Perform a search, wait for completion
- Click "New search" or the link to try again
Expected: Results area clears and form resets to initial state.
TC-17: Backend — Ably Event Publishing (Manual Mock)
Setup: Requires Ably running locally or a sandbox key.
# In Rails console:
Uhi::RealtimePublisher.publish_on_search(
user_id: 123,
transaction_id: "tx_test_001",
provider: {
id: "prov_001",
descriptor: { name: "Dr. Sharma Clinic" },
items: [{ descriptor: { name: "Cardiology" }, price: { currency: "INR", value: "500" } }]
}
)Expected: An Ably message is published to channel private:user:123 with event on_search and the provider payload.
TC-18: Backend — Typesense uhi_enabled Index
Check: Run in Rails console or via rails runner
schema = Identity::Typesense::PractitionersCollection.schema
field = schema['fields'].find { |f| f['name'] == 'uhi_enabled' }
puts field.inspectExpected: {"name"=>"uhi_enabled", "type"=>"bool", "optional"=>true}
TC-19: Backend — uhi_discoverable Logic
Check: Run in Rails console
f = Identity::Facility.last
p = Identity::PractitionerRole.last
f.update!(uhi_enabled: true)
p.update!(uhi_enabled: true)
puts p.uhi_discoverable? # => true
f.update!(uhi_enabled: false)
puts p.uhi_discoverable? # => false
f.update!(uhi_enabled: true)
p.update!(uhi_enabled: false)
puts p.uhi_discoverable? # => falseExpected: uhi_discoverable? is true only when both facility AND role have uhi_enabled: true.
TC-20: Backend — Increment UHI Counters
Check: Run in Rails console
f = Identity::Facility.last
f.increment_uhi_search_count!
f.increment_uhi_view_count!
f.increment_uhi_view_count!
puts f.uhi_searches_count # => 1
puts f.uhi_views_count # => 2Expected: Counters increment correctly.
Cleanup Checklist
After testing, reset the test facility (run in Rails console):
# Disable UHI on City Hospital Main (Tenant 1)
f = Identity::Facility.find_by(name: 'City Hospital Main')
f.update!(uhi_enabled: false, uhi_default_fee: nil)
# Disable UHI on all practitioner roles at that facility
f.practitioner_roles.update_all(uhi_enabled: false)
# Verify
puts "Facility: #{f.uhi_enabled?}"
puts "Roles: #{f.practitioner_roles.pluck(:uhi_enabled).uniq}"Or via API (replace $TOKEN with your CMS admin token from phone login):
TOKEN=$(curl -s -X POST http://localhost:3000/api/identity/session \
-H "Content-Type: application/json" \
-d '{"user_signin_form":{"phone_country_code":"91","phone_number":"5555555558","password":"FacilityAdmin123!"}}' \
| jq -r '.token')
curl -s -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"facility":{"uhi_enabled":false}}' \
http://localhost:3000/api/uhi/hspa/catalog | jqDefect Reporting Template
If you find a bug, use this format:
Test Case: TC-XX
Environment: [local / staging]
Steps:
1.
2.
3.
Expected:
[what should happen]
Actual:
[what actually happened]
Screenshots: [attach]
Console/Network Errors: [copy relevant error]