Module: Phlex::Reactive::TestHelpers::System
- Defined in:
- lib/phlex/reactive/test_helpers/system.rb
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) ⇒ Object
Assert (waiting) that the field with DOM id
idhas valuevalue, RE-RESOLVING the field by its id on every poll. -
#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")
89 90 91 |
# File 'lib/phlex/reactive/test_helpers/system.rb', line 89 def have_reactive_text(id, value, **) have_css("##{id}", text: value, **) end |
#have_reactive_value(id, value) ⇒ Object
Assert (waiting) that the field with DOM id id has value value,
RE-RESOLVING the field by its id on every poll. Use it as the barrier for
a value that settles a beat after the triggering action — a reactive_compute
re-seed or a morph replaces the input node AFTER the action returns, so a
node captured by find would go stale; keying on the id and letting
Capybara re-query each cycle is immune to that.
expect(page).to have_reactive_value("total", "6")
A thin, intention-revealing wrapper over Capybara's field matcher scoped
by id — the value the app is waiting on, named for what it is. 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
79 80 81 |
# File 'lib/phlex/reactive/test_helpers/system.rb', line 79 def have_reactive_value(id, value, **) have_field(id, with: value, **) 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 |