diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-18 23:02:30 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-18 23:02:30 +0300 |
commit | 41fe97390ceddf945f3d967b8fdb3de4c66b7dea (patch) | |
tree | 9c8d89a8624828992f06d892cd2f43818ff5dcc8 /spec/rubocop | |
parent | 0804d2dc31052fb45a1efecedc8e06ce9bc32862 (diff) |
Add latest changes from gitlab-org/gitlab@14-9-stable-eev14.9.0-rc42
Diffstat (limited to 'spec/rubocop')
-rw-r--r-- | spec/rubocop/cop/database/establish_connection_spec.rb | 2 | ||||
-rw-r--r-- | spec/rubocop/cop/database/multiple_databases_spec.rb | 10 | ||||
-rw-r--r-- | spec/rubocop/cop/graphql/graphql_name_position_spec.rb | 44 | ||||
-rw-r--r-- | spec/rubocop/formatter/todo_formatter_spec.rb | 284 | ||||
-rw-r--r-- | spec/rubocop/todo_dir_spec.rb | 218 |
5 files changed, 557 insertions, 1 deletions
diff --git a/spec/rubocop/cop/database/establish_connection_spec.rb b/spec/rubocop/cop/database/establish_connection_spec.rb index a3c27d33cb0..3919872b5e7 100644 --- a/spec/rubocop/cop/database/establish_connection_spec.rb +++ b/spec/rubocop/cop/database/establish_connection_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'spec_helper' +require 'fast_spec_helper' require_relative '../../../../rubocop/cop/database/establish_connection' RSpec.describe RuboCop::Cop::Database::EstablishConnection do diff --git a/spec/rubocop/cop/database/multiple_databases_spec.rb b/spec/rubocop/cop/database/multiple_databases_spec.rb index 16b916d61db..8bcd4710305 100644 --- a/spec/rubocop/cop/database/multiple_databases_spec.rb +++ b/spec/rubocop/cop/database/multiple_databases_spec.rb @@ -12,4 +12,14 @@ RSpec.describe RuboCop::Cop::Database::MultipleDatabases do ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use methods from ActiveRecord::Base, [...] SOURCE end + + described_class::ALLOWED_METHODS.each do |method_name| + it "does not flag use of ActiveRecord::Base.#{method_name}" do + expect_no_offenses(<<~SOURCE) + ActiveRecord::Base.#{method_name} do + Project.save + end + SOURCE + end + end end diff --git a/spec/rubocop/cop/graphql/graphql_name_position_spec.rb b/spec/rubocop/cop/graphql/graphql_name_position_spec.rb new file mode 100644 index 00000000000..42cc398ed84 --- /dev/null +++ b/spec/rubocop/cop/graphql/graphql_name_position_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +require_relative '../../../../rubocop/cop/graphql/graphql_name_position' + +RSpec.describe RuboCop::Cop::Graphql::GraphqlNamePosition do + subject(:cop) { described_class.new } + + it 'adds an offense when graphql_name is not on the first line' do + expect_offense(<<~TYPE) + module Types + class AType < BaseObject + ^^^^^^^^^^^^^^^^^^^^^^^^ `graphql_name` should be the first line of the class: https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#naming-conventions + field :a_thing + field :another_thing + graphql_name 'ATypeName' + end + end + TYPE + end + + it 'does not add an offense for classes that have no call to graphql_name' do + expect_no_offenses(<<~TYPE.strip) + module Types + class AType < BaseObject + authorize :an_ability, :second_ability + + field :a_thing + end + end + TYPE + end + + it 'does not add an offense for classes that only call graphql_name' do + expect_no_offenses(<<~TYPE.strip) + module Types + class AType < BaseObject + graphql_name 'ATypeName' + end + end + TYPE + end +end diff --git a/spec/rubocop/formatter/todo_formatter_spec.rb b/spec/rubocop/formatter/todo_formatter_spec.rb new file mode 100644 index 00000000000..e1b1de33bfe --- /dev/null +++ b/spec/rubocop/formatter/todo_formatter_spec.rb @@ -0,0 +1,284 @@ +# frozen_string_literal: true +# rubocop:disable RSpec/VerifiedDoubles + +require 'fast_spec_helper' +require 'stringio' +require 'fileutils' + +require_relative '../../../rubocop/formatter/todo_formatter' +require_relative '../../../rubocop/todo_dir' + +RSpec.describe RuboCop::Formatter::TodoFormatter do + let(:stdout) { StringIO.new } + let(:tmp_dir) { Dir.mktmpdir } + let(:real_tmp_dir) { File.join(tmp_dir, 'real') } + let(:symlink_tmp_dir) { File.join(tmp_dir, 'symlink') } + let(:rubocop_todo_dir) { "#{symlink_tmp_dir}/.rubocop_todo" } + let(:options) { { rubocop_todo_dir: rubocop_todo_dir } } + let(:todo_dir) { RuboCop::TodoDir.new(rubocop_todo_dir) } + + subject(:formatter) { described_class.new(stdout, options) } + + around do |example| + FileUtils.mkdir(real_tmp_dir) + FileUtils.symlink(real_tmp_dir, symlink_tmp_dir) + + Dir.chdir(symlink_tmp_dir) do + example.run + end + end + + after do + FileUtils.remove_entry(tmp_dir) + end + + context 'with offenses detected' do + let(:offense) { fake_offense('A/Offense') } + let(:offense_too_many) { fake_offense('B/TooManyOffenses') } + let(:offense_autocorrect) { fake_offense('B/AutoCorrect') } + + before do + stub_const("#{described_class}::MAX_OFFENSE_COUNT", 1) + + stub_rubocop_registry( + 'A/Offense' => { autocorrectable: false }, + 'B/AutoCorrect' => { autocorrectable: true } + ) + end + + def run_formatter + formatter.started(%w[a.rb b.rb c.rb d.rb]) + formatter.file_finished('c.rb', [offense_too_many]) + formatter.file_finished('a.rb', [offense_too_many, offense, offense_too_many]) + formatter.file_finished('b.rb', []) + formatter.file_finished('d.rb', [offense_autocorrect]) + formatter.finished(%w[a.rb b.rb c.rb d.rb]) + end + + it 'outputs its actions' do + run_formatter + + expect(stdout.string).to eq(<<~OUTPUT) + Written to .rubocop_todo/a/offense.yml + Written to .rubocop_todo/b/auto_correct.yml + Written to .rubocop_todo/b/too_many_offenses.yml + OUTPUT + end + + it 'creates YAML files', :aggregate_failures do + run_formatter + + expect(rubocop_todo_dir_listing).to contain_exactly( + 'a/offense.yml', 'b/auto_correct.yml', 'b/too_many_offenses.yml' + ) + + expect(todo_yml('A/Offense')).to eq(<<~YAML) + --- + A/Offense: + Exclude: + - 'a.rb' + YAML + + expect(todo_yml('B/AutoCorrect')).to eq(<<~YAML) + --- + # Cop supports --auto-correct. + B/AutoCorrect: + Exclude: + - 'd.rb' + YAML + + expect(todo_yml('B/TooManyOffenses')).to eq(<<~YAML) + --- + B/TooManyOffenses: + Exclude: + - 'a.rb' + - 'c.rb' + YAML + end + + context 'when cop previously not explicitly disabled' do + before do + todo_dir.write('B/TooManyOffenses', <<~YAML) + --- + B/TooManyOffenses: + Exclude: + - 'x.rb' + YAML + end + + it 'does not disable cop' do + run_formatter + + expect(todo_yml('B/TooManyOffenses')).to eq(<<~YAML) + --- + B/TooManyOffenses: + Exclude: + - 'a.rb' + - 'c.rb' + YAML + end + end + + context 'when cop previously explicitly disabled in rubocop_todo/' do + before do + todo_dir.write('B/TooManyOffenses', <<~YAML) + --- + B/TooManyOffenses: + Enabled: false + Exclude: + - 'x.rb' + YAML + + todo_dir.inspect_all + end + + it 'keeps cop disabled' do + run_formatter + + expect(todo_yml('B/TooManyOffenses')).to eq(<<~YAML) + --- + B/TooManyOffenses: + # Offense count: 3 + # Temporarily disabled due to too many offenses + Enabled: false + Exclude: + - 'a.rb' + - 'c.rb' + YAML + end + end + + context 'when cop previously explicitly disabled in rubocop_todo.yml' do + before do + File.write('.rubocop_todo.yml', <<~YAML) + --- + B/TooManyOffenses: + Enabled: false + Exclude: + - 'x.rb' + YAML + end + + it 'keeps cop disabled' do + run_formatter + + expect(todo_yml('B/TooManyOffenses')).to eq(<<~YAML) + --- + B/TooManyOffenses: + # Offense count: 3 + # Temporarily disabled due to too many offenses + Enabled: false + Exclude: + - 'a.rb' + - 'c.rb' + YAML + end + end + + context 'with cop configuration in both .rubocop_todo/ and .rubocop_todo.yml' do + before do + todo_dir.write('B/TooManyOffenses', <<~YAML) + --- + B/TooManyOffenses: + Exclude: + - 'a.rb' + YAML + + todo_dir.write('A/Offense', <<~YAML) + --- + A/Offense: + Exclude: + - 'a.rb' + YAML + + todo_dir.inspect_all + + File.write('.rubocop_todo.yml', <<~YAML) + --- + B/TooManyOffenses: + Exclude: + - 'x.rb' + A/Offense: + Exclude: + - 'y.rb' + YAML + end + + it 'raises an error' do + expect { run_formatter }.to raise_error(RuntimeError, <<~TXT) + Multiple configurations found for cops: + - A/Offense + - B/TooManyOffenses + TXT + end + end + end + + context 'without offenses detected' do + before do + formatter.started(%w[a.rb b.rb]) + formatter.file_finished('a.rb', []) + formatter.file_finished('b.rb', []) + formatter.finished(%w[a.rb b.rb]) + end + + it 'does not output anything' do + expect(stdout.string).to eq('') + end + + it 'does not write any YAML files' do + expect(rubocop_todo_dir_listing).to be_empty + end + end + + context 'without files to inspect' do + before do + formatter.started([]) + formatter.finished([]) + end + + it 'does not output anything' do + expect(stdout.string).to eq('') + end + + it 'does not write any YAML files' do + expect(rubocop_todo_dir_listing).to be_empty + end + end + + private + + def rubocop_todo_dir_listing + Dir.glob("#{rubocop_todo_dir}/**/*") + .select { |path| File.file?(path) } + .map { |path| path.delete_prefix("#{rubocop_todo_dir}/") } + end + + def todo_yml(cop_name) + todo_dir.read(cop_name) + end + + def fake_offense(cop_name) + double(:offense, cop_name: cop_name) + end + + def stub_rubocop_registry(**cops) + rubocop_registry = double(:rubocop_registry) + + allow(RuboCop::Cop::Registry).to receive(:global).and_return(rubocop_registry) + + allow(rubocop_registry).to receive(:find_by_cop_name) + .with(String).and_return(nil) + + cops.each do |cop_name, attributes| + allow(rubocop_registry).to receive(:find_by_cop_name) + .with(cop_name).and_return(fake_cop(**attributes)) + end + end + + def fake_cop(autocorrectable:) + double(:cop, support_autocorrect?: autocorrectable) + end +end + +# rubocop:enable RSpec/VerifiedDoubles diff --git a/spec/rubocop/todo_dir_spec.rb b/spec/rubocop/todo_dir_spec.rb new file mode 100644 index 00000000000..ae59def885d --- /dev/null +++ b/spec/rubocop/todo_dir_spec.rb @@ -0,0 +1,218 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' +require 'fileutils' +require 'active_support/inflector/inflections' + +require_relative '../../rubocop/todo_dir' + +RSpec.describe RuboCop::TodoDir do + let(:todo_dir) { described_class.new(directory) } + let(:directory) { Dir.mktmpdir } + let(:cop_name) { 'RSpec/VariableInstance' } + let(:cop_name_underscore) { ActiveSupport::Inflector.underscore(cop_name) } + let(:yaml_path) { "#{File.join(directory, cop_name_underscore)}.yml" } + + around do |example| + Dir.chdir(directory) do + example.run + end + end + + after do + FileUtils.remove_entry(directory) + end + + describe '#initialize' do + context 'when passing inflector' do + let(:fake_inflector) { double(:inflector) } # rubocop:disable RSpec/VerifiedDoubles + let(:todo_dir) { described_class.new(directory, inflector: fake_inflector) } + + before do + allow(fake_inflector).to receive(:underscore) + .with(cop_name) + .and_return(cop_name_underscore) + end + + it 'calls .underscore' do + todo_dir.write(cop_name, 'a') + + expect(fake_inflector).to have_received(:underscore) + end + end + end + + describe '#directory' do + subject { todo_dir.directory } + + it { is_expected.to eq(directory) } + end + + describe '#read' do + let(:content) { 'a' } + + subject { todo_dir.read(cop_name) } + + context 'when file exists' do + before do + todo_dir.write(cop_name, content) + end + + it { is_expected.to eq(content) } + end + + context 'when file is missing' do + it { is_expected.to be_nil } + end + end + + describe '#write' do + let(:content) { 'a' } + + subject { todo_dir.write(cop_name, content) } + + it { is_expected.to eq(yaml_path) } + + it 'writes content to YAML file' do + subject + + expect(File.read(yaml_path)).to eq(content) + end + end + + describe '#inspect' do + subject { todo_dir.inspect(cop_name) } + + context 'with existing YAML file' do + before do + todo_dir.write(cop_name, 'a') + end + + it { is_expected.to eq(true) } + + it 'moves YAML file to .inspect' do + subject + + expect(File).not_to exist(yaml_path) + expect(File).to exist("#{yaml_path}.inspect") + end + end + + context 'with missing YAML file' do + it { is_expected.to eq(false) } + end + end + + describe '#inspect_all' do + subject { todo_dir.inspect_all } + + context 'with YAML files' do + before do + todo_dir.write(cop_name, 'a') + todo_dir.write('Other/Rule', 'a') + todo_dir.write('Very/Nested/Rule', 'a') + end + + it { is_expected.to eq(3) } + + it 'moves all YAML files to .inspect' do + subject + + expect(Dir.glob('**/*.yml')).to be_empty + expect(Dir.glob('**/*.yml.inspect').size).to eq(3) + end + end + + context 'with non-YAML files' do + before do + File.write('file', 'a') + File.write('file.txt', 'a') + File.write('file.yaml', 'a') # not .yml + end + + it { is_expected.to eq(0) } + + it 'does not move non-YAML files' do + subject + + expect(Dir.glob('**/*')) + .to contain_exactly('file', 'file.txt', 'file.yaml') + end + end + + context 'without files' do + it { is_expected.to eq(0) } + end + end + + describe '#list_inspect' do + let(:content) { 'a' } + + subject { todo_dir.list_inspect } + + context 'when file exists and is being inspected' do + before do + todo_dir.write(cop_name, content) + todo_dir.inspect_all + end + + it do + is_expected.to contain_exactly("#{yaml_path}.inspect") + end + end + + context 'when file exists but not being inspected' do + before do + todo_dir.write(cop_name, content) + end + + it { is_expected.to be_empty } + end + + context 'when file is missing' do + it { is_expected.to be_empty } + end + end + + describe '#delete_inspected' do + subject { todo_dir.delete_inspected } + + context 'with YAML files' do + before do + todo_dir.write(cop_name, 'a') + todo_dir.write('Other/Rule', 'a') + todo_dir.write('Very/Nested/Rule', 'a') + todo_dir.inspect_all + end + + it { is_expected.to eq(3) } + + it 'deletes all .inspected YAML files' do + subject + + expect(Dir.glob('**/*.yml.inspect')).to be_empty + end + end + + context 'with non-YAML files' do + before do + File.write('file.inspect', 'a') + File.write('file.txt.inspect', 'a') + File.write('file.yaml.inspect', 'a') # not .yml + end + + it { is_expected.to eq(0) } + + it 'does not delete non-YAML files' do + subject + + expect(Dir.glob('**/*')).to contain_exactly( + 'file.inspect', 'file.txt.inspect', 'file.yaml.inspect') + end + end + + context 'without files' do + it { is_expected.to eq(0) } + end + end +end |