verify_feature

Every option and step the verify_feature tool accepts, what each expect asserts, and what the tool returns. Formerly record_demo, and the old name still works.

This page lists what your agent can send when it writes the steps of a test itself. Everything on it works on every version of tada-mcp unless a line says “from 0.1.62”. From 0.1.62 the same tool is also listed as check_feature, and verify_feature keeps working with every option below.

verify_feature is the tool your coding agent calls to check a feature. A check is one go at one feature, and the tests of that feature are what the agent sends: steps for one test, journeys for several. Tada walks them in a real browser on its own machines, checks each expect, and returns a verdict. A pass has one film, with a chapter per test. It was called record_demo until 2026-08-24, and that name still works.

Options

OptionTypeDefaultWhat it does
titlestring, 1 to 200 charactersrequiredWhat the check is called, shown on the watch page. It names the feature when feature is left out.
stepsarray, at least onerequired unless journeys or a feature alone is sentThe ordered steps of one test.
journeysup to 24 of { name, steps }noneThe tests of a planned feature, named as the plan names them, each with its steps. Sent with feature set to the id plan_feature returned. The parameter keeps the name journeys from earlier versions; each entry is one test.
featurestringthe titleThe feature the check is for, named as the ticket names it. With no steps and no journeys, it checks that feature’s saved tests again.
repoowner/namethe git remote of the folder the server started inThe app the check is for.
devicedesktop, tablet or mobiledesktopThe screen size: 1920×1080, 820×1180 or 390×844.
initScriptstringnoneJavaScript that runs in every page before the app’s own scripts, to set a locale or a feature flag.
hideSelectorsup to 20 CSS selectorsnoneHides your app’s own floating widgets, such as a chat bubble or cookie banner, for the whole film. A step that touches a hidden element fails the check and names the selector.
captureScale1 or 21Use 2 only when the film will be re-cut as marketing video. It costs four times the pixels and cannot be changed after the check.

From 0.1.62, three more options ask with a goal in place of steps. See MCP server.

OptionTypeDefaultWhat it does
goalstring, up to 240 charactersnoneWhat should work, in a sentence or two. Tada writes the test. Sent with repo, and without steps or title.
rolestringnoneWith goal: the role to sign in as, in your app’s own word.
addressURLthe app’s usual addressWith goal: where to check. An address on localhost is reached through a temporary tunnel.

Use mobile only for features built for phones. A desktop app filmed 390 pixels wide shows your breakpoints, not your feature.

Options that refuse the check

storageState, width, height and taskId are still in the schema so older agent setups do not break. Passing one refuses the check before anything starts or counts, and the answer says what to use instead:

OptionUse instead
storageStateSign in inside the steps. See Keep a sign-in off camera.
width, heightdevice.
taskIdLeave it out. It is not supported.

dryRun is accepted and ignored. The check happens on Tada and is published like any other, and the answer says so.

Steps

Every step is { "action": ..., ...fields }. Steps may also carry a role, to put several people from the app’s cast in one test.

Move and act

ActionFieldsNotes
gotourlOpens a page. Accepts ${magicLink} from an earlier awaitEmail.
clicktext or selectorPrefer text. Visible labels survive a refactor that breaks CSS selectors.
filltext (the label) or selector, valuevalue accepts ${inbox}.
selecttext or selector, valuePicks an option from a dropdown, including custom ones.
uploadtext or selector, valueAttaches a sample file. See Attach a file.
presskeyFor example "Enter".
hovertext or selector
scrollvalue or selector, msvalue is "top", "bottom" or a pixel offset. ms sets how long the scroll takes.
dragtext or selector, then toText or toSelector, nativeSee Drag and drop.
waitmsHolds still.
waitForTexttextWaits for words to appear. It is not a check.

Check

ActionFieldsPasses when
expecttextThose words become visible.
expecturlIncludesThe address contains that text, for example "/library".
expectselectorAn element matching the selector becomes visible.
expectsignedIn: trueThe page is past the sign-in: not a sign-in address, and no password box showing.

An expect waits up to 8 seconds. Give a slow step more with ms:

{ "action": "expect", "text": "Export complete", "ms": 30000 }

Only expect decides the verdict. wait and waitForText set the pace and prove nothing. Put an expect after every step that matters.

Narrate

ActionFieldsNotes
captiontext, msA line of narration for the next action.

A caption holds the frame for as long as it takes to say, up to 12 seconds, so keep each one to a short sentence. Whether captions show and whether they are spoken come from Settings > Narration and captions, and the voice from the actor in the app’s Settings > Cast, not from the agent.

Keep a sign-in off camera

pause and resume take no fields. Between them the browser performs every step, and nothing is filmed.

[
  { "action": "pause" },
  { "action": "goto", "url": "https://staging.example.com/login" },
  { "action": "fill", "text": "Email", "value": "{{secret.TADA_TEST_EMAIL}}" },
  { "action": "fill", "text": "Password", "value": "{{secret.TADA_TEST_PASSWORD}}" },
  { "action": "click", "text": "Sign in" },
  { "action": "expect", "signedIn": true },
  { "action": "resume" }
]

Email steps

ActionFieldsNotes
createInboxnoneMakes a throwaway address. Use it as ${inbox} in a later fill.
awaitEmailtext, ms, linkWaits for an email. text matches part of the subject. link picks which link becomes ${magicLink}: words on its button, such as Review and sign, or part of its address. Waits up to 20 seconds by default.

After awaitEmail, the link in the email is ${magicLink}:

[
  { "action": "createInbox" },
  { "action": "fill", "text": "Email", "value": "${inbox}" },
  { "action": "click", "text": "Send me a link" },
  { "action": "awaitEmail", "text": "Sign in to" },
  { "action": "goto", "url": "${magicLink}" },
  { "action": "expect", "urlIncludes": "/dashboard" }
]

Without link, Tada takes the sign-in link, then an invitation’s link, then a signing link, and skips logos, unsubscribe links and social links. A link that matches nothing in the email fails the check.

An email that never arrives fails the check.

Attach a file

{ "action": "upload", "text": "Attach invoice", "value": "invoice.pdf" }

text or selector names the file field, or the button or drop area that takes the file. value names the file. Tada finds the file field behind a label or a drop area and sets it. When there is no field, it presses the control and answers the file picker that opens.

The file is always one of Tada’s own sample files, named exactly:

valueWhat it is
invoice.pdfA one-page sample invoice.
picture.pngA small picture.
photo.jpgThe same picture as a photo.
contacts.csvA table with four made-up rows.
notes.txtA few lines of plain text.
letter.docxA short Word letter.

Everything in them is made up. A path or an address is refused, because the check happens on Tada, which cannot see the files on your machine. Any other name fails the step and lists the names that work.

A press that opens no file picker, on a page with no file field, blocks the step and says so. Always follow an upload with an expect for what your app shows once it has the file, such as the file’s name.

Drag and drop

{ "action": "drag", "text": "My card", "toText": "In Progress" }

Tada drags with the pointer first, which is what dnd-kit and react-beautiful-dnd listen for. When the source element is draggable="true", it uses the browser’s own drag events instead. Set native: true only if that detection misses. Always follow a drag with an expect that the item landed.

What comes back

Up to 0.1.61 the answer is as below. From 0.1.62 it is the check’s report in the order the app shows it: the result, one line that sums it up, what failed, what was not covered, the link to the report, and the film’s link last. See MCP server.

Passed. The watch link to the film, and a line saying it passed. Notes follow when something needs your attention, such as a tunnel Tada opened. See Check what your coding agent builds.

Failed. No link and no film. Every step that failed the check, by step number and action, with what the screen showed, and the check’s page, where the failing frame is. The agent receives it as a tool error. A planned feature answers Passed: <feature>. Every test passed. or Failed: <feature>. with the same page, and does not list the tests one by one.

Not started. Not signed in, a refused option, or a check the server would not start. Each says why, and nothing is checked.

If Tada is still working after 16 minutes, the tool stops waiting and returns the check’s page. The check finishes on its own.