diff options
Diffstat (limited to 'spec/rubocop/cop')
-rw-r--r-- | spec/rubocop/cop/api/ensure_string_detail_spec.rb | 136 | ||||
-rw-r--r-- | spec/rubocop/cop/gitlab/json_spec.rb | 45 | ||||
-rw-r--r-- | spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb | 4 | ||||
-rw-r--r-- | spec/rubocop/cop/gitlab/rspec/avoid_setup_spec.rb | 36 | ||||
-rw-r--r-- | spec/rubocop/cop/graphql/enum_names_spec.rb | 52 | ||||
-rw-r--r-- | spec/rubocop/cop/graphql/enum_values_spec.rb | 79 | ||||
-rw-r--r-- | spec/rubocop/cop/migration/schema_addition_methods_no_post_spec.rb | 24 | ||||
-rw-r--r-- | spec/rubocop/cop/rake/require_spec.rb | 60 | ||||
-rw-r--r-- | spec/rubocop/cop/rspec/duplicate_spec_location_spec.rb (renamed from spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb) | 18 | ||||
-rw-r--r-- | spec/rubocop/cop/rspec/factory_bot/strategy_in_callback_spec.rb | 71 |
10 files changed, 512 insertions, 13 deletions
diff --git a/spec/rubocop/cop/api/ensure_string_detail_spec.rb b/spec/rubocop/cop/api/ensure_string_detail_spec.rb new file mode 100644 index 00000000000..d4f68711e78 --- /dev/null +++ b/spec/rubocop/cop/api/ensure_string_detail_spec.rb @@ -0,0 +1,136 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' +require_relative '../../../../rubocop/cop/api/ensure_string_detail' + +RSpec.describe RuboCop::Cop::API::EnsureStringDetail do + context "when in_api? == true" do + before do + allow(cop).to receive(:in_api?).and_return(true) + end + + context "when detail field uses a string" do + it "does not add an offense" do + expect_no_offenses(<<~CODE) + class SomeAPI + resource :projects do + desc 'Some API thing related to a project' do + detail "foo bar" + end + end + end + CODE + end + end + + context "when detail field uses interpolation in a string" do + it "does not add an offense" do + baz = "bat" + + expect_no_offenses(<<~CODE) + class SomeAPI + resource :projects do + desc 'Some API thing related to a project' do + detail "foo bar #{baz}" + end + end + end + CODE + end + end + + context "when detail field uses a multiline string" do + it "does not add an offense" do + expect_no_offenses(<<~CODE) + class SomeAPI + resource :projects do + desc 'Some API thing related to a project' do + detail "foo bar"\ + "baz bat" + end + end + end + CODE + end + end + + context "when detail field uses a constant" do + it "does not add an offense" do + pending + + expect_no_offenses(<<~CODE) + class SomeAPI + resource :projects do + DESCRIPTION = 'A string' + + desc 'Some API thing related to a project' do + detail DESCRIPTION + end + end + end + CODE + end + end + + context "when detail field uses a HEREDOC string" do + it "does not add an offense" do + expect_no_offenses(<<~CODE) + class SomeAPI + resource :projects do + desc 'Some API thing related to a project' do + detail <<~END + foo bar + baz bat + END + end + end + end + CODE + end + end + + context "when detail field uses an array" do + it "adds an offense" do + expect_offense(<<~CODE) + class SomeAPI + resource :projects do + desc 'Some API thing related to a project' do + something 'else' + detail ["foo", "bar"] + ^^^^^^^^^^^^^^^^^^^^^ Only String objects are permitted in API detail field. + end + end + end + CODE + end + end + + context "when detail field is outside of desc block" do + it "does not add an offense" do + expect_no_offenses(<<~CODE) + class Foo + detail ["foo", "bar"] + end + CODE + end + end + end + + context "when in_api? == false" do + before do + allow(cop).to receive(:in_api?).and_return(false) + end + + it "does not add an offense" do + expect_no_offenses(<<~CODE) + class SomeAPI + resource :projects do + desc 'Some API thing related to a project' do + detail ["foo", "bar"] + end + end + end + CODE + end + end +end diff --git a/spec/rubocop/cop/gitlab/json_spec.rb b/spec/rubocop/cop/gitlab/json_spec.rb index e4ec107747d..70f63a78dd1 100644 --- a/spec/rubocop/cop/gitlab/json_spec.rb +++ b/spec/rubocop/cop/gitlab/json_spec.rb @@ -5,12 +5,41 @@ require_relative '../../../../rubocop/cop/gitlab/json' RSpec.describe RuboCop::Cop::Gitlab::Json do context 'when ::JSON is called' do - it 'registers an offense' do + it 'registers an offense and autocorrects' do expect_offense(<<~RUBY) class Foo def bar JSON.parse('{ "foo": "bar" }') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid calling `JSON` directly. [...] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `Gitlab::Json` over calling `JSON` directly. [...] + end + end + RUBY + + expect_correction(<<~RUBY) + class Foo + def bar + Gitlab::Json.parse('{ "foo": "bar" }') + end + end + RUBY + end + end + + context 'when ::JSON is called in EE' do + it 'registers an offense and autocorrects' do + expect_offense(<<~RUBY, '/path/to/ee/foo.rb') + class Foo + def bar + JSON.parse('{ "foo": "bar" }') + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `Gitlab::Json` over calling `JSON` directly. [...] + end + end + RUBY + + expect_correction(<<~RUBY) + class Foo + def bar + ::Gitlab::Json.parse('{ "foo": "bar" }') end end RUBY @@ -18,12 +47,20 @@ RSpec.describe RuboCop::Cop::Gitlab::Json do end context 'when ActiveSupport::JSON is called' do - it 'registers an offense' do + it 'registers an offense and autocorrects' do expect_offense(<<~RUBY) class Foo def bar ActiveSupport::JSON.parse('{ "foo": "bar" }') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid calling `JSON` directly. [...] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `Gitlab::Json` over calling `JSON` directly. [...] + end + end + RUBY + + expect_correction(<<~RUBY) + class Foo + def bar + Gitlab::Json.parse('{ "foo": "bar" }') end end RUBY diff --git a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb index a3c9ae8916e..6e60889f737 100644 --- a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb +++ b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb @@ -194,6 +194,10 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do include_examples 'sets flag as used', 'FEATURE_FLAG = :foo', 'foo' end + describe 'ROUTING_FEATURE_FLAG = :foo' do + include_examples 'sets flag as used', 'ROUTING_FEATURE_FLAG = :foo', 'foo' + end + describe 'Worker `data_consistency` method' do include_examples 'sets flag as used', 'data_consistency :delayed, feature_flag: :foo', 'foo' include_examples 'does not set any flags as used', 'data_consistency :delayed' diff --git a/spec/rubocop/cop/gitlab/rspec/avoid_setup_spec.rb b/spec/rubocop/cop/gitlab/rspec/avoid_setup_spec.rb new file mode 100644 index 00000000000..f9226649f65 --- /dev/null +++ b/spec/rubocop/cop/gitlab/rspec/avoid_setup_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' + +require_relative '../../../../../rubocop/cop/gitlab/rspec/avoid_setup' + +RSpec.describe RuboCop::Cop::Gitlab::RSpec::AvoidSetup do + context 'when calling let_it_be' do + let(:source) do + <<~SRC + let_it_be(:user) { create(:user) } + ^^^^^^^^^^^^^^^^ Avoid the use of `let_it_be` [...] + SRC + end + + it 'registers an offense' do + expect_offense(source) + end + end + + context 'without readability issues' do + let(:source) do + <<~SRC + it 'registers the user and sends them to a project listing page' do + user_signs_up + + expect_to_see_account_confirmation_page + end + SRC + end + + it 'does not register an offense' do + expect_no_offenses(source) + end + end +end diff --git a/spec/rubocop/cop/graphql/enum_names_spec.rb b/spec/rubocop/cop/graphql/enum_names_spec.rb new file mode 100644 index 00000000000..f45df068381 --- /dev/null +++ b/spec/rubocop/cop/graphql/enum_names_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' +require_relative '../../../../rubocop/cop/graphql/enum_names' + +RSpec.describe RuboCop::Cop::Graphql::EnumNames do + describe 'class name' do + it 'adds an offense when class name does not end with `Enum`' do + expect_offense(<<~ENUM) + module Types + class Fake < BaseEnum + ^^^^ #{described_class::CLASS_NAME_SUFFIX_MSG} + graphql_name 'Fake' + end + end + ENUM + end + end + + describe 'graphql_name' do + it 'adds an offense when `graphql_name` is not set' do + expect_offense(<<~ENUM) + module Types + class FakeEnum < BaseEnum + ^^^^^^^^^^^^^^^^^^^^^^^^^ #{described_class::GRAPHQL_NAME_MISSING_MSG} + end + end + ENUM + end + + it 'adds no offense when `declarative_enum` is used' do + expect_no_offenses(<<~ENUM) + module Types + class FakeEnum < BaseEnum + declarative_enum ::FakeModule::FakeDeclarativeEnum + end + end + ENUM + end + + it 'adds an offense when `graphql_name` includes `enum`' do + expect_offense(<<~ENUM) + module Types + class FakeEnum < BaseEnum + graphql_name 'FakeEnum' + ^^^^^^^^^^ #{described_class::GRAPHQL_NAME_WITH_ENUM_MSG} + end + end + ENUM + end + end +end diff --git a/spec/rubocop/cop/graphql/enum_values_spec.rb b/spec/rubocop/cop/graphql/enum_values_spec.rb new file mode 100644 index 00000000000..5609c86d9ec --- /dev/null +++ b/spec/rubocop/cop/graphql/enum_values_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' +require_relative '../../../../rubocop/cop/graphql/enum_values' + +RSpec.describe RuboCop::Cop::Graphql::EnumValues do + it 'adds an offense when enum value is not uppercase' do + expect_offense(<<~ENUM) + module Types + class FakeEnum < BaseEnum + graphql_name 'Fake' + + value 'downcase', description: "Downcase." + ^^^^^^^^^^ #{described_class::MSG} + end + end + ENUM + end + + context 'when values are set dynamically' do + it 'adds an offense when enum value is set without `:upcase`' do + expect_offense(<<~ENUM) + VALUES = ['FOO', 'bar'] + + module Types + class FakeEnum < BaseEnum + graphql_name 'Fake' + + VALUES.each do |val| + value val, description: "Dynamic value." + ^^^ #{described_class::MSG} + end + end + end + ENUM + end + + it 'adds no offense when enum value is deprecated' do + expect_no_offenses(<<~ENUM) + module Types + class FakeEnum < BaseEnum + graphql_name 'Fake' + + value 'foo', deprecated: { reason: 'Use something else' } + end + end + ENUM + end + + it 'adds no offense when enum value is uppercased literally' do + expect_no_offenses(<<~'ENUM') + module Types + class FakeEnum < BaseEnum + graphql_name 'Fake' + + value 'FOO' + end + end + ENUM + end + + it 'adds no offense when enum value is calling upcased' do + expect_no_offenses(<<~'ENUM') + VALUES = ['FOO', 'bar'] + + module Types + class FakeEnum < BaseEnum + graphql_name 'Fake' + + VALUES.each do |val| + value val.underscore.upcase, description: "Dynamic value." + value "#{field.upcase.tr(' ', '_')}_ASC" + end + end + end + ENUM + end + end +end diff --git a/spec/rubocop/cop/migration/schema_addition_methods_no_post_spec.rb b/spec/rubocop/cop/migration/schema_addition_methods_no_post_spec.rb new file mode 100644 index 00000000000..fb087269e2d --- /dev/null +++ b/spec/rubocop/cop/migration/schema_addition_methods_no_post_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' +require_relative '../../../../rubocop/cop/migration/schema_addition_methods_no_post' + +RSpec.describe RuboCop::Cop::Migration::SchemaAdditionMethodsNoPost do + before do + allow(cop).to receive(:time_enforced?).and_return true + end + + it "does not allow 'add_column' to be called" do + expect_offense(<<~CODE) + add_column + ^^^^^^^^^^ #{described_class::MSG} + CODE + end + + it "does not allow 'create_table' to be called" do + expect_offense(<<~CODE) + create_table + ^^^^^^^^^^^^ #{described_class::MSG} + CODE + end +end diff --git a/spec/rubocop/cop/rake/require_spec.rb b/spec/rubocop/cop/rake/require_spec.rb new file mode 100644 index 00000000000..bb8c6a1f063 --- /dev/null +++ b/spec/rubocop/cop/rake/require_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' + +require_relative '../../../../rubocop/cop/rake/require' + +RSpec.describe RuboCop::Cop::Rake::Require do + let(:msg) { described_class::MSG } + + it 'registers an offenses for require methods' do + expect_offense(<<~RUBY) + require 'json' + ^^^^^^^^^^^^^^ #{msg} + require_relative 'gitlab/json' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg} + RUBY + end + + it 'does not register offense inside `task` definition' do + expect_no_offenses(<<~RUBY) + task :parse do + require 'json' + end + + namespace :some do + task parse: :env do + require_relative 'gitlab/json' + end + end + RUBY + end + + it 'does not register offense inside a block definition' do + expect_no_offenses(<<~RUBY) + RSpec::Core::RakeTask.new(:parse_json) do |t, args| + require 'json' + end + RUBY + end + + it 'does not register offense inside a method definition' do + expect_no_offenses(<<~RUBY) + def load_deps + require 'json' + end + + task :parse do + load_deps + end + RUBY + end + + it 'does not register offense when require task related files' do + expect_no_offenses(<<~RUBY) + require 'rubocop/rake_tasks' + require 'gettext_i18n_rails/tasks' + require_relative '../../rubocop/check_graceful_task' + RUBY + end +end diff --git a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb b/spec/rubocop/cop/rspec/duplicate_spec_location_spec.rb index 0a121a495c9..f209ae81661 100644 --- a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb +++ b/spec/rubocop/cop/rspec/duplicate_spec_location_spec.rb @@ -2,16 +2,16 @@ require 'rubocop_spec_helper' -require_relative '../../../../rubocop/cop/gitlab/duplicate_spec_location' +require_relative '../../../../rubocop/cop/rspec/duplicate_spec_location' -RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec do +RSpec.describe RuboCop::Cop::RSpec::DuplicateSpecLocation do let(:rails_root) { '../../../../' } def full_path(path) File.expand_path(File.join(rails_root, path), __dir__) end - context 'Non-EE spec file' do + context 'for a non-EE spec file' do it 'registers no offenses' do expect_no_offenses(<<~SOURCE, full_path('spec/foo_spec.rb')) describe 'Foo' do @@ -20,7 +20,7 @@ RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec end end - context 'Non-EE application file' do + context 'for a non-EE application file' do it 'registers no offenses' do expect_no_offenses(<<~SOURCE, full_path('app/models/blog_post.rb')) class BlogPost @@ -29,7 +29,7 @@ RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec end end - context 'EE application file' do + context 'for an EE application file' do it 'registers no offenses' do expect_no_offenses(<<~SOURCE, full_path('ee/app/models/blog_post.rb')) class BlogPost @@ -38,7 +38,7 @@ RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec end end - context 'EE spec file for EE only code' do + context 'for an EE spec file for EE only code' do let(:spec_file_path) { full_path('ee/spec/controllers/foo_spec.rb') } it 'registers no offenses' do @@ -48,7 +48,7 @@ RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec SOURCE end - context 'there is a duplicate file' do + context 'when there is a duplicate file' do before do allow(File).to receive(:exist?).and_call_original @@ -67,7 +67,7 @@ RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec end end - context 'EE spec file for EE extension' do + context 'for an EE spec file for EE extension' do let(:spec_file_path) { full_path('ee/spec/controllers/ee/foo_spec.rb') } it 'registers no offenses' do @@ -77,7 +77,7 @@ RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation, type: :rubocop_rspec SOURCE end - context 'there is a duplicate file' do + context 'when there is a duplicate file' do before do allow(File).to receive(:exist?).and_call_original diff --git a/spec/rubocop/cop/rspec/factory_bot/strategy_in_callback_spec.rb b/spec/rubocop/cop/rspec/factory_bot/strategy_in_callback_spec.rb new file mode 100644 index 00000000000..9dcfebc7c1d --- /dev/null +++ b/spec/rubocop/cop/rspec/factory_bot/strategy_in_callback_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' + +require_relative '../../../../../rubocop/cop/rspec/factory_bot/strategy_in_callback' + +RSpec.describe RuboCop::Cop::RSpec::FactoryBot::StrategyInCallback do + shared_examples 'an offensive factory call' do |namespace| + described_class::FORBIDDEN_METHODS.each do |forbidden_method| + namespaced_forbidden_method = "#{namespace}#{forbidden_method}(:ci_job_artifact, :archive)" + + it "registers an offence for multiple #{namespaced_forbidden_method} calls" do + expect_offense(<<-RUBY) + FactoryBot.define do + factory :ci_build, class: 'Ci::Build', parent: :ci_processable do + trait :artifacts do + before(:create) do + #{namespaced_forbidden_method} + #{'^' * namespaced_forbidden_method.size} Prefer inline `association` over `#{forbidden_method}`. See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#factories + end + + after(:create) do |build| + #{namespaced_forbidden_method} + #{'^' * namespaced_forbidden_method.size} Prefer inline `association` over `#{forbidden_method}`. See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#factories + #{namespaced_forbidden_method} + #{'^' * namespaced_forbidden_method.size} Prefer inline `association` over `#{forbidden_method}`. See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#factories + end + end + end + end + RUBY + end + + it "registers an offense for #{namespaced_forbidden_method} when is a send node" do + expect_offense(<<-RUBY) + FactoryBot.define do + factory :ci_build, class: 'Ci::Build', parent: :ci_processable do + trait :artifacts do + after(:create) do |build| + #{namespaced_forbidden_method} + #{'^' * namespaced_forbidden_method.size} Prefer inline `association` over `#{forbidden_method}`. See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#factories + end + end + end + end + RUBY + end + + it "registers an offense for #{namespaced_forbidden_method} when is assigned" do + expect_offense(<<-RUBY) + FactoryBot.define do + factory :ci_build, class: 'Ci::Build', parent: :ci_processable do + trait :artifacts do + after(:create) do |build| + ci_build = #{namespaced_forbidden_method} + #{'^' * namespaced_forbidden_method.size} Prefer inline `association` over `#{forbidden_method}`. See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#factories + + ci_build + end + end + end + end + RUBY + end + end + end + + it_behaves_like 'an offensive factory call', '' + it_behaves_like 'an offensive factory call', 'FactoryBot.' + it_behaves_like 'an offensive factory call', '::FactoryBot.' +end |