Skip to content

Commit

Permalink
style: add custom RSpec cops
Browse files Browse the repository at this point in the history
  • Loading branch information
palkan committed Mar 22, 2022
1 parent 94293b0 commit de9190e
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .rubocop/custom.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ Bundler/GemComment:

Style/FrozenStringLiteralComment:
Enabled: true

RSpec/Describe:
Enabled: true

RSpec/TypeTag:
Enabled: true
1 change: 1 addition & 0 deletions lib/rubocop/cops.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# frozen_string_literal: true

require_relative "cops/lint_env"
require_relative "cops/rspec"
4 changes: 4 additions & 0 deletions lib/rubocop/cops/rspec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

require_relative "rspec/describe"
require_relative "rspec/type_tag"
31 changes: 31 additions & 0 deletions lib/rubocop/cops/rspec/describe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
# This cops checks that top-level described is not namespaced:
#
# # bad
# RSpec.describe MyClass do
# # ...
# end
#
# # good
# describe MyClass do
# # ...
# end
class Describe < RuboCop::Cop::Cop
MSG = "Use `describe` instead of `RSpec.describe`."

def_node_matcher :rspec_describe?, <<~PATTERN
(send (const nil? :RSpec) :describe ...)
PATTERN

def on_send(node)
return unless rspec_describe?(node)
add_offense(node, location: :selector, message: MSG)
end
end
end
end
end
54 changes: 54 additions & 0 deletions lib/rubocop/cops/rspec/type_tag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

require "rubocop-rspec"

module RuboCop
module Cop
module RSpec
# This cops checks that default `type` tag is not specified explicitly.
#
# # bad
# describe UsersController, type: :controller do
# # ...
# end
#
# # good
# describe UsersController do
# # ...
# end
#
class TypeTag < RuboCop::Cop::RSpec::Base
include RuboCop::Cop::RSpec::TopLevelGroup

MSG = "Avoid specifiying inferrable type tags explicitly. " \
"Remove `type: :%s` (it's inferred automatically)"

def_node_matcher :type_tag, <<~PATTERN
(pair (sym :type) (sym $_))
PATTERN

def on_top_level_example_group(node)
metadata = node.children.first.children[3]
return unless metadata

metadata.children.each do |arg|
actual_tag = type_tag(arg)
next unless actual_tag
next if actual_tag != expected_tag

break add_offense(node, message: MSG % actual_tag)
end
end

private

def expected_tag
file_path = processed_source.file_path
if file_path =~ %r{/spec/([^/]+)/}
Regexp.last_match[1].gsub(/s$/, "").to_sym
end
end
end
end
end
end

0 comments on commit de9190e

Please sign in to comment.