use-case· 15 min read· by Pramod Dutta

AI Testing for Telehealth Booking and Intake

AI testing for telehealth booking and intake: test appointment flows and forms by intent, stay honest on PHI and video-visit limits.

If your telehealth product lives or dies on whether a patient can find a slot, book it, and finish an intake form without rage-quitting, then AI testing for telehealth booking is the part of QA you cannot afford to leave brittle. Booking flows change constantly: providers add availability, insurance fields get reordered, a symptom checker gains a new branch, and the "join video visit" button moves. Selector-based end-to-end suites break on every one of those edits, and a broken suite is a suite nobody trusts. This guide walks through testing appointment scheduling and patient intake by intent, and it stays honest about the two things that make healthcare different from a generic checkout: protected health information (PHI) and real video-visit hardware you cannot fully fake.

The approach here uses BrowserBash, a free, open-source natural-language browser automation CLI. You write a plain-English objective, an AI agent drives a real Chrome browser step by step, and you get back a deterministic verdict plus structured results. No page objects, no selector spelunking. That matters most in healthcare front doors, where the UI churns faster than any team can maintain locators.

Why telehealth booking breaks traditional test suites

A telehealth booking flow is deceptively deep. The happy path looks like five steps (pick specialty, pick provider, pick time, confirm insurance, book), but every step hides a fork. Provider availability is data-driven, so the calendar you see today is not the calendar you saw yesterday. Insurance capture might branch on payer, on state, or on whether the visit is cash-pay. Intake forms change with clinical requirements and legal review, sometimes weekly.

Traditional Selenium or Playwright suites encode all of that as selectors and hardcoded flows. When the intake team splits "Reason for visit" into two fields, #reason stops existing and a dozen tests go red for a reason that has nothing to do with a real defect. Teams respond by either freezing the UI (bad for patients) or letting the suite rot (bad for everyone). Neither is a good place to be when a booking regression means a patient cannot reach care.

Intent-based testing changes the failure mode. Instead of "click #slot-0930," you tell the agent "book the earliest available morning appointment with a family medicine provider." The agent reads the live page and finds the morning slot itself. When the calendar markup changes, the objective still holds, because a human reading the screen would still know what to do. You still get determinism where it counts, and we will get to exactly how below.

The three surfaces you actually need to cover

Telehealth front doors split into three testable surfaces:

  1. Scheduling. Search, filter, availability, slot selection, reschedule, and cancel. The most data-volatile surface and the one where intent-based testing pays off fastest.
  2. Intake. Demographics, insurance, consent forms, symptom questionnaires, medication lists, and file uploads (insurance card photos, referral PDFs). Long forms with conditional logic.
  3. The visit handoff. Confirmation, reminders, and the transition into the video room. Parts of this are genuinely hard to automate, and pretending otherwise helps nobody.

Most of your automated coverage should sit on scheduling and intake. The visit handoff needs a different, more honest strategy that we cover later.

Getting started with a first booking test

Install the CLI globally and run a single objective. BrowserBash defaults to free local models through Ollama, so nothing has to leave your machine, though small local models can be flaky on long multi-step flows (more on model choice later).

npm install -g browserbash-cli

browserbash run "Open https://staging.yourclinic.com/book, choose Family Medicine, \
select the first available appointment tomorrow morning, and store the visible \
provider name as 'provider'. Verify a confirmation heading is shown." \
  --agent --headless --timeout 180

The --agent flag emits NDJSON, one JSON event per line, which is what you want in CI and what an AI coding agent wants when it drives BrowserBash as its validation layer. Exit codes are frozen: 0 passed, 1 failed, 2 error or infra problem, 3 timeout. A failing booking test returns 1, a real signal you can gate a deploy on. If you are new to the tool, the tutorials walk through the objective syntax and event schema.

Notice what the objective does not contain: no selectors, no waits, no "if the modal appears" branches. The agent handles the modal because a person would. What it does contain is a store instruction and a Verify, and those are the difference between a demo and a test you can trust.

Making the verdict deterministic with Verify steps

The fear with AI-driven testing is that the model "decides" a test passed when it did not. BrowserBash addresses this with deterministic Verify assertions. In a Markdown test file, a Verify step compiles to a real Playwright check with no model judgment in the loop: URL contains, title is or contains, text visible, a named button or link or heading visible, element counts, or a stored value equals. A pass means the condition literally held. A fail comes with expected-versus-actual evidence in the run_end.assertions block and the Result.md assertion table.

That split is the whole game for healthcare QA. You let the agent do the fuzzy, resilient part (navigate a changing calendar) and you pin the verdict to hard checks (a confirmation number is visible, the URL landed on /confirmed, the correct provider name is on the page). A Verify line outside the deterministic grammar still runs, but agent-judged and flagged judged: true, so you can always tell which assertions were hard checks and which were opinions.

Here is a committable *_test.md file for the booking-and-intake happy path. The Verify lines are the assertions your compliance and QA leads will actually care about.

# Telehealth booking and intake happy path

- Open https://staging.yourclinic.com/book
- Choose the "Family Medicine" specialty
- Select the first available appointment for tomorrow morning
- Store the visible provider name as "provider"
- Continue to the intake form
- Fill demographics with name "Test Patient", DOB "01/02/1990"
- Enter insurance payer "Acme Health" and member id "{{member_id}}"
- Submit the intake form

- Verify URL contains "/confirmed"
- Verify text "Your appointment is booked" is visible
- Verify "Join video visit" button is visible
- Verify stored "provider" equals "{{expected_provider}}"

The {{member_id}} and {{expected_provider}} placeholders are variables. Mark the sensitive ones as secrets and they get masked as ***** in every log line. That masking is the first of several PHI safeguards, and PHI deserves its own section.

Handling PHI honestly, not hopefully

Healthcare testing is not generic e-commerce testing with a nicer logo. The moment a test touches a real patient name, date of birth, member ID, or clinical answer, you are handling PHI, and your test harness is now in scope for the same scrutiny as the app. Being honest about this is how you avoid leaking data through your own tooling.

A few practical rules that BrowserBash supports directly:

None of this makes BrowserBash a compliance product, and it would be dishonest to imply otherwise. What it gives you is a testing layer that runs on your infrastructure by default, masks the sensitive values you tell it about, and never forces PHI through a cloud service. The compliance posture is still yours to design. If you want the model and provider routing details before you decide, the features page lays out which engines and providers do what.

A note on consent forms and legal text

Intake includes consent. Consent text is legally reviewed and changes without warning, and a booking flow that silently drops a required consent checkbox is a real defect with real liability. This is a great place for a deterministic Verify on visible text: "Verify text 'I consent to telehealth services' is visible" catches a consent block that got refactored out of the DOM. Do not leave legally required elements to agent judgment.

Seeding appointment data with testmd v2

The hard part of scheduling tests is state. To test "book the earliest slot," you need an earliest slot to exist, and clicking through an admin UI to create availability before every run is slow and flaky. testmd v2 solves this with deterministic API steps that never touch a model.

Add version: 2 to the frontmatter and steps execute one at a time against a single browser session. Two step types are fully deterministic: API steps for seeding data (GET/POST/PUT/DELETE/PATCH url [with body {...}] plus Expect status N, optionally storing a value from the JSON response), and Verify steps for checking the result through the UI. Consecutive plain-English steps run as grouped agent blocks on the same page.

---
version: 2
auth: clinic-patient
---
# Seed availability then book it

- POST https://staging.yourclinic.com/api/availability with body {"providerId": "fm-101", "date": "tomorrow", "slots": ["09:00", "09:30"]}
- Expect status 201, store $.slots[0].id as "slot_id"

- Open https://staging.yourclinic.com/book
- Choose Family Medicine and select the 9:00 AM slot for tomorrow
- Complete intake with the synthetic patient profile
- Submit

- Verify URL contains "/confirmed"
- Verify text "9:00 AM" is visible

The API step creates the exact slot the UI test depends on, deterministically and without a model call, then the agent books it through the real UI, and a deterministic Verify confirms the booked time. Seed with the API, verify through the interface. One honest caveat: testmd v2 currently drives the builtin engine, which needs an ANTHROPIC_API_KEY or a compatible ANTHROPIC_BASE_URL gateway. It does not yet run directly on Ollama or OpenRouter, so plan your model access accordingly for v2 suites.

Reusing patient logins so you are not logging in every test

Most intake flows sit behind a patient login. Re-authenticating on every test is slow, and worse, it turns your booking suite into an accidental login-load test against your own auth provider. BrowserBash saves a session once and reuses it. Run browserbash auth save clinic-patient --url https://staging.yourclinic.com/login and it opens a browser, you log in once as your synthetic test patient, press Enter, and the session (a Playwright storageState) is saved. From then on, add --auth clinic-patient to any run, testmd, run-all, or monitor command, or put auth: clinic-patient in a test file's frontmatter as shown above. If a saved profile's origins do not cover the start URL, BrowserBash prints a warning instead of silently doing nothing, which saves you from the classic "why is it stuck at the login page" mystery. This one feature removes the largest single source of slowness and flakiness from an intake suite.

Running the whole suite in CI without burning budget

A real telehealth product has dozens of booking and intake variations: multiple specialties, cash-pay versus insured, new versus returning patient, multiple states with different consent text. You want to run them in parallel, split across CI machines, and not get a surprise model bill.

run-all .browserbash/tests \
  --shard 2/4 \
  --budget-usd 2.00 \
  --junit out/junit.xml

run-all is a memory-aware orchestrator: it derives concurrency from real CPU and RAM, orders previously-failed and slowest tests first, and flags flaky tests. --shard 2/4 runs a deterministic slice computed on sorted discovery order, so four parallel CI machines agree on who runs what with zero coordination. --budget-usd 2.00 stops launching new tests once the suite crosses the budget: remaining tests report skipped, the suite exits 2, and the spend lands in RunAll-Result.md and the JUnit <properties>. For a suite that runs on every PR, that hard budget stop is the difference between predictable cost and a bad Monday.

The replay cache makes repeat runs nearly free. A green run records its actions, and the next identical run replays them with zero model calls, stepping the agent back in only when the page actually changed. For a booking flow that is stable day to day, most CI runs cost almost nothing and finish fast while still exercising the real browser. If you are wiring this into GitHub, the official GitHub Action installs the CLI, runs the suite, uploads JUnit and NDJSON artifacts, supports shard matrix jobs and a budget cap, and posts a self-updating PR comment with the verdict table.

Monitoring the live booking funnel

Testing before deploy is half the job. A booking flow that passed in CI can still break in production when a provider-data feed hiccups or a third-party insurance service goes down. Monitor mode runs a real booking objective on an interval and alerts only when the state flips.

browserbash monitor .browserbash/tests/booking_smoke_test.md \
  --auth clinic-patient \
  --every 10m \
  --notify https://hooks.slack.com/services/XXX/YYY/ZZZ

It alerts only on pass-to-fail and fail-to-pass transitions, both directions, never on every green run. You are not going to train your on-call team to ignore a channel that pings every ten minutes with "still fine." You get a Slack message the moment real booking breaks, and another when it recovers. Slack incoming-webhook URLs get Slack formatting automatically, and any other URL gets the raw JSON payload. Because the replay cache handles the steady state, an always-on booking monitor is nearly token-free.

The honest limits: video visits and hardware

Here is where a lot of telehealth QA content gets vague, so let me be direct. BrowserBash drives a real Chrome browser through the booking and intake flow reliably. The actual video visit is a different animal.

A live video visit needs a working camera and microphone, real WebRTC negotiation, network conditions, and often a native or third-party video SDK. You can automate the handoff up to a point: click "Join video visit," land in the waiting room, and confirm the device-check screen and correct appointment details render. Those checks catch the most common "patient cannot get into the visit" defects, and a deterministic Verify on "Join video visit button is visible" plus "URL contains /waiting-room" covers the handoff that breaks most often.

What browser automation does not do well is validate the video and audio stream itself: picture quality, echo, dropped frames, screen sharing, or the clinical experience of the call. That needs real devices, synthetic media injection, and often specialized WebRTC testing tools. Pretending an English objective can verify audio quality would be a lie, and this brand does not do that. Scope your automated coverage to booking, intake, and the join handoff, and cover live media separately.

A sensible coverage split

Surface Automate with BrowserBash Cover another way
Provider search and filtering Yes, intent-based objectives -
Slot selection, reschedule, cancel Yes, with API seeding via testmd v2 -
Intake forms and conditional logic Yes, with deterministic Verify checks -
Consent and legal text presence Yes, hard Verify on visible text Legal review of content itself
Insurance-card and referral uploads Yes, file upload steps Payer-side verification results
Join-visit handoff and waiting room Yes, up to the device-check screen -
Live video and audio quality No Real devices, WebRTC-specific tooling

The table draws a defensible line so your test plan promises only what it can keep. Everything in the left column is genuinely automatable by intent today, and that is the large majority of what breaks in a booking funnel.

When intent-based AI testing is the right call

Intent-based AI testing for telehealth booking is the right call when your booking and intake UI changes often, when maintaining selector-based tests has become a tax nobody wants to pay, and when you want a plain-English suite that a clinical product manager can read and a QA engineer can trust. It is especially strong for the long, conditional intake forms that traditional frameworks turn into unmaintainable spaghetti.

It is not the right call for everything. If you need pixel-level rendering of a symptom-checker chart, use visual regression tooling. To load-test your scheduling API, use a load tool. To test the live video stream, you need real-device and WebRTC infrastructure. And if your flows are truly static and your existing Playwright suite is stable and green, there may be no reason to switch. Honest positioning means saying that out loud.

Where BrowserBash fits is the resilient middle: real-browser, intent-driven coverage of scheduling and intake, with deterministic verdicts you can gate deploys on, PHI kept local by default, and honest scoping around the parts a browser cannot see. For teams shipping telehealth front doors that change every sprint, that is exactly where the pain is. You can read more patterns on the BrowserBash blog, and the CLI is on npm.

FAQ

Is AI testing safe for PHI in telehealth booking flows?

It can be, if you design it right. Use only synthetic patient data in tests, mark sensitive values as secrets so they render as ***** in every log line, and keep runs on local models so page content never leaves your machine. BrowserBash defaults to local Ollama models and masks secret variables, but the overall compliance posture is still yours to build. The tool runs on your infrastructure by default and does not force PHI through a cloud API.

Can you test the actual video visit with browser automation?

Only partially, and it is important to be honest about that. Browser automation reliably covers the handoff into the visit: clicking "Join video visit," reaching the waiting room, and confirming the device-check screen and appointment details render. It cannot validate the live video or audio stream, picture quality, echo, or dropped frames, because that needs real devices and WebRTC-specific tooling. Scope your automated coverage to booking, intake, and the join handoff, and test live media separately.

How is this different from Selenium or Playwright for booking tests?

Selenium and Playwright encode the flow as selectors and hardcoded steps, so every UI change to the calendar or intake form breaks the test even when nothing is actually wrong. Intent-based testing describes the goal in plain English ("book the earliest morning slot") and an AI agent reads the live page to accomplish it, so cosmetic markup changes do not break the suite. You still get deterministic verdicts through Verify assertions that compile to real Playwright checks. BrowserBash can even import existing Playwright specs to plain-English tests to help you migrate.

How do you make an AI test give a reliable pass or fail?

Pin the verdict to deterministic Verify steps rather than model judgment. In a BrowserBash test file, a Verify step compiles to a real Playwright assertion (URL contains, text visible, a named button visible, element counts, stored value equals) with no LLM in the decision. The agent handles the resilient navigation, and the Verify lines produce a hard pass or fail with expected-versus-actual evidence. Verify lines outside the deterministic grammar still run but are flagged as agent-judged, so you always know which checks were hard.

Booking and intake are the front door to care, and they change too fast for brittle selector suites to keep up. Testing them by intent, with deterministic verdicts and PHI kept local, gets you resilient coverage where it matters and honest scoping where a browser cannot go. Install with npm install -g browserbash-cli and run your first booking objective in minutes. An account is optional, but for the free cloud dashboard and retention you can sign up here.

Try it on your own appnpm install -g browserbash-cli
Start learning