Module: RSpecTracer::CLI::Explain Private
- Defined in:
- lib/rspec_tracer/cli/explain.rb
Overview
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
‘rspec-tracer explain <example>` — show why a given example is scheduled to run or skip on the next rspec invocation. Backend- agnostic: dispatches through Storage::Backend.build so `storage_backend :sqlite` resolves the latest run from the meta table instead of the JsonBackend-only `last_run.json` file.
Class Method Summary collapse
-
.dig_meta(meta, *keys) ⇒ Object
private
Look up a nested key from a Hash, tolerating both String and Symbol storage at each level.
-
.fetch_meta(meta, *keys) ⇒ Object
private
Look up a key from a Hash, tolerating both String and Symbol storage.
-
.find_example(all_examples, query) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.format_lines(meta) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.load_snapshot(cache_path, stderr) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.no_match(query, all_examples, stderr) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.print_dependency_summary(stdout, meta, snapshot) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.print_explanation(stdout, meta, snapshot) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.print_help(stdout) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.run(args, stdout: $stdout, stderr: $stderr) ⇒ Integer
private
Exit status (0 = explanation printed, 1 = example not found / cache missing).
Class Method Details
.dig_meta(meta, *keys) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Look up a nested key from a Hash, tolerating both String and Symbol storage at each level. See fetch_meta for rationale.
138 139 140 141 142 143 144 |
# File 'lib/rspec_tracer/cli/explain.rb', line 138 def self.(, *keys) keys.reduce() do |acc, k| break nil if acc.nil? || !acc.is_a?(::Hash) acc[k] || acc[k.to_sym] end end |
.fetch_meta(meta, *keys) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Look up a key from a Hash, tolerating both String and Symbol storage. Snapshot Hashes round-tripped through JSON yield String keys; the post-#182 msgpack serializer preserves Symbol keys end-to-end, so callers can’t assume either shape.
125 126 127 128 129 130 131 132 133 134 |
# File 'lib/rspec_tracer/cli/explain.rb', line 125 def self.(, *keys) keys.each do |k| v = [k] return v unless v.nil? sym_value = [k.to_sym] return sym_value unless sym_value.nil? end nil end |
.find_example(all_examples, query) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
87 88 89 90 91 92 93 94 95 |
# File 'lib/rspec_tracer/cli/explain.rb', line 87 def self.find_example(all_examples, query) return all_examples[query] if all_examples.key?(query) all_examples.find do |id, | = {} unless .is_a?(::Hash) desc = (, 'full_description') || (, 'description') || '' id.include?(query) || desc.include?(query) end&.last end |
.format_lines(meta) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/rspec_tracer/cli/explain.rb', line 107 def self.format_lines() id = (, 'example_id', 'id') || '<unknown>' file = (, 'rerun_file_name', 'file_name') line = (, 'rerun_line_number', 'line_number') status = (, 'execution_result', 'status') || (, 'status') || 'unknown' [ "id: #{id}", "description: #{(, 'full_description', 'description')}", "location: #{file}:#{line}", "last status: #{status}", "run reason: #{(, 'run_reason') || '<not recorded>'}" ] end |
.load_snapshot(cache_path, stderr) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/rspec_tracer/cli/explain.rb', line 45 def self.load_snapshot(cache_path, stderr) backend = Storage::Backend.build(cache_path: cache_path, configuration: RSpecTracer) run_id = backend.last_run_id if run_id.nil? || run_id.to_s.empty? stderr.puts "explain: no cache yet at #{cache_path} — run rspec first" return nil end snapshot = backend.load_graph(schema_version: Storage::Schema::CURRENT) if snapshot.nil? stderr.puts "explain: cache at #{cache_path} is incompatible with this rspec-tracer; next rspec run is cold" return nil end snapshot end |
.no_match(query, all_examples, stderr) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
64 65 66 67 68 |
# File 'lib/rspec_tracer/cli/explain.rb', line 64 def self.no_match(query, all_examples, stderr) stderr.puts "explain: no example matching #{query.inspect}" stderr.puts " cache has #{all_examples.size} examples; pass an example_id or substring of description" 1 end |
.print_dependency_summary(stdout, meta, snapshot) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
148 149 150 151 152 153 154 155 |
# File 'lib/rspec_tracer/cli/explain.rb', line 148 def self.print_dependency_summary(stdout, , snapshot) id = (, 'example_id', 'id') deps = snapshot.dependency || {} files = Array(deps[id]) stdout.puts "dependencies: #{files.size} files tracked" files.first(10).each { |f| stdout.puts " - #{f}" } stdout.puts " ... (#{files.size - 10} more)" if files.size > 10 end |
.print_explanation(stdout, meta, snapshot) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
99 100 101 102 103 |
# File 'lib/rspec_tracer/cli/explain.rb', line 99 def self.print_explanation(stdout, , snapshot) = {} unless .is_a?(::Hash) format_lines().each { |line| stdout.puts line } print_dependency_summary(stdout, , snapshot) end |
.print_help(stdout) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/rspec_tracer/cli/explain.rb', line 72 def self.print_help(stdout) stdout.puts <<~HELP Usage: rspec-tracer explain <example_id_or_substring> Show why an example is scheduled to run or skip. Matches against example_id exactly first, then falls back to a substring match on the example's full_description. Backend-aware: works under `storage_backend :json` (default) and `storage_backend :sqlite`. Requires a prior rspec run. HELP 0 end |
.run(args, stdout: $stdout, stderr: $stderr) ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns exit status (0 = explanation printed, 1 = example not found / cache missing).
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rspec_tracer/cli/explain.rb', line 24 def self.run(args, stdout: $stdout, stderr: $stderr) return print_help(stdout) if args.empty? || args.include?('-h') || args.include?('--help') require 'rspec_tracer/load_config' cache_path = RSpecTracer.cache_path snapshot = load_snapshot(cache_path, stderr) return 1 if snapshot.nil? match = find_example(snapshot.all_examples, args.first) return no_match(args.first, snapshot.all_examples, stderr) if match.nil? print_explanation(stdout, match, snapshot) 0 rescue StandardError => e stderr.puts "explain: #{e.class}: #{e.}" 1 end |