Skip to content

Commit 71304ca

Browse files
authored
Merge pull request #1789 from G-Rath/support-predicate
feat: support some "predicate" assertions in `RSpec/Rails/MinitestAssertions`
2 parents 63e512b + 17c92fb commit 71304ca

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Support asserts with messages in `Rspec/BeEmpty`. ([@G-Rath])
66
- Add support for `assert_empty`, `assert_not_empty` and `refute_empty` to `RSpec/Rails/MinitestAssertions`. ([@ydah])
7+
- Support correcting some `*_predicate` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath])
78
- Support correcting `*_match` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath])
89
- Support correcting `*_instance_of` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath])
910
- Support correcting `*_includes` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath])

lib/rubocop/cop/rspec_rails/minitest_assertions.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class MinitestAssertions < Base
3434
assert_not_instance_of
3535
assert_includes
3636
assert_not_includes
37+
assert_predicate
38+
assert_not_predicate
3739
assert_match
3840
assert_nil
3941
assert_not_nil
@@ -42,6 +44,7 @@ class MinitestAssertions < Base
4244
refute_equal
4345
refute_instance_of
4446
refute_includes
47+
refute_predicate
4548
refute_nil
4649
refute_empty
4750
refute_match
@@ -62,6 +65,11 @@ class MinitestAssertions < Base
6265
(send nil? {:assert_includes :assert_not_includes :refute_includes} $_ $_ $_?)
6366
PATTERN
6467

68+
# @!method minitest_predicate(node)
69+
def_node_matcher :minitest_predicate, <<~PATTERN
70+
(send nil? {:assert_predicate :assert_not_predicate :refute_predicate} $_ ${sym} $_?)
71+
PATTERN
72+
6573
# @!method minitest_match(node)
6674
def_node_matcher :minitest_match, <<~PATTERN
6775
(send nil? {:assert_match :refute_match} $_ $_ $_?)
@@ -88,6 +96,13 @@ def on_send(node) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
8896
failure_message.first))
8997
end
9098

99+
minitest_predicate(node) do |subject, predicate, failure_message|
100+
next unless predicate.value.end_with?('?')
101+
102+
on_assertion(node, PredicateAssertion.new(predicate, subject,
103+
failure_message.first))
104+
end
105+
91106
minitest_includes(node) do |collection, expected, failure_message|
92107
on_assertion(node, IncludesAssertion.new(expected, collection,
93108
failure_message.first))
@@ -171,6 +186,17 @@ def assertion
171186
end
172187
end
173188

189+
# :nodoc:
190+
class PredicateAssertion < BasicAssertion
191+
def negated?(node)
192+
!node.method?(:assert_predicate)
193+
end
194+
195+
def assertion
196+
"be_#{@expected.delete_prefix(':').delete_suffix('?')}"
197+
end
198+
end
199+
174200
# :nodoc:
175201
class MatchAssertion < BasicAssertion
176202
def negated?(node)

spec/rubocop/cop/rspec_rails/minitest_assertions_spec.rb

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,4 +507,134 @@
507507
RUBY
508508
end
509509
end
510+
511+
context 'with predicate assertions' do
512+
it 'registers an offense when using `assert_predicate` with ' \
513+
'an actual predicate' do
514+
expect_offense(<<~RUBY)
515+
assert_predicate(a, :valid?)
516+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(a).to be_valid`.
517+
RUBY
518+
519+
expect_correction(<<~RUBY)
520+
expect(a).to be_valid
521+
RUBY
522+
end
523+
524+
it 'registers an offense when using `assert_predicate` with ' \
525+
'an actual predicate and no parentheses' do
526+
expect_offense(<<~RUBY)
527+
assert_predicate a, :valid?
528+
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(a).to be_valid`.
529+
RUBY
530+
531+
expect_correction(<<~RUBY)
532+
expect(a).to be_valid
533+
RUBY
534+
end
535+
536+
it 'registers an offense when using `assert_predicate` with ' \
537+
'an actual predicate and a failure message' do
538+
expect_offense(<<~RUBY)
539+
assert_predicate a, :valid?, "must be valid"
540+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(a).to(be_valid, "must be valid")`.
541+
RUBY
542+
543+
expect_correction(<<~RUBY)
544+
expect(a).to(be_valid, "must be valid")
545+
RUBY
546+
end
547+
548+
it 'registers an offense when using `assert_predicate` with ' \
549+
'an actual predicate and multi-line arguments' do
550+
expect_offense(<<~RUBY)
551+
assert_predicate(a,
552+
^^^^^^^^^^^^^^^^^^^ Use `expect(a).to(be_valid, "must be valid")`.
553+
:valid?,
554+
"must be valid")
555+
RUBY
556+
557+
expect_correction(<<~RUBY)
558+
expect(a).to(be_valid, "must be valid")
559+
RUBY
560+
end
561+
562+
it 'registers an offense when using `assert_not_predicate` with ' \
563+
'an actual predicate' do
564+
expect_offense(<<~RUBY)
565+
assert_not_predicate a, :valid?
566+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(a).not_to be_valid`.
567+
RUBY
568+
569+
expect_correction(<<~RUBY)
570+
expect(a).not_to be_valid
571+
RUBY
572+
end
573+
574+
it 'registers an offense when using `refute_predicate` with ' \
575+
'an actual predicate' do
576+
expect_offense(<<~RUBY)
577+
refute_predicate a, :valid?
578+
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(a).not_to be_valid`.
579+
RUBY
580+
581+
expect_correction(<<~RUBY)
582+
expect(a).not_to be_valid
583+
RUBY
584+
end
585+
586+
it 'does not register an offense when using `expect(a).to be_predicate`' do
587+
expect_no_offenses(<<~RUBY)
588+
expect(a).to be_predicate
589+
RUBY
590+
end
591+
592+
it 'does not register an offense when using ' \
593+
'`expect(a).not_to be_predicate`' do
594+
expect_no_offenses(<<~RUBY)
595+
expect(a).not_to be_predicate
596+
RUBY
597+
end
598+
599+
it 'does not register an offense when using `assert_predicate` with ' \
600+
'not a predicate' do
601+
expect_no_offenses(<<~RUBY)
602+
assert_predicate foo, :do_something
603+
RUBY
604+
end
605+
606+
it 'does not register an offense when using `assert_not_predicate` with ' \
607+
'not a predicate' do
608+
expect_no_offenses(<<~RUBY)
609+
assert_not_predicate foo, :do_something
610+
RUBY
611+
end
612+
613+
it 'does not register an offense when using `refute_predicate` with ' \
614+
'not a predicate' do
615+
expect_no_offenses(<<~RUBY)
616+
refute_predicate foo, :do_something
617+
RUBY
618+
end
619+
620+
it 'does not register an offense when the predicate is not a symbol' do
621+
expect_no_offenses(<<~RUBY)
622+
assert_predicate a, 1
623+
RUBY
624+
end
625+
626+
it 'does not register an offense when the predicate is missing' do
627+
expect_no_offenses(<<~RUBY)
628+
assert_predicate a, "whoops, we forgot about the actual predicate!"
629+
RUBY
630+
end
631+
632+
it 'does not register an offense when the predicate is a variable' do
633+
expect_no_offenses(<<~RUBY)
634+
foo = :foo?
635+
636+
assert_predicate a, foo
637+
RUBY
638+
end
639+
end
510640
end

0 commit comments

Comments
 (0)