Available since v0.1.0
fs-assert-after
StableResolves immediately at creation time — passes if every referenced parent assertion has already passed, fails otherwise. Use to validate that user actions happened in the correct order.
Syntax
fs-assert-after="<key>"
fs-assert-after="<key1>,<key2>,..."
Comma-separated parent keys, AND semantics: every listed parent must have passed for after to pass.
When to use it
- Multi-step wizards ("Step 3 requires Step 2 which requires Step 1")
- Checkout funnels ("Submit payment requires add-to-cart")
- Multi-click workflows that must happen in order
- Analytics funnel validation without network instrumentation
Example
<!-- Step 1 -->
<button fs-assert="checkout/add-to-cart" fs-trigger="click"
fs-assert-added=".cart-item">Add to cart</button>
<!-- Step 2: must have added to cart first -->
<button fs-assert="checkout/submit-payment" fs-trigger="click"
fs-assert-after="checkout/add-to-cart"
fs-assert-visible=".confirmation">Pay</button>
If the user clicks Pay without adding to cart, checkout/submit-payment/after fails with a sequence violation — even if the .confirmation element still appears.
Semantics
- Immediate resolution.
afterdoesn't wait. At trigger time, it checks the stored "has passed" state of every parent key. If all passed, it passes. Otherwise it fails. - Independent data point.
afterproduces its own assertion event alongside any DOM assertions on the same element. A sequence violation with a healthy-looking UI shows up as a failedafterassertion and a passingvisibleassertion — both signals are valuable. - Recovery on re-trigger. A failed
aftercan recover if the parent assertion later passes and the trigger fires again. - Chaining. A → B → C works naturally: each
afterchecks only its direct parent.
Pairs well with
fs-trigger="click"— the canonical triggerfs-trigger="submit"— form-based wizards- Any DOM assertion type on the same element —
afterruns alongside, not in place of
Gotchas
- Don't combine with
fs-trigger="invariant". Invariants skip the immediate resolution path thatafterdepends on — it would never be checked. - Parent keys must be stable across releases. If you rename
checkout/add-to-carttocheckout/cart-add, everyafterreferencing the old key fails until you update them. - "Has passed" is session-scoped. Parent state is tracked in memory, not in localStorage. Navigating to a new page via a hard reload resets the state. For cross-page sequences, use
fs-assert-mpa="true"on both the parent and theafterassertion.