diff options
author | Rémy Coutable <remy@rymai.me> | 2017-10-11 13:25:40 +0200 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2017-10-18 18:42:09 +0200 |
commit | 8a31b0743753f080e0ba07c8d6d0da863a5c4726 (patch) | |
tree | 0a5d03d993597a3f68b4f233b4f7f1ebc0481fa2 /rubocop | |
parent | 4774b6cfd2095974df4267e4e4871b38b274a956 (diff) | |
download | gitlab-ce-8a31b0743753f080e0ba07c8d6d0da863a5c4726.tar.gz |
Add a new RSpec::EnvAssignment cop to prevent assigning to ENV in specs18765-stub_env_in_specs
Signed-off-by: Rémy Coutable <remy@rymai.me>
Diffstat (limited to 'rubocop')
-rw-r--r-- | rubocop/cop/rspec/env_assignment.rb | 58 | ||||
-rw-r--r-- | rubocop/rubocop.rb | 11 | ||||
-rw-r--r-- | rubocop/spec_helpers.rb | 12 |
3 files changed, 76 insertions, 5 deletions
diff --git a/rubocop/cop/rspec/env_assignment.rb b/rubocop/cop/rspec/env_assignment.rb new file mode 100644 index 00000000000..257454af0e1 --- /dev/null +++ b/rubocop/cop/rspec/env_assignment.rb @@ -0,0 +1,58 @@ +require 'rubocop-rspec' +require_relative '../../spec_helpers' + +module RuboCop + module Cop + module RSpec + # This cop checks for ENV assignment in specs + # + # @example + # + # # bad + # before do + # ENV['FOO'] = 'bar' + # end + # + # # good + # before do + # stub_env('FOO', 'bar') + # end + class EnvAssignment < Cop + include SpecHelpers + + MESSAGE = "Don't assign to ENV, use `stub_env` instead.".freeze + + def_node_search :env_assignment?, <<~PATTERN + (send (const nil? :ENV) :[]= ...) + PATTERN + + # Following is what node.children looks like on a match + # [s(:const, nil, :ENV), :[]=, s(:str, "key"), s(:str, "value")] + def on_send(node) + return unless in_spec?(node) + return unless env_assignment?(node) + + add_offense(node, :expression, MESSAGE) + end + + def autocorrect(node) + lambda do |corrector| + corrector.replace(node.loc.expression, stub_env(env_key(node), env_value(node))) + end + end + + def env_key(node) + node.children[2].source + end + + def env_value(node) + node.children[3].source + end + + def stub_env(key, value) + "stub_env(#{key}, #{value})" + end + end + end + end +end diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb index 1df23899efb..4ebbe010e90 100644 --- a/rubocop/rubocop.rb +++ b/rubocop/rubocop.rb @@ -1,11 +1,11 @@ +require_relative 'cop/active_record_dependent' +require_relative 'cop/active_record_serialize' require_relative 'cop/custom_error_class' require_relative 'cop/gem_fetcher' -require_relative 'cop/active_record_serialize' -require_relative 'cop/redirect_with_status' +require_relative 'cop/in_batches' require_relative 'cop/polymorphic_associations' require_relative 'cop/project_path_helper' -require_relative 'cop/active_record_dependent' -require_relative 'cop/in_batches' +require_relative 'cop/redirect_with_status' require_relative 'cop/migration/add_column' require_relative 'cop/migration/add_column_with_default_to_large_table' require_relative 'cop/migration/add_concurrent_foreign_key' @@ -13,12 +13,13 @@ require_relative 'cop/migration/add_concurrent_index' require_relative 'cop/migration/add_index' require_relative 'cop/migration/add_timestamps' require_relative 'cop/migration/datetime' -require_relative 'cop/migration/safer_boolean_column' require_relative 'cop/migration/hash_index' require_relative 'cop/migration/remove_concurrent_index' require_relative 'cop/migration/remove_index' require_relative 'cop/migration/reversible_add_column_with_default' +require_relative 'cop/migration/safer_boolean_column' require_relative 'cop/migration/timestamps' require_relative 'cop/migration/update_column_in_batches' +require_relative 'cop/rspec/env_assignment' require_relative 'cop/rspec/single_line_hook' require_relative 'cop/rspec/verbose_include_metadata' diff --git a/rubocop/spec_helpers.rb b/rubocop/spec_helpers.rb new file mode 100644 index 00000000000..a702a083958 --- /dev/null +++ b/rubocop/spec_helpers.rb @@ -0,0 +1,12 @@ +module RuboCop + module SpecHelpers + SPEC_HELPERS = %w[spec_helper.rb rails_helper.rb].freeze + + # Returns true if the given node originated from the spec directory. + def in_spec?(node) + path = node.location.expression.source_buffer.name + + !SPEC_HELPERS.include?(File.basename(path)) && path.start_with?(File.join(Dir.pwd, 'spec')) + end + end +end |