BigW Consortium Gitlab

verbose_include_metadata.rb 1.74 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
# frozen_string_literal: true

require 'rubocop-rspec'

module RuboCop
  module Cop
    module RSpec
      # Checks for verbose include metadata used in the specs.
      #
      # @example
      #   # bad
      #   describe MyClass, js: true do
      #   end
      #
      #   # good
      #   describe MyClass, :js do
      #   end
      class VerboseIncludeMetadata < Cop
        MSG = 'Use `%s` instead of `%s`.'

        SELECTORS = %i[describe context feature example_group it specify example scenario its].freeze

        def_node_matcher :include_metadata, <<-PATTERN
          (send {(const nil :RSpec) nil} {#{SELECTORS.map(&:inspect).join(' ')}}
            !const
            ...
            (hash $...))
        PATTERN

        def_node_matcher :invalid_metadata?, <<-PATTERN
          (pair
            (sym $...)
            (true))
        PATTERN

        def on_send(node)
          invalid_metadata_matches(node) do |match|
            add_offense(node, :expression, format(MSG, good(match), bad(match)))
          end
        end

        def autocorrect(node)
          lambda do |corrector|
            invalid_metadata_matches(node) do |match|
              corrector.replace(match.loc.expression, good(match))
            end
          end
        end

        private

        def invalid_metadata_matches(node)
          include_metadata(node) do |matches|
            matches.select(&method(:invalid_metadata?)).each do |match|
              yield match
            end
          end
        end

        def bad(match)
          "#{metadata_key(match)}: true"
        end

        def good(match)
          ":#{metadata_key(match)}"
        end

        def metadata_key(match)
          match.children[0].source
        end
      end
    end
  end
end