diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /spec/factories/design_management | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) | |
download | gitlab-ce-9f46488805e86b1bc341ea1620b866016c2ce5ed.tar.gz |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'spec/factories/design_management')
-rw-r--r-- | spec/factories/design_management/actions.rb | 13 | ||||
-rw-r--r-- | spec/factories/design_management/design_at_version.rb | 23 | ||||
-rw-r--r-- | spec/factories/design_management/designs.rb | 128 | ||||
-rw-r--r-- | spec/factories/design_management/versions.rb | 142 |
4 files changed, 306 insertions, 0 deletions
diff --git a/spec/factories/design_management/actions.rb b/spec/factories/design_management/actions.rb new file mode 100644 index 00000000000..e2561f98f52 --- /dev/null +++ b/spec/factories/design_management/actions.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :design_action, class: 'DesignManagement::Action' do + design + association :version, factory: :design_version + event { :creation } + + trait :with_image_v432x230 do + image_v432x230 { fixture_file_upload('spec/fixtures/dk.png') } + end + end +end diff --git a/spec/factories/design_management/design_at_version.rb b/spec/factories/design_management/design_at_version.rb new file mode 100644 index 00000000000..b73df71595c --- /dev/null +++ b/spec/factories/design_management/design_at_version.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :design_at_version, class: 'DesignManagement::DesignAtVersion' do + skip_create # This is not an Active::Record model. + + design { nil } + + version { nil } + + transient do + issue { design&.issue || version&.issue || create(:issue) } + end + + initialize_with do + attrs = attributes.dup + attrs[:design] ||= create(:design, issue: issue) + attrs[:version] ||= create(:design_version, issue: issue) + + new(attrs) + end + end +end diff --git a/spec/factories/design_management/designs.rb b/spec/factories/design_management/designs.rb new file mode 100644 index 00000000000..59d4cc56f95 --- /dev/null +++ b/spec/factories/design_management/designs.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :design, class: 'DesignManagement::Design' do + issue { create(:issue) } + project { issue&.project || create(:project) } + sequence(:filename) { |n| "homescreen-#{n}.jpg" } + + transient do + author { issue.author } + end + + trait :importing do + issue { nil } + + importing { true } + imported { false } + end + + trait :imported do + importing { false } + imported { true } + end + + create_versions = ->(design, evaluator, commit_version) do + unless evaluator.versions_count.zero? + project = design.project + issue = design.issue + repository = project.design_repository + repository.create_if_not_exists + dv_table_name = DesignManagement::Action.table_name + updates = [0, evaluator.versions_count - (evaluator.deleted ? 2 : 1)].max + + run_action = ->(action) do + sha = commit_version[action] + version = DesignManagement::Version.new(sha: sha, issue: issue, author: evaluator.author) + version.save(validate: false) # We need it to have an ID, validate later + Gitlab::Database.bulk_insert(dv_table_name, [action.row_attrs(version)]) + end + + # always a creation + run_action[DesignManagement::DesignAction.new(design, :create, evaluator.file)] + + # 0 or more updates + updates.times do + run_action[DesignManagement::DesignAction.new(design, :update, evaluator.file)] + end + + # and maybe a deletion + run_action[DesignManagement::DesignAction.new(design, :delete)] if evaluator.deleted + end + + design.clear_version_cache + end + + # Use this trait to build designs that are backed by Git LFS, committed + # to the repository, and with an LfsObject correctly created for it. + trait :with_lfs_file do + with_file + + transient do + raw_file { fixture_file_upload('spec/fixtures/dk.png', 'image/png') } + lfs_pointer { Gitlab::Git::LfsPointerFile.new(SecureRandom.random_bytes) } + file { lfs_pointer.pointer } + end + + after :create do |design, evaluator| + lfs_object = create(:lfs_object, file: evaluator.raw_file, oid: evaluator.lfs_pointer.sha256, size: evaluator.lfs_pointer.size) + create(:lfs_objects_project, project: design.project, lfs_object: lfs_object, repository_type: :design) + end + end + + # Use this trait if you want versions in a particular history, but don't + # want to pay for gitlay calls. + trait :with_versions do + transient do + deleted { false } + versions_count { 1 } + sequence(:file) { |n| "some-file-content-#{n}" } + end + + after :create do |design, evaluator| + counter = (1..).lazy + + # Just produce a SHA by hashing the action and a monotonic counter + commit_version = ->(action) do + Digest::SHA1.hexdigest("#{action.gitaly_action}.#{counter.next}") + end + + create_versions[design, evaluator, commit_version] + end + end + + # Use this trait to build designs that have commits in the repository + # and files that can be retrieved. + trait :with_file do + transient do + deleted { false } + versions_count { 1 } + file { File.join(Rails.root, 'spec/fixtures/dk.png') } + end + + after :create do |design, evaluator| + project = design.project + repository = project.design_repository + + commit_version = ->(action) do + repository.multi_action( + evaluator.author, + branch_name: 'master', + message: "#{action.action} for #{design.filename}", + actions: [action.gitaly_action] + ) + end + + create_versions[design, evaluator, commit_version] + end + end + + trait :with_smaller_image_versions do + with_lfs_file + + after :create do |design| + design.versions.each { |v| DesignManagement::GenerateImageVersionsService.new(v).execute } + end + end + end +end diff --git a/spec/factories/design_management/versions.rb b/spec/factories/design_management/versions.rb new file mode 100644 index 00000000000..e6d17ba691c --- /dev/null +++ b/spec/factories/design_management/versions.rb @@ -0,0 +1,142 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :design_version, class: 'DesignManagement::Version' do + sha + issue { designs.first&.issue || create(:issue) } + author { issue&.author || create(:user) } + + transient do + designs_count { 1 } + created_designs { [] } + modified_designs { [] } + deleted_designs { [] } + end + + # Warning: this will intentionally result in an invalid version! + trait :empty do + designs_count { 0 } + end + + trait :importing do + issue { nil } + + designs_count { 0 } + importing { true } + imported { false } + end + + trait :imported do + importing { false } + imported { true } + end + + after(:build) do |version, evaluator| + # By default all designs are created_designs, so just add them. + specific_designs = [].concat( + evaluator.created_designs, + evaluator.modified_designs, + evaluator.deleted_designs + ) + version.designs += specific_designs + + unless evaluator.designs_count.zero? || version.designs.present? + version.designs << create(:design, issue: version.issue) + end + end + + after :create do |version, evaluator| + # FactoryBot does not like methods, so we use lambdas instead + events = DesignManagement::Action.events + + version.actions + .where(design_id: evaluator.modified_designs.map(&:id)) + .update_all(event: events[:modification]) + + version.actions + .where(design_id: evaluator.deleted_designs.map(&:id)) + .update_all(event: events[:deletion]) + + version.designs.reload + # Ensure version.issue == design.issue for all version.designs + version.designs.update_all(issue_id: version.issue_id) + + needed = evaluator.designs_count + have = version.designs.size + + create_list(:design, [0, needed - have].max, issue: version.issue).each do |d| + version.designs << d + end + + version.actions.reset + end + + # Use this trait to build versions with designs that are backed by Git LFS, committed + # to the repository, and with an LfsObject correctly created for it. + trait :with_lfs_file do + committed + + transient do + raw_file { fixture_file_upload('spec/fixtures/dk.png', 'image/png') } + lfs_pointer { Gitlab::Git::LfsPointerFile.new(SecureRandom.random_bytes) } + file { lfs_pointer.pointer } + end + + after :create do |version, evaluator| + lfs_object = create(:lfs_object, file: evaluator.raw_file, oid: evaluator.lfs_pointer.sha256, size: evaluator.lfs_pointer.size) + create(:lfs_objects_project, project: version.project, lfs_object: lfs_object, repository_type: :design) + end + end + + # This trait is for versions that must be present in the git repository. + trait :committed do + transient do + file { File.join(Rails.root, 'spec/fixtures/dk.png') } + end + + after :create do |version, evaluator| + project = version.issue.project + repository = project.design_repository + repository.create_if_not_exists + + designs = version.designs_by_event + base_change = { content: evaluator.file } + + actions = %w[modification deletion].flat_map { |k| designs.fetch(k, []) }.map do |design| + base_change.merge(action: :create, file_path: design.full_path) + end + + if actions.present? + repository.multi_action( + evaluator.author, + branch_name: 'master', + message: "created #{actions.size} files", + actions: actions + ) + end + + mapping = { + 'creation' => :create, + 'modification' => :update, + 'deletion' => :delete + } + + version_actions = designs.flat_map do |(event, designs)| + base = event == 'deletion' ? {} : base_change + designs.map do |design| + base.merge(action: mapping[event], file_path: design.full_path) + end + end + + sha = repository.multi_action( + evaluator.author, + branch_name: 'master', + message: "edited #{version_actions.size} files", + actions: version_actions + ) + + version.update(sha: sha) + end + end + end +end |