Module: RSpecTracer::RSpec::Metadata Private

Defined in:
lib/rspec_tracer/rspec/metadata.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.

Per-example tracking DSL. Reads the ‘tracks:` metadata key off an example and its ancestor example groups and emits a normalized union of declared file globs + env-var names.

DSL shape (user-facing):

RSpec.describe 'AdminController',
               tracks: { files: 'app/policies/**/*.rb', env: 'ROLE_CONFIG' } do
  ...
end

Values for ‘:files` and `:env` accept either a single String or an Array of Strings. Nested groups each contribute their own tracks hash; the union (not the replace) is what the example inherits. RSpec’s built-in metadata cascade uses Hash#merge which would clobber a parent ‘tracks:` with a child `tracks:` on a shared key - almost never the user’s intent. ‘tracks_for` bypasses the auto-cascade and walks ancestors explicitly.

Returns ‘{ files: Set<String>, env: Set<String> }`. Empty sets when nothing is declared - callers can short-circuit on `result.empty? && result.empty?` to skip the attribution/env-snapshot plumbing.

Pure-function (module-level, no state). Safe to call from the RunnerHook filter loop without synchronization.

Constant Summary collapse

TRACKS_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Internal constant.

:tracks
FILES_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Internal constant.

:files
ENV_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Internal constant.

:env

Class Method Summary collapse

Class Method Details

.collect(parent_groups, files, envs) ⇒ 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.

parent_groups returns outer-first. Walk from outer to inner so the set-union is order-agnostic anyway; the order is documented for future readers who need it deterministic.



63
64
65
66
67
# File 'lib/rspec_tracer/rspec/metadata.rb', line 63

def self.collect(parent_groups, files, envs)
  parent_groups.reverse_each do |group|
    merge_hash(group.[TRACKS_KEY], files, envs)
  end
end

.merge_hash(tracks, files, envs) ⇒ 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.

A ‘tracks:` value of nil, non-Hash, or an empty Hash contributes nothing. Non-Hash values are silently ignored - tolerating user typos over raising is consistent with the rest of the DSL surface (add_filter, coverage_track_files).



73
74
75
76
77
78
# File 'lib/rspec_tracer/rspec/metadata.rb', line 73

def self.merge_hash(tracks, files, envs)
  return unless tracks.is_a?(Hash)

  normalize(tracks[FILES_KEY]).each { |v| files << v }
  normalize(tracks[ENV_KEY]).each { |v| envs << v }
end

.normalize(value) ⇒ 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.

String -> [String]; Array -> itself; anything else -> []. nil, empty-string, and blank values are filtered so ‘tracks: { files: ”, env: nil }` doesn’t inject empty entries into the attribution set.



84
85
86
87
88
89
90
91
92
93
# File 'lib/rspec_tracer/rspec/metadata.rb', line 84

def self.normalize(value)
  case value
  when String
    value.empty? ? [] : [value]
  when Array
    value.map(&:to_s).reject(&:empty?)
  else
    []
  end
end

.tracks_for(example) ⇒ 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.

Keep methods module-level via ‘def self.x` (not module_function) so mutant can observe them - module_function attaches the methods to an anonymous singleton that Method#source_location can’t trace (memory: feedback_mutation_friendly_modules).



50
51
52
53
54
55
56
57
58
# File 'lib/rspec_tracer/rspec/metadata.rb', line 50

def self.tracks_for(example)
  files = Set.new
  envs = Set.new

  collect(example.example_group.parent_groups, files, envs)
  merge_hash(example.[TRACKS_KEY], files, envs)

  { FILES_KEY => files, ENV_KEY => envs }
end