Available since v0.1.0
fs-assert-added
StableResolves when a new element matching the selector is inserted into the DOM after the trigger fires. Mutation-observed — captures the exact insertion moment via MutationObserver.
Syntax
fs-assert-added="<selector>"
fs-assert-added="<selector>[modifier=value]..."
When to use it
Use when the target element doesn't exist yet and will be created by the triggered action. The canonical choice for:
- Adding items to lists (todos, cart, notifications)
- Showing a new overlay, modal, or toast
- Rendering a success or error element that wasn't in the DOM before
- Appending search results
If the element already exists and its content changes, use updated instead. This is the #1 instrumentation mistake.
Example
<button
fs-assert="todos/add-item"
fs-trigger="click"
fs-assert-added=".todo-item">
Add
</button>
Passes when a new .todo-item element is inserted into the DOM after the click.
Pre-existing matches don't pass
If a matching element is already in the DOM at the moment the trigger fires, added does not pass on that. It waits for an actual insertion event. This is intentional — a pre-existing match isn't "added by this trigger" and reporting it as a pass would mask real failures.
Pairs well with
fs-trigger="click"— canonical user interactionfs-trigger="submit"— form submissions that add a confirmation element[count-min=1]— assert at least N new elements appeared[text-matches=...]— verify the new element's content- Conditional assertions — branch on
added-successvsadded-error fs-assert-mutex="each"— group with a failure branchfs-assert-oob— fire side-effect checks when this passes
Gotchas
- Using
addedwhenupdatedis correct. Class toggles, text changes, and attribute updates on existing elements areupdated, not added.fs-assert-added=".foo.complete"will never match if.fooalready exists and merely gains thecompleteclass. - Using
addedon HTMXhx-swap="morph:outerHTML". Idiomorph patches the element in place; identity is preserved. The correct type isupdated. See the HTMX swap table. - Broad selectors in lists. Under a standard (non-morph)
outerHTMLswap the old and new elements briefly coexist. Prefer specific ids over class selectors:fs-assert-added="#todo-123[classlist=completed:true]"overfs-assert-added=".todo-item[classlist=completed:true]". - With OOB or invariant. State types work with OOB and invariant;
addedis a state type and is fine for both.updated/loadedare event types and miss mutations that already happened — preferadded/removed/visible/hiddenfor OOB and invariant.
See also
updated— for in-place content changesremoved— the complementary type- Assertions index