summaryrefslogtreecommitdiff
path: root/spec/factories/design_management/designs.rb
blob: 3d95c754a96c16380c8ff2b4767e55f185536ea2 (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
# frozen_string_literal: true

FactoryBot.define do
  factory :design, traits: [:has_internal_id], class: 'DesignManagement::Design' do
    issue { association(:issue) }
    project { issue&.project || association(: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

    trait :with_relative_position do
      sequence(:relative_position) { |n| n * 1000 }
    end

    create_versions = ->(design, evaluator, commit_version) do
      unless evaluator.versions_count == 0
        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
          ApplicationRecord.legacy_bulk_insert(dv_table_name, [action.row_attrs(version)]) # rubocop:disable Gitlab/BulkInsert
        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 gitaly 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.commit_files(
            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