# frozen_string_literal: true
module ParameterizedTesting
# {Input} represents a single test case for a parameterized test.
class Input
# @return [Integer] index of the input
attr_reader :index
# @return [Thread::Backtrace::Location] the location of the input { ... } block
attr_reader :location
# @return [Proc] the block to compute the value of this input
attr_reader :initializer
# @return [String, nil] description of the input
attr_reader :description
def initialize(index:, location:, initializer:, description:)
@index = index
@location = location
@initializer = initializer
@description = description
end
# Returns a human-readable label string.
# @return [String]
def label
"#{@description || "input[#{index}]"} (at line #{location.lineno})"
end
# Collects all input { ... } in a block.
# It is important to notice that this method collects inputs by actually #instance_executing
# the block in a dedicated context, in order to get the line number of input.
# In this context, all other method calls are ignored.
# @return [Array]
def self.collect(&)
inputs = []
Collector.new(inputs).instance_exec(&)
inputs
end
class Collector # :nodoc:
def initialize(inputs)
@inputs = inputs
@next_index = 0
end
def input(description = nil, &initializer)
index = @next_index
@next_index += 1
location = caller_locations(1, 1).first
@inputs << Input.new(index:, location:, initializer:, description:)
end
def method_missing(_name, ...)
# do nothing
end
def respond_to_missing?(_name, _include_private)
true
end
end
private_constant :Collector
end
end