capybara-simulated 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f13ed6ad46dbf9e9537d89bc384c5ef7386242fa28c9e4fc549b1fda04fd7d8
4
- data.tar.gz: 2cd0e24a3eb808728d7a533369b3ac2beafc99accf8fa4c1ec9f9b4af1b60f03
3
+ metadata.gz: 02f56bfd3215e67c4a8faa799352e0ae3c399557f928926cafcdc9dde7dd2b9c
4
+ data.tar.gz: 12e88e441d93de921d0727bfae9e3728cc56d100f8e32e525e37e21a28f0e273
5
5
  SHA512:
6
- metadata.gz: b26b98c5b972110458565e0a60b6292cd6a446e331636d662e34aed1a4c9456a130aa67f52499f4954820c30a0b9ae22dff2870b25f50556bb577a37a719b042
7
- data.tar.gz: cf2cb128d6187eff1fa4c3fd06b928e933cbc1d4c0ec062f4885f3bd31ad847136e8736e604879e0fdb9eba629647802133265d596e3abc451238f499dfb0be3
6
+ metadata.gz: a1f22b4a5d7ffec1b33080982aa169b5b3356c014d49a399de4cf5b5a430021eec7fb1ba4d624b00769640ffdcd314e55df765afdd44ac90575c88cb137519c9
7
+ data.tar.gz: 04d95fd0e7215800124d4d81de11247b814e352c0b511d550bb9bb1557a0af069c1261b52a570e82f6100cab90e07d627b18b7a02267f193dd92c4c98c92e2cd
data/README.md CHANGED
@@ -14,6 +14,59 @@ resolve through css-select (CSS) and xpathway (XPath) running in the
14
14
  same context as the page's JS, so `find` / `has_css?` / `within` see
15
15
  exactly the tree the app sees.
16
16
 
17
+ ## Is it a fit?
18
+
19
+ **A good fit when** your tests are JavaScript-driven but don't depend on
20
+ visual layout:
21
+
22
+ - **Fast, in-process** — no Chrome to boot, no WebDriver, no Node
23
+ toolchain. About **1.9× faster** than a headless browser on
24
+ server-rendered / Hotwire apps, and roughly at parity on JS-heavy SPAs
25
+ (with rusty_racer).
26
+ - **Deterministic** — a virtual clock and synchronous in-process execution
27
+ remove the wall-clock timing, network, and rendering races that make
28
+ headless-browser suites flaky.
29
+ - **Real front-end JS runs**: inline `<script>` + event handlers,
30
+ MutationObserver, custom elements, `<template>`, Shadow DOM, ES modules
31
+ + importmap, **Hotwire (Stimulus + Turbo)**, Trix.
32
+ - **Drop-in**: the Capybara DSL is unchanged — register `:simulated` and
33
+ go. Just this gem plus one JS-engine gem.
34
+ - **Held to spec**: a vendored
35
+ [web-platform-tests](https://github.com/web-platform-tests/wpt)
36
+ conformance gate plus five real app suites (see [Status](#status)).
37
+
38
+ **Reach for a real browser** (Selenium / Cuprite) **when** your tests need
39
+ what this driver doesn't simulate **by design** — there's no rendering
40
+ engine or real network stack, the same ground Selenium covers via a real
41
+ browser:
42
+
43
+ - **Pixel layout** — `getBoundingClientRect()` returns zeros and
44
+ `elementFromPoint()` isn't implemented, so visual hit-testing,
45
+ coordinate drag-and-drop, and sticky-scroll math don't work.
46
+ - **Real networking** — `fetch` / XHR are synchronous through Rack: no
47
+ streaming, no HTTP concurrency. (`EventSource` and `WebSocket` *do*
48
+ work — they ride real reader threads / the in-process `rack.hijack`
49
+ socket; see below.)
50
+ - **Screenshots**.
51
+
52
+ **`within_frame` / `switch_to_frame`** work on the V8 (rusty_racer) engine:
53
+ each `<iframe>` runs its own scripts in its own per-frame realm, and the DSL
54
+ routes finds, reads, interactions, `evaluate_script`, and self-targeted
55
+ navigation (a link or form submit inside the frame) into the active frame —
56
+ nested frames included. (QuickJS keeps a same-realm fallback, so
57
+ `within_frame` is V8-only.)
58
+
59
+ **Multiple windows / tabs** work on both engines: each window is its own
60
+ Browser + JS VM (own DOM, sessionStorage, history; cookies + localStorage
61
+ shared). `open_new_window` / `within_window` / `switch_to_window` /
62
+ `window_opened_by` drive them, and JS `window.open` opens a real window,
63
+ `window.opener` points back to the opener, and `postMessage` is delivered
64
+ across windows. (`target="_blank"` defaults to no-opener, matching modern
65
+ browsers; cross-window `postMessage` data is JSON-shaped, not a full
66
+ structured clone.)
67
+
68
+ See [Known limits](#known-limits) for the full picture.
69
+
17
70
  ## Status
18
71
 
19
72
  The architecture and behaviour are stable. Correctness is held to two
@@ -305,15 +358,44 @@ referenced page-specific DOM.
305
358
  but there's no real network, no streaming, no `Request#body`
306
359
  ReadableStream, and no concurrent requests. XHR is implemented
307
360
  with the same Rack pass-through.
308
- - **Multi-window** is URL-tracking only `target="_blank"` clicks
309
- open a window-handle and `current_window` / `switch_to_window`
310
- work, but each aux window only records its URL (no per-window JS
311
- context or cross-window `postMessage`).
312
- - **`within_frame`, WebSocket, screenshots, and drag pixel
313
- coordinates** are out of scope use Selenium / Cuprite. There's no
314
- frame-switching DSL to drive a test into an `<iframe>`, though an
315
- iframe's own scripts do run, in a per-frame JS realm. (EventSource
316
- and Web Workers *are* implemented.)
361
+ - **WebSocket** works in-process: `new WebSocket(url)` rides the
362
+ `rack.hijack` socket the Rack app hijacks, with a hand-rolled RFC6455
363
+ client (handshake + subprotocol negotiation, masked client frames,
364
+ ping/pong, close handshake). Frames deliver as `message` events when
365
+ the page next settles, like SSE. **Action Cable** works end-to-end on
366
+ this: the real `@rails/actioncable` consumer connects, subscribes, and
367
+ receives server broadcasts (so `turbo_stream_from` live updates are
368
+ reachable) Action Cable hijacks the connection just as csim drives
369
+ it. Caveats: server pushes land at settle (not instant); the app must
370
+ use the **async / in-process** Cable adapter (a real Redis adapter
371
+ would need real Redis); binary frames are V8-only (QuickJS corrupts
372
+ raw bytes across the host boundary — text, hence Action Cable, is fine
373
+ on both). `EventSource` and Web Workers are likewise implemented.
374
+ - **Screenshots and drag pixel coordinates** are out of scope by
375
+ design — use Selenium / Cuprite.
376
+ - **`within_frame` / `switch_to_frame`** work on the V8 engine: each
377
+ `<iframe>` runs in its own per-frame realm and the DSL routes finds,
378
+ reads, interactions, `evaluate_script`, and self-targeted navigation
379
+ (link / form submit) into the active frame (nested frames included) — the
380
+ frame's realm is rebuilt from the fetched document, leaving the top page
381
+ untouched. `_top` navigates the main page; a `_parent` target from a
382
+ frame nested ≥2 levels falls back to navigating the main page, and
383
+ cross-origin frame locality resolves against the main origin. QuickJS has
384
+ no nested browsing context, so `within_frame` raises there.
385
+ - **Multiple windows / tabs** work on both engines: each window is its own
386
+ Browser + JS VM (own DOM, sessionStorage, history; cookies + localStorage
387
+ shared across windows). `open_new_window` / `within_window` /
388
+ `switch_to_window` / `window_opened_by` drive them; JS `window.open` opens
389
+ a real window, `window.opener` links back, and `postMessage` is routed
390
+ across windows (delivered as a `message` event when the target window next
391
+ settles). Caveats: `target="_blank"` opens with no opener (modern-browser
392
+ no-opener default); cross-window `postMessage` data is JSON-shaped, not a
393
+ full structured clone (no `DataCloneError`, `undefined`→`null`) — but a
394
+ buffer in the `transfer` list moves **zero-copy** (its backing store crosses
395
+ isolates by token and the source is detached); and only the active window's
396
+ event loop runs, so a message is delivered when you switch to its window.
397
+ Window viewport APIs (`maximize` / `fullscreen` /
398
+ pixel-exact `resize_to`) are no-ops — no layout engine.
317
399
 
318
400
  ## Architecture
319
401