206 lines
6.7 KiB
Ruby
206 lines
6.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'fast_spec_helper'
|
|
require 'rubocop'
|
|
require_relative '../../../../rubocop/cop/migration/create_table_with_foreign_keys'
|
|
|
|
RSpec.describe RuboCop::Cop::Migration::CreateTableWithForeignKeys, type: :rubocop do
|
|
include CopHelper
|
|
|
|
let(:cop) { described_class.new }
|
|
|
|
context 'outside of a migration' do
|
|
it 'does not register any offenses' do
|
|
expect_no_offenses(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
t.references :bar, foreign_key: { on_delete: 'cascade' }
|
|
t.references :zoo, foreign_key: { on_delete: 'cascade' }
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
|
|
context 'in a migration' do
|
|
before do
|
|
allow(cop).to receive(:in_migration?).and_return(true)
|
|
end
|
|
|
|
context 'without foreign key' do
|
|
it 'does not register any offenses' do
|
|
expect_no_offenses(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
t.references :bar
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
|
|
context 'with foreign key' do
|
|
context 'with just one foreign key' do
|
|
context 'when the foreign_key targets a high traffic table' do
|
|
context 'when the foreign_key has to_table option set' do
|
|
it 'does not register any offenses' do
|
|
expect_no_offenses(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
t.references :project, "foreign_key" => { on_delete: 'cascade', to_table: 'projects' }
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
|
|
context 'when the foreign_key does not have to_table option set' do
|
|
it 'does not register any offenses' do
|
|
expect_no_offenses(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
t.references :project, foreign_key: { on_delete: 'cascade' }
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when the foreign_key does not target a high traffic table' do
|
|
it 'does not register any offenses' do
|
|
expect_no_offenses(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
t.references :bar, foreign_key: { on_delete: 'cascade' }
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with more than one foreign keys' do
|
|
let(:offense) do
|
|
'Creating a table with more than one foreign key at once violates our migration style guide. ' \
|
|
'For more details check the https://docs.gitlab.com/ee/development/migration_style_guide.html#examples'
|
|
end
|
|
|
|
shared_examples 'target to high traffic table' do |dsl_method, table_name|
|
|
context 'when the target is defined as option' do
|
|
it 'registers an offense ' do
|
|
expect_offense(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
^^^^^^^^^^^^^^^^^^ #{offense}
|
|
t.#{dsl_method} :#{table_name.singularize} #{explicit_target_opts}
|
|
t.#{dsl_method} :zoo #{implicit_target_opts}
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
|
|
context 'when the target has implicit definition' do
|
|
it 'registers an offense ' do
|
|
expect_offense(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
^^^^^^^^^^^^^^^^^^ #{offense}
|
|
t.#{dsl_method} :#{table_name.singularize} #{implicit_target_opts}
|
|
t.#{dsl_method} :zoo #{implicit_target_opts}
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_context 'when there is a target to a high traffic table' do |dsl_method|
|
|
%w[
|
|
audit_events
|
|
ci_build_trace_sections
|
|
ci_builds
|
|
ci_builds_metadata
|
|
ci_job_artifacts
|
|
ci_pipeline_variables
|
|
ci_pipelines
|
|
ci_stages
|
|
deployments
|
|
events
|
|
gitlab_subscriptions
|
|
issues
|
|
merge_request_diff_commits
|
|
merge_request_diff_files
|
|
merge_request_diffs
|
|
merge_request_metrics
|
|
merge_requests
|
|
namespaces
|
|
note_diff_files
|
|
notes
|
|
project_authorizations
|
|
projects
|
|
project_ci_cd_settings
|
|
project_features
|
|
push_event_payloads
|
|
resource_label_events
|
|
routes
|
|
sent_notifications
|
|
system_note_metadata
|
|
taggings
|
|
todos
|
|
users
|
|
web_hook_logs
|
|
].each do |table|
|
|
let(:table_name) { table }
|
|
|
|
it_behaves_like 'target to high traffic table', dsl_method, table
|
|
end
|
|
end
|
|
|
|
context 'when the foreign keys are defined as options' do
|
|
context 'when there is no target to a high traffic table' do
|
|
it 'does not register any offenses' do
|
|
expect_no_offenses(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
t.references :bar, foreign_key: { on_delete: 'cascade', to_table: :bars }
|
|
t.references :zoo, 'foreign_key' => { on_delete: 'cascade' }
|
|
t.references :john, 'foreign_key' => { on_delete: 'cascade' }
|
|
t.references :doe, 'foreign_key' => { on_delete: 'cascade', to_table: 'doe' }
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
|
|
include_context 'when there is a target to a high traffic table', :references do
|
|
let(:explicit_target_opts) { ", foreign_key: { to_table: :#{table_name} }" }
|
|
let(:implicit_target_opts) { ", foreign_key: true" }
|
|
end
|
|
end
|
|
|
|
context 'when the foreign keys are defined by standlone migration helper' do
|
|
context 'when there is no target to a high traffic table' do
|
|
it 'does not register any offenses' do
|
|
expect_no_offenses(<<~RUBY)
|
|
def up
|
|
create_table(:foo) do |t|
|
|
t.foreign_key :bar
|
|
t.foreign_key :zoo, to_table: 'zoos'
|
|
end
|
|
end
|
|
RUBY
|
|
end
|
|
end
|
|
|
|
include_context 'when there is a target to a high traffic table', :foreign_key do
|
|
let(:explicit_target_opts) { ", to_table: :#{table_name}" }
|
|
let(:implicit_target_opts) { }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|