Sha256: 7a862734b2b145cb8857a76693a083a649d0e9cec0f477043d9cca489c0a7bd5

Contents?: true

Size: 1.53 KB

Versions: 1

Compression:

Stored size: 1.53 KB

Contents

# encoding: utf-8

module Rubocop
  module Cop
    # Checks the path of the spec file and enforces that it reflects the
    # described class/module.
    #
    # @example
    #   class/method_spec.rb
    #   class_spec.rb
    class RSpecFileName < Cop
      include RSpec::TopLevelDescribe

      MESSAGE = 'Spec path should end with `%s`'
      METHOD_STRING_MATCHER = /^[\#\.].+/

      def on_top_level_describe(node, args)
        return unless single_top_level_describe?
        object = const_name(args.first)
        return unless object

        glob_matcher = matcher(object, args[1])
        return if source_filename =~ regexp_from_glob(glob_matcher)

        add_offense(node, :expression, format(MESSAGE, glob_matcher))
      end

      private

      def matcher(object, method)
        method_string = method ? method.children.first.gsub(/\W+/, '') : nil
        path = [File.join(path_parts(object)), method_string].compact.join('_')
        "#{path}*_spec.rb"
      end

      def path_parts(object)
        object.split('::').map do |part|
          camel_to_underscore(part)
        end
      end

      def source_filename
        processed_source.buffer.name
      end

      def camel_to_underscore(string)
        string.dup.tap do |result|
          result.gsub!(/([^A-Z])([A-Z]+)/,       '\\1_\\2')
          result.gsub!(/([A-Z]{2,})([A-Z][^A-Z]+)/, '\\1_\\2')
          result.downcase!
        end
      end

      def regexp_from_glob(glob)
        Regexp.new(glob.gsub('.', '\\.').gsub('*', '.*') + '$')
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
rubocop-rspec-1.0.rc1 lib/rubocop/cop/rspec_file_name.rb