Skip to content

Commit

Permalink
Fix location filtering.
Browse files Browse the repository at this point in the history
For examples defined in an example group in a shared
example group in an external file, it did not work
properly because the location filtering only considered
the immediate parent example group’s file path, which
did not match the passed location filter. By considering
all parent example group file paths, it filters properly.

Fixes #835.

Note: this commit began from a failing spec that
originated with @soulcutter and was fixed up by
@xaviershay.
  • Loading branch information
myronmarston committed Jan 8, 2015
1 parent 2c1a4a5 commit 10791a2
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 10 deletions.
3 changes: 3 additions & 0 deletions Changelog.md
Expand Up @@ -54,6 +54,9 @@ Bug Fixes:
* When a shared example defined in an external file fails, use the host
example group (from a loaded spec file) for the re-run command to
ensure the command will actually work. (Myron Marston, #1835)
* Fix location filtering to work properly for examples defined in
a nested example group within a shared example group defined in
an external file. (Bradley Schaefer, Xavier Shay, Myron Marston, #1837)

### 3.1.8 Development

Expand Down
12 changes: 6 additions & 6 deletions lib/rspec/core/metadata_filter.rb
Expand Up @@ -43,9 +43,8 @@ def filter_applies_to_any_value?(key, value, metadata)
end

def location_filter_applies?(locations, metadata)
# it ignores location filters for other files
line_number = example_group_declaration_line(locations, metadata)
line_number ? line_number_filter_applies?(line_number, metadata) : true
line_numbers = example_group_declaration_lines(locations, metadata)
line_numbers ? line_number_filter_applies?(line_numbers, metadata) : true
end

def line_number_filter_applies?(line_numbers, metadata)
Expand All @@ -57,9 +56,10 @@ def relevant_line_numbers(metadata)
Metadata.ascend(metadata).map { |meta| meta[:line_number] }
end

def example_group_declaration_line(locations, metadata)
return nil unless (parent = metadata.fetch(:example_group) { metadata[:parent_example_group] })
locations[File.expand_path(parent[:file_path])]
def example_group_declaration_lines(locations, metadata)
FlatMap.flat_map(Metadata.ascend(metadata)) do |meta|
locations[File.expand_path(meta[:file_path])]
end.uniq
end

def filters_apply?(key, value, metadata)
Expand Down
27 changes: 27 additions & 0 deletions spec/integration/shared_example_rerun_commands_spec.rb
Expand Up @@ -36,4 +36,31 @@ def run_rerun_command_for_failing_spec
command = last_cmd_stdout[/Failed examples:\s+rspec (\S+) #/, 1]
run_command command
end

context "with a shared example containing a context in a separate file" do
it "runs the example nested inside the shared" do
write_file_formatted 'spec/shared_example.rb', """
RSpec.shared_examples_for 'a shared example' do
it 'succeeds' do
end
context 'with a nested context' do
it 'succeeds (nested)' do
end
end
end
"""

write_file_formatted 'spec/simple_spec.rb', """
require File.join(File.dirname(__FILE__), 'shared_example.rb')
RSpec.describe 'top level' do
it_behaves_like 'a shared example'
end
"""

run_command 'spec/simple_spec.rb:3 -fd'
expect(last_cmd_stdout).to match(/2 examples, 0 failures/)
end
end
end
4 changes: 0 additions & 4 deletions spec/rspec/core/metadata_filter_spec.rb
Expand Up @@ -84,10 +84,6 @@ def filter_applies?(key, value, metadata)
end
end

it "ignores location filters for other files" do
expect(filter_applies?(:locations, {"/path/to/other_spec.rb" => [3,5,7]}, example_metadata)).to be_truthy
end

it "matches a proc with no arguments that evaluates to true" do
expect(filter_applies?(:if, lambda { true }, example_metadata)).to be_truthy
end
Expand Down
14 changes: 14 additions & 0 deletions spec/support/aruba_support.rb
Expand Up @@ -34,6 +34,20 @@ def run_command(cmd)
stdout.write(@last_cmd_stdout)
stderr.write(@last_cmd_stderr)
end

def write_file_formatted(file_name, contents)
# remove blank line at the start of the string and
# strip extra indentation.
formatted_contents = unindent(contents.sub(/\A\n/, ""))
write_file file_name, formatted_contents
end

# Intended for use with indented heredocs.
# taken from Ruby Tapas:
# https://rubytapas.dpdcart.com/subscriber/post?id=616#files
def unindent(s)
s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, "")
end
end

RSpec.configure do |c|
Expand Down

0 comments on commit 10791a2

Please sign in to comment.