diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
commit | f64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch) | |
tree | a2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /spec/lib/gitlab/background_migration | |
parent | bfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff) |
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'spec/lib/gitlab/background_migration')
8 files changed, 391 insertions, 132 deletions
diff --git a/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb new file mode 100644 index 00000000000..8febe850e04 --- /dev/null +++ b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy, '#next_batch' do + let(:batching_strategy) { described_class.new } + let(:namespaces) { table(:namespaces) } + + let!(:namespace1) { namespaces.create!(name: 'batchtest1', path: 'batch-test1') } + let!(:namespace2) { namespaces.create!(name: 'batchtest2', path: 'batch-test2') } + let!(:namespace3) { namespaces.create!(name: 'batchtest3', path: 'batch-test3') } + let!(:namespace4) { namespaces.create!(name: 'batchtest4', path: 'batch-test4') } + + context 'when starting on the first batch' do + it 'returns the bounds of the next batch' do + batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace1.id, batch_size: 3) + + expect(batch_bounds).to eq([namespace1.id, namespace3.id]) + end + end + + context 'when additional batches remain' do + it 'returns the bounds of the next batch' do + batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace2.id, batch_size: 3) + + expect(batch_bounds).to eq([namespace2.id, namespace4.id]) + end + end + + context 'when on the final batch' do + it 'returns the bounds of the next batch' do + batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3) + + expect(batch_bounds).to eq([namespace4.id, namespace4.id]) + end + end + + context 'when no additional batches remain' do + it 'returns nil' do + batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id + 1, batch_size: 1) + + expect(batch_bounds).to be_nil + end + end +end diff --git a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb index 110a1ff8a08..7ad93c3124a 100644 --- a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb +++ b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb @@ -38,22 +38,9 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo describe '#perform' do let(:migration_class) { described_class.name } - let!(:job1) do - table(:background_migration_jobs).create!( - class_name: migration_class, - arguments: [1, 10, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size] - ) - end - - let!(:job2) do - table(:background_migration_jobs).create!( - class_name: migration_class, - arguments: [11, 20, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size] - ) - end it 'copies all primary keys in range' do - subject.perform(12, 15, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size) + subject.perform(12, 15, table_name, 'id', sub_batch_size, 'id', 'id_convert_to_bigint') expect(test_table.where('id = id_convert_to_bigint').pluck(:id)).to contain_exactly(12, 15) expect(test_table.where(id_convert_to_bigint: 0).pluck(:id)).to contain_exactly(11, 19) @@ -61,7 +48,7 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo end it 'copies all foreign keys in range' do - subject.perform(10, 14, table_name, 'id', 'fk', 'fk_convert_to_bigint', sub_batch_size) + subject.perform(10, 14, table_name, 'id', sub_batch_size, 'fk', 'fk_convert_to_bigint') expect(test_table.where('fk = fk_convert_to_bigint').pluck(:id)).to contain_exactly(11, 12) expect(test_table.where(fk_convert_to_bigint: 0).pluck(:id)).to contain_exactly(15, 19) @@ -71,21 +58,11 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo it 'copies columns with NULLs' do expect(test_table.where("name_convert_to_text = 'no name'").count).to eq(4) - subject.perform(10, 20, table_name, 'id', 'name', 'name_convert_to_text', sub_batch_size) + subject.perform(10, 20, table_name, 'id', sub_batch_size, 'name', 'name_convert_to_text') expect(test_table.where('name = name_convert_to_text').pluck(:id)).to contain_exactly(11, 12, 19) expect(test_table.where('name is NULL and name_convert_to_text is NULL').pluck(:id)).to contain_exactly(15) expect(test_table.where("name_convert_to_text = 'no name'").count).to eq(0) end - - it 'tracks completion with BackgroundMigrationJob' do - expect do - subject.perform(11, 20, table_name, 'id', 'id', 'id_convert_to_bigint', sub_batch_size) - end.to change { Gitlab::Database::BackgroundMigrationJob.succeeded.count }.from(0).to(1) - - expect(job1.reload.status).to eq(0) - expect(job2.reload.status).to eq(1) - expect(test_table.where('id = id_convert_to_bigint').count).to eq(4) - end end end diff --git a/spec/lib/gitlab/background_migration/merge_request_assignees_migration_progress_check_spec.rb b/spec/lib/gitlab/background_migration/merge_request_assignees_migration_progress_check_spec.rb deleted file mode 100644 index 85a9c88ebff..00000000000 --- a/spec/lib/gitlab/background_migration/merge_request_assignees_migration_progress_check_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::MergeRequestAssigneesMigrationProgressCheck do - context 'rescheduling' do - context 'when there are ongoing and no dead jobs' do - it 'reschedules check' do - allow(Gitlab::BackgroundMigration).to receive(:exists?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(true) - - allow(Gitlab::BackgroundMigration).to receive(:dead_jobs?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(false) - - expect(BackgroundMigrationWorker).to receive(:perform_in).with(described_class::RESCHEDULE_DELAY, described_class.name) - - described_class.new.perform - end - end - - context 'when there are ongoing and dead jobs' do - it 'reschedules check' do - allow(Gitlab::BackgroundMigration).to receive(:exists?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(true) - - allow(Gitlab::BackgroundMigration).to receive(:dead_jobs?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(true) - - expect(BackgroundMigrationWorker).to receive(:perform_in).with(described_class::RESCHEDULE_DELAY, described_class.name) - - described_class.new.perform - end - end - - context 'when there retrying jobs and no scheduled' do - it 'reschedules check' do - allow(Gitlab::BackgroundMigration).to receive(:exists?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(false) - - allow(Gitlab::BackgroundMigration).to receive(:retrying_jobs?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(true) - - expect(BackgroundMigrationWorker).to receive(:perform_in).with(described_class::RESCHEDULE_DELAY, described_class.name) - - described_class.new.perform - end - end - end - - context 'when there are no scheduled, or retrying or dead' do - before do - stub_feature_flags(multiple_merge_request_assignees: false) - end - - it 'enables feature' do - allow(Gitlab::BackgroundMigration).to receive(:exists?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(false) - - allow(Gitlab::BackgroundMigration).to receive(:retrying_jobs?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(false) - - allow(Gitlab::BackgroundMigration).to receive(:dead_jobs?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(false) - - described_class.new.perform - - expect(Feature.enabled?(:multiple_merge_request_assignees, type: :licensed)).to eq(true) - end - end - - context 'when there are only dead jobs' do - it 'raises DeadJobsError error' do - allow(Gitlab::BackgroundMigration).to receive(:exists?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(false) - - allow(Gitlab::BackgroundMigration).to receive(:retrying_jobs?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(false) - - allow(Gitlab::BackgroundMigration).to receive(:dead_jobs?) - .with('PopulateMergeRequestAssigneesTable') - .and_return(true) - - expect { described_class.new.perform } - .to raise_error(described_class::DeadJobsError, - "Only dead background jobs in the queue for #{described_class::WORKER}") - end - end -end diff --git a/spec/lib/gitlab/background_migration/migrate_legacy_artifacts_spec.rb b/spec/lib/gitlab/background_migration/migrate_legacy_artifacts_spec.rb index 08f2b2a043e..5c93e69b5e5 100644 --- a/spec/lib/gitlab/background_migration/migrate_legacy_artifacts_spec.rb +++ b/spec/lib/gitlab/background_migration/migrate_legacy_artifacts_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BackgroundMigration::MigrateLegacyArtifacts do +RSpec.describe Gitlab::BackgroundMigration::MigrateLegacyArtifacts, schema: 20210210093901 do let(:namespaces) { table(:namespaces) } let(:projects) { table(:projects) } let(:pipelines) { table(:ci_pipelines) } diff --git a/spec/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature_spec.rb b/spec/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature_spec.rb new file mode 100644 index 00000000000..1c62d703a34 --- /dev/null +++ b/spec/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature_spec.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::MoveContainerRegistryEnabledToProjectFeature, :migration, schema: 2021_02_26_120851 do + let(:enabled) { 20 } + let(:disabled) { 0 } + + let(:namespaces) { table(:namespaces) } + let(:project_features) { table(:project_features) } + let(:projects) { table(:projects) } + + let(:namespace) { namespaces.create!(name: 'user', path: 'user') } + let!(:project1) { projects.create!(namespace_id: namespace.id) } + let!(:project2) { projects.create!(namespace_id: namespace.id) } + let!(:project3) { projects.create!(namespace_id: namespace.id) } + let!(:project4) { projects.create!(namespace_id: namespace.id) } + + # pages_access_level cannot be null. + let(:non_null_project_features) { { pages_access_level: enabled } } + let!(:project_feature1) { project_features.create!(project_id: project1.id, **non_null_project_features) } + let!(:project_feature2) { project_features.create!(project_id: project2.id, **non_null_project_features) } + let!(:project_feature3) { project_features.create!(project_id: project3.id, **non_null_project_features) } + + describe '#perform' do + before do + project1.update!(container_registry_enabled: true) + project2.update!(container_registry_enabled: false) + project3.update!(container_registry_enabled: nil) + project4.update!(container_registry_enabled: true) + end + + it 'copies values to project_features' do + expect(project1.container_registry_enabled).to eq(true) + expect(project2.container_registry_enabled).to eq(false) + expect(project3.container_registry_enabled).to eq(nil) + expect(project4.container_registry_enabled).to eq(true) + + expect(project_feature1.container_registry_access_level).to eq(disabled) + expect(project_feature2.container_registry_access_level).to eq(disabled) + expect(project_feature3.container_registry_access_level).to eq(disabled) + + expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |logger| + expect(logger).to receive(:info) + .with(message: "#{described_class}: Copied container_registry_enabled values for projects with IDs between #{project1.id}..#{project4.id}") + + expect(logger).not_to receive(:info) + end + + subject.perform(project1.id, project4.id) + + expect(project1.reload.container_registry_enabled).to eq(true) + expect(project2.reload.container_registry_enabled).to eq(false) + expect(project3.reload.container_registry_enabled).to eq(nil) + expect(project4.container_registry_enabled).to eq(true) + + expect(project_feature1.reload.container_registry_access_level).to eq(enabled) + expect(project_feature2.reload.container_registry_access_level).to eq(disabled) + expect(project_feature3.reload.container_registry_access_level).to eq(disabled) + end + + context 'when no projects exist in range' do + it 'does not fail' do + expect(project1.container_registry_enabled).to eq(true) + expect(project_feature1.container_registry_access_level).to eq(disabled) + + expect { subject.perform(-1, -2) }.not_to raise_error + + expect(project1.container_registry_enabled).to eq(true) + expect(project_feature1.container_registry_access_level).to eq(disabled) + end + end + + context 'when projects in range all have nil container_registry_enabled' do + it 'does not fail' do + expect(project3.container_registry_enabled).to eq(nil) + expect(project_feature3.container_registry_access_level).to eq(disabled) + + expect { subject.perform(project3.id, project3.id) }.not_to raise_error + + expect(project3.container_registry_enabled).to eq(nil) + expect(project_feature3.container_registry_access_level).to eq(disabled) + end + end + end +end diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb index 8e74935e127..07b1d99d333 100644 --- a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb +++ b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb @@ -27,12 +27,33 @@ RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityF let(:finding_1) { finding_creator.call(sast_report, location_fingerprint_1) } let(:finding_2) { finding_creator.call(dast_report, location_fingerprint_2) } let(:finding_3) { finding_creator.call(secret_detection_report, location_fingerprint_3) } - let(:uuid_1_components) { ['sast', identifier.fingerprint, location_fingerprint_1, project.id].join('-') } - let(:uuid_2_components) { ['dast', identifier.fingerprint, location_fingerprint_2, project.id].join('-') } - let(:uuid_3_components) { ['secret_detection', identifier.fingerprint, location_fingerprint_3, project.id].join('-') } - let(:expected_uuid_1) { Gitlab::UUID.v5(uuid_1_components) } - let(:expected_uuid_2) { Gitlab::UUID.v5(uuid_2_components) } - let(:expected_uuid_3) { Gitlab::UUID.v5(uuid_3_components) } + let(:expected_uuid_1) do + Security::VulnerabilityUUID.generate( + report_type: 'sast', + primary_identifier_fingerprint: identifier.fingerprint, + location_fingerprint: location_fingerprint_1, + project_id: project.id + ) + end + + let(:expected_uuid_2) do + Security::VulnerabilityUUID.generate( + report_type: 'dast', + primary_identifier_fingerprint: identifier.fingerprint, + location_fingerprint: location_fingerprint_2, + project_id: project.id + ) + end + + let(:expected_uuid_3) do + Security::VulnerabilityUUID.generate( + report_type: 'secret_detection', + primary_identifier_fingerprint: identifier.fingerprint, + location_fingerprint: location_fingerprint_3, + project_id: project.id + ) + end + let(:finding_creator) do -> (report_type, location_fingerprint) do findings.create!( diff --git a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb new file mode 100644 index 00000000000..990ef4fbe6a --- /dev/null +++ b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb @@ -0,0 +1,149 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid, schema: 20201110110454 do + let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') } + let(:users) { table(:users) } + let(:user) { create_user! } + let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) } + let(:scanners) { table(:vulnerability_scanners) } + let(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') } + let(:different_scanner) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') } + let(:vulnerabilities) { table(:vulnerabilities) } + let(:vulnerabilities_findings) { table(:vulnerability_occurrences) } + let(:vulnerability_identifiers) { table(:vulnerability_identifiers) } + let(:vulnerability_identifier) do + vulnerability_identifiers.create!( + project_id: project.id, + external_type: 'uuid-v5', + external_id: 'uuid-v5', + fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a', + name: 'Identifier for UUIDv5') + end + + let(:different_vulnerability_identifier) do + vulnerability_identifiers.create!( + project_id: project.id, + external_type: 'uuid-v4', + external_id: 'uuid-v4', + fingerprint: '772da93d34a1ba010bcb5efa9fb6f8e01bafcc89', + name: 'Identifier for UUIDv4') + end + + let!(:vulnerability_for_uuidv4) do + create_vulnerability!( + project_id: project.id, + author_id: user.id + ) + end + + let!(:vulnerability_for_uuidv5) do + create_vulnerability!( + project_id: project.id, + author_id: user.id + ) + end + + let(:known_uuid_v5) { "77211ed6-7dff-5f6b-8c9a-da89ad0a9b60" } + let(:known_uuid_v4) { "b3cc2518-5446-4dea-871c-89d5e999c1ac" } + let(:desired_uuid_v5) { "3ca8ad45-6344-508b-b5e3-306a3bd6c6ba" } + + subject { described_class.new.perform(finding.id, finding.id) } + + context "when finding has a UUIDv4" do + before do + @uuid_v4 = create_finding!( + vulnerability_id: vulnerability_for_uuidv4.id, + project_id: project.id, + scanner_id: different_scanner.id, + primary_identifier_id: different_vulnerability_identifier.id, + report_type: 0, # "sast" + location_fingerprint: "fa18f432f1d56675f4098d318739c3cd5b14eb3e", + uuid: known_uuid_v4 + ) + end + + let(:finding) { @uuid_v4 } + + it "replaces it with UUIDv5" do + expect(vulnerabilities_findings.pluck(:uuid)).to eq([known_uuid_v4]) + + subject + + expect(vulnerabilities_findings.pluck(:uuid)).to eq([desired_uuid_v5]) + end + end + + context "when finding has a UUIDv5" do + before do + @uuid_v5 = create_finding!( + vulnerability_id: vulnerability_for_uuidv5.id, + project_id: project.id, + scanner_id: scanner.id, + primary_identifier_id: vulnerability_identifier.id, + report_type: 0, # "sast" + location_fingerprint: "838574be0210968bf6b9f569df9c2576242cbf0a", + uuid: known_uuid_v5 + ) + end + + let(:finding) { @uuid_v5 } + + it "stays the same" do + expect(vulnerabilities_findings.pluck(:uuid)).to eq([known_uuid_v5]) + + subject + + expect(vulnerabilities_findings.pluck(:uuid)).to eq([known_uuid_v5]) + end + end + + private + + def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0) + vulnerabilities.create!( + project_id: project_id, + author_id: author_id, + title: title, + severity: severity, + confidence: confidence, + report_type: report_type + ) + end + + # rubocop:disable Metrics/ParameterLists + def create_finding!( + vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:, + name: "test", severity: 7, confidence: 7, report_type: 0, + project_fingerprint: '123qweasdzxc', location_fingerprint: 'test', + metadata_version: 'test', raw_metadata: 'test', uuid: 'test') + vulnerabilities_findings.create!( + vulnerability_id: vulnerability_id, + project_id: project_id, + name: name, + severity: severity, + confidence: confidence, + report_type: report_type, + project_fingerprint: project_fingerprint, + scanner_id: scanner.id, + primary_identifier_id: vulnerability_identifier.id, + location_fingerprint: location_fingerprint, + metadata_version: metadata_version, + raw_metadata: raw_metadata, + uuid: uuid + ) + end + # rubocop:enable Metrics/ParameterLists + + def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.zone.now, confirmed_at: Time.zone.now) + users.create!( + name: name, + email: email, + username: name, + projects_limit: 0, + user_type: user_type, + confirmed_at: confirmed_at + ) + end +end diff --git a/spec/lib/gitlab/background_migration/set_default_iteration_cadences_spec.rb b/spec/lib/gitlab/background_migration/set_default_iteration_cadences_spec.rb new file mode 100644 index 00000000000..46c919f0854 --- /dev/null +++ b/spec/lib/gitlab/background_migration/set_default_iteration_cadences_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::SetDefaultIterationCadences, schema: 20201231133921 do + let(:namespaces) { table(:namespaces) } + let(:iterations) { table(:sprints) } + let(:iterations_cadences) { table(:iterations_cadences) } + + describe '#perform' do + context 'when no iteration cadences exists' do + let!(:group_1) { namespaces.create!(name: 'group 1', path: 'group-1') } + let!(:group_2) { namespaces.create!(name: 'group 2', path: 'group-2') } + let!(:group_3) { namespaces.create!(name: 'group 3', path: 'group-3') } + + let!(:iteration_1) { iterations.create!(group_id: group_1.id, iid: 1, title: 'Iteration 1', start_date: 10.days.ago, due_date: 8.days.ago) } + let!(:iteration_2) { iterations.create!(group_id: group_3.id, iid: 1, title: 'Iteration 2', start_date: 10.days.ago, due_date: 8.days.ago) } + let!(:iteration_3) { iterations.create!(group_id: group_3.id, iid: 1, title: 'Iteration 3', start_date: 5.days.ago, due_date: 2.days.ago) } + + subject { described_class.new.perform(group_1.id, group_2.id, group_3.id, namespaces.last.id + 1) } + + before do + subject + end + + it 'creates iterations_cadence records for the requested groups' do + expect(iterations_cadences.count).to eq(2) + end + + it 'assigns the iteration cadences to the iterations correctly' do + iterations_cadence = iterations_cadences.find_by(group_id: group_1.id) + iteration_records = iterations.where(iterations_cadence_id: iterations_cadence.id) + + expect(iterations_cadence.start_date).to eq(iteration_1.start_date) + expect(iterations_cadence.last_run_date).to eq(iteration_1.start_date) + expect(iterations_cadence.title).to eq('group 1 Iterations') + expect(iteration_records.size).to eq(1) + expect(iteration_records.first.id).to eq(iteration_1.id) + + iterations_cadence = iterations_cadences.find_by(group_id: group_3.id) + iteration_records = iterations.where(iterations_cadence_id: iterations_cadence.id) + + expect(iterations_cadence.start_date).to eq(iteration_3.start_date) + expect(iterations_cadence.last_run_date).to eq(iteration_3.start_date) + expect(iterations_cadence.title).to eq('group 3 Iterations') + expect(iteration_records.size).to eq(2) + expect(iteration_records.first.id).to eq(iteration_2.id) + expect(iteration_records.second.id).to eq(iteration_3.id) + end + + it 'does not call Group class' do + expect(::Group).not_to receive(:where) + + subject + end + end + + context 'when an iteration cadence exists for a group' do + let!(:group) { namespaces.create!(name: 'group', path: 'group') } + + let!(:iterations_cadence_1) { iterations_cadences.create!(group_id: group.id, start_date: 2.days.ago, title: 'Cadence 1') } + + let!(:iteration_1) { iterations.create!(group_id: group.id, iid: 1, title: 'Iteration 1', start_date: 10.days.ago, due_date: 8.days.ago) } + let!(:iteration_2) { iterations.create!(group_id: group.id, iterations_cadence_id: iterations_cadence_1.id, iid: 2, title: 'Iteration 2', start_date: 5.days.ago, due_date: 3.days.ago) } + + subject { described_class.new.perform(group.id) } + + it 'does not create a new iterations_cadence' do + expect { subject }.not_to change { iterations_cadences.count } + end + + it 'assigns iteration cadences to iterations if needed' do + subject + + expect(iteration_1.reload.iterations_cadence_id).to eq(iterations_cadence_1.id) + expect(iteration_2.reload.iterations_cadence_id).to eq(iterations_cadence_1.id) + end + end + end +end |