|
| 1 | +# @intent-framework/testing |
| 2 | + |
| 3 | +Semantic test harness for Intent screens. |
| 4 | + |
| 5 | +## Install |
| 6 | + |
| 7 | +```sh |
| 8 | +pnpm add -D @intent-framework/testing@0.1.0-alpha.1 |
| 9 | +``` |
| 10 | + |
| 11 | +```sh |
| 12 | +npm install --save-dev @intent-framework/testing@0.1.0-alpha.1 |
| 13 | +``` |
| 14 | + |
| 15 | +## What it provides |
| 16 | + |
| 17 | +- `testScreen()` — create a runtime and run semantic assertions |
| 18 | +- Answer asks by setting state directly |
| 19 | +- Assert action enabled/blocked state and blocked reasons |
| 20 | +- Execute actions through the runtime |
| 21 | +- Inspect feedback after action execution |
| 22 | +- Test resource load, reload, invalidation, and staleness |
| 23 | + |
| 24 | +## Minimal example |
| 25 | + |
| 26 | +```ts |
| 27 | +import { test, expect } from "vitest" |
| 28 | +import { testScreen } from "@intent-framework/testing" |
| 29 | +import { screen } from "@intent-framework/core" |
| 30 | + |
| 31 | +const InviteMember = screen("InviteMember", $ => { |
| 32 | + const email = $.state.text("email") |
| 33 | + |
| 34 | + const emailAsk = $.ask("Email", email) |
| 35 | + .required() |
| 36 | + .validate(value => value.includes("@") ? true : "Enter a valid email") |
| 37 | + |
| 38 | + const invite = $.act("Invite member") |
| 39 | + .primary() |
| 40 | + .when(emailAsk.valid, "Enter a valid email first") |
| 41 | + |
| 42 | + $.surface("main").contains(emailAsk, invite) |
| 43 | +}) |
| 44 | + |
| 45 | +test("invite is blocked until email is valid", async () => { |
| 46 | + await testScreen(InviteMember, async app => { |
| 47 | + await app.act("Invite member").toBeBlockedBy("Enter a valid email first") |
| 48 | + await app.answer("Email", "ada@example.com") |
| 49 | + await app.act("Invite member").toBeEnabled() |
| 50 | + }) |
| 51 | +}) |
| 52 | + |
| 53 | +test("invite action can be executed", async () => { |
| 54 | + await testScreen(InviteMember, async app => { |
| 55 | + await app.answer("Email", "ada@example.com") |
| 56 | + await app.act("Invite member").run() |
| 57 | + }) |
| 58 | +}) |
| 59 | +``` |
| 60 | + |
| 61 | +No DOM, no selectors, no render waits. Tests speak product language. |
| 62 | + |
| 63 | +## Where this fits |
| 64 | + |
| 65 | +Testing provides a runtime harness for Intent screens. It depends on `@intent-framework/core`. Use it with any test runner (Vitest recommended). It pairs with `inspectScreen()` for diagnostics assertions. |
| 66 | + |
| 67 | +## Learn more |
| 68 | + |
| 69 | +- [Root README](../../README.md) — project overview and testing philosophy |
| 70 | +- [Quickstart](../../docs/Quickstart.md) — step-by-step guide with testing |
| 71 | +- [Canonical runnable example](../../examples/canonical-invite) — matches the Quickstart one-to-one |
| 72 | + |
| 73 | +## Status |
| 74 | + |
| 75 | +Experimental alpha. Version `0.1.0-alpha.1`. APIs may change. Not recommended for production use. |
0 commit comments