summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/import_export/import_test_coverage_spec.rb
blob: 038b95809b4a22625ea137fd8beeee63c8124b1f (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
# frozen_string_literal: true

require 'spec_helper'

# We want to test Import on "complete" data set,
# which means that every relation (as in our Import/Export definition) is covered.
# Fixture JSONs we use for testing Import such as
# `spec/fixtures/lib/gitlab/import_export/complex/project.json`
# should include these relations being non-empty.
describe 'Test coverage of the Project Import' do
  include ConfigurationHelper

  # `MUTED_RELATIONS` is a technical debt.
  # This list expected to be empty or used as a workround
  # in case this spec blocks an important urgent MR.
  # It is also expected that adding a relation in the list should lead to
  # opening a follow-up issue to fix this.
  MUTED_RELATIONS = %w[
    project.milestones.events.push_event_payload
    project.issues.events
    project.issues.events.push_event_payload
    project.issues.notes.events
    project.issues.notes.events.push_event_payload
    project.issues.milestone.events.push_event_payload
    project.issues.issue_milestones
    project.issues.issue_milestones.milestone
    project.issues.resource_label_events.label.priorities
    project.issues.designs.notes
    project.issues.designs.notes.author
    project.issues.designs.notes.events
    project.issues.designs.notes.events.push_event_payload
    project.merge_requests.metrics
    project.merge_requests.notes.events.push_event_payload
    project.merge_requests.events.push_event_payload
    project.merge_requests.timelogs
    project.merge_requests.label_links
    project.merge_requests.label_links.label
    project.merge_requests.label_links.label.priorities
    project.merge_requests.milestone
    project.merge_requests.milestone.events
    project.merge_requests.milestone.events.push_event_payload
    project.merge_requests.merge_request_milestones
    project.merge_requests.merge_request_milestones.milestone
    project.merge_requests.resource_label_events.label
    project.merge_requests.resource_label_events.label.priorities
    project.ci_pipelines.notes.events
    project.ci_pipelines.notes.events.push_event_payload
    project.protected_branches.unprotect_access_levels
    project.prometheus_metrics
    project.metrics_setting
    project.boards.lists.label.priorities
    project.service_desk_setting
  ].freeze

  # A list of JSON fixture files we use to test Import.
  # Most of the relations are present in `complex/project.json`
  # which is our main fixture.
  PROJECT_JSON_FIXTURES = [
    'spec/fixtures/lib/gitlab/import_export/complex/project.json',
    'spec/fixtures/lib/gitlab/import_export/group/project.json',
    'spec/fixtures/lib/gitlab/import_export/light/project.json',
    'spec/fixtures/lib/gitlab/import_export/milestone-iid/project.json',
    'spec/fixtures/lib/gitlab/import_export/designs/project.json'
  ].freeze

  it 'ensures that all imported/exported relations are present in test JSONs' do
    not_tested_relations = (relations_from_config - tested_relations) - MUTED_RELATIONS

    expect(not_tested_relations).to be_empty, failure_message(not_tested_relations)
  end

  def relations_from_config
    relation_paths_for(:project)
      .map { |relation_names| relation_names.join(".") }
      .to_set
  end

  def tested_relations
    PROJECT_JSON_FIXTURES.flat_map(&method(:relations_from_json)).to_set
  end

  def relations_from_json(json_file)
    json = ActiveSupport::JSON.decode(IO.read(json_file))

    [].tap {|res| gather_relations({ project: json }, res, [])}
      .map {|relation_names| relation_names.join('.')}
  end

  def gather_relations(item, res, path)
    case item
    when Hash
      item.each do |k, v|
        if (v.is_a?(Array) || v.is_a?(Hash)) && v.present?
          new_path = path + [k]
          res << new_path
          gather_relations(v, res, new_path)
        end
      end
    when Array
      item.each {|i| gather_relations(i, res, path)}
    end
  end

  def failure_message(not_tested_relations)
    <<~MSG
      These relations seem to be added recenty and
      they expected to be covered in our Import specs: #{not_tested_relations}.

      To do that, expand one of the files listed in `PROJECT_JSON_FIXTURES`
      (or expand the list if you consider adding a new fixture file).

      After that, add a new spec into
      `spec/lib/gitlab/import_export/project_tree_restorer_spec.rb`
      to check that the relation is being imported correctly.

      In case the spec breaks the master or there is a sense of urgency,
      you could include the relations into the `MUTED_RELATIONS` list.

      Muting relations is considered to be a temporary solution, so please
      open a follow-up issue and try to fix that when it is possible.
    MSG
  end
end