Welcome to mirror list, hosted at ThFree Co, Russian Federation.

create_table_with_foreign_keys_spec.rb « migration « cop « rubocop « spec - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 072edb5827b05baacf7dd1b5ef42b10e9912f5f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# frozen_string_literal: true

require 'rubocop_spec_helper'
require_relative '../../../../rubocop/cop/migration/create_table_with_foreign_keys'

RSpec.describe RuboCop::Cop::Migration::CreateTableWithForeignKeys do
  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 'when 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_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