Sha256: c01af572bd16133a65436c46fe663746ad15ec275c8d40c675da1bfe4db53e24

Contents?: true

Size: 1.5 KB

Versions: 1

Compression:

Stored size: 1.5 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 and its optionally called out method.
    #
    # @example
    #   my_class/method_spec.rb  # describe MyClass, '#method'
    #   my_class_spec.rb         # describe MyClass
    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

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

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

      private

      def matcher(object, method)
        path = File.join(object.split('::').map { |p| camel_to_underscore(p) })
        path += '*' + method.children.first.gsub(/\W+/, '') if method

        "#{path}*_spec.rb"
      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.rc2 lib/rubocop/cop/rspec_file_name.rb