Skip to content

Commit

Permalink
Refactor and adding a common matcher in SkipOrPending module
Browse files Browse the repository at this point in the history
This PR is refactor and adding a common matcher in SkipOrPending module.
  • Loading branch information
ydah authored and pirj committed Mar 4, 2023
1 parent d114b99 commit b0c5ea9
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 16 deletions.
24 changes: 20 additions & 4 deletions lib/rubocop/cop/rspec/mixin/skip_or_pending.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,29 @@ module SkipOrPending
# @!method skipped_in_metadata?(node)
def_node_matcher :skipped_in_metadata?, <<-PATTERN
{
(send _ _ <#skip_or_pending? ...>)
(send _ _ ... (hash <(pair #skip_or_pending? { true str dstr }) ...>))
(send _ _ <(sym {:skip :pending}) ...>)
(send _ _ ... (hash <(pair (sym {:skip :pending}) { true str dstr }) ...>))
}
PATTERN

# @!method skip_or_pending?(node)
def_node_matcher :skip_or_pending?, '{(sym :skip) (sym :pending)}'
# @!method skip_or_pending_inside_block?(node)
# Match skip/pending statements inside a block (e.g. `context`)
#
# @example source that matches
# context 'when color is blue' do
# skip 'not implemented yet'
# pending 'not implemented yet'
# end
#
# @example source that does not match
# skip 'not implemented yet'
# pending 'not implemented yet'
#
# @param node [RuboCop::AST::Node]
# @return [Array<RuboCop::AST::Node>] matching nodes
def_node_matcher :skip_or_pending_inside_block?, <<-PATTERN
(block <(send nil? {:skip :pending} ...) ...>)
PATTERN
end
end
end
Expand Down
9 changes: 3 additions & 6 deletions lib/rubocop/cop/rspec/repeated_example_group_body.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ module RSpec
# end
#
class RepeatedExampleGroupBody < Base
include SkipOrPending

MSG = 'Repeated %<group>s block body on line(s) %<loc>s'

# @!method several_example_groups?(node)
Expand All @@ -59,11 +61,6 @@ class RepeatedExampleGroupBody < Base
# @!method const_arg(node)
def_node_matcher :const_arg, '(block (send _ _ $const ...) ...)'

# @!method skip_or_pending?(node)
def_node_matcher :skip_or_pending?, <<-PATTERN
(block <(send nil? {:skip :pending} ...) ...>)
PATTERN

def on_begin(node)
return unless several_example_groups?(node)

Expand All @@ -78,7 +75,7 @@ def repeated_group_bodies(node)
node
.children
.select { |child| example_group_with_body?(child) }
.reject { |child| skip_or_pending?(child) }
.reject { |child| skip_or_pending_inside_block?(child) }
.group_by { |group| signature_keys(group) }
.values
.reject(&:one?)
Expand Down
9 changes: 3 additions & 6 deletions lib/rubocop/cop/rspec/repeated_example_group_description.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ module RSpec
# end
#
class RepeatedExampleGroupDescription < Base
include SkipOrPending

MSG = 'Repeated %<group>s block description on line(s) %<loc>s'

# @!method several_example_groups?(node)
Expand All @@ -55,11 +57,6 @@ class RepeatedExampleGroupDescription < Base
(block (send _ _ $_ $...) ...)
PATTERN

# @!method skip_or_pending?(node)
def_node_matcher :skip_or_pending?, <<-PATTERN
(block <(send nil? {:skip :pending}) ...>)
PATTERN

# @!method empty_description?(node)
def_node_matcher :empty_description?, '(block (send _ _) ...)'

Expand All @@ -77,7 +74,7 @@ def repeated_group_descriptions(node)
node
.children
.select { |child| example_group?(child) }
.reject { |child| skip_or_pending?(child) }
.reject { |child| skip_or_pending_inside_block?(child) }
.reject { |child| empty_description?(child) }
.group_by { |group| doc_string_and_metadata(group) }
.values
Expand Down
105 changes: 105 additions & 0 deletions spec/rubocop/cop/rspec/mixin/skip_or_pending_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::RSpec::SkipOrPending do
describe '#skipped_in_metadata?' do
subject(:skipped_in_metadata?) do
stub_class.new.send(:skipped_in_metadata?, ast)
end

let(:stub_class) do
Class.new do
include RuboCop::Cop::RSpec::SkipOrPending
end
end
let(:ast) { parse_source(source).ast.children.first }

context 'when given node contains skip' do
let(:source) { <<~RUBY }
it 'is skipped', :skip do
foo
end
RUBY

it 'returns true' do
expect(skipped_in_metadata?).to be_truthy
end
end

context 'when given node contains pending' do
let(:source) { <<~RUBY }
it 'is pending', :pending do
foo
end
RUBY

it 'returns true' do
expect(skipped_in_metadata?).to be_truthy
end
end

context 'when given node does not contain skip/pending' do
let(:source) { 'it("example") { }' }

it 'returns false' do
expect(skipped_in_metadata?).to be_falsey
end
end
end

describe '#skip_or_pending_inside_block?' do
subject(:skip_or_pending_inside_block?) do
stub_class.new.send(:skip_or_pending_inside_block?, ast)
end

let(:stub_class) do
Class.new do
include RuboCop::Cop::RSpec::SkipOrPending
end
end
let(:ast) { parse_source(source).ast }

context 'when given node contains skip inside block' do
let(:source) do
<<~RUBY
context 'when color is blue' do
skip 'not implemented yet'
end
RUBY
end

it 'returns true' do
expect(skip_or_pending_inside_block?).to be_truthy
end
end

context 'when given node contains pending inside block' do
let(:source) do
<<~RUBY
context 'when color is blue' do
pending 'not implemented yet'
end
RUBY
end

it 'returns true' do
expect(skip_or_pending_inside_block?).to be_truthy
end
end

context 'when given node does not contain skip inside block' do
let(:source) { "skip 'not implemented yet'" }

it 'returns false' do
expect(skip_or_pending_inside_block?).to be_falsey
end
end

context 'when given node does not contain pending inside block' do
let(:source) { "pending 'not implemented yet'" }

it 'returns false' do
expect(skip_or_pending_inside_block?).to be_falsey
end
end
end
end

0 comments on commit b0c5ea9

Please sign in to comment.