Repository navigation
chore: version packages - #774
Conversation
b87c949 to
a4b1b7a
Compare
🟢 e2e web: 91 passedAll 91 tests in 41 files
e2e 0.17.0 · 1m 50s · web · run artifacts |
🟢 e2e web agent: 33 passed33 agent steps · 120 model calls · 548.7k tokens (91% cached) · $0.0260 All 33 tests in 5 files
e2e 0.17.0 · 4m 36s · web · run artifacts |
🟢 e2e android: 54 passed, 1 skippedAll 55 tests in 7 files
e2e 0.17.0 · 7m 47s · android-emulator · run artifacts |
🟢 e2e ios: 1 flaky, 51 passed, 1 skipped
|
| Test | Time | |
|---|---|---|
| tests/controls.e2e.ts · 1 flaky, 22 passed, 1 skipped | 3m 58s | |
| 🟢 | control inventory › a label query resolves a labeled text field | 13.4s |
| 🟢 | control inventory › a labeled field answers name, display value, value reads, fill, and clear | 20.2s |
| 🟢 | control inventory › a placeholder query and attribute reads find the field | 8.9s |
| 🟢 | control inventory › a secure field takes a fill and denies value reads | 11.7s |
| 🟢 | control inventory › press sends a character and Enter through the soft keyboard | 9.7s |
| 🟢 | control inventory › a field autofocuses on mount and focus() moves the focus | 13.6s |
| control inventory › toBeFocused follows the focus (2 failed attempts first) | 15.6s | |
| 🟢 | control inventory › a switch checks, unchecks, and reports its state | 13.8s |
| 🟢 | control inventory › checkbox and radio roles answer getByRole, and a checkbox toggles by tap | 10.2s |
| 🟢 | control inventory › checkbox and radio roles check, uncheck, and report their state | 17.0s |
| 🟢 | control inventory › a radio group reports the checked option | 11.0s |
| 🟢 | control inventory › buttons report disabled, enabled, and a state that arrives later | 9.7s |
| 🟢 | control inventory › a display: none element is absent rather than hidden, its visible twin attached | 9.1s |
| 🟢 | control inventory › a header answers its accessible name | 5.5s |
| 🟢 | control inventory › a tab row answers count, all, texts, filters, positions, and switching | 9.1s |
| 🟢 | control inventory › a list answers counts, list-form text, reads, and boxes in order | 10.4s |
| ⏭️ | control inventory › a row contains its texts (skipped: React Native flattens a plain View out of the accessibility tree on both platforms: XCTest and the Android helper report a View with a testID as a leaf beside its children, so filter({ has }) and a query scoped to it match nothing; only Sc…) | |
| 🟢 | control inventory › a long press lands as one | 11.0s |
| 🟢 | control inventory › pointer verbs land at the point asked for | 13.4s |
| 🟢 | control inventory › an ambiguous locator fails at once | 7.8s |
| 🟢 | control inventory › screenshot, restart, and clearState reopen the app on its home list | 15.0s |
| 🟢 | refusals › verbs a device never declares are refused before the engine | 3ms |
| 🟢 | refusals › keys the soft keyboard cannot send are refused by the engine | 486ms |
| 🟢 | refusals › a missing locator fails as not found once its timeout passes | 1.3s |
| 🟢 | tests/device-fixture.e2e.ts · 9 passed | 1m 45s |
| 🟢 | device fixture › setAppearance flips the color scheme the app reads | 16.3s |
| 🟢 | device fixture › setOrientation rotates the window the app measures | 7.9s |
| 🟢 | device fixture › the clipboard reads back what was written | 6.6s |
| 🟢 | device fixture › home leaves the app, openApp brings it back where it was | 13.5s |
| 🟢 | device fixture › closeApp then openApp relaunches on the home list | 10.9s |
| 🟢 | device fixture › foregroundApp after closeApp reports the closed session as APP_NOT_OPEN | 6.7s |
| 🟢 | device fixture › device.back pops the scenario | 7.4s |
| 🟢 | device fixture › setLocation and clearLocation change what the app reads | 19.4s |
| 🟢 | device fixture › enrollBiometrics and setBiometrics answer a biometric prompt | 16.3s |
| 🟢 | tests/device.e2e.ts · 2 passed | 1m 3s |
| 🟢 | sequential onboarding echoes the exact values | 47.0s |
| 🟢 | onboarding rejects a malformed email before advancing | 15.6s |
| 🟢 | tests/flows-lists.e2e.ts · 7 passed | 4m 18s |
| 🟢 | infinite scroll reaches the target item | 31.9s |
| 🟢 | product catalog adds exactly two of the right variant | 14.3s |
| 🟢 | gestures: long-press, then swipe left | 11.9s |
| 🟢 | sticky chrome: accept below the fold, then continue | 13.6s |
| 🟢 | async states: load, pull to refresh, claim through the toast | 12.6s |
| 🟢 | huge virtualized list reaches row 512 | 2m 37s |
| 🟢 | web view coupon form applies the code shown on the page | 16.8s |
| 🟢 | tests/flows.e2e.ts · 7 passed | 1m 30s |
| 🟢 | text inputs unlock the submit button | 20.0s |
| 🟢 | filled text inputs report their values | 12.9s |
| 🟢 | modal flow confirms through the native alert | 11.9s |
| 🟢 | bottom tabs act inside the last tab | 9.6s |
| 🟢 | error recovery retries, then confirms the delete | 11.8s |
| 🟢 | choice controls place the exact order | 10.8s |
| 🟢 | debounced search selects the target once results arrive | 13.3s |
| 🟢 | tests/login-form.e2e.ts · 3 passed | 55.8s |
| 🟢 | login form › rejects a malformed email | 14.9s |
| 🟢 | login form › rejects an unknown account | 14.7s |
| 🟢 | login form › signs in and logs out | 26.2s |
| 🟢 | tests/smoke.e2e.ts · 1 passed | 11.9s |
| 🟢 | home lists the scenarios and opens one | 11.9s |
e2e 0.17.0 · 7m 26s · ios-simulator · run artifacts
🟢 e2e android agent: 20 passed24 agent steps · 117 model calls · 648.3k tokens (84% cached) · $0.0404 All 20 tests in 1 file
e2e 0.17.0 · 9m 18s · android-emulator · run artifacts |
🟢 e2e ios agent: 1 flaky, 20 passed, 1 skipped25 agent steps · 129 model calls · 54.6k tokens (85% cached) · $0.0035
|
| Test | Agent | Time | |
|---|---|---|---|
| tests-agent/scenarios.e2e.ts · 1 flaky, 20 passed, 1 skipped | 25 steps · 129 calls | 14m 2s | |
| 🟢 | act completes Login Form | 1 step · 7 calls | 1m 9s |
| 🟢 | act completes Infinite Scroll List | 1 step · 3 calls | 56.8s |
| 🟢 | act completes Modal Flow | 1 step · 4 calls | 17.3s |
| 🟢 | act completes Bottom Tabs | 1 step · 3 calls | 13.9s |
| 🟢 | act completes Text Input Variations | 1 step · 3 calls | 28.8s |
| 🟢 | act completes Broken Accessibility | 2 steps · 7 calls | 41.1s |
| 🟢 | act completes Vision Only | 2 steps · 6 calls | 53.7s |
| act completes Gestures (2 failed attempts first) | 1 step · 10 calls | 56.8s | |
| 🟢 | act completes Async States | 1 step · 8 calls | 39.7s |
| 🟢 | act completes Debounced Search | 1 step · 5 calls | 23.2s |
| 🟢 | act completes Flattened Registration Form | 2 steps · 14 calls | 1m 43s |
| 🟢 | act completes Flattened Login | 2 steps · 12 calls | 1m 29s |
| 🟢 | act completes Sticky Chrome Target | 1 step · 7 calls | 40.8s |
| 🟢 | act completes WebView Accessibility | 1 step · 4 calls | 25.8s |
| 🟢 | act completes Permission Prompt | 1 step · 3 calls | 21.5s |
| 🟢 | act completes Photo Picker | 1 step · 4 calls | 19.4s |
| 🟢 | act completes Product Catalog | 1 step · 5 calls | 17.7s |
| 🟢 | act completes Error Recovery | 1 step · 6 calls | 17.3s |
| 🟢 | act completes Choice Controls | 1 step · 8 calls | 37.9s |
| 🟢 | act completes Stripe PaymentSheet | 1 step · 6 calls | 41.4s |
| 🟢 | act completes Apple Pay | 1 step · 4 calls | 27.8s |
| ⏭️ | act completes Apple Pay Billing Address (skipped: the CI simulator's Apple Pay sheet skips the billing-address step, so the scenario cannot be completed there) |
e2e 0.17.0 · 16m 14s · ios-simulator · run artifacts
4dac129 to
4b6baaa
Compare
4b6baaa to
210b68e
Compare
…-army#929) Every engine minor re-keyed all committed recordings, so each `chore: version packages` merge failed the strict web agent job with REPLAY_STALE on main (tester-army#825 after tester-army#774). The key keeps the engine's name and SPI version; a release of the same engine is caught at replay, where each action re-finds its node. The 30 web benchmark entries move to their new hashes by a re-key verified against the old ones.
…-army#929) Every engine minor re-keyed all committed recordings, so each `chore: version packages` merge failed the strict web agent job with REPLAY_STALE on main (tester-army#825 after tester-army#774). The key keeps the engine's name and SPI version; a release of the same engine is caught at replay, where each action re-finds its node. The 30 web benchmark entries move to their new hashes by a re-key verified against the old ones.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
e2e@0.17.0
Minor Changes
#779
6639bfaThanks @fecolinhares! -copilot()reaches the models Copilot serves only over its Responses API, such asgpt-6-luna,gpt-5.3-codex, andgrok-4.5. On the first call it reads the plan's model listing and picks chat completions or the Responses API from the model'ssupported_endpoints; a model served over chat completions, or one the listing does not place, stays on chat completions. A listing that cannot be read sends that call over chat completions without remembering it, and a revoked login fails on the listing with the sign-in command. Responses models run through@ai-sdk/openai, whiche2e initnow adds for Copilot; without it the call names the package to install. Responses turns carry the same initiator and vision headers as chat turns.e2e models github-copilotmarks whatcopilot()cannot call withno chat or responsesin place ofno chat completions, and a disabled model asnot enabledonly.#794
c66176bThanks @neriousy! - Sign in with OpenCode Console to use OpenCode Zen and OpenCode Go models for agent steps.e2e login opencode-consoleruns Console's device flow: approve the code, pick the workspace, and the login is stored and refreshed like the other subscriptions.opencodeConsole('<id>')frome2e/oauth/opencode-consolecalls a Zen model for a bare id and a Go model for ago/id (go/deepseek-v4.1-flash); on its first call it reads the workspace config to pick the model's API (OpenAI chat completions, OpenAI Responses, Anthropic Messages, or Google) and loads only that AI SDK package, so@ai-sdk/anthropicand@ai-sdk/googlejoin the optional peers. Once the workspace config is read, a model it does not serve, or a Go model without the subscription, fails withMISCONFIGUREDnaming the fix. Each model sends onex-opencode-session, so a worker's calls stay on one upstream cache, and prompts cache the way e2e caches them for OpenAI and Anthropic directly: models served over Anthropic Messages get a breakpoint on the system prompt and, in agent steps, on the newest message, and Responses models get the system prompt's cache key. Reports name the modelopencode/<id>oropencode.go/<id>, and chat models of both plans read provider options underopencode.e2e models opencode-consolelists the enabled models tagged Zen or Go,e2e initoffers OpenCode Console among the subscriptions, andOPENCODE_API_KEY, the variable OpenCode reads, takes a Console service account key in place of the stored login.#741
bfa58c7Thanks @Marve10s! - Keep soft assertion failures in the report when a test skips itself, and showthem in the CLI under
Skipped After Failure. A failed attempt followed by askip on retry also appears there with its original error.
Add
failOnSkippedFailure: trueto fail the run with exit code 1 for thesetests. The default is
false, preserving the existing exit code. Tests retaintheir skipped status and reason, teardown still runs, and a skip does not
trigger another retry.
#713
7ab80bcThanks @okwasniewski! - Breaking: an interrupted test is no longer counted as failed.report.jsongainsrun.summary.interrupted, andrun.summary.failedcounts only failed and timed-out tests.run.summary.skippednow counts only selected tests, sopassed + failed + interrupted + flaky + skippedequalsselected; the tests a filter left out arediscovered - selected. Thelistreporter prints3 interruptedin its own column,summary.mdshows them with ⏹️ and gives them no failure block or page, andjunit.xmlwrites each one as a<skipped>whose message startsinterrupted:. A test that failed and whose retry an interrupt cut short stays failed, and its failure is the one reported. A--repeat-eachrun the interrupt stopped is listed as interrupted, not as a flake. The telemetry event gainstests_interrupted. In@e2e-dev/github, a test that was interrupted and then passed on a--last-failedrerun shows as passed, not flaky.Patch Changes
#711
a3da00dThanks @okwasniewski! -device.installApp()no longer pins the build's file path as the app when agent-device reports no bundle id or package for it, which on Android madeapp.open()fail with "Android runtime hints require an installed package name". It fails at the install withENGINE_FAILUREnamingapp.bundleIdor installApp'sappoption; the mobile docs' Troubleshooting covers the Android cause (agent-device 0.21.18 reads an aapt2-built APK's package only through the SDK'saapt, which it does not find in the macOS default SDK location, or when the install added the package).app.open()on a device now keeps the engine's own reason it cannot launch, such as a build not installed yet withdevice.installApp(), instead of a generic "pin one with app.bundleId or app.appPath".#732
3bf295eThanks @okwasniewski! - The replay cache no longer passes a step whose effect did not happen. Entries are keyed by the agent and a hash of its redacted context, so one persona never replays another's steps and a changedagentContextrecords again. A route now includes the origin and the query (ids, tokens, and timestamps aside), and the end route must match exactly. A replay checks what the step made appear, with checked or selected state, and what it made disappear, needs at least one of those changes to happen during the replay, and stops on an alert the recording never saw. A count the step made appear is part of the effect, and an unnamed control with twins needs a named row or group to replay. Every existing entry is re-recorded on the first run after the upgrade.#713
7ab80bcThanks @okwasniewski! - A forced interrupt (a second Ctrl-C, or a CI cancel that sends SIGINT and then SIGTERM) still writesjunit.xmlandsummary.md. The runner used to abandon them along with every other reporter, which left the previous run's files beside the newreport.json. Custom reporters are still abandoned on force.#799
96ff11bThanks @okwasniewski! - A recorded step that removes a control while something else on screen keeps its text, such as a radio labelled "Express" replaced by a status reading "Express", now replays. Its recording used to fail its own end check on every replay (end-mismatch, orREPLAY_STALEunder--strict-cache). Re-record such a step once to pick up the fix.#726
f7c0756Thanks @okwasniewski! -locator.waitForadds Playwright'sattachedanddetachedstates and refuses any other state, or an option key besidesstateandtimeout, withINVALID_ARGUMENT. Before, every state butvisibleran ashidden, sowaitFor({ state: 'attached' })and a misspelled state passed at once on an absent node.toBeHidden,toBeVisible({ visible: false }),toBeAttached({ attached: false }), andwaitFordetachedandhiddenread a locator under a frame missing from the document as zero matches instead of timing out waiting for the frame.toHavePropertyreads a primitive on the path through its wrapper, as Jest does, sotoHaveProperty('label.length', 3)passes.expect(browser).toHaveURLtakesignoreCase, andurlMatchesine2e/enginetakes it as an optional fourth argument.#784
cc54c6bThanks @okwasniewski! - Every model call now identifies e2e, whichever provider serves it: theUser-Agentstarts withe2e/<version> (<platform>; <arch>)ahead of the AI SDK's own, andHTTP-Referer: https://tester.army/e2ewithX-Title: e2eattribute the traffic on the Vercel AI Gateway and OpenRouter. These replace anHTTP-RefererorX-Titleset on the provider instance. Before, only subscription logins sent the e2e user agent.#722
f0f9c8dThanks @okwasniewski! - Explicit navigation now uses an allowlist instead of a denylist:app.open,browser.goto, and the agent'snavigateverb admithttp:,https:, and the exactabout:blank, and every other scheme (chrome:,blob:,about:srcdoc, ...) isPOLICY_DENIED. A wrapped scheme such asview-source:file:///...no longer loads a local file; it isPOLICY_DENIEDlikefile:itself.device.openLinkanddevice.openAppalso refuseview-source:,blob:, andfilesystem:links.browser.setCookiesrefuses anabout:blankcookie URL withPOLICY_DENIED.#729
4ce01b2Thanks @okwasniewski! - A registered secret no longer leaks through the observed screen: a test id, an iframe name in a frame path, a selector, or an attribute holding one is masked in the model's text, an executor's tree, and cache entries, and a secret with a line break, tab, CRLF, no-break space, or repeated spaces that an engine collapsed and then cut at the name or text limit no longer leaves its leading part in observations or end anchors.#798
02ad48aThanks @okwasniewski! - Breaking:@e2e-dev/webdepends onplaywright-corepinned to an exact version instead of peering onplaywright. Projects no longer install Playwright themselves, and the engine always runs the Playwright it was tested against. Removeplaywrightfrom your dependencies unless your app uses it for its own tests:Install browsers in CI with the package's new command, which runs the engine's Playwright:
npx @e2e-dev/web install chromium --with-deps(pnpm exec e2e-web install chromium --with-depsunder pnpm) replacesnpx playwright install chromium --with-deps. Open traces withnpx playwright-core@1.63.0 show-trace <file>(pnpm dlxin a pnpm project). An app that also depends on@playwright/testkeeps its own copy; the two share a browser cache only when their versions match.e2e initno longer addsplaywrightto a new project.#725
9b93575Thanks @okwasniewski! - Anexpect.pollthat the test body, anafterEachhook, or a fixture teardown returns without awaiting is now cancelled and fails that phase withSTEP_NOT_AWAITEDat the line of the call; in abeforeAllorafterAllhook it fails the hook withHOOK_FAILED. Before, the test passed and the poll's timeout failed whichever test ran next, or nothing at all.The negation window of a negated
expect(locator)orexpect(browser)matcher now starts when the first read that saw the negation was issued, not when it returned, so a slow read counts toward it. With atimeoutunder a second, a negation that held for the whole budget now passes at the deadline; before, a slow first read made a true negation time out.#777
79931d0Thanks @DeryFerd! - The replay cache abstracts short prefixed record ids as minted segments. A route segment of letters, a dash, and a digit tail of two or more (PROJ-016,INV-2041) now reduces to:id, so a step recorded on one record replays on the next instead of missing withwrong-contextand running live every time. A single trailing digit (page-2) stays a route word.#724
3a9667cThanks @okwasniewski! ---last-failedno longer goes green on tests it never ran. It reruns tests--max-failuresskipped, and a test or failedbeforeAll/afterAllanother filter leaves out stays owed in the report's newrun.carrieduntil a rerun runs it. A rerun also keeps the artifacts of the run it reruns and writes its own underartifacts/rerun-<n>/in the output directory (.e2eby default), so the folded pull request comment keeps its evidence and stays red while anything is owed.#721
94ddbfeThanks @okwasniewski! - Two credentials or two secrets whose names map to the same override variable (api-keyandapi_keyboth readE2E_SECRET_API_KEY) now fail the config load withINVALID_CONFIGinstead of both silently taking one value.#800
b5dc0f8Thanks @okwasniewski! ---strict-cachenow fails a step withREPLAY_STALEwhen the cache directory holds its recording under another key, for example after ane2eor engine upgrade or a change to the agent's context. Before, such a step ran live and spent model calls with no error. The message names the old entry file. A step with no recording still runs live.@e2e-dev/web@0.12.0
Minor Changes
#798
02ad48aThanks @okwasniewski! - Breaking:@e2e-dev/webdepends onplaywright-corepinned to an exact version instead of peering onplaywright. Projects no longer install Playwright themselves, and the engine always runs the Playwright it was tested against. Removeplaywrightfrom your dependencies unless your app uses it for its own tests:Install browsers in CI with the package's new command, which runs the engine's Playwright:
npx @e2e-dev/web install chromium --with-deps(pnpm exec e2e-web install chromium --with-depsunder pnpm) replacesnpx playwright install chromium --with-deps. Open traces withnpx playwright-core@1.63.0 show-trace <file>(pnpm dlxin a pnpm project). An app that also depends on@playwright/testkeeps its own copy; the two share a browser cache only when their versions match.e2e initno longer addsplaywrightto a new project.#795
3b026faThanks @okwasniewski! - Init scripts, like Playwright'saddInitScript:web({ initScripts })for every test,browser.addInitScript(script, arg?)for one. A script is source, a{ path }, or a function.#786
f88233fThanks @okwasniewski! - web({ locale, timezoneId }) sets the language and time zone every attempt's context runs in, as Playwright'suse.localeanduse.timezoneIddo:navigator.language,Intl, theAccept-Languageheader, and localDatetime. A tagIntlrejects isINVALID_CONFIGat config load, and so is anaccept-languageentry inheadersbesidelocale, and either option on a persistent remote context (connect.reconnectEndpoint, or a provider withscope: 'attempt').Patch Changes
#788
baa32c6Thanks @okwasniewski! -check()anduncheck(), and the agent'schecktool, pass when the click removes the control or navigates away from it, such as a radio the app replaces with its selected view. The click landed, so the action is recorded and replays. What replaced the control is not read, so a test that needs it asserts on it. They used to fail: an agent step reportedLOCATOR_NOT_FOUNDand left the action out of its recording, so the next run handed off withend-mismatch, and a locatorcheck()timed out. Unchecking a checked radio and a click that leaves the state unchanged now fail withNOT_ACTIONABLEinstead ofENGINE_FAILURE.#726
f7c0756Thanks @okwasniewski! -locator.waitForadds Playwright'sattachedanddetachedstates and refuses any other state, or an option key besidesstateandtimeout, withINVALID_ARGUMENT. Before, every state butvisibleran ashidden, sowaitFor({ state: 'attached' })and a misspelled state passed at once on an absent node.toBeHidden,toBeVisible({ visible: false }),toBeAttached({ attached: false }), andwaitFordetachedandhiddenread a locator under a frame missing from the document as zero matches instead of timing out waiting for the frame.toHavePropertyreads a primitive on the path through its wrapper, as Jest does, sotoHaveProperty('label.length', 3)passes.expect(browser).toHaveURLtakesignoreCase, andurlMatchesine2e/enginetakes it as an optional fourth argument.#722
f0f9c8dThanks @okwasniewski! - Explicit navigation now uses an allowlist instead of a denylist:app.open,browser.goto, and the agent'snavigateverb admithttp:,https:, and the exactabout:blank, and every other scheme (chrome:,blob:,about:srcdoc, ...) isPOLICY_DENIED. A wrapped scheme such asview-source:file:///...no longer loads a local file; it isPOLICY_DENIEDlikefile:itself.device.openLinkanddevice.openAppalso refuseview-source:,blob:, andfilesystem:links.browser.setCookiesrefuses anabout:blankcookie URL withPOLICY_DENIED.#785
9844c30Thanks @okwasniewski! - A string role name with a quote (getByRole('button', { name: "Yes, I'm sure" })) no longer fails withInvalidSelectorErroronce the locator is chained (.first(),nth, a filter, or the read itself). The same goes for auorvflag RegExp with a quote or>>ingetByRole,getByText,getByLabel,getByPlaceholder, andgetByTestId.#723
cdc3a53Thanks @okwasniewski! - Route decisions behave like Playwright's.route.continue()now sends the request to the network instead of handing it to an earlier route, and still carries the configuredheadersto the app's site; the newroute.fallback()keeps the old chaining.continuetakesurl,method,headers, andpostData, withurlchecked by the same rule asgoto, andfulfilltakespath(relative to the project root) andcontentType. An option a decision does not take, such asabort(errorCode)or a misspelled key, isINVALID_ARGUMENTinstead of being ignored.browser.waitForResponseresolves once a matching response's headers arrive, so a slow body no longer fails the match with a timeout;text()andjson()wait for the body up to the action timeout.browser.setCookieswith a relativeurlsets the cookie on the base URL instead of failing withENGINE_FAILURE.#728
7f9ee10Thanks @okwasniewski! - Web visibility and reads follow what renders, as Playwright reads them: anaria-hiddennode that paints is visible, sotoBeHidden()on a decorative spinner waits until it leaves; content undercontent-visibility: hiddenis hidden; a child that setsvisibility: visibleunder a hidden parent is visible and in the agent's observation; text under adisplay: contentselement withvisibility: hiddenis hidden, where Playwright calls it visible, since it paints nothing.boundingBox()isnullfor a node with no layout box.inputValue()andtoHaveValueread a checkbox's or radio's value (onby default) whatever its checked state. An accessible name reads an embedded control's value:<button>Flash the screen <input value="3"> times</button>is "Flash the screen 3 times".@e2e-dev/github@0.3.3
Patch Changes
#713
7ab80bcThanks @okwasniewski! - Breaking: an interrupted test is no longer counted as failed.report.jsongainsrun.summary.interrupted, andrun.summary.failedcounts only failed and timed-out tests.run.summary.skippednow counts only selected tests, sopassed + failed + interrupted + flaky + skippedequalsselected; the tests a filter left out arediscovered - selected. Thelistreporter prints3 interruptedin its own column,summary.mdshows them with ⏹️ and gives them no failure block or page, andjunit.xmlwrites each one as a<skipped>whose message startsinterrupted:. A test that failed and whose retry an interrupt cut short stays failed, and its failure is the one reported. A--repeat-eachrun the interrupt stopped is listed as interrupted, not as a flake. The telemetry event gainstests_interrupted. In@e2e-dev/github, a test that was interrupted and then passed on a--last-failedrerun shows as passed, not flaky.#724
3a9667cThanks @okwasniewski! ---last-failedno longer goes green on tests it never ran. It reruns tests--max-failuresskipped, and a test or failedbeforeAll/afterAllanother filter leaves out stays owed in the report's newrun.carrieduntil a rerun runs it. A rerun also keeps the artifacts of the run it reruns and writes its own underartifacts/rerun-<n>/in the output directory (.e2eby default), so the folded pull request comment keeps its evidence and stays red while anything is owed.@e2e-dev/mobile@0.9.2
Patch Changes
#711
a3da00dThanks @okwasniewski! -device.installApp()no longer pins the build's file path as the app when agent-device reports no bundle id or package for it, which on Android madeapp.open()fail with "Android runtime hints require an installed package name". It fails at the install withENGINE_FAILUREnamingapp.bundleIdor installApp'sappoption; the mobile docs' Troubleshooting covers the Android cause (agent-device 0.21.18 reads an aapt2-built APK's package only through the SDK'saapt, which it does not find in the macOS default SDK location, or when the install added the package).app.open()on a device now keeps the engine's own reason it cannot launch, such as a build not installed yet withdevice.installApp(), instead of a generic "pin one with app.bundleId or app.appPath".#791
b3e1fd1Thanks @DimaMishchenko! - Update agent-device to 0.21.20 so sibling-sized iOS toolbar containers no longer falsely mark nearby controls as covered.#801
ae3dc64Thanks @thymikee! - Recognize agent-device's stale-ref refusals by theirdetails.reasoninstead of matching their message, so a reworded message in a later agent-device release cannot turn a stale ref into an engine failure. Every ref-frame reason agent-device 0.21.20 sends is covered, including the three whose messages the old pattern did not match.#722
f0f9c8dThanks @okwasniewski! - Explicit navigation now uses an allowlist instead of a denylist:app.open,browser.goto, and the agent'snavigateverb admithttp:,https:, and the exactabout:blank, and every other scheme (chrome:,blob:,about:srcdoc, ...) isPOLICY_DENIED. A wrapped scheme such asview-source:file:///...no longer loads a local file; it isPOLICY_DENIEDlikefile:itself.device.openLinkanddevice.openAppalso refuseview-source:,blob:, andfilesystem:links.browser.setCookiesrefuses anabout:blankcookie URL withPOLICY_DENIED.#793
4db7d6dThanks @DeryFerd! -device.openLinkno longer echoes the string it refused in itsINVALID_ARGUMENTmessage. A malformed link can carry a magic-link token in its query, path, or userinfo, so the message names no part of the input, matching whatdevice.openAppalready does.