Skip to content

journey-runner.js cannot express a hand-over journey, a toggle set to a known state, an expected ERROR span, or a row-scoped click (harvest from a field-run copy) #148

Closed

Description

@MendixMau

What happens

The toolkit runner (project-tests/e2e/journey-runner.js) signs in once and has no vocabulary for several things a real multi-role journey needs. A field build patched its installed copy (a ~214-line diff) and ran its journeys green with it. This issue is the harvest request: port the vocabulary, not the project file.

The gaps the toolkit runner still has today:

Gap What goes wrong without it Local extension that closed it
Hand a walk to another role "Admin arms a fault, a second role looks, a third decides" cannot be one journey signInAs {role}: H.logout, then H.loginAs with project.config.js roles[role], or "persona" to return to TEST_USER. Credentials are never read from the journey file.
Set a toggle to a known state A pluggable switch is a toggle, so click depends on the start state. A dialog that reopens with the last run's settings made a second run turn a switch off by "turning it on". switch {widget, on}: click only if aria-checked differs, then read it back and FAIL if it still differs
A step that injects an error on purpose Every step after an armed fault FAILs rung 2's "no ERROR at any level" by design spans.expectErrors: [regex]: each regex must match at least one ERROR span over <op> | <error text> | http <status>. Every other ERROR still fails.
A grid repeats one widget name per row First-match .mx-name-<w> clicks whichever row renders first click / switch gain row (text of one row, innermost match last()), in (scope to one grid) and target (child selector), via one scoped() helper
Radio option No act radio: choose an option by caption, then read the checked option back
Mendix confirmation dialog No act confirm {button, says?}: says goes through subst() like button. The first cut did not do that and took {{run}} literally.
System-to-system call No act request {method, path, body, auth:{userEnv,passEnv}, expectStatus, expectText}: missing env credentials or an unreachable URL is an InstrumentFault
A step that deletes rows on purpose (fixture reset) Every later delta is measured from a baseline count that no longer exists data.rebase: [entity] re-takes the baseline after the step
Effects that land on the next engine/scheduler pass A single read FAILs a claim that is true 5 s later withinMs / everyMs on OQL checks (checkOqlWithin), and spans.withinMs (stretch capture retries). Mutants delete withinMs, because a floor that is never reached is not reached by waiting.
Separate findings file per run Controls overwrite the real walk's findings --out=<file.json>
Faults vs findings A missing credential read as FAIL class InstrumentFault → the step's action row is INVALID, never FAIL

The numeric mustPointAt sentinel (-424242) from the same patch set is already in the toolkit runner.

Evidence (card-disbursement requirements-driven build, 2026-09-26/27)

  • Two hand-over journeys ran 97/97 and 80/80 (92/92 after says went through subst()).
  • A mutant expectErrors regex that matches nothing fails its step.
  • The switch read-back caught the second-run toggle inversion described above. The journey had gone red on its second run only.
  • Admin-console journeys with radio/confirm/request/row ran 57/0/0 and 52/0/0.

Suggested fix

  • Port the acts, the scoped() helper, InstrumentFault, data.rebase, withinMs, spans.expectErrors and --out= into project-tests/e2e/journey-runner.js.
  • Add loginAs to helpers.js; it has login/logout/loginOnce today.
  • Document the schema in skills/journey-proof.md.
  • Extend --positive-control so each new claim kind has a mutant: expectErrors → a regex that matches nothing; switch → invert on; confirm.says → a string the dialog does not say.

The field-proof bar needs a real journey run on a scratch app. That is why this is filed rather than ported directly. bin/harvest-learnings.sh will also pick up the locally patched installed script.

Files

  • project-tests/e2e/journey-runner.js
  • project-tests/e2e/helpers.js
  • project-tests/e2e/project.config.template.js (roles)
  • project-tests/e2e/journey-runner.selftest.js
  • skills/journey-proof.md

Related: the persona/TEST_USER refusal and negative-only span claims are filed separately.

Activity

  1. MendixMau commented on Oct 26, 2026

    @MendixMau
    OwnerAuthor

    One slice shipped in #578 (squash a088b4e): click takes row and in. The row must show the text as whole words, and an ambiguous match throws. The rest (signInAs, switch, expectErrors, radio, confirm, request, rebase, withinMs) needs control mutants and a scratch-app field run each. It's on the roadmap (#579); next is switch with its read-back.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions