447 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
		
		
			
		
	
	
			447 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
|   | # frozen_string_literal: true | ||
|  | 
 | ||
|  | require "rubocops/presence" | ||
|  | 
 | ||
|  | RSpec.describe RuboCop::Cop::Homebrew::Presence, :config do | ||
|  |   it "registers an offense and corrects when `a.present? ? a : nil`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a.present? ? a : nil | ||
|  |       ^^^^^^^^^^^^^^^^^^^^ Use `a.presence` instead of `a.present? ? a : nil`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `!a.present? ? nil: a`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       !a.present? ? nil: a | ||
|  |       ^^^^^^^^^^^^^^^^^^^^ Use `a.presence` instead of `!a.present? ? nil: a`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a.blank? ? nil : a`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a.blank? ? nil : a | ||
|  |       ^^^^^^^^^^^^^^^^^^ Use `a.presence` instead of `a.blank? ? nil : a`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `!a.blank? ? a : nil`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       !a.blank? ? a : nil | ||
|  |       ^^^^^^^^^^^^^^^^^^^ Use `a.presence` instead of `!a.blank? ? a : nil`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a.present? ? a : b`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a.present? ? a : b | ||
|  |       ^^^^^^^^^^^^^^^^^^ Use `a.presence || b` instead of `a.present? ? a : b`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || b | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `!a.present? ? b : a`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       !a.present? ? b : a | ||
|  |       ^^^^^^^^^^^^^^^^^^^ Use `a.presence || b` instead of `!a.present? ? b : a`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || b | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a.blank? ? b : a`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a.blank? ? b : a | ||
|  |       ^^^^^^^^^^^^^^^^ Use `a.presence || b` instead of `a.blank? ? b : a`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || b | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `!a.blank? ? a : b`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       !a.blank? ? a : b | ||
|  |       ^^^^^^^^^^^^^^^^^ Use `a.presence || b` instead of `!a.blank? ? a : b`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || b | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a.present? ? a : 1`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a.present? ? a : 1
 | ||
|  |       ^^^^^^^^^^^^^^^^^^ Use `a.presence || 1` instead of `a.present? ? a : 1`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || 1
 | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a.blank? ? 1 : a`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a.blank? ? 1 : a | ||
|  |       ^^^^^^^^^^^^^^^^ Use `a.presence || 1` instead of `a.blank? ? 1 : a`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || 1
 | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a(:bar).map(&:baz).present? ? a(:bar).map(&:baz) : nil`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a(:bar).map(&:baz).present? ? a(:bar).map(&:baz) : nil | ||
|  |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `a(:bar).map(&:baz).presence` instead of `a(:bar).map(&:baz).present? ? a(:bar).map(&:baz) : nil`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a(:bar).map(&:baz).presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a.present? ? a : b[:c]`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a.present? ? a : b[:c] | ||
|  |       ^^^^^^^^^^^^^^^^^^^^^^ Use `a.presence || b[:c]` instead of `a.present? ? a : b[:c]`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || b[:c] | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when multi-line if node" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       if a.present? | ||
|  |       ^^^^^^^^^^^^^ Use `a.presence` instead of `if a.present? ... end`. | ||
|  |         a | ||
|  |       else | ||
|  |         nil | ||
|  |       end | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when multi-line unless node" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       unless a.present? | ||
|  |       ^^^^^^^^^^^^^^^^^ Use `a.presence` instead of `unless a.present? ... end`. | ||
|  |         nil | ||
|  |       else | ||
|  |         a | ||
|  |       end | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when multi-line if node with `+` operators in the else branch" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       if a.present? | ||
|  |       ^^^^^^^^^^^^^ Use `a.presence || b.to_f + 12.0` instead of `if a.present? ... end`. | ||
|  |         a | ||
|  |       else | ||
|  |         b.to_f + 12.0
 | ||
|  |       end | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || b.to_f + 12.0
 | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when multi-line if `*` operators in the else branch" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       if a.present? | ||
|  |       ^^^^^^^^^^^^^ Use `a.presence || b.to_f * 12.0` instead of `if a.present? ... end`. | ||
|  |         a | ||
|  |       else | ||
|  |         b.to_f * 12.0
 | ||
|  |       end | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence || b.to_f * 12.0
 | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a if a.present?`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a if a.present? | ||
|  |       ^^^^^^^^^^^^^^^ Use `a.presence` instead of `a if a.present?`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `a unless a.blank?`" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       a unless a.blank? | ||
|  |       ^^^^^^^^^^^^^^^^^ Use `a.presence` instead of `a unless a.blank?`. | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "registers an offense and corrects when `.present?` with method chain" do | ||
|  |     expect_offense(<<~RUBY) | ||
|  |       if [1, 2, 3].map { |num| num + 1 } | ||
|  |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `[1, 2, 3].map { |num| num + 1 }.map { |num| num + 2 }.presence || b` instead of `if [1, 2, 3].map { |num| num + 1 }.map { |num| num + 2 }.present? ... end`. | ||
|  |                   .map { |num| num + 2 } | ||
|  |                   .present? | ||
|  |                   [1, 2, 3].map { |num| num + 1 }.map { |num| num + 2 } | ||
|  |       else | ||
|  |         b | ||
|  |       end | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_correction(<<~RUBY) | ||
|  |       [1, 2, 3].map { |num| num + 1 } | ||
|  |                   .map { |num| num + 2 }.presence || b | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   context "when multiline ternary can be replaced" do | ||
|  |     it "registers an offense and corrects" do | ||
|  |       expect_offense(<<~RUBY) | ||
|  |         a.present? ? | ||
|  |         ^^^^^^^^^^^^ Use `a.presence` instead of `a.present? ? a : nil`. | ||
|  |           a : | ||
|  |           nil | ||
|  |       RUBY | ||
|  | 
 | ||
|  |       expect_correction(<<~RUBY) | ||
|  |         a.presence | ||
|  |       RUBY | ||
|  |     end | ||
|  |   end | ||
|  | 
 | ||
|  |   context "when a method argument of `else` branch is enclosed in parentheses" do | ||
|  |     it "registers an offense and corrects" do | ||
|  |       expect_offense(<<~RUBY) | ||
|  |         if value.present? | ||
|  |         ^^^^^^^^^^^^^^^^^ Use `value.presence || do_something(value)` instead of `if value.present? ... end`. | ||
|  |           value | ||
|  |         else | ||
|  |           do_something(value) | ||
|  |         end | ||
|  |       RUBY | ||
|  | 
 | ||
|  |       expect_correction(<<~RUBY) | ||
|  |         value.presence || do_something(value) | ||
|  |       RUBY | ||
|  |     end | ||
|  |   end | ||
|  | 
 | ||
|  |   context "when a method argument of `else` branch is not enclosed in parentheses" do | ||
|  |     it "registers an offense and corrects" do | ||
|  |       expect_offense(<<~RUBY) | ||
|  |         if value.present? | ||
|  |         ^^^^^^^^^^^^^^^^^ Use `value.presence || do_something(value)` instead of `if value.present? ... end`. | ||
|  |           value | ||
|  |         else | ||
|  |           do_something value | ||
|  |         end | ||
|  |       RUBY | ||
|  | 
 | ||
|  |       expect_correction(<<~RUBY) | ||
|  |         value.presence || do_something(value) | ||
|  |       RUBY | ||
|  |     end | ||
|  |   end | ||
|  | 
 | ||
|  |   context "when multiple method arguments of `else` branch is not enclosed in parentheses" do | ||
|  |     it "registers an offense and corrects" do | ||
|  |       expect_offense(<<~RUBY) | ||
|  |         if value.present? | ||
|  |         ^^^^^^^^^^^^^^^^^ Use `value.presence || do_something(arg1, arg2)` instead of `if value.present? ... end`. | ||
|  |           value | ||
|  |         else | ||
|  |           do_something arg1, arg2 | ||
|  |         end | ||
|  |       RUBY | ||
|  | 
 | ||
|  |       expect_correction(<<~RUBY) | ||
|  |         value.presence || do_something(arg1, arg2) | ||
|  |       RUBY | ||
|  |     end | ||
|  |   end | ||
|  | 
 | ||
|  |   context "when a method argument with a receiver of `else` branch is not enclosed in parentheses" do | ||
|  |     it "registers an offense and corrects" do | ||
|  |       expect_offense(<<~RUBY) | ||
|  |         if value.present? | ||
|  |         ^^^^^^^^^^^^^^^^^ Use `value.presence || foo.do_something(value)` instead of `if value.present? ... end`. | ||
|  |           value | ||
|  |         else | ||
|  |           foo.do_something value | ||
|  |         end | ||
|  |       RUBY | ||
|  | 
 | ||
|  |       expect_correction(<<~RUBY) | ||
|  |         value.presence || foo.do_something(value) | ||
|  |       RUBY | ||
|  |     end | ||
|  |   end | ||
|  | 
 | ||
|  |   context "when a right-hand side of the relational operator" do | ||
|  |     %w[< > <= >= == !=].each do |operator| | ||
|  |       it "registers an offense and corrects when `#{operator}`" do | ||
|  |         expect_offense(<<~RUBY, operator: operator) | ||
|  |           a #{operator} if b.present? | ||
|  |             _{operator} ^^^^^^^^^^^^^ Use `(b.presence || c)` instead of `if b.present? ... end`. | ||
|  |             b | ||
|  |           else | ||
|  |             c | ||
|  |           end | ||
|  |         RUBY | ||
|  | 
 | ||
|  |         expect_correction(<<~RUBY) | ||
|  |           a #{operator} (b.presence || c) | ||
|  |         RUBY | ||
|  |       end | ||
|  |     end | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when using `#presence`" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       a.presence | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when the expression does not return the receiver of `#present?`" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       a.present? ? b : nil | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       puts foo if present? | ||
|  |       puts foo if !present? | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when the expression does not return the receiver of `#blank?`" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       a.blank? ? nil : b | ||
|  |     RUBY | ||
|  | 
 | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       puts foo if blank? | ||
|  |       puts foo if !blank? | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when if or unless modifier is used" do | ||
|  |     [ | ||
|  |       "a if a.blank?", | ||
|  |       "a unless a.present?", | ||
|  |     ].each { |source| expect_no_offenses(source) } | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when the else block is multiline" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       if a.present? | ||
|  |         a | ||
|  |       else | ||
|  |         something | ||
|  |         something | ||
|  |         something | ||
|  |       end | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when the else block has multiple statements" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       if a.present? | ||
|  |         a | ||
|  |       else | ||
|  |         something; something; something | ||
|  |       end | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when including the elsif block" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       if a.present? | ||
|  |         a | ||
|  |       elsif b | ||
|  |         b | ||
|  |       end | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when the else block has `if` node" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       if a.present? | ||
|  |         a | ||
|  |       else | ||
|  |         b if c | ||
|  |       end | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when the else block has `rescue` node" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       if something_method.present? | ||
|  |         something_method | ||
|  |       else | ||
|  |         invalid_method rescue StandardError | ||
|  |       end | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when the else block has `while` node" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       if a.present? | ||
|  |         a | ||
|  |       else | ||
|  |         fetch_state while waiting? | ||
|  |       end | ||
|  |     RUBY | ||
|  |   end | ||
|  | 
 | ||
|  |   it "does not register an offense when using #present? with elsif block" do | ||
|  |     expect_no_offenses(<<~RUBY) | ||
|  |       if something? | ||
|  |         a | ||
|  |       elsif b.present? | ||
|  |         b | ||
|  |       end | ||
|  |     RUBY | ||
|  |   end | ||
|  | end |