Support multiple block arguments in sample block

https://github.com/icy-arctic-fox/spectator/issues/41#issuecomment-1010192486
This commit is contained in:
Michael Miller 2022-01-11 15:53:53 -07:00
parent c1841526d4
commit 4057089c20
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2
4 changed files with 30 additions and 11 deletions

View file

@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added ### Added
- Support string interpolation for example name/description. [#41](https://github.com/icy-arctic-fox/spectator/issues/41) - Support string interpolation for example name/description. [#41](https://github.com/icy-arctic-fox/spectator/issues/41)
- Support multiple block arguments in `sample` block (`Hash#each`). [#41](https://github.com/icy-arctic-fox/spectator/issues/41#issuecomment-1010192486)
### Changed ### Changed
- Source line reported by failure list changed to line containing `expect` instead of example start line. - Source line reported by failure list changed to line containing `expect` instead of example start line.

View file

@ -16,4 +16,14 @@ Spectator.describe "Spec metadata" do
expect(example.name).to eq("works with #{string}") expect(example.name).to eq("works with #{string}")
end end
end end
def self.a_hash
{"foo" => 42, "bar" => 123, "baz" => 7}
end
sample a_hash do |key, value|
it "works with #{key} = #{value}" do |example|
expect(example.name).to eq("works with #{key} = #{value}")
end
end
end end

View file

@ -95,18 +95,16 @@ module Spectator::DSL
::Spectator::DSL::Builder.start_iterative_group( ::Spectator::DSL::Builder.start_iterative_group(
\%collection, \%collection,
\{{collection.stringify}}, \{{collection.stringify}},
\{{block.args.empty? ? :nil.id : block.args.first.stringify}}, [\{{block.args.empty? ? "".id : block.args.map(&.stringify).splat}}] of String,
::Spectator::Location.new(\{{block.filename}}, \{{block.line_number}}, \{{block.end_line_number}}), ::Spectator::Location.new(\{{block.filename}}, \{{block.line_number}}, \{{block.end_line_number}}),
metadata metadata
) )
\{% if block %} \{% if block %}
\{% if block.args.size == 1 %} \{% for arg, i in block.args %}
let(\{{block.args.first}}) do |example| let(\{{arg}}) do |example|
example.group.as(::Spectator::ExampleGroupIteration(typeof(Group\%group.\%collection.first))).item example.group.as(::Spectator::ExampleGroupIteration(typeof(Group\%group.\%collection.first))).item[\{{i}}]
end end
\{% elsif block.args.size > 1 %}
\{% raise "Expected 1 argument for 'sample' block, but got #{block.args.size}" %}
\{% end %} \{% end %}
\{{block.body}} \{{block.body}}

View file

@ -13,8 +13,8 @@ module Spectator
# Initially, the builder will have no children and no hooks. # Initially, the builder will have no children and no hooks.
# The *name*, *location*, and *metadata* will be applied to the `ExampleGroup` produced by `#build`. # The *name*, *location*, and *metadata* will be applied to the `ExampleGroup` produced by `#build`.
# The *collection* is the set of items to create sub-nodes for. # The *collection* is the set of items to create sub-nodes for.
# The *iterator* is an optional name given to a single item in the collection. # The *iterators* is a list of optional names given to items in the collection.
def initialize(@collection : Enumerable(T), name : String? = nil, @iterator : String? = nil, def initialize(@collection : Enumerable(T), name : String? = nil, @iterators : Array(String) = [] of String,
location : Location? = nil, metadata : Metadata = Metadata.new) location : Location? = nil, metadata : Metadata = Metadata.new)
super(name, location, metadata) super(name, location, metadata)
end end
@ -38,10 +38,20 @@ module Spectator
# Constructs the name of an example group iteration. # Constructs the name of an example group iteration.
private def iteration_name(item) private def iteration_name(item)
if iterator = @iterator if item.is_a?(Tuple) && @iterators.size > 1
"#{iterator}: #{item.inspect}" item.zip?(@iterators).map do |(subitem, iterator)|
if iterator
"#{iterator}: #{subitem.inspect}"
else
subitem.inspect
end
end.join("; ")
else else
item.inspect if iterator = @iterators.first?
"#{iterator}: #{item.inspect}"
else
item.inspect
end
end end
end end
end end