Skip to content

Commit 806ece4

Browse files
committed
harden request_changes API endpoint and expand test coverage
- Return 422 if submitter has not yet completed the form - Wrap state update in a transaction and create a SubmissionEvent (with optional reason and requested_by) to match web controller behavior - Add tests for: SubmissionEvent creation, reason param, non-completed submitter guard, and idempotent protection (duplicate creation on multiple calls) - Clean up routes: replace %i[] with [] and 'slug' string with :slug symbol
1 parent c46482a commit 806ece4

3 files changed

Lines changed: 62 additions & 5 deletions

File tree

app/controllers/api/submitters_request_changes_controller.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,23 @@ class SubmittersRequestChangesController < ApiBaseController
55
before_action :load_submitter
66

77
def request_changes
8-
@submitter.update!(changes_requested_at: Time.current, completed_at: nil) unless @submitter.changes_requested_at?
8+
unless @submitter.completed_at?
9+
return render json: { error: 'Submitter has not completed the form' }, status: :unprocessable_entity
10+
end
11+
12+
unless @submitter.changes_requested_at?
13+
ApplicationRecord.transaction do
14+
@submitter.update!(changes_requested_at: Time.current, completed_at: nil)
15+
16+
SubmissionEvents.create_with_tracking_data(
17+
@submitter,
18+
'request_changes',
19+
request,
20+
{ reason: params[:reason], requested_by: current_user.id },
21+
current_user
22+
)
23+
end
24+
end
925

1026
render json: Submitters::SerializeForApi.call(@submitter), status: :ok
1127
end

config/routes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
resources :submitter_email_clicks, only: %i[create]
3535
resources :submitter_form_views, only: %i[create]
3636
resources :submitters, only: %i[index show update]
37-
resources :submitters, only: %i[], param: 'slug' do
37+
resources :submitters, only: [], param: :slug do
3838
member do
3939
post :request_changes, controller: 'submitters_request_changes'
4040
end

spec/requests/api_submitters_request_changes_spec.rb

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,55 @@
2727
expect(response).to have_http_status(:ok)
2828
end
2929

30-
it 'is idempotent when changes already requested' do
31-
submitter.update!(changes_requested_at: 1.hour.ago)
30+
it 'creates a submission event' do
31+
expect do
32+
post "/api/submitters/#{submitter.slug}/request_changes",
33+
headers: { 'x-auth-token': user.access_token.token }
34+
end.to change(SubmissionEvent, :count).by(1)
3235

36+
event = SubmissionEvent.last
37+
expect(event.event_type).to eq('request_changes')
38+
expect(event.submitter).to eq(submitter)
39+
end
40+
41+
it 'records the reason in the submission event when provided' do
3342
expect do
43+
post "/api/submitters/#{submitter.slug}/request_changes",
44+
params: { reason: 'Missing signature on page 2' }.to_json,
45+
headers: { 'x-auth-token': user.access_token.token }
46+
end.to change(SubmissionEvent, :count).by(1)
47+
48+
expect(SubmissionEvent.last.data).to include('reason' => 'Missing signature on page 2')
49+
end
50+
51+
context 'when submitter has not completed the form' do
52+
let(:submitter) do
53+
create(
54+
:submitter,
55+
submission:,
56+
account:,
57+
completed_at: nil,
58+
uuid: template.submitters.first['uuid']
59+
)
60+
end
61+
62+
it 'returns unprocessable entity' do
3463
post "/api/submitters/#{submitter.slug}/request_changes",
3564
headers: { 'x-auth-token': user.access_token.token }
36-
end.not_to(change { submitter.reload.changes_requested_at })
3765

66+
expect(response).to have_http_status(:unprocessable_entity)
67+
end
68+
end
69+
70+
it 'is idempotent when changes already requested' do
71+
submitter.update!(changes_requested_at: 1.hour.ago)
72+
original_changes_requested_at = submitter.changes_requested_at
73+
74+
post "/api/submitters/#{submitter.slug}/request_changes",
75+
headers: { 'x-auth-token': user.access_token.token }
76+
77+
expect(submitter.reload.changes_requested_at).to eq(original_changes_requested_at)
78+
expect(SubmissionEvent.count).to eq(0)
3879
expect(response).to have_http_status(:ok)
3980
end
4081
end

0 commit comments

Comments
 (0)