capybara-simulated 0.4.0 → 0.5.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 +4 -4
- data/README.md +37 -5
- data/exe/capybara-simulated +143 -0
- data/lib/capybara/simulated/browser.rb +570 -53
- data/lib/capybara/simulated/driver.rb +52 -6
- data/lib/capybara/simulated/js/bridge.bundle.js +11575 -5716
- data/lib/capybara/simulated/js/snapshot_stubs.js +34 -0
- data/lib/capybara/simulated/minitest.rb +65 -0
- data/lib/capybara/simulated/quickjs_runtime.rb +9 -0
- data/lib/capybara/simulated/rspec.rb +32 -0
- data/lib/capybara/simulated/runtime_shared.rb +26 -2
- data/lib/capybara/simulated/trace.rb +35 -2
- data/lib/capybara/simulated/trace_persistence.rb +48 -0
- data/lib/capybara/simulated/trace_viewer.html +408 -0
- data/lib/capybara/simulated/v8_runtime.rb +182 -17
- data/lib/capybara/simulated/version.rb +1 -1
- data/vendor/js/vendor.bundle.js +21 -10
- metadata +23 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 67e9168ef15e413c1d85b1805ea4d68f36cae09578af5fc539bd1613d52ac04d
|
|
4
|
+
data.tar.gz: 6214303ef25079d567bc91db43460eda49a54a292ed08021b98a81ce48af0c31
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8112cd3056184946f65739dfb30e76e55bee2a79f1058e3128bc8ae15f0b5790f195d0c289759518e667b69902962e70922af21f48dea6610744ab1093a10ca4
|
|
7
|
+
data.tar.gz: 53ccb66cb2bd4723d1e999ebd03b0a56bdbc83978834f82b66c128aa2c7e3ba1c4f5464c5965442104de94de2fbabe79e185a74f6e1aaa3cd2c2c2c2bfe68a26
|
data/README.md
CHANGED
|
@@ -200,11 +200,18 @@ end
|
|
|
200
200
|
|
|
201
201
|
### File output
|
|
202
202
|
|
|
203
|
-
|
|
204
|
-
RSpec
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
203
|
+
Require the test-framework integration in your `spec_helper` /
|
|
204
|
+
`rails_helper` (RSpec) or `test_helper` /
|
|
205
|
+
`application_system_test_case.rb` (Minitest):
|
|
206
|
+
|
|
207
|
+
```ruby
|
|
208
|
+
require 'capybara/simulated/rspec' # RSpec
|
|
209
|
+
require 'capybara/simulated/minitest' # Minitest / Rails system tests
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
With `CSIM_TRACE_DIR=/path/to/dir` set, each example that recorded a
|
|
213
|
+
trace is written to `<dir>/<slug>.json` after it runs; both integrations
|
|
214
|
+
are inert when the env var is unset.
|
|
208
215
|
|
|
209
216
|
```sh
|
|
210
217
|
CSIM_TRACE_DIR=tmp/csim-traces bundle exec rspec spec/system
|
|
@@ -214,6 +221,31 @@ The metadata block on each trace includes `title`, `file`, `outcome`
|
|
|
214
221
|
(`passed` / `failed`), and the exception message — enough to index a
|
|
215
222
|
CI artifact directory by failure.
|
|
216
223
|
|
|
224
|
+
### Viewing traces
|
|
225
|
+
|
|
226
|
+
The recorded JSON stays plain data; to look at one, render it into a
|
|
227
|
+
self-contained HTML viewer with the bundled CLI:
|
|
228
|
+
|
|
229
|
+
```sh
|
|
230
|
+
capybara-simulated trace tmp/csim-traces/checkout_flow.json
|
|
231
|
+
# wrote /tmp/checkout_flow.html (then opens it in your browser)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
By default the HTML is written to a temp file and opened in your
|
|
235
|
+
browser. The viewer works straight from `file://` — the trace JSON is
|
|
236
|
+
embedded inline, so no server is needed — and shows a step-by-step UI: a
|
|
237
|
+
timeline of actions, and per step the URL before/after, console output,
|
|
238
|
+
network requests, the error, and a rendered preview of the post-action
|
|
239
|
+
DOM snapshot. Its **Load JSON…** button / drag-and-drop swaps in any
|
|
240
|
+
other trace file.
|
|
241
|
+
|
|
242
|
+
`-o PATH` writes the HTML somewhere specific (`-o -` to stdout);
|
|
243
|
+
`--no-open` skips launching the browser. Browser launching uses
|
|
244
|
+
[launchy](https://rubygems.org/gems/launchy) when it's installed
|
|
245
|
+
(`gem 'launchy'`, recommended for reliable cross-platform / WSL opening)
|
|
246
|
+
and falls back to the platform opener (`xdg-open` / `open` / `start`)
|
|
247
|
+
otherwise.
|
|
248
|
+
|
|
217
249
|
### Programmatic
|
|
218
250
|
|
|
219
251
|
For finer control, call `driver.start_tracing(...)` /
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# capybara-simulated CLI. Currently one subcommand:
|
|
5
|
+
#
|
|
6
|
+
# capybara-simulated trace TRACE.json [-o OUT.html] [--no-open]
|
|
7
|
+
#
|
|
8
|
+
# Renders a trace JSON (produced by CSIM_TRACE_DIR / driver.stop_tracing)
|
|
9
|
+
# into a self-contained HTML viewer and opens it in your browser. The
|
|
10
|
+
# viewer embeds the JSON inline so it opens straight from file:// — no
|
|
11
|
+
# server, unlike a fetch/import-based loader (CORS blocks those for
|
|
12
|
+
# file:// origins). The persisted trace stays plain JSON; this turns one
|
|
13
|
+
# into a UI on demand.
|
|
14
|
+
|
|
15
|
+
require 'optparse'
|
|
16
|
+
require 'tmpdir'
|
|
17
|
+
|
|
18
|
+
# Prefer the library co-located with this executable. In an installed
|
|
19
|
+
# gem that's the gem's own lib (correct version); in a checkout it's the
|
|
20
|
+
# working tree — so `ruby exe/capybara-simulated` doesn't accidentally
|
|
21
|
+
# load an older *installed* capybara-simulated that predates this CLI.
|
|
22
|
+
lib = File.expand_path('../lib', __dir__)
|
|
23
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
|
24
|
+
require 'capybara/simulated/trace'
|
|
25
|
+
|
|
26
|
+
PROG = 'capybara-simulated'
|
|
27
|
+
|
|
28
|
+
# `file://` URL for a local path, percent-encoding each segment so a
|
|
29
|
+
# path with spaces / special chars stays a valid URI for launchy.
|
|
30
|
+
def file_url(path)
|
|
31
|
+
require 'cgi'
|
|
32
|
+
'file://' + path.split('/').map {|seg| CGI.escapeURIComponent(seg) }.join('/')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Hand the raw path (not a URL) to the platform opener; `system`'s array
|
|
36
|
+
# form needs no shell-quoting, so spaces are fine.
|
|
37
|
+
def open_with_platform(path)
|
|
38
|
+
cmd =
|
|
39
|
+
case RbConfig::CONFIG['host_os']
|
|
40
|
+
when /darwin/ then ['open', path]
|
|
41
|
+
when /mswin|mingw/ then ['cmd', '/c', 'start', '', path]
|
|
42
|
+
else ['xdg-open', path] # Linux / *BSD
|
|
43
|
+
end
|
|
44
|
+
system(*cmd)
|
|
45
|
+
rescue StandardError
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Open a local file in the default browser. Prefer launchy (handles
|
|
50
|
+
# macOS / Linux / Windows / WSL) when installed; on either a missing gem
|
|
51
|
+
# OR a launchy runtime failure (headless box, no opener), fall back to
|
|
52
|
+
# the platform opener.
|
|
53
|
+
def open_in_browser(path)
|
|
54
|
+
begin
|
|
55
|
+
require 'launchy'
|
|
56
|
+
Launchy.open(file_url(path))
|
|
57
|
+
return true
|
|
58
|
+
rescue LoadError
|
|
59
|
+
# launchy not installed
|
|
60
|
+
rescue StandardError
|
|
61
|
+
# launchy present but failed — try the platform opener below
|
|
62
|
+
end
|
|
63
|
+
open_with_platform(path)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def cmd_trace(argv)
|
|
67
|
+
out = nil
|
|
68
|
+
open = nil # nil → default (open), unless writing to stdout
|
|
69
|
+
parser = OptionParser.new do |o|
|
|
70
|
+
o.banner = "Usage: #{PROG} trace [options] TRACE.json\n\n" \
|
|
71
|
+
"Render TRACE.json into a self-contained HTML viewer and open it\n" \
|
|
72
|
+
"in your browser. By default the HTML goes to a temp file."
|
|
73
|
+
o.on('-o', '--output PATH', "write HTML to PATH instead of a temp file ('-' = stdout)") {|v| out = v }
|
|
74
|
+
o.on('--[no-]open', 'open the HTML in your browser (default: yes)') {|v| open = v }
|
|
75
|
+
o.on('-h', '--help') do
|
|
76
|
+
puts o
|
|
77
|
+
exit
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
begin
|
|
81
|
+
parser.parse!(argv)
|
|
82
|
+
rescue OptionParser::ParseError => e
|
|
83
|
+
warn e.message
|
|
84
|
+
warn parser.help
|
|
85
|
+
exit 1
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
input = argv.shift
|
|
89
|
+
unless input
|
|
90
|
+
warn parser.help
|
|
91
|
+
exit 1
|
|
92
|
+
end
|
|
93
|
+
unless File.file?(input)
|
|
94
|
+
warn "#{PROG}: no such file: #{input}"
|
|
95
|
+
exit 1
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
json = File.read(input)
|
|
99
|
+
begin
|
|
100
|
+
require 'json'
|
|
101
|
+
JSON.parse(json) # fail fast on a non-JSON / corrupt trace
|
|
102
|
+
rescue JSON::ParserError => e
|
|
103
|
+
warn "#{PROG}: #{input} is not valid JSON: #{e.message}"
|
|
104
|
+
exit 1
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
html = Capybara::Simulated::Trace.render_viewer(json)
|
|
108
|
+
|
|
109
|
+
if out == '-'
|
|
110
|
+
$stdout.write(html)
|
|
111
|
+
return
|
|
112
|
+
end
|
|
113
|
+
# Default output: a temp file named after the trace (re-runs overwrite).
|
|
114
|
+
out ||= File.join(Dir.tmpdir, File.basename(input).sub(/\.json\z/, '') + '.html')
|
|
115
|
+
File.write(out, html)
|
|
116
|
+
warn "wrote #{out}"
|
|
117
|
+
open_in_browser(File.expand_path(out)) unless open == false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def main(argv)
|
|
121
|
+
case argv.first
|
|
122
|
+
when 'trace'
|
|
123
|
+
cmd_trace(argv.drop(1))
|
|
124
|
+
when '-v', '--version'
|
|
125
|
+
require 'capybara/simulated/version'
|
|
126
|
+
puts Capybara::Simulated::VERSION
|
|
127
|
+
when nil, '-h', '--help'
|
|
128
|
+
puts <<~USAGE
|
|
129
|
+
Usage: #{PROG} <command> [options]
|
|
130
|
+
|
|
131
|
+
Commands:
|
|
132
|
+
trace TRACE.json render a trace JSON into a self-contained HTML viewer
|
|
133
|
+
|
|
134
|
+
Run `#{PROG} trace --help` for command options.
|
|
135
|
+
USAGE
|
|
136
|
+
else
|
|
137
|
+
warn "#{PROG}: unknown command: #{argv.first}"
|
|
138
|
+
warn "Run `#{PROG} --help`."
|
|
139
|
+
exit 1
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
main(ARGV)
|