2021-09-04 01:27:46 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
2023-05-27 22:25:52 +05:30
|
|
|
RSpec.describe BulkImports::NdjsonPipeline, feature_category: :importers do
|
2021-09-04 01:27:46 +05:30
|
|
|
let_it_be(:group) { create(:group) }
|
|
|
|
let_it_be(:project) { create(:project) }
|
|
|
|
let_it_be(:user) { create(:user) }
|
|
|
|
|
|
|
|
let(:klass) do
|
|
|
|
Class.new do
|
|
|
|
include BulkImports::NdjsonPipeline
|
|
|
|
|
|
|
|
relation_name 'test'
|
|
|
|
|
|
|
|
attr_reader :portable, :current_user
|
|
|
|
|
|
|
|
def initialize(portable, user)
|
|
|
|
@portable = portable
|
|
|
|
@current_user = user
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
stub_const('NdjsonPipelineClass', klass)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject { NdjsonPipelineClass.new(group, user) }
|
|
|
|
|
|
|
|
it 'marks pipeline as ndjson' do
|
2022-07-16 23:28:13 +05:30
|
|
|
expect(NdjsonPipelineClass.file_extraction_pipeline?).to eq(true)
|
2021-09-04 01:27:46 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe '#deep_transform_relation!' do
|
|
|
|
it 'transforms relation hash' do
|
|
|
|
transformed = subject.deep_transform_relation!({}, 'test', {}) do |key, hash|
|
|
|
|
hash.merge(relation_key: key)
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(transformed[:relation_key]).to eq('test')
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when subrelations is an array' do
|
|
|
|
it 'transforms each element of the array' do
|
|
|
|
relation_hash = {
|
|
|
|
'key' => 'value',
|
|
|
|
'labels' => [
|
|
|
|
{ 'title' => 'label 1' },
|
|
|
|
{ 'title' => 'label 2' },
|
|
|
|
{ 'title' => 'label 3' }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
relation_definition = { 'labels' => {} }
|
|
|
|
|
|
|
|
transformed = subject.deep_transform_relation!(relation_hash, 'test', relation_definition) do |key, hash|
|
|
|
|
hash.merge(relation_key: key)
|
|
|
|
end
|
|
|
|
|
|
|
|
transformed['labels'].each do |label|
|
|
|
|
expect(label[:relation_key]).to eq('group_labels')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when subrelation is a hash' do
|
|
|
|
it 'transforms subrelation hash' do
|
|
|
|
relation_hash = {
|
|
|
|
'key' => 'value',
|
|
|
|
'label' => { 'title' => 'label' }
|
|
|
|
}
|
|
|
|
relation_definition = { 'label' => {} }
|
|
|
|
|
|
|
|
transformed = subject.deep_transform_relation!(relation_hash, 'test', relation_definition) do |key, hash|
|
|
|
|
hash.merge(relation_key: key)
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(transformed['label'][:relation_key]).to eq('group_label')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when subrelation is nil' do
|
|
|
|
it 'removes subrelation' do
|
|
|
|
relation_hash = {
|
|
|
|
'key' => 'value',
|
|
|
|
'label' => { 'title' => 'label' }
|
|
|
|
}
|
|
|
|
relation_definition = { 'label' => {} }
|
|
|
|
|
|
|
|
transformed = subject.deep_transform_relation!(relation_hash, 'test', relation_definition) do |key, hash|
|
|
|
|
if key == 'group_label'
|
|
|
|
nil
|
|
|
|
else
|
|
|
|
hash
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(transformed['label']).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#transform' do
|
|
|
|
it 'calls relation factory' do
|
|
|
|
hash = { key: :value }
|
|
|
|
data = [hash, 1]
|
|
|
|
user = double
|
|
|
|
config = double(relation_excluded_keys: nil, top_relation_tree: [])
|
2021-09-30 23:02:18 +05:30
|
|
|
import_double = instance_double(BulkImport, id: 1)
|
|
|
|
entity_double = instance_double(BulkImports::Entity, id: 2)
|
|
|
|
context = double(portable: group, current_user: user, import_export_config: config, bulk_import: import_double, entity: entity_double)
|
2021-09-04 01:27:46 +05:30
|
|
|
allow(subject).to receive(:import_export_config).and_return(config)
|
2021-09-30 23:02:18 +05:30
|
|
|
allow(subject).to receive(:context).and_return(context)
|
2021-12-11 22:18:48 +05:30
|
|
|
relation_object = double
|
2021-09-04 01:27:46 +05:30
|
|
|
|
|
|
|
expect(Gitlab::ImportExport::Group::RelationFactory)
|
|
|
|
.to receive(:create)
|
|
|
|
.with(
|
|
|
|
relation_index: 1,
|
|
|
|
relation_sym: :test,
|
|
|
|
relation_hash: hash,
|
|
|
|
importable: group,
|
2021-09-30 23:02:18 +05:30
|
|
|
members_mapper: instance_of(BulkImports::UsersMapper),
|
2021-09-04 01:27:46 +05:30
|
|
|
object_builder: Gitlab::ImportExport::Group::ObjectBuilder,
|
|
|
|
user: user,
|
|
|
|
excluded_keys: nil
|
|
|
|
)
|
2021-12-11 22:18:48 +05:30
|
|
|
.and_return(relation_object)
|
|
|
|
expect(relation_object).to receive(:assign_attributes).with(group: group)
|
2021-09-04 01:27:46 +05:30
|
|
|
|
|
|
|
subject.transform(context, data)
|
|
|
|
end
|
2022-01-26 12:08:38 +05:30
|
|
|
|
|
|
|
context 'when data is nil' do
|
|
|
|
before do
|
|
|
|
expect(Gitlab::ImportExport::Group::RelationFactory).not_to receive(:create)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns' do
|
|
|
|
expect(subject.transform(nil, nil)).to be_nil
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when relation hash is nil' do
|
|
|
|
it 'returns' do
|
|
|
|
expect(subject.transform(nil, [nil, 0])).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-09-04 01:27:46 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe '#load' do
|
|
|
|
context 'when object is not persisted' do
|
2023-05-27 22:25:52 +05:30
|
|
|
it 'saves the object using RelationObjectSaver' do
|
|
|
|
object = double(persisted?: false, new_record?: true)
|
|
|
|
|
|
|
|
allow(subject).to receive(:relation_definition)
|
|
|
|
|
|
|
|
expect_next_instance_of(Gitlab::ImportExport::Base::RelationObjectSaver) do |saver|
|
|
|
|
expect(saver).to receive(:execute)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject.load(nil, object)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when object is invalid' do
|
|
|
|
it 'captures invalid subrelations' do
|
|
|
|
entity = create(:bulk_import_entity, group: group)
|
|
|
|
tracker = create(:bulk_import_tracker, entity: entity)
|
|
|
|
context = BulkImports::Pipeline::Context.new(tracker)
|
|
|
|
|
|
|
|
allow(subject).to receive(:context).and_return(context)
|
|
|
|
|
|
|
|
object = group.labels.new(priorities: [LabelPriority.new])
|
|
|
|
object.validate
|
|
|
|
|
|
|
|
allow_next_instance_of(Gitlab::ImportExport::Base::RelationObjectSaver) do |saver|
|
|
|
|
allow(saver).to receive(:execute)
|
|
|
|
allow(saver).to receive(:invalid_subrelations).and_return(object.priorities)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject.load(context, object)
|
|
|
|
|
|
|
|
failure = entity.failures.first
|
|
|
|
|
|
|
|
expect(failure.pipeline_class).to eq(tracker.pipeline_name)
|
|
|
|
expect(failure.exception_class).to eq('RecordInvalid')
|
|
|
|
expect(failure.exception_message).to eq("Project can't be blank, Priority can't be blank, and Priority is not a number")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when object is persisted' do
|
2021-09-04 01:27:46 +05:30
|
|
|
it 'saves the object' do
|
2023-05-27 22:25:52 +05:30
|
|
|
object = double(new_record?: false, invalid?: false)
|
2021-09-04 01:27:46 +05:30
|
|
|
|
|
|
|
expect(object).to receive(:save!)
|
|
|
|
|
|
|
|
subject.load(nil, object)
|
|
|
|
end
|
2023-05-27 22:25:52 +05:30
|
|
|
|
|
|
|
context 'when object is invalid' do
|
|
|
|
it 'raises ActiveRecord::RecordInvalid exception' do
|
|
|
|
object = build_stubbed(:issue)
|
|
|
|
|
|
|
|
expect(Gitlab::Import::Errors).to receive(:merge_nested_errors).with(object)
|
|
|
|
|
|
|
|
expect { subject.load(nil, object) }.to raise_error(ActiveRecord::RecordInvalid)
|
|
|
|
end
|
|
|
|
end
|
2021-09-04 01:27:46 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context 'when object is missing' do
|
|
|
|
it 'returns' do
|
|
|
|
expect(subject.load(nil, nil)).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#relation_class' do
|
|
|
|
context 'when relation name is pluralized' do
|
|
|
|
it 'returns constantized class' do
|
|
|
|
expect(subject.relation_class('MergeRequest::Metrics')).to eq(MergeRequest::Metrics)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when relation name is singularized' do
|
|
|
|
it 'returns constantized class' do
|
|
|
|
expect(subject.relation_class('Badge')).to eq(Badge)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#relation_key_override' do
|
|
|
|
context 'when portable is group' do
|
|
|
|
it 'returns group relation name override' do
|
|
|
|
expect(subject.relation_key_override('labels')).to eq('group_labels')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when portable is project' do
|
|
|
|
subject { NdjsonPipelineClass.new(project, user) }
|
|
|
|
|
|
|
|
it 'returns group relation name override' do
|
|
|
|
expect(subject.relation_key_override('labels')).to eq('project_labels')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-11-18 22:05:49 +05:30
|
|
|
|
|
|
|
describe '#relation_factory' do
|
|
|
|
context 'when portable is group' do
|
|
|
|
it 'returns group relation factory' do
|
|
|
|
expect(subject.relation_factory).to eq(Gitlab::ImportExport::Group::RelationFactory)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when portable is project' do
|
|
|
|
subject { NdjsonPipelineClass.new(project, user) }
|
|
|
|
|
|
|
|
it 'returns project relation factory' do
|
|
|
|
expect(subject.relation_factory).to eq(Gitlab::ImportExport::Project::RelationFactory)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-09-04 01:27:46 +05:30
|
|
|
end
|