diff --git a/app/services/protocol_importers/import_protocol_service.rb b/app/services/protocol_importers/import_protocol_service.rb new file mode 100644 index 000000000..bd430e389 --- /dev/null +++ b/app/services/protocol_importers/import_protocol_service.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module ProtocolImporters + class ImportProtocolService + extend Service + + attr_reader :errors, :protocol + + def initialize(protocol_params:, steps_params:, team_id:, user_id:) + @user = User.find user_id + @team = Team.find team_id + @protocol_params = protocol_params + @steps_params = steps_params + @errors = {} + end + + def call + return self unless valid? + + @protocol = Protocol.new(@protocol_params.merge!(added_by: @user, team: @team)) + + @protocol.steps << @steps_params.collect do |step_params| + Step.new(step_params.merge(user: @user, completed: false)) + end + + @errors[:protocol] = @protocol.errors.messages unless @protocol.save + + self + end + + def succeed? + @errors.none? + end + + private + + def valid? + unless [@protocol_params, @user, @team].all? + @errors[:invalid_arguments] = { + 'user': @user, + 'team': @team, + '@protocol_params': @protocol_params + }.map { |key, value| "Can't find #{key.capitalize}" if value.nil? }.compact + return false + end + true + end + end +end diff --git a/spec/factories/tables.rb b/spec/factories/tables.rb index f43110090..423710a27 100644 --- a/spec/factories/tables.rb +++ b/spec/factories/tables.rb @@ -3,6 +3,6 @@ FactoryBot.define do factory :table do name { Faker::Name.unique.name } - contents { { some_data: 'needs to be here' } } + contents { { data: [%w(A B C), %w(D E F), %w(G H I)] } } end end diff --git a/spec/services/protocol_importers/import_protocol_service_spec.rb b/spec/services/protocol_importers/import_protocol_service_spec.rb new file mode 100644 index 000000000..af31a9646 --- /dev/null +++ b/spec/services/protocol_importers/import_protocol_service_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ProtocolImporters::ImportProtocolService do + let(:user) { create :user } + let(:team) { create :team } + let(:protocol_params) { attributes_for :protocol, :in_public_repository } + let(:steps_params) do + [ + attributes_for(:step).merge!(assets_attributes: [attributes_for(:asset)]), + attributes_for(:step).merge!(tables_attributes: [attributes_for(:table), attributes_for(:table)]) + ] + end + + let(:service_call) do + ProtocolImporters::ImportProtocolService + .call(protocol_params: protocol_params, steps_params: steps_params, user_id: user.id, team_id: team.id) + end + + context 'when have invalid arguments' do + it 'returns an error when can\'t find user' do + allow(User).to receive(:find).and_return(nil) + + expect(service_call.errors).to have_key(:invalid_arguments) + end + + it 'returns invalid protocol when can\'t save it' do + # step with file without name + steps_invalid_params = [ + attributes_for(:step).merge!(assets_attributes: [attributes_for(:asset).except(:file_file_name)]) + ] + + s = ProtocolImporters::ImportProtocolService.call(protocol_params: protocol_params, + steps_params: steps_invalid_params, + user_id: user.id, team_id: team.id) + + expect(s.protocol).to be_invalid + end + end + + context 'when have valid arguments' do + before do + @protocol = Protocol.new + end + + # rubocop:disable MultilineMethodCallIndentation + it do + expect do + service_result = service_call + @protocol = service_result.protocol + end.to change { Protocol.all.count }.by(1) + .and change { @protocol.steps.count }.by(2) + .and change { Table.joins(:step_table).where('step_tables.step_id': @protocol.steps.pluck(:id)).count }.by(2) + .and change { Asset.joins(:step_asset).where('step_assets.step_id': @protocol.steps.pluck(:id)).count }.by(1) + end + # rubocop:enable MultilineMethodCallIndentation + end +end