govuk_content_models 23.0.0 → 24.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +10 -0
- data/app/models/action.rb +8 -1
- data/app/models/edition.rb +5 -0
- data/app/models/user.rb +28 -2
- data/app/models/workflow.rb +20 -66
- data/app/traits/recordable_actions.rb +53 -0
- data/lib/govuk_content_models.rb +4 -5
- data/lib/govuk_content_models/action_processors.rb +23 -0
- data/lib/govuk_content_models/action_processors/approve_fact_check_processor.rb +6 -0
- data/lib/govuk_content_models/action_processors/approve_review_processor.rb +11 -0
- data/lib/govuk_content_models/action_processors/archive_processor.rb +6 -0
- data/lib/govuk_content_models/action_processors/assign_processor.rb +12 -0
- data/lib/govuk_content_models/action_processors/base_processor.rb +59 -0
- data/lib/govuk_content_models/action_processors/cancel_scheduled_publishing_processor.rb +6 -0
- data/lib/govuk_content_models/action_processors/create_edition_processor.rb +22 -0
- data/lib/govuk_content_models/action_processors/emergency_publish_processor.rb +6 -0
- data/lib/govuk_content_models/action_processors/new_version_processor.rb +23 -0
- data/lib/govuk_content_models/action_processors/publish_processor.rb +6 -0
- data/lib/govuk_content_models/action_processors/receive_fact_check_processor.rb +18 -0
- data/lib/govuk_content_models/action_processors/request_amendments_processor.rb +15 -0
- data/lib/govuk_content_models/action_processors/request_review_processor.rb +6 -0
- data/lib/govuk_content_models/action_processors/schedule_for_publishing_processor.rb +14 -0
- data/lib/govuk_content_models/action_processors/send_fact_check_processor.rb +14 -0
- data/lib/govuk_content_models/action_processors/skip_fact_check_processor.rb +6 -0
- data/lib/govuk_content_models/test_helpers/action_processor_helpers.rb +39 -0
- data/lib/govuk_content_models/version.rb +1 -1
- data/test/models/action_test.rb +13 -0
- data/test/models/edition_test.rb +87 -64
- data/test/models/user_test.rb +2 -2
- data/test/models/workflow_test.rb +160 -55
- data/test/test_helper.rb +2 -0
- metadata +25 -7
- data/app/models/workflow_actor.rb +0 -157
- data/test/models/workflow_actor_test.rb +0 -112
@@ -0,0 +1,22 @@
|
|
1
|
+
module GovukContentModels
|
2
|
+
module ActionProcessors
|
3
|
+
class CreateEditionProcessor < BaseProcessor
|
4
|
+
|
5
|
+
def action_name
|
6
|
+
Action::CREATE
|
7
|
+
end
|
8
|
+
|
9
|
+
def process
|
10
|
+
format = event_attributes[:format]
|
11
|
+
format_name = "#{format}_edition" unless format.to_s.match(/edition$/)
|
12
|
+
publication_class = format_name.to_s.camelize.constantize
|
13
|
+
@edition = publication_class.create(event_attributes[:edition_attributes])
|
14
|
+
end
|
15
|
+
|
16
|
+
def record_action?
|
17
|
+
edition.persisted?
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module GovukContentModels
|
2
|
+
module ActionProcessors
|
3
|
+
class NewVersionProcessor < BaseProcessor
|
4
|
+
|
5
|
+
def process?
|
6
|
+
edition.published?
|
7
|
+
end
|
8
|
+
|
9
|
+
def process
|
10
|
+
convert_to = event_attributes[:convert_to]
|
11
|
+
@edition = if !convert_to.nil?
|
12
|
+
edition.build_clone(convert_to.to_s.camelize.constantize)
|
13
|
+
else
|
14
|
+
edition.build_clone
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def record_action?
|
19
|
+
!!edition
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module GovukContentModels
|
2
|
+
module ActionProcessors
|
3
|
+
class ReceiveFactCheckProcessor < BaseProcessor
|
4
|
+
|
5
|
+
# Always records the action.
|
6
|
+
def process
|
7
|
+
edition.perform_event_without_validations(:receive_fact_check)
|
8
|
+
# Fact checks are processed async, so the user doesn't get an opportunity
|
9
|
+
# to retry without the content that (inadvertantly) fails validation, which happens frequently.
|
10
|
+
record_action_without_validation
|
11
|
+
end
|
12
|
+
|
13
|
+
def record_action?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module GovukContentModels
|
2
|
+
module ActionProcessors
|
3
|
+
class ScheduleForPublishingProcessor < BaseProcessor
|
4
|
+
|
5
|
+
def process
|
6
|
+
publish_at = action_attributes.delete(:publish_at).to_time.utc
|
7
|
+
action_attributes.merge!(request_details: { scheduled_time: publish_at })
|
8
|
+
|
9
|
+
edition.schedule_for_publishing(publish_at)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module GovukContentModels
|
2
|
+
module ActionProcessors
|
3
|
+
class SendFactCheckProcessor < BaseProcessor
|
4
|
+
|
5
|
+
def process
|
6
|
+
return false if action_attributes[:email_addresses].blank?
|
7
|
+
action_attributes[:comment] ||= "Fact check requested"
|
8
|
+
|
9
|
+
edition.send_fact_check
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module GovukContentModels
|
2
|
+
module TestHelpers
|
3
|
+
module ActionProcessorHelpers
|
4
|
+
def request_review(user, edition)
|
5
|
+
user.progress(edition, { request_type: :request_review, comment: "Review this edition please." })
|
6
|
+
end
|
7
|
+
|
8
|
+
def approve_review(user, edition)
|
9
|
+
user.progress(edition, { request_type: :approve_review, comment: "I've reviewed it" })
|
10
|
+
end
|
11
|
+
|
12
|
+
def send_fact_check(user, edition, comment="Fact check this guide please.")
|
13
|
+
user.progress(edition,{ request_type: :send_fact_check, comment: comment, email_addresses: "test@test.com" })
|
14
|
+
end
|
15
|
+
|
16
|
+
def receive_fact_check(user, edition, comment="Please verify these facts.")
|
17
|
+
user.progress(edition, { request_type: :receive_fact_check, comment: comment })
|
18
|
+
end
|
19
|
+
|
20
|
+
def approve_fact_check(user, edition, comment="No changes needed, this is all correct")
|
21
|
+
user.progress(edition, { request_type: :approve_fact_check, comment: comment })
|
22
|
+
end
|
23
|
+
|
24
|
+
def request_amendments(user, edition)
|
25
|
+
user.progress(edition, { request_type: :request_amendments, comment: "More amendments are required" })
|
26
|
+
end
|
27
|
+
|
28
|
+
def publish(user, edition, comment='Yo!')
|
29
|
+
user.progress(edition, { request_type: :publish, comment: comment })
|
30
|
+
end
|
31
|
+
|
32
|
+
def schedule_for_publishing(user, edition, action_attributes)
|
33
|
+
user.progress(edition, { request_type: :schedule_for_publishing,
|
34
|
+
publish_at: action_attributes[:publish_at] || Time.zone.now.utc,
|
35
|
+
comment: action_attributes[:comment] || 'Schedule!' })
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ActionTest < ActiveSupport::TestCase
|
4
|
+
test "#to_s should return the humanized version of the request type" do
|
5
|
+
assert_equal "Approve review", Action.new(request_type: 'approve_review').to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
test "#to_s should contain the scheduled time when request type is SCHEDULE_FOR_PUBLISHING" do
|
9
|
+
assert_equal "Scheduled for publishing on 12/12/2014 00:00 UTC",
|
10
|
+
Action.new(:request_type => 'schedule_for_publishing',
|
11
|
+
:request_details => { 'scheduled_time' => Date.parse('12/12/2014').to_time.utc }).to_s
|
12
|
+
end
|
13
|
+
end
|
data/test/models/edition_test.rb
CHANGED
@@ -68,18 +68,18 @@ class EditionTest < ActiveSupport::TestCase
|
|
68
68
|
end
|
69
69
|
|
70
70
|
test "it should be able to find its siblings" do
|
71
|
-
|
71
|
+
artefact2 = FactoryGirl.create(:artefact)
|
72
72
|
g1 = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, version_number: 1)
|
73
|
-
g2 = FactoryGirl.create(:guide_edition, panopticon_id:
|
73
|
+
g2 = FactoryGirl.create(:guide_edition, panopticon_id: artefact2.id, version_number: 1)
|
74
74
|
g3 = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, version_number: 2)
|
75
75
|
assert_equal [], g2.siblings.to_a
|
76
76
|
assert_equal [g3], g1.siblings.to_a
|
77
77
|
end
|
78
78
|
|
79
79
|
test "it should be able to find its previous siblings" do
|
80
|
-
|
80
|
+
artefact2 = FactoryGirl.create(:artefact)
|
81
81
|
g1 = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, version_number: 1)
|
82
|
-
g2 = FactoryGirl.create(:guide_edition, panopticon_id:
|
82
|
+
g2 = FactoryGirl.create(:guide_edition, panopticon_id: artefact2.id, version_number: 1)
|
83
83
|
g3 = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, version_number: 2)
|
84
84
|
|
85
85
|
assert_equal [], g1.previous_siblings.to_a
|
@@ -108,6 +108,29 @@ class EditionTest < ActiveSupport::TestCase
|
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
+
context "change note" do
|
112
|
+
should "be a minor change by default" do
|
113
|
+
refute Edition.new.major_change
|
114
|
+
end
|
115
|
+
should "not be valid for major changes with a blank change note" do
|
116
|
+
edition = Edition.new(major_change: true, change_note: "")
|
117
|
+
refute edition.valid?
|
118
|
+
assert edition.errors.has_key?(:change_note)
|
119
|
+
end
|
120
|
+
should "be valid for major changes with a change note" do
|
121
|
+
edition = Edition.new(title: "Edition", version_number: 1, panopticon_id: 123, major_change: true, change_note: "Changed")
|
122
|
+
assert edition.valid?
|
123
|
+
end
|
124
|
+
should "be valid when blank for minor changes" do
|
125
|
+
edition = Edition.new(title: "Edition", version_number: 1, panopticon_id: 123, change_note: "")
|
126
|
+
assert edition.valid?
|
127
|
+
end
|
128
|
+
should "be valid when populated for minor changes" do
|
129
|
+
edition = Edition.new(title: "Edition", version_number: 1, panopticon_id: 123, change_note: "Changed")
|
130
|
+
assert edition.valid?
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
111
134
|
test "it should build a clone" do
|
112
135
|
edition = FactoryGirl.create(:guide_edition,
|
113
136
|
state: "published",
|
@@ -634,11 +657,11 @@ class EditionTest < ActiveSupport::TestCase
|
|
634
657
|
edition = FactoryGirl.create(:guide_edition_with_two_parts, panopticon_id: @artefact.id, state: "ready")
|
635
658
|
|
636
659
|
user = User.create name: "bob"
|
637
|
-
user
|
660
|
+
publish(user, edition, "First publication")
|
638
661
|
|
639
662
|
second_edition = edition.build_clone
|
640
663
|
second_edition.state = "ready"
|
641
|
-
user
|
664
|
+
publish(user, second_edition, "Second publication")
|
642
665
|
|
643
666
|
# simulate link validation errors in published edition
|
644
667
|
second_edition.parts.first.update_attribute(:body, "[register your vehicle](registering-an-imported-vehicle)")
|
@@ -647,7 +670,7 @@ class EditionTest < ActiveSupport::TestCase
|
|
647
670
|
# fix link validation error in cloned edition by appending a '/' to the relative url
|
648
671
|
third_edition.parts.first.body = "[register your vehicle](/registering-an-imported-vehicle)"
|
649
672
|
third_edition.state = "ready"
|
650
|
-
user
|
673
|
+
publish(user, third_edition, "Third publication")
|
651
674
|
|
652
675
|
edition.reload
|
653
676
|
assert edition.archived?
|
@@ -662,7 +685,7 @@ class EditionTest < ActiveSupport::TestCase
|
|
662
685
|
user = FactoryGirl.create(:user)
|
663
686
|
edition = FactoryGirl.create(:edition, :scheduled_for_publishing)
|
664
687
|
|
665
|
-
user
|
688
|
+
publish(user, edition, "First publication")
|
666
689
|
|
667
690
|
assert_nil edition.reload.publish_at
|
668
691
|
end
|
@@ -670,7 +693,7 @@ class EditionTest < ActiveSupport::TestCase
|
|
670
693
|
test "edition can return latest status action of a specified request type" do
|
671
694
|
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "draft")
|
672
695
|
user = User.create(name: "George")
|
673
|
-
user
|
696
|
+
request_review(user, edition)
|
674
697
|
|
675
698
|
assert_equal edition.actions.size, 1
|
676
699
|
assert edition.latest_status_action(Action::REQUEST_REVIEW).present?
|
@@ -688,17 +711,17 @@ class EditionTest < ActiveSupport::TestCase
|
|
688
711
|
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "ready")
|
689
712
|
|
690
713
|
user = User.create name: "bob"
|
691
|
-
user
|
714
|
+
publish(user, edition, "First publication")
|
692
715
|
|
693
716
|
second_edition = edition.build_clone
|
694
717
|
second_edition.update_attribute(:state, "ready")
|
695
718
|
second_edition.save!
|
696
|
-
user
|
719
|
+
publish(user, second_edition, "Second publication")
|
697
720
|
|
698
721
|
third_edition = second_edition.build_clone
|
699
722
|
third_edition.update_attribute(:state, "ready")
|
700
723
|
third_edition.save!
|
701
|
-
user
|
724
|
+
publish(user, third_edition, "Third publication")
|
702
725
|
|
703
726
|
edition.reload
|
704
727
|
assert edition.actions.where("request_type" => "publish")
|
@@ -716,12 +739,12 @@ class EditionTest < ActiveSupport::TestCase
|
|
716
739
|
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "ready")
|
717
740
|
|
718
741
|
user = User.create name: "bob"
|
719
|
-
user
|
742
|
+
publish(user, edition, "First publication")
|
720
743
|
|
721
744
|
new_edition = edition.build_clone
|
722
745
|
new_edition.state = "ready"
|
723
746
|
new_edition.save!
|
724
|
-
user
|
747
|
+
publish(user, new_edition, "Second publication")
|
725
748
|
|
726
749
|
edition = edition.reload
|
727
750
|
|
@@ -733,7 +756,7 @@ class EditionTest < ActiveSupport::TestCase
|
|
733
756
|
edition.save!
|
734
757
|
|
735
758
|
user = User.create name: "bob"
|
736
|
-
user
|
759
|
+
publish(user, edition, "First publication")
|
737
760
|
|
738
761
|
new_edition = edition.build_clone
|
739
762
|
new_edition.save!
|
@@ -771,8 +794,8 @@ class EditionTest < ActiveSupport::TestCase
|
|
771
794
|
|
772
795
|
edition = ProgrammeEdition.new(title: "Childcare", slug: "childcare", panopticon_id: @artefact.id)
|
773
796
|
assert edition.can_request_review?
|
774
|
-
|
775
|
-
|
797
|
+
request_review(user, edition)
|
798
|
+
refute request_amendments(user, edition)
|
776
799
|
end
|
777
800
|
|
778
801
|
test "a published publication with a draft edition is in progress" do
|
@@ -800,37 +823,37 @@ class EditionTest < ActiveSupport::TestCase
|
|
800
823
|
# test denormalisation
|
801
824
|
|
802
825
|
test "should denormalise an edition with an assigned user and action requesters" do
|
803
|
-
|
804
|
-
|
805
|
-
|
826
|
+
user1 = FactoryGirl.create(:user, name: "Morwenna")
|
827
|
+
user2 = FactoryGirl.create(:user, name: "John")
|
828
|
+
user3 = FactoryGirl.create(:user, name: "Nick")
|
806
829
|
|
807
830
|
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "archived")
|
808
831
|
|
809
|
-
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "archived", assigned_to_id:
|
810
|
-
edition.actions.create request_type: Action::CREATE, requester:
|
811
|
-
edition.actions.create request_type: Action::PUBLISH, requester:
|
812
|
-
edition.actions.create request_type: Action::ARCHIVE, requester:
|
832
|
+
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "archived", assigned_to_id: user1.id)
|
833
|
+
edition.actions.create request_type: Action::CREATE, requester: user2
|
834
|
+
edition.actions.create request_type: Action::PUBLISH, requester: user3
|
835
|
+
edition.actions.create request_type: Action::ARCHIVE, requester: user1
|
813
836
|
edition.save! and edition.reload
|
814
837
|
|
815
|
-
assert_equal
|
816
|
-
assert_equal
|
817
|
-
assert_equal
|
818
|
-
assert_equal
|
838
|
+
assert_equal user1.name, edition.assignee
|
839
|
+
assert_equal user2.name, edition.creator
|
840
|
+
assert_equal user3.name, edition.publisher
|
841
|
+
assert_equal user1.name, edition.archiver
|
819
842
|
end
|
820
843
|
|
821
844
|
test "should denormalise an assignee's name when an edition is assigned" do
|
822
|
-
|
823
|
-
|
845
|
+
user1 = FactoryGirl.create(:user)
|
846
|
+
user2 = FactoryGirl.create(:user)
|
824
847
|
|
825
848
|
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "draft")
|
826
|
-
|
849
|
+
user1.assign edition, user2
|
827
850
|
|
828
|
-
assert_equal
|
829
|
-
assert_equal
|
851
|
+
assert_equal user2, edition.assigned_to
|
852
|
+
assert_equal user2.name, edition.assignee
|
830
853
|
end
|
831
854
|
|
832
855
|
test "should denormalise a creator's name when an edition is created" do
|
833
|
-
|
856
|
+
user = FactoryGirl.create(:user)
|
834
857
|
FactoryGirl.create(:live_tag, tag_id: "test-section", title: "Test section", tag_type: "section")
|
835
858
|
artefact = FactoryGirl.create(:artefact,
|
836
859
|
slug: "foo-bar",
|
@@ -842,53 +865,53 @@ class EditionTest < ActiveSupport::TestCase
|
|
842
865
|
owning_app: "publisher",
|
843
866
|
)
|
844
867
|
|
845
|
-
edition = AnswerEdition.find_or_create_from_panopticon_data(artefact.id,
|
868
|
+
edition = AnswerEdition.find_or_create_from_panopticon_data(artefact.id, user, {})
|
846
869
|
|
847
|
-
assert_equal
|
870
|
+
assert_equal user.name, edition.creator
|
848
871
|
end
|
849
872
|
|
850
873
|
test "should denormalise a publishing user's name when an edition is published" do
|
851
|
-
|
874
|
+
user = FactoryGirl.create(:user)
|
852
875
|
|
853
876
|
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "ready")
|
854
|
-
|
877
|
+
publish(user, edition, "First publication")
|
855
878
|
|
856
|
-
assert_equal
|
879
|
+
assert_equal user.name, edition.publisher
|
857
880
|
end
|
858
881
|
|
859
882
|
test "should set siblings in progress to nil for new editions" do
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
assert_equal 1,
|
864
|
-
assert_nil
|
883
|
+
user = FactoryGirl.create(:user)
|
884
|
+
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "ready")
|
885
|
+
published_edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "published")
|
886
|
+
assert_equal 1, edition.version_number
|
887
|
+
assert_nil edition.sibling_in_progress
|
865
888
|
end
|
866
889
|
|
867
890
|
test "should update previous editions when new edition is added" do
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
891
|
+
user = FactoryGirl.create(:user)
|
892
|
+
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "archived")
|
893
|
+
published_edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "published")
|
894
|
+
new_edition = published_edition.build_clone
|
895
|
+
new_edition.save!
|
896
|
+
published_edition.reload
|
874
897
|
|
875
|
-
assert_equal 3,
|
876
|
-
assert_equal 3,
|
898
|
+
assert_equal 3, new_edition.version_number
|
899
|
+
assert_equal 3, published_edition.sibling_in_progress
|
877
900
|
end
|
878
901
|
|
879
902
|
test "should update previous editions when new edition is published" do
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
assert_equal 3,
|
890
|
-
assert_nil
|
891
|
-
assert_nil
|
903
|
+
user = FactoryGirl.create(:user)
|
904
|
+
edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "archived")
|
905
|
+
published_edition = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id, state: "published")
|
906
|
+
|
907
|
+
new_edition = published_edition.build_clone
|
908
|
+
new_edition.save!
|
909
|
+
new_edition.update_attribute(:state, "ready")
|
910
|
+
publish(user, new_edition, "First publication")
|
911
|
+
|
912
|
+
assert_equal 3, new_edition.version_number
|
913
|
+
assert_nil new_edition.sibling_in_progress
|
914
|
+
assert_nil published_edition.reload.sibling_in_progress
|
892
915
|
end
|
893
916
|
|
894
917
|
test "all subclasses should provide a working whole_body method for diffing" do
|