Read about our upcoming Code of Conduct on this issue

projects.rb 11.5 KB
Newer Older
1
require_relative '../support/helpers/test_env'
2

3
FactoryBot.define do
4
  PAGES_ACCESS_LEVEL_SCHEMA_VERSION ||= 20180423204600
5

6
7
8
  # Project without repository
  #
  # Project does not have bare repository.
9
  # Use this factory if you don't need repository in tests
10
  factory :project, class: 'Project' do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
11
12
    sequence(:name) { |n| "project#{n}" }
    path { name.downcase.gsub(/\s/, '_') }
13
14
15
    # Behaves differently to nil due to cache_has_external_issue_tracker
    has_external_issue_tracker false

16
17
18
19
20
    # Associations
    namespace
    creator { group ? create(:user) : namespace&.owner }

    transient do
21
      # Nest Project Feature attributes
22
23
24
25
26
27
      wiki_access_level ProjectFeature::ENABLED
      builds_access_level ProjectFeature::ENABLED
      snippets_access_level ProjectFeature::ENABLED
      issues_access_level ProjectFeature::ENABLED
      merge_requests_access_level ProjectFeature::ENABLED
      repository_access_level ProjectFeature::ENABLED
28
      pages_access_level ProjectFeature::ENABLED
29
30
31
32

      # we can't assign the delegated `#ci_cd_settings` attributes directly, as the
      # `#ci_cd_settings` relation needs to be created first
      group_runners_enabled nil
33
34
      import_status nil
      import_jid nil
35
36
37
38
39
40
41
    end

    after(:create) do |project, evaluator|
      # Builds and MRs can't have higher visibility level than repository access level.
      builds_access_level = [evaluator.builds_access_level, evaluator.repository_access_level].min
      merge_requests_access_level = [evaluator.merge_requests_access_level, evaluator.repository_access_level].min

42
      hash = {
43
44
45
46
47
        wiki_access_level: evaluator.wiki_access_level,
        builds_access_level: builds_access_level,
        snippets_access_level: evaluator.snippets_access_level,
        issues_access_level: evaluator.issues_access_level,
        merge_requests_access_level: merge_requests_access_level,
48
49
50
51
52
53
54
55
        repository_access_level: evaluator.repository_access_level
      }

      if ActiveRecord::Migrator.current_version >= PAGES_ACCESS_LEVEL_SCHEMA_VERSION
        hash.store("pages_access_level", evaluator.pages_access_level)
      end

      project.project_feature.update(hash)
56
57
58
59
60
61

      # Normally the class Projects::CreateService is used for creating
      # projects, and this class takes care of making sure the owner and current
      # user have access to the project. Our specs don't use said service class,
      # thus we must manually refresh things here.
      unless project.group || project.pending_delete
62
        project.add_maintainer(project.owner)
63
64
65
      end

      project.group&.refresh_members_authorized_projects
66
67
68

      # assign the delegated `#ci_cd_settings` attributes after create
      project.reload.group_runners_enabled = evaluator.group_runners_enabled unless evaluator.group_runners_enabled.nil?
69
70
71
72
73
74
75

      if evaluator.import_status
        import_state = project.import_state || project.build_import_state
        import_state.status = evaluator.import_status
        import_state.jid = evaluator.import_jid
        import_state.save
      end
76
77
    end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
78
79
80
81
82
83
84
85
86
87
88
    trait :public do
      visibility_level Gitlab::VisibilityLevel::PUBLIC
    end

    trait :internal do
      visibility_level Gitlab::VisibilityLevel::INTERNAL
    end

    trait :private do
      visibility_level Gitlab::VisibilityLevel::PRIVATE
    end
89

90
    trait :import_scheduled do
91
      import_status :scheduled
92
93
94
    end

    trait :import_started do
95
      import_status :started
96
97
98
    end

    trait :import_finished do
99
      import_status :finished
100
101
102
    end

    trait :import_failed do
103
      import_status :failed
104
105
    end

106
107
108
109
    trait :archived do
      archived true
    end

Nick Thomas's avatar
Nick Thomas committed
110
111
112
113
    storage_version Project::LATEST_STORAGE_VERSION

    trait :legacy_storage do
      storage_version nil
114
115
    end

116
117
118
119
    trait :access_requestable do
      request_access_enabled true
    end

120
    trait :with_avatar do
121
      avatar { fixture_file_upload('spec/fixtures/dk.png') }
122
123
    end

124
    trait :with_export do
125
126
127
128
129
      after(:create) do |project, _evaluator|
        ProjectExportWorker.new.perform(project.creator.id, project.id)
      end
    end

130
131
132
133
134
135
    trait :broken_storage do
      after(:create) do |project|
        project.update_column(:repository_storage, 'broken')
      end
    end

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
    # Build a custom repository by specifying a hash of `filename => content` in
    # the transient `files` attribute. Each file will be created in its own
    # commit, operating against the master branch. So, the following call:
    #
    #     create(:project, :custom_repo, files: { 'foo/a.txt' => 'foo', 'b.txt' => bar' })
    #
    # will create a repository containing two files, and two commits, in master
    trait :custom_repo do
      transient do
        files {}
      end

      after :create do |project, evaluator|
        raise "Failed to create repository!" unless project.create_repository

        evaluator.files.each do |filename, content|
          project.repository.create_file(
            project.creator,
            filename,
            content,
            message: "Automatically created file #{filename}",
            branch_name: 'master'
          )
        end
      end
    end

163
    # Test repository - https://gitlab.com/gitlab-org/gitlab-test
164
    trait :repository do
165
166
167
      test_repo

      transient do
168
        create_templates nil
169
170
171
      end

      after :create do |project, evaluator|
172
173
        if evaluator.create_templates
          templates_path = "#{evaluator.create_templates}_templates"
174
175

          project.repository.create_file(
176
177
            project.creator,
            ".gitlab/#{templates_path}/bug.md",
178
179
180
181
            'something valid',
            message: 'test 3',
            branch_name: 'master')
          project.repository.create_file(
182
183
            project.creator,
            ".gitlab/#{templates_path}/template_test.md",
184
185
186
187
            'template_test',
            message: 'test 1',
            branch_name: 'master')
          project.repository.create_file(
188
189
            project.creator,
            ".gitlab/#{templates_path}/feature_proposal.md",
190
191
192
193
194
            'feature_proposal',
            message: 'test 2',
            branch_name: 'master')
        end
      end
195
196
    end

197
198
    trait :empty_repo do
      after(:create) do |project|
199
        raise "Failed to create repository!" unless project.create_repository
200
201
      end
    end
Felipe Artur's avatar
Felipe Artur committed
202

203
204
205
206
207
208
209
210
211
212
213
    trait :remote_mirror do
      transient do
        remote_name "remote_mirror_#{SecureRandom.hex}"
        url "http://foo.com"
        enabled true
      end
      after(:create) do |project, evaluator|
        project.remote_mirrors.create!(url: evaluator.url, enabled: evaluator.enabled)
      end
    end

214
215
216
217
    trait :stubbed_repository do
      after(:build) do |project|
        allow(project).to receive(:empty_repo?).and_return(false)
        allow(project.repository).to receive(:empty?).and_return(false)
218
219
      end
    end
Felipe Artur's avatar
Felipe Artur committed
220

221
222
223
224
225
226
    trait :wiki_repo do
      after(:create) do |project|
        raise 'Failed to create wiki repository!' unless project.create_wiki
      end
    end

Toon Claes's avatar
Toon Claes committed
227
    trait :read_only do
228
229
230
      repository_read_only true
    end

231
232
    trait :broken_repo do
      after(:create) do |project|
233
        raise "Failed to create repository!" unless project.create_repository
234

235
236
        project.gitlab_shell.rm_directory(project.repository_storage,
                                          File.join("#{project.disk_path}.git", 'refs'))
237
238
239
      end
    end

240
241
    trait :test_repo do
      after :create do |project|
242
243
244
        TestEnv.copy_repo(project,
          bare_repo: TestEnv.factory_repo_path_bare,
          refs: TestEnv::BRANCH_SHA)
245
246
247
      end
    end

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    trait(:wiki_enabled)            { wiki_access_level ProjectFeature::ENABLED }
    trait(:wiki_disabled)           { wiki_access_level ProjectFeature::DISABLED }
    trait(:wiki_private)            { wiki_access_level ProjectFeature::PRIVATE }
    trait(:builds_enabled)          { builds_access_level ProjectFeature::ENABLED }
    trait(:builds_disabled)         { builds_access_level ProjectFeature::DISABLED }
    trait(:builds_private)          { builds_access_level ProjectFeature::PRIVATE }
    trait(:snippets_enabled)        { snippets_access_level ProjectFeature::ENABLED }
    trait(:snippets_disabled)       { snippets_access_level ProjectFeature::DISABLED }
    trait(:snippets_private)        { snippets_access_level ProjectFeature::PRIVATE }
    trait(:issues_disabled)         { issues_access_level ProjectFeature::DISABLED }
    trait(:issues_enabled)          { issues_access_level ProjectFeature::ENABLED }
    trait(:issues_private)          { issues_access_level ProjectFeature::PRIVATE }
    trait(:merge_requests_enabled)  { merge_requests_access_level ProjectFeature::ENABLED }
    trait(:merge_requests_disabled) { merge_requests_access_level ProjectFeature::DISABLED }
    trait(:merge_requests_private)  { merge_requests_access_level ProjectFeature::PRIVATE }
    trait(:repository_enabled)      { repository_access_level ProjectFeature::ENABLED }
    trait(:repository_disabled)     { repository_access_level ProjectFeature::DISABLED }
    trait(:repository_private)      { repository_access_level ProjectFeature::PRIVATE }
266
267
268
269
    trait(:pages_public)            { pages_access_level ProjectFeature::PUBLIC }
    trait(:pages_enabled)           { pages_access_level ProjectFeature::ENABLED }
    trait(:pages_disabled)          { pages_access_level ProjectFeature::DISABLED }
    trait(:pages_private)           { pages_access_level ProjectFeature::PRIVATE }
270
271
272
273

    trait :auto_devops do
      association :auto_devops, factory: :project_auto_devops
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
274
275
  end

276
277
278
279
  # Project with empty repository
  #
  # This is a case when you just created a project
  # but not pushed any code there yet
280
  factory :project_empty_repo, parent: :project do
281
    empty_repo
282
283
  end

284
285
286
  # Project with broken repository
  #
  # Project with an invalid repository state
287
  factory :project_broken_repo, parent: :project do
288
289
290
    broken_repo
  end

291
  factory :forked_project_with_submodules, parent: :project do
292
293
294
    path { 'forked-gitlabhq' }

    after :create do |project|
295
296
297
      TestEnv.copy_repo(project,
        bare_repo: TestEnv.forked_repo_path_bare,
        refs: TestEnv::FORKED_BRANCH_SHA)
298
299
300
    end
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
301
  factory :redmine_project, parent: :project do
302
303
    has_external_issue_tracker true

304
305
306
307
    after :create do |project|
      project.create_redmine_service(
        active: true,
        properties: {
308
          'project_url' => 'http://redmine/projects/project_name_in_redmine',
309
          'issues_url' => 'http://redmine/projects/project_name_in_redmine/issues/:id',
310
          'new_issue_url' => 'http://redmine/projects/project_name_in_redmine/issues/new'
311
312
313
        }
      )
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
314
  end
315

Yauhen Kotau's avatar
Yauhen Kotau committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
  factory :youtrack_project, parent: :project do
    has_external_issue_tracker true

    after :create do |project|
      project.create_youtrack_service(
        active: true,
        properties: {
          'project_url' => 'http://youtrack/projects/project_guid_in_youtrack',
          'issues_url' => 'http://youtrack/issues/:id',
          'new_issue_url' => 'http://youtrack/newIssue'
        }
      )
    end
  end

331
  factory :jira_project, parent: :project do
332
    has_external_issue_tracker true
333
    jira_service
334
  end
335

336
  factory :kubernetes_project, parent: :project do
337
    kubernetes_service
338
  end
339

340
341
342
343
  factory :mock_deployment_project, parent: :project do
    mock_deployment_service
  end

344
  factory :prometheus_project, parent: :project do
345
346
347
348
    after :create do |project|
      project.create_prometheus_service(
        active: true,
        properties: {
349
          api_url: 'https://prometheus.example.com/',
350
          manual_configuration: true
351
352
353
354
        }
      )
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
355
end