Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 0a4937b

Browse files
committed
Apply tag filters only to files not having an id or location filter.
Fixes #1889.
1 parent e4a2897 commit 0a4937b

File tree

4 files changed

+85
-19
lines changed

4 files changed

+85
-19
lines changed

lib/rspec/core/filter_manager.rb

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@ def prune(examples)
3535
examples = prune_conditionally_filtered_examples(examples)
3636

3737
if inclusions.standalone?
38-
examples.select { |e| include?(e) }
38+
examples.select { |e| inclusions.include_example?(e) }
3939
else
40-
locations = inclusions.fetch(:locations) { Hash.new([]) }
41-
ids = inclusions.fetch(:ids) { Hash.new([]) }
40+
locations, ids, non_scoped_inclusions = inclusions.split_file_scoped_rules
4241

43-
examples.select { |e| priority_include?(e, ids, locations) || (!exclude?(e) && include?(e)) }
42+
examples.select do |ex|
43+
file_scoped_include?(ex.metadata, ids, locations) do
44+
!exclusions.include_example?(ex) && non_scoped_inclusions.include_example?(ex)
45+
end
46+
end
4447
end
4548
end
4649

@@ -76,14 +79,6 @@ def add_path_to_arrays_filter(filter_key, path, values)
7679
inclusions.add(filter_key => filter)
7780
end
7881

79-
def exclude?(example)
80-
exclusions.include_example?(example)
81-
end
82-
83-
def include?(example)
84-
inclusions.include_example?(example)
85-
end
86-
8782
def prune_conditionally_filtered_examples(examples)
8883
examples.reject do |ex|
8984
meta = ex.metadata
@@ -96,10 +91,14 @@ def prune_conditionally_filtered_examples(examples)
9691
# and there is a `:slow => true` exclusion filter), but only for specs
9792
# defined in the same file as the location filters. Excluded specs in
9893
# other files should still be excluded.
99-
def priority_include?(example, ids, locations)
100-
return true if MetadataFilter.filter_applies?(:ids, ids, example.metadata)
101-
return false if locations[example.metadata[:absolute_file_path]].empty?
102-
MetadataFilter.filter_applies?(:locations, locations, example.metadata)
94+
def file_scoped_include?(ex_metadata, ids, locations)
95+
no_location_filters = locations[ex_metadata[:absolute_file_path]].empty?
96+
no_id_filters = ids[ex_metadata[:rerun_file_path]].empty?
97+
98+
return yield if no_location_filters && no_id_filters
99+
100+
MetadataFilter.filter_applies?(:ids, ids, ex_metadata) ||
101+
MetadataFilter.filter_applies?(:locations, locations, ex_metadata)
103102
end
104103
end
105104

@@ -119,8 +118,8 @@ def self.build
119118
[exclusions, inclusions]
120119
end
121120

122-
def initialize(*args, &block)
123-
@rules = Hash.new(*args, &block)
121+
def initialize(rules={})
122+
@rules = rules
124123
end
125124

126125
def add(updated)
@@ -196,6 +195,14 @@ def standalone?
196195
is_standalone_filter?(@rules)
197196
end
198197

198+
def split_file_scoped_rules
199+
rules_dup = @rules.dup
200+
locations = rules_dup.delete(:locations) { Hash.new([]) }
201+
ids = rules_dup.delete(:ids) { Hash.new([]) }
202+
203+
return locations, ids, self.class.new(rules_dup)
204+
end
205+
199206
private
200207

201208
def apply_standalone_filter(updated)

lib/rspec/core/metadata_filter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def id_filter_applies?(rerun_paths_to_scoped_ids, metadata)
5353

5454
def location_filter_applies?(locations, metadata)
5555
line_numbers = example_group_declaration_lines(locations, metadata)
56-
line_numbers.empty? || line_number_filter_applies?(line_numbers, metadata)
56+
line_number_filter_applies?(line_numbers, metadata)
5757
end
5858

5959
def line_number_filter_applies?(line_numbers, metadata)

spec/integration/filtering_spec.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,28 @@ def run_rerun_command_for_failing_spec
123123
expect(last_cmd_stdout).to match(/3 examples, 0 failures/)
124124
expect(last_cmd_stdout).not_to match(/fails/)
125125
end
126+
127+
it 'applies command line tag filters only to files that lack a line number filter' do
128+
write_file_formatted "spec/file_1_spec.rb", "
129+
RSpec.describe 'File 1' do
130+
it('is selected by line') { }
131+
it('is not selected', :tag) { }
132+
end
133+
"
134+
135+
write_file_formatted "spec/file_2_spec.rb", "
136+
RSpec.describe 'File 2' do
137+
it('is not selected') { }
138+
it('is selected by tag', :tag) { }
139+
end
140+
"
141+
142+
run_command "spec/file_1_spec.rb:2 spec/file_2_spec.rb --tag tag -fd"
143+
expect(last_cmd_stdout).to include(
144+
"2 examples, 0 failures",
145+
"is selected by line", "is selected by tag"
146+
).and exclude("not selected")
147+
end
126148
end
127149

128150
context "passing example ids at the command line" do

spec/rspec/core/filter_manager_spec.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,25 @@ def example_with(*args)
129129

130130
expect(filter_manager.prune([included, excluded])).to eq([included])
131131
end
132+
133+
it "still applies inclusion filters to examples from files with no #{type} filters" do
134+
group = RSpec.describe("group")
135+
included_via_loc_or_id = group.example("inc via #{type}"); line = __LINE__
136+
excluded_via_loc_or_id = group.example("exc via #{type}", :foo)
137+
138+
included_via_tag, excluded_via_tag = instance_eval <<-EOS, "some/other_spec.rb", 1
139+
group = RSpec.describe("group")
140+
[group.example("inc via tag", :foo), group.example("exc via tag")]
141+
EOS
142+
143+
add_filter(:line_number => line, :scoped_id => "1:1")
144+
filter_manager.include_with_low_priority :foo => true
145+
146+
expect(filter_manager.prune([
147+
included_via_loc_or_id, excluded_via_loc_or_id,
148+
included_via_tag, excluded_via_tag
149+
]).map(&:description)).to eq([included_via_loc_or_id, included_via_tag].map(&:description))
150+
end
132151
end
133152

134153
describe "location filtering" do
@@ -299,6 +318,24 @@ def add_filter(options)
299318
filter_manager.add_ids(Metadata.relative_path(__FILE__), %w[ 2 ])
300319
expect(filter_manager.prune([ex_1, ex_2, ex_3])).to eq([ex_2, ex_3])
301320
end
321+
322+
it 'uses the rerun file path when applying the id filter' do
323+
ex_1, ex_2 = instance_eval <<-EOS, "./some/spec.rb", 1
324+
ex_1 = ex_2 = nil
325+
326+
RSpec.shared_examples "shared" do
327+
ex_1 = example("ex 1")
328+
ex_2 = example("ex 2")
329+
end
330+
331+
[ex_1, ex_2]
332+
EOS
333+
334+
RSpec.describe { include_examples "shared" }
335+
336+
filter_manager.add_ids(__FILE__, %w[ 1:1 ])
337+
expect(filter_manager.prune([ex_1, ex_2]).map(&:description)).to eq([ex_1].map(&:description))
338+
end
302339
end
303340
end
304341

0 commit comments

Comments
 (0)