Module: RSpec::Paramz::ExampleGroupMethods

Included in:
Core::ExampleGroup
Defined in:
lib/rspec/paramz.rb

Instance Method Summary collapse

Instance Method Details

#paramz(*args, &block) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rspec/paramz.rb', line 7

def paramz(*args, &block)
  unless block_given?
    raise ArgumentError, "No block given to paramz."
  end

  labels = args.first
  labels = labels.call if labels.respond_to?(:call)
  args[1..].each do |arg|
    location = arg.source_location
    source = spec_file_content(location.first).each_line.to_a[location[1] - 1].strip.delete_suffix(",")
    result = Prism.parse(source)
    lambda_node = result.value.compact_child_nodes.first.compact_child_nodes.first
    array_nodes = lambda_node.body.compact_child_nodes.first
    nodes = array_nodes.elements

    texts = nodes.map do |node|
      range = node.location.start_offset...node.location.end_offset
      source.byteslice(range)
    end

    context_name =
      "[#{[labels, texts].transpose.map {|label, text| "#{label} = #{text}" }.join(" | ")}]"

    context(context_name) do
      nodes.each.with_index do |node, index|
        let(labels[index]) do
          if node.type == :true_node
            true
          elsif node.type == :false_node
            false
          elsif node.type == :nil_node
            nil
          elsif node.type == :symbol_node
            node.value.to_sym
          elsif node.type == :string_node
            node.unescaped
          elsif node.type == :array_node
            range = node.opening_loc.start_offset...node.closing_loc.end_offset
            eval(source.byteslice(range)) # rubocop:disable Security/Eval
          elsif node.respond_to?(:value)
            node.value
          elsif node.respond_to?(:content)
            node.content
          else
            loc = node.location
            eval(source[loc.start_character_offset...loc.end_code_units_offset]) # rubocop:disable Security/Eval
          end
        end
      end

      module_exec(&block)

      after(:each) do |example|
        if example.exception
          location = arg.source_location
          example.exception.backtrace.push("failed paramz: #{location.first}:#{location.last}")
        end
      end
    end
  end
end