Class: Capybara::Simulated::Trace
- Inherits:
-
Object
- Object
- Capybara::Simulated::Trace
- Defined in:
- lib/capybara/simulated/trace.rb
Overview
Per-test trace of Capybara actions with DOM snapshots, console output, and network requests interleaved. JSON output, one file per test — downstream tooling builds whatever viewer it wants.
Off by default. ‘CSIM_TRACE_DIR=/path/to/dir` enables auto-mode via `Browser#record_action`; the RSpec hook in `csim_rspec.rb` persists with a slugged filename. Programmatic activation is via `Driver#start_tracing` / `#stop_tracing`.
Defined Under Namespace
Classes: Step
Constant Summary collapse
- VIEWER_TEMPLATE_PATH =
File.('trace_viewer.html', __dir__)
- VIEWER_DATA_TOKEN =
'__CSIM_TRACE_DATA__'
Instance Attribute Summary collapse
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
-
#steps ⇒ Object
readonly
Returns the value of attribute steps.
Class Method Summary collapse
-
.render_viewer(json_text) ⇒ Object
Render the self-contained HTML viewer for a trace JSON string, embedding it inline (the ‘capybara-simulated trace` CLI is the caller).
Instance Method Summary collapse
- #begin_step(kind, description:, url_before: nil) ⇒ Object
- #empty? ⇒ Boolean
- #finish_step(url_after: nil, dom_after: nil, error: nil) ⇒ Object
-
#initialize(metadata: {}) ⇒ Trace
constructor
A new instance of Trace.
-
#log_console(severity, message) ⇒ Object
Pushed from ‘Browser#log_console` (the JS bridge’s ‘console.*` host-fn target) and `Browser#rack_request` (network).
- #log_network(method, url, status, content_type: nil, size: nil, duration_ms: nil, redirected: nil, request_headers: nil, request_body: nil, response_headers: nil, response_body: nil) ⇒ Object
- #to_h ⇒ Object
- #to_json(*args) ⇒ Object
- #write_json(path) ⇒ Object
Constructor Details
#initialize(metadata: {}) ⇒ Trace
Returns a new instance of Trace.
52 53 54 55 56 57 58 59 |
# File 'lib/capybara/simulated/trace.rb', line 52 def initialize(metadata: {}) @steps = [] @metadata = @started_at = monotonic_ms @console_buf = [] @network_buf = [] @open_step = nil end |
Instance Attribute Details
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
50 51 52 |
# File 'lib/capybara/simulated/trace.rb', line 50 def @metadata end |
#steps ⇒ Object (readonly)
Returns the value of attribute steps.
50 51 52 |
# File 'lib/capybara/simulated/trace.rb', line 50 def steps @steps end |
Class Method Details
.render_viewer(json_text) ⇒ Object
Render the self-contained HTML viewer for a trace JSON string, embedding it inline (the ‘capybara-simulated trace` CLI is the caller). `</` → `</` so an embedded `</script>` inside a DOM snapshot can’t close the data block early — still valid JSON (‘/` is a legal JSON escape for `/`). The whole point of inline embedding over fetch / `import … with { type: ’json’ }‘ is that the result opens straight from `file://` with no server (module / fetch loads are CORS-blocked for `file://` origins).
43 44 45 46 47 48 |
# File 'lib/capybara/simulated/trace.rb', line 43 def self.render_viewer(json_text) template = (@viewer_template ||= File.read(VIEWER_TEMPLATE_PATH)) # Block form: the replacement is taken literally, so backslashes # in the JSON aren't interpreted as regexp backreferences. template.sub(VIEWER_DATA_TOKEN) { json_text.to_s.gsub('</', '<\/') } end |
Instance Method Details
#begin_step(kind, description:, url_before: nil) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/capybara/simulated/trace.rb', line 90 def begin_step(kind, description:, url_before: nil) finish_step if @open_step @open_step = { kind: kind, description: description, url_before: url_before, start_ms: monotonic_ms } @console_buf = [] @network_buf = [] end |
#empty? ⇒ Boolean
123 |
# File 'lib/capybara/simulated/trace.rb', line 123 def empty? = @steps.empty? |
#finish_step(url_after: nil, dom_after: nil, error: nil) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/capybara/simulated/trace.rb', line 102 def finish_step(url_after: nil, dom_after: nil, error: nil) return unless @open_step s = @open_step @steps << Step.new( index: @steps.size, kind: s[:kind], description: s[:description], url_before: s[:url_before], url_after: url_after, dom_after: dom_after, console: @console_buf, network: @network_buf, elapsed_ms: (s[:start_ms] - @started_at).round, duration_ms: (monotonic_ms - s[:start_ms]).round, error: error ) @open_step = nil @console_buf = [] @network_buf = [] end |
#log_console(severity, message) ⇒ Object
Pushed from ‘Browser#log_console` (the JS bridge’s ‘console.*` host-fn target) and `Browser#rack_request` (network). Entries land on the currently-open step; outside a step they’re dropped (boot noise, post-test cleanup).
65 66 67 68 |
# File 'lib/capybara/simulated/trace.rb', line 65 def log_console(severity, ) return unless @open_step @console_buf << {severity: severity.to_s, message: .to_s} end |
#log_network(method, url, status, content_type: nil, size: nil, duration_ms: nil, redirected: nil, request_headers: nil, request_body: nil, response_headers: nil, response_body: nil) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/capybara/simulated/trace.rb', line 70 def log_network(method, url, status, content_type: nil, size: nil, duration_ms: nil, redirected: nil, request_headers: nil, request_body: nil, response_headers: nil, response_body: nil) return unless @open_step @network_buf << { method: method.to_s, url: url.to_s, status: status, content_type: content_type, size: size, duration_ms: duration_ms, redirected: redirected, request_headers: request_headers, request_body: request_body, response_headers: response_headers, response_body: response_body }.compact # drop fields the caller couldn't determine, keeping entries lean end |
#to_h ⇒ Object
125 126 127 |
# File 'lib/capybara/simulated/trace.rb', line 125 def to_h {version: 1, metadata: @metadata, steps: @steps.map(&:to_h)} end |
#to_json(*args) ⇒ Object
129 |
# File 'lib/capybara/simulated/trace.rb', line 129 def to_json(*args) = JSON.generate(to_h, *args) |
#write_json(path) ⇒ Object
131 132 133 134 135 |
# File 'lib/capybara/simulated/trace.rb', line 131 def write_json(path) FileUtils.mkdir_p(File.dirname(path)) File.write(path, to_json) path end |