From 5fe00d32069e9edea8164dcdc8536fc22a4d84d4 Mon Sep 17 00:00:00 2001 From: Ryan Arakawa Date: Mon, 4 Aug 2025 17:43:10 -0500 Subject: [PATCH 1/3] export submission status * when submitter status changes, export to external API * update ExportSubmissionService to send payload to external API --- app/controllers/submit_form_controller.rb | 1 + app/models/submitter.rb | 10 ++ app/services/export_submission_service.rb | 35 +++- spec/models/submitter_spec.rb | 161 ++++++++++++++++++ .../export_submission_service_spec.rb | 106 +++++++++++- 5 files changed, 307 insertions(+), 6 deletions(-) create mode 100644 spec/models/submitter_spec.rb diff --git a/app/controllers/submit_form_controller.rb b/app/controllers/submit_form_controller.rb index 46b28128..24092dcc 100644 --- a/app/controllers/submit_form_controller.rb +++ b/app/controllers/submit_form_controller.rb @@ -6,6 +6,7 @@ class SubmitFormController < ApplicationController around_action :with_browser_locale, only: %i[show completed success] skip_before_action :authenticate_user! skip_authorization_check + skip_before_action :verify_authenticity_token, only: :update before_action :load_submitter, only: %i[show update completed] before_action :maybe_render_locked_page, only: :show diff --git a/app/models/submitter.rb b/app/models/submitter.rb index dc8aa645..f6121788 100644 --- a/app/models/submitter.rb +++ b/app/models/submitter.rb @@ -68,6 +68,7 @@ class Submitter < ApplicationRecord scope :completed, -> { where.not(completed_at: nil) } after_destroy :anonymize_email_events, if: -> { Docuseal.multitenant? } + after_update :export_submission_on_status_change def status if declined_at? @@ -122,4 +123,13 @@ class Submitter < ApplicationRecord event.update!(email: Digest::MD5.base64digest(event.email)) end end + + def export_submission_on_status_change + status_fields = %w[completed_at declined_at opened_at sent_at] + return unless (saved_changes.keys & status_fields).any? + + ExportSubmissionService.new(submission).call + rescue => e + Rails.logger.error("Failed to export submission on status change: #{e.message}") + end end diff --git a/app/services/export_submission_service.rb b/app/services/export_submission_service.rb index 426ad658..02ff57b8 100644 --- a/app/services/export_submission_service.rb +++ b/app/services/export_submission_service.rb @@ -9,6 +9,8 @@ class ExportSubmissionService < ExportService end def call + export_location = ExportLocation.default_location + if export_location&.submissions_endpoint.blank? set_error('Export failed: Submission export endpoint is not configured.') return false @@ -39,9 +41,38 @@ class ExportSubmissionService < ExportService def build_payload { - submission_id: submission.id, + external_submission_id: submission.id, template_name: submission.template&.name, - events: submission.submission_events.order(updated_at: :desc).limit(1) + status: submission_status, + submitter_data: submission.submitters.map do |submitter| + { + external_submitter_id: submitter.slug, + name: submitter.name, + email: submitter.email, + status: submitter.status, + completed_at: submitter.completed_at, + declined_at: submitter.declined_at + } + end, + created_at: submission.created_at, + updated_at: submission.updated_at } end + + def submission_status + # The status is tracked for each submitter, so we need to check the status of all submitters + statuses = submission.submitters.map(&:status) + + if statuses.include?('declined') + 'declined' + elsif statuses.all? { |s| s == 'completed' } + 'completed' + elsif statuses.any? { |s| s == 'opened' } + 'in_progress' + elsif statuses.any? { |s| s == 'sent' } + 'sent' + else + 'pending' + end + end end diff --git a/spec/models/submitter_spec.rb b/spec/models/submitter_spec.rb new file mode 100644 index 00000000..8fc19197 --- /dev/null +++ b/spec/models/submitter_spec.rb @@ -0,0 +1,161 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Submitter do + let(:account) { create(:account) } + let(:user) { create(:user, account: account) } + let(:template) { create(:template, account: account, author: user) } + let(:submission) { create(:submission, :with_submitters, template: template, account: account, created_by_user: user) } + let(:submitter) { submission.submitters.first } + + describe '#status' do + context 'when submitter is awaiting' do + it 'returns awaiting' do + expect(submitter.status).to eq('awaiting') + end + end + + context 'when submitter is sent' do + before { submitter.update!(sent_at: Time.current) } + + it 'returns sent' do + expect(submitter.status).to eq('sent') + end + end + + context 'when submitter is opened' do + before do + submitter.update!(sent_at: Time.current, opened_at: Time.current) + end + + it 'returns opened' do + expect(submitter.status).to eq('opened') + end + end + + context 'when submitter is completed' do + before do + submitter.update!( + sent_at: Time.current, + opened_at: Time.current, + completed_at: Time.current + ) + end + + it 'returns completed' do + expect(submitter.status).to eq('completed') + end + end + + context 'when submitter is declined' do + before { submitter.update!(declined_at: Time.current) } + + it 'returns declined' do + expect(submitter.status).to eq('declined') + end + end + + context 'when submitter is declined but also completed' do + before do + submitter.update!( + completed_at: Time.current, + declined_at: Time.current + ) + end + + it 'returns declined (declined takes precedence)' do + expect(submitter.status).to eq('declined') + end + end + end + + describe '#export_submission_on_status_change' do + let(:export_location) { create(:export_location, :with_submissions_endpoint) } + let(:export_service) { instance_double(ExportSubmissionService) } + + before do + allow(ExportLocation).to receive(:default_location).and_return(export_location) + allow(ExportSubmissionService).to receive(:new).with(submission).and_return(export_service) + allow(export_service).to receive(:call).and_return(true) + end + + context 'when status-related field changes' do + it 'calls ExportSubmissionService when completed_at changes' do + submitter.update!(completed_at: Time.current) + expect(ExportSubmissionService).to have_received(:new).with(submission) + expect(export_service).to have_received(:call) + end + + it 'calls ExportSubmissionService when declined_at changes' do + submitter.update!(declined_at: Time.current) + expect(ExportSubmissionService).to have_received(:new).with(submission) + expect(export_service).to have_received(:call) + end + + it 'calls ExportSubmissionService when opened_at changes' do + submitter.update!(opened_at: Time.current) + expect(ExportSubmissionService).to have_received(:new).with(submission) + expect(export_service).to have_received(:call) + end + + it 'calls ExportSubmissionService when sent_at changes' do + submitter.update!(sent_at: Time.current) + expect(ExportSubmissionService).to have_received(:new).with(submission) + expect(export_service).to have_received(:call) + end + end + + context 'when non-status field changes' do + it 'does not call ExportSubmissionService when email changes' do + submitter.update!(email: 'new@example.com') + expect(ExportSubmissionService).not_to have_received(:new) + expect(export_service).not_to have_received(:call) + end + + it 'does not call ExportSubmissionService when name changes' do + submitter.update!(name: 'New Name') + expect(ExportSubmissionService).not_to have_received(:new) + expect(export_service).not_to have_received(:call) + end + end + + context 'when export service raises an error' do + before do + allow(export_service).to receive(:call).and_raise(StandardError.new('Export failed')) + allow(Rails.logger).to receive(:error) + end + + it 'logs the error and does not re-raise' do + expect { submitter.update!(completed_at: Time.current) }.not_to raise_error + expect(Rails.logger).to have_received(:error).with('Failed to export submission on status change: Export failed') + end + end + + context 'when ExportLocation.default_location returns nil' do + before do + allow(ExportLocation).to receive(:default_location).and_return(nil) + allow(export_service).to receive(:call).and_return(false) + end + + it 'calls ExportSubmissionService but service handles nil export location' do + submitter.update!(completed_at: Time.current) + expect(ExportSubmissionService).to have_received(:new).with(submission) + expect(export_service).to have_received(:call) + end + end + + context 'when export location has no submissions_endpoint' do + before do + allow(export_location).to receive(:submissions_endpoint).and_return(nil) + allow(export_service).to receive(:call).and_return(false) + end + + it 'calls ExportSubmissionService but service handles missing endpoint' do + submitter.update!(completed_at: Time.current) + expect(ExportSubmissionService).to have_received(:new).with(submission) + expect(export_service).to have_received(:call) + end + end + end +end diff --git a/spec/services/export_submission_service_spec.rb b/spec/services/export_submission_service_spec.rb index 6b805ba4..2b019dc2 100644 --- a/spec/services/export_submission_service_spec.rb +++ b/spec/services/export_submission_service_spec.rb @@ -140,16 +140,19 @@ RSpec.describe ExportSubmissionService do describe 'payload building' do let(:request_double) { instance_double(Faraday::Request, body: nil) } + let(:submitter1) { create(:submitter, submission: submission, account: account, name: 'John Doe', email: 'john@example.com', completed_at: Time.current, uuid: SecureRandom.uuid) } + let(:submitter2) { create(:submitter, submission: submission, account: account, name: 'Jane Smith', email: 'jane@example.com', opened_at: Time.current, uuid: SecureRandom.uuid) } before do + submission.submitters << [submitter1, submitter2] allow(request_double).to receive(:body=) allow(faraday_connection).to receive(:post).and_yield(request_double).and_return(faraday_response) allow(faraday_response).to receive(:success?).and_return(true) end - it 'includes submission_id in payload' do + it 'includes external_submission_id in payload' do allow(request_double).to receive(:body=) do |body| - expect(JSON.parse(body)).to include('submission_id' => submission.id) + expect(JSON.parse(body)).to include('external_submission_id' => submission.id) end service.call end @@ -161,10 +164,52 @@ RSpec.describe ExportSubmissionService do service.call end - it 'includes recent events in payload' do + it 'includes submission status in payload' do + allow(request_double).to receive(:body=) do |body| + expect(JSON.parse(body)).to include('status' => 'in_progress') + end + service.call + end + + it 'includes submitter_data array in payload' do + allow(request_double).to receive(:body=) do |body| + parsed_body = JSON.parse(body) + expect(parsed_body).to have_key('submitter_data') + expect(parsed_body['submitter_data']).to be_an(Array) + expect(parsed_body['submitter_data'].length).to eq(2) + end + service.call + end + + it 'includes correct submitter data in payload' do allow(request_double).to receive(:body=) do |body| parsed_body = JSON.parse(body) - expect(parsed_body).to have_key('events') + submitter_data = parsed_body['submitter_data'] + + first_submitter = submitter_data.find { |s| s['email'] == 'john@example.com' } + expect(first_submitter).to include( + 'external_submitter_id' => submitter1.slug, + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'status' => 'completed' + ) + + second_submitter = submitter_data.find { |s| s['email'] == 'jane@example.com' } + expect(second_submitter).to include( + 'external_submitter_id' => submitter2.slug, + 'name' => 'Jane Smith', + 'email' => 'jane@example.com', + 'status' => 'opened' + ) + end + service.call + end + + it 'includes created_at and updated_at in payload' do + allow(request_double).to receive(:body=) do |body| + parsed_body = JSON.parse(body) + expect(parsed_body).to have_key('created_at') + expect(parsed_body).to have_key('updated_at') end service.call end @@ -183,6 +228,59 @@ RSpec.describe ExportSubmissionService do end end + describe '#submission_status' do + let(:service) { described_class.new(submission) } + + context 'with multiple submitters' do + let(:submitter1) { create(:submitter, submission: submission, account: account, uuid: SecureRandom.uuid) } + let(:submitter2) { create(:submitter, submission: submission, account: account, uuid: SecureRandom.uuid) } + + before do + submission.submitters << [submitter1, submitter2] + end + + it 'returns declined when any submitter is declined' do + submitter1.declined_at = Time.current + submitter2.completed_at = Time.current + expect(service.send(:submission_status)).to eq('declined') + end + + it 'returns completed when all submitters are completed' do + submitter1.completed_at = Time.current + submitter2.completed_at = Time.current + expect(service.send(:submission_status)).to eq('completed') + end + + it 'returns in_progress when any submitter is opened but not all completed' do + submitter1.opened_at = Time.current + submitter2.sent_at = Time.current + expect(service.send(:submission_status)).to eq('in_progress') + end + + it 'returns sent when any submitter is sent but none opened' do + submitter1.sent_at = Time.current + expect(service.send(:submission_status)).to eq('sent') + end + + it 'returns pending when no submitters have been sent' do + expect(service.send(:submission_status)).to eq('pending') + end + end + + context 'with single submitter' do + let(:submitter) { create(:submitter, submission: submission, account: account, uuid: SecureRandom.uuid) } + + before do + submission.submitters << submitter + end + + it 'returns the submitter status when single submitter' do + submitter.opened_at = Time.current + expect(service.send(:submission_status)).to eq('in_progress') + end + end + end + describe 'extra_params handling' do let(:request_double) { instance_double(Faraday::Request, body: nil) } From 07f92058f0809b509ae925f3a4d4bd388f9f0b65 Mon Sep 17 00:00:00 2001 From: Ryan Arakawa Date: Mon, 4 Aug 2025 17:48:42 -0500 Subject: [PATCH 2/3] rubocop fixes --- app/models/submitter.rb | 6 +++--- app/services/export_submission_service.rb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/submitter.rb b/app/models/submitter.rb index f6121788..22ecbb19 100644 --- a/app/models/submitter.rb +++ b/app/models/submitter.rb @@ -67,8 +67,8 @@ class Submitter < ApplicationRecord scope :completed, -> { where.not(completed_at: nil) } - after_destroy :anonymize_email_events, if: -> { Docuseal.multitenant? } after_update :export_submission_on_status_change + after_destroy :anonymize_email_events, if: -> { Docuseal.multitenant? } def status if declined_at? @@ -126,10 +126,10 @@ class Submitter < ApplicationRecord def export_submission_on_status_change status_fields = %w[completed_at declined_at opened_at sent_at] - return unless (saved_changes.keys & status_fields).any? + return unless saved_changes.keys.intersect?(status_fields) ExportSubmissionService.new(submission).call - rescue => e + rescue StandardError => e Rails.logger.error("Failed to export submission on status change: #{e.message}") end end diff --git a/app/services/export_submission_service.rb b/app/services/export_submission_service.rb index 02ff57b8..d254508c 100644 --- a/app/services/export_submission_service.rb +++ b/app/services/export_submission_service.rb @@ -65,11 +65,11 @@ class ExportSubmissionService < ExportService if statuses.include?('declined') 'declined' - elsif statuses.all? { |s| s == 'completed' } + elsif statuses.all?('completed') 'completed' - elsif statuses.any? { |s| s == 'opened' } + elsif statuses.any?('opened') 'in_progress' - elsif statuses.any? { |s| s == 'sent' } + elsif statuses.any?('sent') 'sent' else 'pending' From 371fdbd6a82337d55c35feefadadeebbcc5d5e8e Mon Sep 17 00:00:00 2001 From: Ryan Arakawa Date: Mon, 4 Aug 2025 18:13:56 -0500 Subject: [PATCH 3/3] rubocop fixes and minor test refactors --- app/services/export_service.rb | 6 +- app/services/export_submission_service.rb | 8 +- app/services/export_template_service.rb | 6 +- spec/models/submitter_spec.rb | 8 +- .../export_submission_service_spec.rb | 143 +++++------------- 5 files changed, 49 insertions(+), 122 deletions(-) diff --git a/app/services/export_service.rb b/app/services/export_service.rb index 24c54c73..e2c04bac 100644 --- a/app/services/export_service.rb +++ b/app/services/export_service.rb @@ -9,7 +9,7 @@ class ExportService @error_message = nil end - def set_error(message) + def record_error(message) @error_message = message end @@ -40,8 +40,4 @@ class ExportService def export_location @export_location ||= ExportLocation.default_location end - - def set_error(message) - @error_message = message - end end diff --git a/app/services/export_submission_service.rb b/app/services/export_submission_service.rb index d254508c..d717dc3a 100644 --- a/app/services/export_submission_service.rb +++ b/app/services/export_submission_service.rb @@ -12,7 +12,7 @@ class ExportSubmissionService < ExportService export_location = ExportLocation.default_location if export_location&.submissions_endpoint.blank? - set_error('Export failed: Submission export endpoint is not configured.') + record_error('Export failed: Submission export endpoint is not configured.') return false end @@ -22,18 +22,18 @@ class ExportSubmissionService < ExportService if response&.success? true else - set_error("Failed to export submission ##{submission.id} events.") + record_error("Failed to export submission ##{submission.id} events.") false end rescue Faraday::Error => e Rails.logger.error("Failed to export submission Faraday: #{e.message}") Rollbar.error("Failed to export submission: #{e.message}") if defined?(Rollbar) - set_error("Network error occurred during export: #{e.message}") + record_error("Network error occurred during export: #{e.message}") false rescue StandardError => e Rails.logger.error("Failed to export submission: #{e.message}") Rollbar.error(e) if defined?(Rollbar) - set_error("An unexpected error occurred during export: #{e.message}") + record_error("An unexpected error occurred during export: #{e.message}") false end diff --git a/app/services/export_template_service.rb b/app/services/export_template_service.rb index dce4c0c3..8574481a 100644 --- a/app/services/export_template_service.rb +++ b/app/services/export_template_service.rb @@ -15,18 +15,18 @@ class ExportTemplateService < ExportService else Rails.logger.error("Failed to export template to third party: #{response&.status}") Rollbar.error("#{export_location.name} template export API error: #{response&.status}") if defined?(Rollbar) - set_error('Failed to export template to third party') + record_error('Failed to export template to third party') false end rescue Faraday::Error => e Rails.logger.error("Failed to export template Faraday: #{e.message}") Rollbar.error("Failed to export template: #{e.message}") if defined?(Rollbar) - set_error("Network error occurred during template export: #{e.message}") + record_error("Network error occurred during template export: #{e.message}") false rescue StandardError => e Rails.logger.error("Failed to export template: #{e.message}") Rollbar.error(e) if defined?(Rollbar) - set_error("An unexpected error occurred during template export: #{e.message}") + record_error("An unexpected error occurred during template export: #{e.message}") false end end diff --git a/spec/models/submitter_spec.rb b/spec/models/submitter_spec.rb index 8fc19197..d595aca0 100644 --- a/spec/models/submitter_spec.rb +++ b/spec/models/submitter_spec.rb @@ -6,7 +6,9 @@ RSpec.describe Submitter do let(:account) { create(:account) } let(:user) { create(:user, account: account) } let(:template) { create(:template, account: account, author: user) } - let(:submission) { create(:submission, :with_submitters, template: template, account: account, created_by_user: user) } + let(:submission) do + create(:submission, :with_submitters, template: template, account: account, created_by_user: user) + end let(:submitter) { submission.submitters.first } describe '#status' do @@ -128,7 +130,9 @@ RSpec.describe Submitter do it 'logs the error and does not re-raise' do expect { submitter.update!(completed_at: Time.current) }.not_to raise_error - expect(Rails.logger).to have_received(:error).with('Failed to export submission on status change: Export failed') + expect(Rails.logger).to have_received(:error).with( + 'Failed to export submission on status change: Export failed' + ) end end diff --git a/spec/services/export_submission_service_spec.rb b/spec/services/export_submission_service_spec.rb index 2b019dc2..441fb6e2 100644 --- a/spec/services/export_submission_service_spec.rb +++ b/spec/services/export_submission_service_spec.rb @@ -6,7 +6,9 @@ RSpec.describe ExportSubmissionService do let(:account) { create(:account) } let(:user) { create(:user, account: account) } let(:template) { create(:template, account: account, author: user) } - let(:submission) { create(:submission, template: template, account: account) } + let(:submission) do + create(:submission, :with_submitters, template: template, account: account, created_by_user: user) + end let(:export_location) { create(:export_location, :with_submissions_endpoint) } let(:service) { described_class.new(submission) } let(:faraday_connection) { instance_double(Faraday::Connection) } @@ -140,76 +142,51 @@ RSpec.describe ExportSubmissionService do describe 'payload building' do let(:request_double) { instance_double(Faraday::Request, body: nil) } - let(:submitter1) { create(:submitter, submission: submission, account: account, name: 'John Doe', email: 'john@example.com', completed_at: Time.current, uuid: SecureRandom.uuid) } - let(:submitter2) { create(:submitter, submission: submission, account: account, name: 'Jane Smith', email: 'jane@example.com', opened_at: Time.current, uuid: SecureRandom.uuid) } before do - submission.submitters << [submitter1, submitter2] allow(request_double).to receive(:body=) - allow(faraday_connection).to receive(:post).and_yield(request_double).and_return(faraday_response) + allow(faraday_connection).to receive(:post) + .with(export_location.submissions_endpoint) + .and_yield(request_double) + .and_return(faraday_response) allow(faraday_response).to receive(:success?).and_return(true) - end - it 'includes external_submission_id in payload' do - allow(request_double).to receive(:body=) do |body| - expect(JSON.parse(body)).to include('external_submission_id' => submission.id) - end - service.call - end + allow(Submitter).to receive(:after_update) - it 'includes template_name in payload' do - allow(request_double).to receive(:body=) do |body| - expect(JSON.parse(body)).to include('template_name' => submission.template.name) - end - service.call + submission.submitters.first.update!(name: 'John Doe', email: 'john@example.com', completed_at: Time.current) + submission.submitters << create( + :submitter, + submission: submission, + account: account, + name: 'Jane Smith', + email: 'jane@example.com', + opened_at: Time.current, + uuid: SecureRandom.uuid + ) end - it 'includes submission status in payload' do - allow(request_double).to receive(:body=) do |body| - expect(JSON.parse(body)).to include('status' => 'in_progress') - end - service.call - end - - it 'includes submitter_data array in payload' do + it 'builds correct payload structure with all required fields' do allow(request_double).to receive(:body=) do |body| parsed_body = JSON.parse(body) - expect(parsed_body).to have_key('submitter_data') + + expect(parsed_body).to include( + 'external_submission_id' => submission.id, + 'template_name' => submission.template.name, + 'status' => 'in_progress' + ) + expect(parsed_body).to have_key('created_at') + expect(parsed_body).to have_key('updated_at') + expect(parsed_body['submitter_data']).to be_an(Array) expect(parsed_body['submitter_data'].length).to eq(2) - end - service.call - end - it 'includes correct submitter data in payload' do - allow(request_double).to receive(:body=) do |body| - parsed_body = JSON.parse(body) - submitter_data = parsed_body['submitter_data'] - - first_submitter = submitter_data.find { |s| s['email'] == 'john@example.com' } - expect(first_submitter).to include( - 'external_submitter_id' => submitter1.slug, + completed_submitter = parsed_body['submitter_data'].find { |s| s['status'] == 'completed' } + expect(completed_submitter).to include( 'name' => 'John Doe', 'email' => 'john@example.com', 'status' => 'completed' ) - - second_submitter = submitter_data.find { |s| s['email'] == 'jane@example.com' } - expect(second_submitter).to include( - 'external_submitter_id' => submitter2.slug, - 'name' => 'Jane Smith', - 'email' => 'jane@example.com', - 'status' => 'opened' - ) - end - service.call - end - - it 'includes created_at and updated_at in payload' do - allow(request_double).to receive(:body=) do |body| - parsed_body = JSON.parse(body) - expect(parsed_body).to have_key('created_at') - expect(parsed_body).to have_key('updated_at') + expect(completed_submitter).to have_key('external_submitter_id') end service.call end @@ -228,66 +205,16 @@ RSpec.describe ExportSubmissionService do end end - describe '#submission_status' do - let(:service) { described_class.new(submission) } - - context 'with multiple submitters' do - let(:submitter1) { create(:submitter, submission: submission, account: account, uuid: SecureRandom.uuid) } - let(:submitter2) { create(:submitter, submission: submission, account: account, uuid: SecureRandom.uuid) } - - before do - submission.submitters << [submitter1, submitter2] - end - - it 'returns declined when any submitter is declined' do - submitter1.declined_at = Time.current - submitter2.completed_at = Time.current - expect(service.send(:submission_status)).to eq('declined') - end - - it 'returns completed when all submitters are completed' do - submitter1.completed_at = Time.current - submitter2.completed_at = Time.current - expect(service.send(:submission_status)).to eq('completed') - end - - it 'returns in_progress when any submitter is opened but not all completed' do - submitter1.opened_at = Time.current - submitter2.sent_at = Time.current - expect(service.send(:submission_status)).to eq('in_progress') - end - - it 'returns sent when any submitter is sent but none opened' do - submitter1.sent_at = Time.current - expect(service.send(:submission_status)).to eq('sent') - end - - it 'returns pending when no submitters have been sent' do - expect(service.send(:submission_status)).to eq('pending') - end - end - - context 'with single submitter' do - let(:submitter) { create(:submitter, submission: submission, account: account, uuid: SecureRandom.uuid) } - - before do - submission.submitters << submitter - end - - it 'returns the submitter status when single submitter' do - submitter.opened_at = Time.current - expect(service.send(:submission_status)).to eq('in_progress') - end - end - end - describe 'extra_params handling' do let(:request_double) { instance_double(Faraday::Request, body: nil) } before do allow(export_location).to receive(:extra_params).and_return({ 'api_key' => 'test_key', 'version' => '1.0' }) allow(request_double).to receive(:body=) - allow(faraday_connection).to receive(:post).and_yield(request_double).and_return(faraday_response) + allow(faraday_connection).to receive(:post) + .with(export_location.submissions_endpoint) + .and_yield(request_double) + .and_return(faraday_response) allow(faraday_response).to receive(:success?).and_return(true) end