Skip to content

Commit d3cedc4

Browse files
committed
Add rake task and spec for changing the state of a form
1 parent 4ffb44b commit d3cedc4

2 files changed

Lines changed: 132 additions & 0 deletions

File tree

lib/tasks/forms.rake

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,30 @@ namespace :forms do
2525
end
2626
end
2727

28+
desc "set the state for a form by transitioning through the form state machine"
29+
task :set_state, %i[form_id state] => :environment do |_, args|
30+
usage_message = "usage: rake forms:set_state[<form_id>, <state>]".freeze
31+
abort usage_message if args[:form_id].blank? || args[:state].blank?
32+
abort "state must be one of #{Form.states.keys.join(', ')}" unless Form.states.key?(args[:state])
33+
34+
form = Form.find(args[:form_id])
35+
36+
# the make_live event guard checks the form's task statuses through a
37+
# service that is normally injected by the controller
38+
form.set_task_status_service(TaskStatusService.new(form:, current_user: nil))
39+
40+
events = Form.event_path(from: form.aasm.current_state, to: args[:state].to_sym)
41+
42+
abort "cannot transition form from \'#{form.state}\' to \'#{args[:state]}\'" if events.nil?
43+
44+
ActiveRecord::Base.transaction do
45+
events.each do |event|
46+
Rails.logger.info "forms:set_state: firing #{event} on #{fmt_form(form)} in state \'#{form.state}\'"
47+
form.public_send(:"#{event}!")
48+
end
49+
end
50+
end
51+
2852
namespace :submission_email do
2953
desc "set the submission email for a form, without validation"
3054
task :update, %i[form_id submission_email] => :environment do |_, args|

spec/lib/tasks/forms.rake_spec.rb

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,114 @@
119119
end
120120
end
121121

122+
describe "forms:set_state" do
123+
subject(:task) do
124+
Rake::Task["forms:set_state"]
125+
end
126+
127+
let(:form) { create :form, :ready_for_live }
128+
let!(:other_form) { create :form }
129+
130+
context "with valid arguments" do
131+
it "sets a draft form's state to archived by transitioning through live" do
132+
expect {
133+
task.invoke(form.id, "archived")
134+
}.to change { form.reload.state }.from("draft").to("archived")
135+
end
136+
137+
it "runs the event callbacks for the intermediate transitions" do
138+
task.invoke(form.id, "archived")
139+
140+
form.reload
141+
expect(form.first_made_live_at).not_to be_nil
142+
expect(form.archived_form_document).not_to be_nil
143+
end
144+
145+
it "sets an archived form's state to live" do
146+
archived_form = create :form, :archived
147+
148+
expect {
149+
task.invoke(archived_form.id, "live")
150+
}.to change { archived_form.reload.state }.from("archived").to("live")
151+
end
152+
153+
it "leaves a form already in the target state unchanged" do
154+
expect {
155+
task.invoke(form.id, "draft")
156+
}.not_to(change { form.reload.state })
157+
end
158+
159+
it "does not change other forms" do
160+
expect {
161+
task.invoke(form.id, "archived")
162+
}.not_to(change { other_form.reload.state })
163+
end
164+
end
165+
166+
context "when the form is not ready to be made live" do
167+
let(:form) { create :form }
168+
169+
it "raises an invalid transition error and does not change the form's state" do
170+
expect {
171+
task.invoke(form.id, "archived")
172+
}.to raise_error(AASM::InvalidTransition)
173+
174+
expect(form.reload.state).to eq("draft")
175+
end
176+
end
177+
178+
context "when no sequence of events reaches the target state" do
179+
it "aborts with a message" do
180+
live_form = create :form, :live
181+
182+
expect {
183+
task.invoke(live_form.id, "draft")
184+
}.to raise_error(SystemExit)
185+
.and output(/cannot transition form from 'live' to 'draft'/).to_stderr
186+
end
187+
end
188+
189+
context "with invalid arguments" do
190+
shared_examples_for "usage error" do
191+
it "aborts with a usage message" do
192+
expect {
193+
task.invoke(*invalid_args)
194+
}.to raise_error(SystemExit)
195+
.and output(/usage: rake forms:set_state/).to_stderr
196+
end
197+
end
198+
199+
context "with no arguments" do
200+
it_behaves_like "usage error" do
201+
let(:invalid_args) { [] }
202+
end
203+
end
204+
205+
context "with only one argument" do
206+
it_behaves_like "usage error" do
207+
let(:invalid_args) { [form.id] }
208+
end
209+
end
210+
211+
context "with a state that is not a form state" do
212+
it "aborts with a message listing the valid states" do
213+
expect {
214+
task.invoke(form.id, "not_a_state")
215+
}.to raise_error(SystemExit)
216+
.and output(/state must be one of draft, deleted, live, live_with_draft, archived, archived_with_draft/).to_stderr
217+
end
218+
end
219+
220+
context "with invalid form_id" do
221+
it "raises an error" do
222+
expect {
223+
task.invoke("99", "archived")
224+
}.to raise_error(ActiveRecord::RecordNotFound)
225+
end
226+
end
227+
end
228+
end
229+
122230
describe "forms:submission_email:update" do
123231
subject(:task) do
124232
Rake::Task["forms:submission_email:update"]

0 commit comments

Comments
 (0)