Skip to content

Commit eb62998

Browse files
committed
Prevent publishing/scheduling a standard edition with invalid tab form
We have agreed to only send a globally valid edition to Publishing API. In that sense, the Edition Publisher and Edition Scheduler services now collect each tab's failure reasons (e.g. "Social media accounts tab is invalid") so publishers see useful messages rather than a generic one. Consequently, the Draft Edition Updater service skips pushing to Publishing API if any tab is invalid.
1 parent dc778e7 commit eb62998

7 files changed

Lines changed: 132 additions & 1 deletion

File tree

app/services/draft_edition_updater.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class DraftEditionUpdater < EditionService
22
def perform!
33
if can_perform?
4-
update_publishing_api!
4+
update_publishing_api! if can_push_draft?
55
notify!
66
true
77
end
@@ -30,4 +30,12 @@ def should_check_current_user_will_retain_access?
3030
def access_limit_excludes_current_user?
3131
edition.organisation_association_enabled? && edition.edition_organisations.map(&:organisation_id).exclude?(@options[:current_user].organisation.id)
3232
end
33+
34+
def can_push_draft?
35+
return true unless edition.is_a?(StandardEdition)
36+
37+
edition.type_instance.form_keys.all? do |tab_key|
38+
StandardEdition::TabForm.new(edition, tab_key).valid?
39+
end
40+
end
3341
end

app/services/edition_publisher.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def failure_reasons
1010
reasons << "This edition is invalid: #{edition.errors.full_messages.to_sentence}" unless edition.valid?(:publish)
1111
reasons << "An edition that is #{edition.current_state} cannot be #{past_participle}" unless can_transition?
1212
reasons << "Scheduled editions cannot be published. This edition is scheduled for publication on #{edition.scheduled_publication}" if scheduled_for_publication?
13+
reasons.concat(invalid_tab_reasons) if edition.is_a?(StandardEdition)
1314

1415
@failure_reasons = reasons
1516
end

app/services/edition_scheduler.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def failure_reasons
2424
elsif scheduled_publication_is_not_within_cache_limit?
2525
reasons << "Scheduled publication date must be at least #{Whitehall.default_cache_max_age / 60} minutes from now"
2626
end
27+
reasons.concat(invalid_tab_reasons) if edition.is_a?(StandardEdition)
2728
@failure_reasons = reasons
2829
end
2930

app/services/edition_service.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,14 @@ def prepare_edition
6767
def fire_transition!
6868
edition.public_send("#{verb}!")
6969
end
70+
71+
def invalid_tab_reasons
72+
edition.type_instance.form_keys.filter_map do |tab_key|
73+
tab_form = StandardEdition::TabForm.new(edition, tab_key)
74+
unless tab_form.valid?(:publish)
75+
tab_label = edition.type_instance.form(tab_key)["label"] || tab_key.humanize
76+
"#{tab_label} tab is invalid"
77+
end
78+
end
79+
end
7080
end

test/unit/app/services/draft_edition_updater_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,15 @@ class DraftEditionUpdaterTest < ActiveSupport::TestCase
4747

4848
updater.perform!
4949
end
50+
51+
test "#perform! skips update_publishing_api! when a draft edition is invalid" do
52+
edition = create(:draft_edition)
53+
edition.freeze
54+
updater = DraftEditionUpdater.new(edition)
55+
updater.stubs(:can_push_draft?).returns(false)
56+
updater.expects(:update_publishing_api!).never
57+
updater.expects(:notify!).once
58+
59+
updater.perform!
60+
end
5061
end

test/unit/app/services/edition_publisher_test.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,56 @@ class EditionPublisherTest < ActiveSupport::TestCase
5151
assert_equal "This edition is invalid: Title cannot be blank", publisher.failure_reason
5252
end
5353

54+
test "#perform! with an invalid form tab on a standard edition refuses to publish" do
55+
configurable_document_type = build_configurable_document_type("test_type", {
56+
"forms" => {
57+
"documents" => {
58+
"fields" => {
59+
"body" => {
60+
"title" => "Body",
61+
"block" => "govspeak",
62+
"attribute_path" => %w[block_content body],
63+
},
64+
},
65+
},
66+
"extra_tab" => {
67+
"dynamic" => true,
68+
"label" => "Extra tab",
69+
"fields" => {
70+
"sidebar" => {
71+
"title" => "Sidebar",
72+
"block" => "govspeak",
73+
"attribute_path" => %w[block_content sidebar],
74+
},
75+
},
76+
},
77+
},
78+
"schema" => {
79+
"attributes" => {
80+
"body" => { "type" => "string" },
81+
"sidebar" => { "type" => "string" },
82+
},
83+
"validations" => {
84+
"presence" => { "attributes" => %w[body sidebar] },
85+
},
86+
},
87+
})
88+
ConfigurableDocumentType.setup_test_types(configurable_document_type)
89+
90+
edition = create(:submitted_standard_edition, :with_organisations,
91+
configurable_document_type: "test_type",
92+
title: "Title", summary: "Summary",
93+
block_content: { body: "Content", sidebar: "Sidebar content" })
94+
edition.translations.update_all(block_content: { body: "New content", sidebar: "" })
95+
edition.reload
96+
97+
publisher = EditionPublisher.new(edition)
98+
99+
assert_not publisher.perform!
100+
assert_not edition.published?
101+
assert_includes publisher.failure_reasons, "Extra tab tab is invalid"
102+
end
103+
54104
test "#perform! with a re-editioned document updates the version numbers" do
55105
published_edition = create(:published_edition, major_change_published_at: 1.week.ago)
56106
edition = published_edition.create_draft(create(:writer))

test/unit/app/services/edition_scheduler_test.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,54 @@ class EditionSchedulerTest < ActiveSupport::TestCase
6161
assert_match %r{Scheduled publication date must be at least 15 minutes from now}, scheduler.failure_reason
6262
end
6363
end
64+
65+
test "#perform! with an invalid form tab on a standard edition cannot be scheduled" do
66+
configurable_document_type = build_configurable_document_type("test_type", {
67+
"forms" => {
68+
"documents" => {
69+
"fields" => {
70+
"body" => {
71+
"title" => "Body",
72+
"block" => "govspeak",
73+
"attribute_path" => %w[block_content body],
74+
},
75+
},
76+
},
77+
"extra_tab" => {
78+
"dynamic" => true,
79+
"label" => "Extra tab",
80+
"fields" => {
81+
"sidebar" => {
82+
"title" => "Sidebar",
83+
"block" => "govspeak",
84+
"attribute_path" => %w[block_content sidebar],
85+
},
86+
},
87+
},
88+
},
89+
"schema" => {
90+
"attributes" => {
91+
"body" => { "type" => "string" },
92+
"sidebar" => { "type" => "string" },
93+
},
94+
"validations" => {
95+
"presence" => { "attributes" => %w[body sidebar] },
96+
},
97+
},
98+
})
99+
ConfigurableDocumentType.setup_test_types(configurable_document_type)
100+
101+
edition = create(:submitted_standard_edition, :with_organisations,
102+
configurable_document_type: "test_type",
103+
title: "Title", summary: "Summary",
104+
block_content: { body: "Content", sidebar: "Sidebar content" })
105+
edition.translations.update_all(block_content: { body: "New content", sidebar: "" })
106+
edition.reload
107+
108+
scheduler = EditionScheduler.new(edition)
109+
110+
assert_not scheduler.perform!
111+
assert_not edition.scheduled?
112+
assert_includes scheduler.failure_reasons, "Extra tab tab is invalid"
113+
end
64114
end

0 commit comments

Comments
 (0)