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
202
203
|
# frozen_string_literal: true
require 'spec_helper'
# `:saas` is used to test `gitlab_subscription` factory.
# It's not available on FOSS but also this very factory is not.
RSpec.describe 'factories', :saas do
include Database::DatabaseHelpers
# Used in `skipped` and indicates whether to skip any traits including the
# plain factory.
any = Object.new
# https://gitlab.com/groups/gitlab-org/-/epics/5464 tracks the remaining
# skipped factories or traits.
#
# Consider adding a code comment if a trait cannot produce a valid object.
skipped = [
[:audit_event, :unauthenticated],
[:ci_build_trace_chunk, :fog_with_data],
[:ci_job_artifact, :remote_store],
[:ci_job_artifact, :raw],
[:ci_job_artifact, :gzip],
[:ci_job_artifact, :correct_checksum],
[:dependency_proxy_blob, :remote_store],
[:environment, :non_playable],
[:composer_cache_file, :object_storage],
[:debian_project_component_file, :object_storage],
[:debian_project_distribution, :object_storage],
[:debian_file_metadatum, :unknown],
[:issue_customer_relations_contact, :for_contact],
[:issue_customer_relations_contact, :for_issue],
[:package_file, :object_storage],
[:rpm_repository_file, :object_storage],
[:pages_domain, :without_certificate],
[:pages_domain, :without_key],
[:pages_domain, :with_missing_chain],
[:pages_domain, :with_trusted_chain],
[:pages_domain, :with_trusted_expired_chain],
[:pages_domain, :explicit_ecdsa],
[:project_member, :blocked],
[:remote_mirror, :ssh],
[:user_preference, :only_comments],
[:ci_pipeline_artifact, :remote_store],
# EE
[:dast_profile, :with_dast_site_validation],
[:ee_ci_build, :dependency_scanning_report],
[:ee_ci_build, :license_scan_v1],
[:ee_ci_job_artifact, :v1],
[:ee_ci_job_artifact, :v1_1],
[:ee_ci_job_artifact, :v2],
[:ee_ci_job_artifact, :v2_1],
[:geo_ci_secure_file_state, any],
[:geo_dependency_proxy_blob_state, any],
[:geo_event_log, :geo_event],
[:geo_job_artifact_state, any],
[:geo_lfs_object_state, any],
[:geo_pages_deployment_state, any],
[:geo_upload_state, any],
[:geo_ci_secure_file_state, any],
[:lfs_object, :checksum_failure],
[:lfs_object, :checksummed],
[:merge_request, :blocked],
[:merge_request_diff, :verification_failed],
[:merge_request_diff, :verification_succeeded],
[:package_file, :verification_failed],
[:package_file, :verification_succeeded],
[:project, :with_vulnerabilities],
[:scan_execution_policy, :with_schedule_and_agent],
[:vulnerability, :with_cluster_image_scanning_finding],
[:vulnerability, :with_findings],
[:vulnerability_export, :finished]
].freeze
shared_examples 'factory' do |factory|
skip_any = skipped.include?([factory.name, any])
describe "#{factory.name} factory" do
it 'does not raise error when built' do
# We use `skip` here because using `build` mostly work even if
# factories break when creating them.
skip 'Factory skipped linting due to legacy error' if skip_any
expect { build(factory.name) }.not_to raise_error
end
it 'does not raise error when created' do
pending 'Factory skipped linting due to legacy error' if skip_any
expect { create(factory.name) }.not_to raise_error # rubocop:disable Rails/SaveBang
end
factory.definition.defined_traits.map(&:name).each do |trait_name|
skip_trait = skip_any || skipped.include?([factory.name, trait_name.to_sym])
describe "linting :#{trait_name} trait" do
it 'does not raise error when created' do
pending 'Trait skipped linting due to legacy error' if skip_trait
expect { create(factory.name, trait_name) }.not_to raise_error
end
end
end
end
end
# FactoryDefault speed up specs by creating associations only once
# and reuse them in other factories.
#
# However, for some factories we cannot use FactoryDefault because the
# associations must be unique and cannot be reused, or the factory default
# is being mutated.
skip_factory_defaults = %i[
ci_job_token_project_scope_link
ci_subscriptions_project
evidence
exported_protected_branch
fork_network_member
group_member
import_state
issue_customer_relations_contact
member_task
merge_request_block
milestone_release
namespace
project_namespace
project_repository
project_security_setting
prometheus_alert
prometheus_alert_event
prometheus_metric
protected_branch
protected_branch_merge_access_level
protected_branch_push_access_level
protected_branch_unprotect_access_level
protected_tag
protected_tag_create_access_level
release
release_link
self_managed_prometheus_alert_event
shard
users_star_project
vulnerabilities_finding_identifier
wiki_page
wiki_page_meta
].to_set.freeze
# Some factories and their corresponding models are based on
# database views. In order to use those, we have to swap the
# view out with a table of the same structure.
factories_based_on_view = %i[
postgres_index
postgres_index_bloat_estimate
postgres_autovacuum_activity
].to_set.freeze
without_fd, with_fd = FactoryBot.factories
.partition { |factory| skip_factory_defaults.include?(factory.name) }
# Some EE models check licensed features so stub them.
shared_context 'with licensed features' do
licensed_features = %i[
board_milestone_lists
board_assignee_lists
].index_with(true)
if Gitlab.jh?
licensed_features.merge! %i[
dingtalk_integration
feishu_bot_integration
].index_with(true)
end
before do
stub_licensed_features(licensed_features)
end
end
include_context 'with licensed features' if Gitlab.ee?
context 'with factory defaults', factory_default: :keep do
let_it_be(:namespace) { create_default(:namespace).freeze }
let_it_be(:project) { create_default(:project, :repository).freeze }
let_it_be(:user) { create_default(:user).freeze }
before do
factories_based_on_view.each do |factory|
view = build(factory).class.table_name
swapout_view_for_table(view)
end
end
with_fd.each do |factory|
it_behaves_like 'factory', factory
end
end
context 'without factory defaults' do
without_fd.each do |factory|
it_behaves_like 'factory', factory
end
end
end
|