Module: Phlex::Reactive::TestHelpers::System
- Defined in:
- lib/phlex/reactive/test_helpers/system.rb
Defined Under Namespace
Classes: ReactiveValueMatcher
Constant Summary collapse
- ACTIVE_MARKER =
The marker the client sets while the reactive layer is busy. Kept in lockstep with reactive_controller.js's ACTIVE_ATTR — the ONE selector every wait keys off. A [data-reactive-active] presence check is the system twin of wait_for_turbo watching the Turbo progress bar.
"data-reactive-active"
Instance Method Summary collapse
-
#have_reactive_text(id, value) ⇒ Object
Assert (waiting) that the node with DOM id
idhas TEXTvalue, re-resolving by id each poll — the mirror/recap twin of have_reactive_value for a text sink (a reactive_computetext:/mirror target, a recap node) rather than a form field. -
#have_reactive_value(id, value, timeout: nil, wait: nil) ⇒ Object
Assert (waiting) that the field with DOM id
idhas valuevalue, RE-RESOLVING the field by its id on every poll and reading its live.valuePROPERTY (issue #204) — NOT the value attribute. -
#wait_for_reactive(timeout: nil) ⇒ Object
Block until the reactive layer is IDLE — every dispatch round trip and deferred render has settled and the marker is gone.
Instance Method Details
#have_reactive_text(id, value) ⇒ Object
Assert (waiting) that the node with DOM id id has TEXT value,
re-resolving by id each poll — the mirror/recap twin of
have_reactive_value for a text sink (a reactive_compute text:/mirror
target, a recap node) rather than a form field.
expect(page).to have_reactive_text("recap", "6 items")
92 93 94 |
# File 'lib/phlex/reactive/test_helpers/system.rb', line 92 def have_reactive_text(id, value, **) have_css("##{id}", text: value, **) end |
#have_reactive_value(id, value, timeout: nil, wait: nil) ⇒ Object
Assert (waiting) that the field with DOM id id has value value,
RE-RESOLVING the field by its id on every poll and reading its live
.value PROPERTY (issue #204) — NOT the value attribute. A
reactive_compute reducer paints a computed output with el.value = …
(the property); for a DISABLED / read-only output the value attribute
never reflects that, so an attribute-based matcher reads "" and fails.
Reading the property covers enabled AND disabled/computed fields — the
exact case this matcher was built for — and keeps the morph-immunity
(each poll re-finds the node by id, so a re-seed/morph that replaces the
input can't surface a stale node or a transient blank).
expect(page).to have_reactive_value("total", "6")
timeout: (or wait:) overrides Capybara's default max wait. The
have_ prefix is Capybara-matcher convention (have_field/have_css), NOT
a predicate — hence the PredicatePrefix disable, mirroring matchers.rb.
rubocop:disable Naming/PredicatePrefix
82 83 84 |
# File 'lib/phlex/reactive/test_helpers/system.rb', line 82 def have_reactive_value(id, value, timeout: nil, wait: nil) ReactiveValueMatcher.new(id, value, wait: timeout || wait) end |
#wait_for_reactive(timeout: nil) ⇒ Object
Block until the reactive layer is IDLE — every dispatch round trip and deferred render has settled and the marker is gone. The system-test twin of wait_for_turbo (which watches the Turbo progress bar, NOT a reactive morph/seed, so it can't cover this).
Implemented as a Capybara WAITING assertion (have_no_css on the document
element with the default max wait), so it re-checks the live DOM each poll
and raises a readable Capybara::ElementNotFound-style error if the layer
never settles inside timeout — never a bare sleep, never a stale read.
timeout: overrides Capybara.default_max_wait_time for a slow operation
(a deferred render behind a real job). Returns nil; call it as a barrier
BEFORE asserting a settled value if you are not already using one of the
waiting matchers below.
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/phlex/reactive/test_helpers/system.rb', line 53 def wait_for_reactive(timeout: nil) # Scope the check to <html> via the :xpath "/html" so the marker is read # on the document element the client writes it to — not a descendant. # assert_no_selector WAITS (retries) until the marker clears or the wait # budget elapses; a persistent marker fails LOUDLY with Capybara's own # timeout error rather than a silent pass. Called on `page` (the current # session) so it works regardless of whether the example group mixed in # Capybara::DSL. page.assert_no_selector(:xpath, "/html[@#{ACTIVE_MARKER}]", **wait_option(timeout)) nil end |