module RuboCop::Cop::RSpec::AggregateExamples::Its

@example `its`

# Supports regular `its` call with an attribute/method name,
# or a chain of methods expressed as a string with dots.

its(:one) { is_expected.to be(true) }
its('two') { is_expected.to be(false) }
its('phone_numbers.size') { is_expected.to be 2 }

@example `its` with single-element array argument

# Also supports single-element array argument.

its(['headers']) { is_expected.to include(encoding: 'text') }

@example `its` with multi-element array argument is ambiguous

# Does not support `its` with multi-element array argument due to
# an ambiguity. Transformation depends on the type of the subject:
# - a Hash: `hash[element1][element2]...`
# - and arbitrary type: `hash[element1, element2, ...]`
# It is impossible to infer the type to propose a proper correction.

its(['ambiguous', 'elements']) { ... }

@example `its` with metadata

its('header', html: true) { is_expected.to include(text: 'hello') }

Private Instance Methods

example_metadata(example) click to toggle source
Calls superclass method
# File lib/test_prof/cops/rspec/aggregate_examples/its.rb, line 62
def example_metadata(example)
  return super unless its?(example.send_node)

  # First parameter to `its` is not metadata.
  example.send_node.arguments[1..-1]
end
its?(node) click to toggle source
# File lib/test_prof/cops/rspec/aggregate_examples/its.rb, line 69
def its?(node)
  node.method_name == :its
end
new_body(node) click to toggle source

It's impossible to aggregate `its` body as is, it needs to be converted to `expect(subject.something).to …`

Calls superclass method
# File lib/test_prof/cops/rspec/aggregate_examples/its.rb, line 43
def new_body(node)
  return super unless its?(node)

  transform_its(node.body, node.send_node.arguments)
end
transform_its(body, arguments) click to toggle source
# File lib/test_prof/cops/rspec/aggregate_examples/its.rb, line 49
def transform_its(body, arguments)
  argument = arguments.first
  replacement = case argument.type
                when :array
                  key = argument.values.first
                  "expect(subject[#{key.source}])"
                else
                  property = argument.value
                  "expect(subject.#{property})"
  end
  body.source.gsub(/is_expected|are_expected/, replacement)
end