govuk_content_models 6.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. data/.gitignore +17 -0
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +14 -0
  4. data/CONTRIBUTING.md +22 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +5 -0
  8. data/Rakefile +46 -0
  9. data/app/models/action.rb +60 -0
  10. data/app/models/answer_edition.rb +13 -0
  11. data/app/models/artefact.rb +341 -0
  12. data/app/models/artefact_action.rb +27 -0
  13. data/app/models/artefact_external_link.rb +15 -0
  14. data/app/models/business_support/business_size.rb +14 -0
  15. data/app/models/business_support/business_type.rb +14 -0
  16. data/app/models/business_support/location.rb +14 -0
  17. data/app/models/business_support/purpose.rb +14 -0
  18. data/app/models/business_support/sector.rb +14 -0
  19. data/app/models/business_support/stage.rb +14 -0
  20. data/app/models/business_support/support_type.rb +14 -0
  21. data/app/models/business_support_edition.rb +69 -0
  22. data/app/models/campaign_edition.rb +72 -0
  23. data/app/models/completed_transaction_edition.rb +14 -0
  24. data/app/models/curated_list.rb +32 -0
  25. data/app/models/edition.rb +286 -0
  26. data/app/models/expectant.rb +21 -0
  27. data/app/models/expectation.rb +12 -0
  28. data/app/models/guide_edition.rb +19 -0
  29. data/app/models/help_page_edition.rb +13 -0
  30. data/app/models/licence_edition.rb +35 -0
  31. data/app/models/local_authority.rb +58 -0
  32. data/app/models/local_interaction.rb +20 -0
  33. data/app/models/local_service.rb +49 -0
  34. data/app/models/local_transaction_edition.rb +49 -0
  35. data/app/models/overview_dashboard.rb +25 -0
  36. data/app/models/part.rb +28 -0
  37. data/app/models/parted.rb +32 -0
  38. data/app/models/place_edition.rb +20 -0
  39. data/app/models/programme_edition.rb +26 -0
  40. data/app/models/simple_smart_answer_edition.rb +66 -0
  41. data/app/models/simple_smart_answer_edition/node.rb +40 -0
  42. data/app/models/simple_smart_answer_edition/node/option.rb +31 -0
  43. data/app/models/tag.rb +88 -0
  44. data/app/models/transaction_edition.rb +28 -0
  45. data/app/models/travel_advice_edition.rb +177 -0
  46. data/app/models/user.rb +54 -0
  47. data/app/models/video_edition.rb +24 -0
  48. data/app/models/workflow.rb +217 -0
  49. data/app/models/workflow_actor.rb +141 -0
  50. data/app/traits/attachable.rb +60 -0
  51. data/app/traits/govspeak_smart_quotes_fixer.rb +19 -0
  52. data/app/traits/taggable.rb +113 -0
  53. data/app/validators/safe_html.rb +33 -0
  54. data/app/validators/slug_validator.rb +53 -0
  55. data/config/mongoid.yml +5 -0
  56. data/govuk_content_models.gemspec +42 -0
  57. data/jenkins.sh +7 -0
  58. data/lib/fact_check_address.rb +36 -0
  59. data/lib/govuk_content_models.rb +12 -0
  60. data/lib/govuk_content_models/require_all.rb +14 -0
  61. data/lib/govuk_content_models/test_helpers/factories.rb +213 -0
  62. data/lib/govuk_content_models/test_helpers/local_services.rb +24 -0
  63. data/lib/govuk_content_models/version.rb +4 -0
  64. data/test/fixtures/contactotron_api_response.json +1 -0
  65. data/test/fixtures/uploads/image.jpg +0 -0
  66. data/test/models/artefact_action_test.rb +123 -0
  67. data/test/models/artefact_external_link_test.rb +32 -0
  68. data/test/models/artefact_tag_test.rb +52 -0
  69. data/test/models/artefact_test.rb +583 -0
  70. data/test/models/business_support/business_size_test.rb +25 -0
  71. data/test/models/business_support/business_type_test.rb +25 -0
  72. data/test/models/business_support/location_test.rb +25 -0
  73. data/test/models/business_support/purpose_test.rb +29 -0
  74. data/test/models/business_support/sector_test.rb +25 -0
  75. data/test/models/business_support/stage_test.rb +25 -0
  76. data/test/models/business_support/support_type_test.rb +25 -0
  77. data/test/models/business_support_edition_test.rb +186 -0
  78. data/test/models/campaign_edition_test.rb +90 -0
  79. data/test/models/curated_list_test.rb +32 -0
  80. data/test/models/edition_test.rb +826 -0
  81. data/test/models/fact_check_address_test.rb +36 -0
  82. data/test/models/help_page_edition_test.rb +38 -0
  83. data/test/models/licence_edition_test.rb +104 -0
  84. data/test/models/local_authority_test.rb +113 -0
  85. data/test/models/local_service_test.rb +199 -0
  86. data/test/models/local_transaction_edition_test.rb +78 -0
  87. data/test/models/overview_dashboard_test.rb +47 -0
  88. data/test/models/simple_smart_answer_edition_test.rb +169 -0
  89. data/test/models/simple_smart_answer_node_test.rb +134 -0
  90. data/test/models/simple_smart_answer_option_test.rb +90 -0
  91. data/test/models/tag_test.rb +92 -0
  92. data/test/models/time_zone_test.rb +48 -0
  93. data/test/models/transaction_edition_test.rb +20 -0
  94. data/test/models/travel_advice_edition_test.rb +480 -0
  95. data/test/models/user_test.rb +114 -0
  96. data/test/models/video_edition_test.rb +64 -0
  97. data/test/models/workflow_actor_test.rb +61 -0
  98. data/test/models/workflow_test.rb +307 -0
  99. data/test/test_helper.rb +47 -0
  100. data/test/traits/attachable_test.rb +143 -0
  101. data/test/traits/taggable_test.rb +114 -0
  102. data/test/validators/safe_html_validator_test.rb +86 -0
  103. data/test/validators/slug_validator_test.rb +42 -0
  104. metadata +511 -0
@@ -0,0 +1,114 @@
1
+ require "test_helper"
2
+
3
+ class UserTest < ActiveSupport::TestCase
4
+ def setup
5
+ @artefact = FactoryGirl.create(:artefact)
6
+ end
7
+
8
+ test "should convert to string using name by preference" do
9
+ user = User.new(name: "Bob", email: "user@example.com")
10
+ assert_equal "Bob", user.to_s
11
+ end
12
+
13
+ test "should convert to string using email if name if missing" do
14
+ user = User.new(email: "user@example.com")
15
+ assert_equal "user@example.com", user.to_s
16
+ end
17
+
18
+ test "should convert to empty string if name and email are missing" do
19
+ user = User.new
20
+ assert_equal "", user.to_s
21
+ end
22
+
23
+ test "should create new user with oauth params" do
24
+ auth_hash = {
25
+ "uid" => "1234abcd",
26
+ "info" => {
27
+ "uid" => "1234abcd",
28
+ "email" => "user@example.com",
29
+ "name" => "Luther Blisset"
30
+ },
31
+ "extra" => {
32
+ "user" => {
33
+ "permissions" => ["signin"]
34
+ }
35
+ }
36
+ }
37
+ user = User.find_for_gds_oauth(auth_hash).reload
38
+ assert_equal "1234abcd", user.uid
39
+ assert_equal "user@example.com", user.email
40
+ assert_equal "Luther Blisset", user.name
41
+ assert_equal(["signin"], user.permissions)
42
+ end
43
+
44
+ test "should find and update the user with oauth params" do
45
+ attributes = {uid: "1234abcd", name: "Old", email: "old@m.com",
46
+ permissions: ["everything"]}
47
+ User.create!(attributes, without_protection: true)
48
+ auth_hash = {
49
+ "uid" => "1234abcd",
50
+ "info" => {
51
+ "email" => "new@m.com",
52
+ "name" => "New"
53
+ },
54
+ "extra" => {
55
+ "user" => {
56
+ "permissions" => []
57
+ }
58
+ }
59
+ }
60
+ user = User.find_for_gds_oauth(auth_hash).reload
61
+ assert_equal "1234abcd", user.uid
62
+ assert_equal "new@m.com", user.email
63
+ assert_equal "New", user.name
64
+ assert_equal([], user.permissions)
65
+ end
66
+
67
+ test "should create insecure gravatar URL" do
68
+ user = User.new(email: "User@example.com")
69
+ expected = "http://www.gravatar.com/avatar/b58996c504c5638798eb6b511e6f49af"
70
+ assert_equal expected, user.gravatar_url
71
+ end
72
+
73
+ test "should create secure gravatar URL" do
74
+ user = User.new(email: "user@example.com")
75
+ expected = "https://secure.gravatar.com/avatar/b58996c504c5638798eb6b511e6f49af"
76
+ assert_equal expected, user.gravatar_url(ssl: true)
77
+ end
78
+
79
+ test "should add escaped s parameter if supplied" do
80
+ user = User.new(email: "user@example.com")
81
+ expected = "http://www.gravatar.com/avatar/b58996c504c5638798eb6b511e6f49af?s=foo+bar"
82
+ assert_equal expected, user.gravatar_url(s: "foo bar")
83
+ end
84
+
85
+ test "creating a transaction with the initial details creates a valid transaction" do
86
+ user = User.create(:name => "bob")
87
+ trans = user.create_edition(:transaction, title: "test", slug: "test", panopticon_id: @artefact.id)
88
+ assert trans.valid?
89
+ end
90
+
91
+ test "user can't okay a publication they've sent for review" do
92
+ user = User.create(:name => "bob")
93
+
94
+ trans = user.create_edition(:transaction, title: "test answer", slug: "test", panopticon_id: @artefact.id)
95
+ user.request_review(trans, {comment: "Hello"})
96
+ assert ! user.approve_review(trans, {comment: "Hello"})
97
+ end
98
+
99
+ test "Edition becomes assigned to user when user is assigned an edition" do
100
+ boss_user = User.create(:name => "Mat")
101
+ worker_user = User.create(:name => "Grunt")
102
+
103
+ publication = boss_user.create_edition(:answer, title: "test answer", slug: "test", panopticon_id: @artefact.id)
104
+ boss_user.assign(publication, worker_user)
105
+ publication.save
106
+ publication.reload
107
+
108
+ assert_equal(worker_user, publication.assigned_to)
109
+ end
110
+
111
+ test "should default to a collection called 'users'" do
112
+ assert_equal "users", User.collection_name
113
+ end
114
+ end
@@ -0,0 +1,64 @@
1
+ require "test_helper"
2
+
3
+ class VideoEditionTest < ActiveSupport::TestCase
4
+ setup do
5
+ @artefact = FactoryGirl.create(:artefact)
6
+ end
7
+
8
+ should "have correct extra fields" do
9
+ v = FactoryGirl.build(:video_edition, panopticon_id: @artefact.id)
10
+ v.video_url = "http://www.youtube.com/watch?v=qySFp3qnVmM"
11
+ v.video_summary = "Coke smoothie"
12
+ v.body = "Description of video"
13
+ v.caption_file_id = 'file-to-an-asset-of-the-caption-file'
14
+ v.safely.save!
15
+
16
+ v = VideoEdition.first
17
+ assert_equal "http://www.youtube.com/watch?v=qySFp3qnVmM", v.video_url
18
+ assert_equal "Coke smoothie", v.video_summary
19
+ assert_equal "Description of video", v.body
20
+ assert_equal 'file-to-an-asset-of-the-caption-file', v.caption_file_id
21
+ end
22
+
23
+ should "give a friendly (legacy supporting) description of its format" do
24
+ video = VideoEdition.new
25
+ assert_equal "Video", video.format
26
+ end
27
+
28
+ context "whole_body" do
29
+ should "combine the video_summary, video_url and body" do
30
+ v = FactoryGirl.build(:video_edition,
31
+ :panopticon_id => @artefact.id,
32
+ :video_summary => "Coke smoothie",
33
+ :video_url => "http://www.youtube.com/watch?v=qySFp3qnVmM",
34
+ :body => "Make a smoothie from a whole can of coke")
35
+ expected = ["Coke smoothie", "http://www.youtube.com/watch?v=qySFp3qnVmM", "Make a smoothie from a whole can of coke"].join("\n\n")
36
+ assert_equal expected, v.whole_body
37
+ end
38
+
39
+ should "cope with a field being nil" do
40
+ v = FactoryGirl.build(:video_edition,
41
+ :panopticon_id => @artefact.id,
42
+ :video_summary => nil,
43
+ :video_url => "http://www.youtube.com/watch?v=qySFp3qnVmM",
44
+ :body => "Make a smoothie from a whole can of coke")
45
+ expected = ["", "http://www.youtube.com/watch?v=qySFp3qnVmM", "Make a smoothie from a whole can of coke"].join("\n\n")
46
+ assert_equal expected, v.whole_body
47
+ end
48
+ end
49
+
50
+ should "clone extra fields when cloning edition" do
51
+ video = FactoryGirl.create(:video_edition,
52
+ :panopticon_id => @artefact.id,
53
+ :state => "published",
54
+ :video_url => "http://www.youtube.com/watch?v=qySFp3qnVmM",
55
+ :video_summary => "Coke smoothie",
56
+ :body => "Description of video")
57
+
58
+ new_video = video.build_clone
59
+
60
+ assert_equal video.video_url, new_video.video_url
61
+ assert_equal video.video_summary, new_video.video_summary
62
+ assert_equal video.body, new_video.body
63
+ end
64
+ end
@@ -0,0 +1,61 @@
1
+ require_relative "../test_helper"
2
+
3
+ class WorkflowActorTest < ActiveSupport::TestCase
4
+
5
+ context "creating a new version of an edition" do
6
+ setup do
7
+ @user = User.new
8
+ @user.stubs(:record_action)
9
+ @edition = stub("AnswerEdition", :published? => true, :build_clone => :new_version)
10
+ end
11
+
12
+ should "return false if the edition is not published" do
13
+ @edition.stubs(:published?).returns(false)
14
+ @edition.expects(:build_clone).never
15
+ @user.expects(:record_action).never
16
+ assert_equal false, @user.new_version(@edition)
17
+ end
18
+
19
+ should "build a clone" do
20
+ @edition.expects(:build_clone).with(nil).returns(:new_verison)
21
+ @user.new_version(@edition)
22
+ end
23
+
24
+ should "record the action" do
25
+ @user.expects(:record_action).with(:new_version, Action::NEW_VERSION)
26
+ @user.new_version(@edition)
27
+ end
28
+
29
+ should "return the new edition" do
30
+ assert_equal :new_version, @user.new_version(@edition)
31
+ end
32
+
33
+ context "creating an edition of a different type" do
34
+ should "build a clone of a new type" do
35
+ @edition.expects(:build_clone).with(GuideEdition).returns(:new_verison)
36
+ @user.new_version(@edition, "GuideEdition")
37
+ end
38
+
39
+ should "record the action" do
40
+ @user.expects(:record_action).with(:new_version, Action::NEW_VERSION)
41
+ @user.new_version(@edition)
42
+ end
43
+ end
44
+
45
+ context "when building the edition fails" do
46
+ setup do
47
+ @edition.stubs(:build_clone).returns(nil)
48
+ end
49
+
50
+ should "not record the action" do
51
+ @user.expects(:record_action).never
52
+ @user.new_version(@edition)
53
+ end
54
+
55
+ should "return false" do
56
+ assert_equal false, @user.new_version(@edition)
57
+ end
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,307 @@
1
+ require "test_helper"
2
+
3
+ class WorkflowTest < ActiveSupport::TestCase
4
+ def setup
5
+ @artefact = FactoryGirl.create(:artefact)
6
+ end
7
+
8
+ def template_users
9
+ user = User.create(name: "Bob")
10
+ other_user = User.create(name: "James")
11
+ return user, other_user
12
+ end
13
+
14
+ def template_programme
15
+ p = ProgrammeEdition.new(slug:"childcare", title:"Children", panopticon_id: @artefact.id)
16
+ p.start_work
17
+ p.save
18
+ p
19
+ end
20
+
21
+ def template_guide
22
+ edition = FactoryGirl.create(:guide_edition, slug: "childcare", title: "One", panopticon_id: @artefact.id)
23
+ edition.start_work
24
+ edition.save
25
+ edition
26
+ end
27
+
28
+ def publisher_and_guide
29
+ user = User.create(name: "Ben")
30
+ other_user = User.create(name: "James")
31
+
32
+ guide = user.create_edition(:guide, panopticon_id: @artefact.id, overview: "My Overview", title: "My Title", slug: "my-title", alternative_title: "My Other Title")
33
+ edition = guide
34
+ user.start_work(edition)
35
+ user.request_review(edition,{comment: "Review this guide please."})
36
+ other_user.approve_review(edition, {comment: "I've reviewed it"})
37
+ user.send_fact_check(edition,{comment: "Review this guide please.", email_addresses: "test@test.com"})
38
+ user.receive_fact_check(edition, {comment: "No changes needed, this is all correct"})
39
+ other_user.approve_fact_check(edition, {comment: "Looks good to me"})
40
+ user.publish(edition, {comment: "PUBLISHED!"})
41
+ return user, guide
42
+ end
43
+
44
+ def template_user_and_published_transaction
45
+ user = User.create(name: "Ben")
46
+ other_user = User.create(name: "James")
47
+ expectation = Expectation.create text:"Credit card required"
48
+
49
+ transaction = user.create_edition(:transaction, title: "My title", slug: "my-title", panopticon_id: @artefact.id)
50
+ transaction.expectation_ids = [expectation.id]
51
+ transaction.save
52
+
53
+ transaction.start_work
54
+ transaction.save
55
+ user.request_review(transaction, {comment: "Review this guide please."})
56
+ transaction.save
57
+ other_user.approve_review(transaction, {comment: "I've reviewed it"})
58
+ transaction.save
59
+ user.publish(transaction, {comment: "Let's go"})
60
+ transaction.save
61
+ return user, transaction
62
+ end
63
+
64
+ test "permits the creation of new editions" do
65
+ user, transaction = template_user_and_published_transaction
66
+ assert transaction.persisted?
67
+ assert transaction.published?
68
+
69
+ reloaded_transaction = TransactionEdition.find(transaction.id)
70
+ new_edition = user.new_version(reloaded_transaction)
71
+
72
+ assert new_edition.save
73
+ end
74
+
75
+ test "should allow creation of new editions from GuideEdition to AnswerEdition" do
76
+ user, guide = publisher_and_guide
77
+ new_edition = user.new_version(guide, AnswerEdition)
78
+
79
+ assert_equal "AnswerEdition", new_edition._type
80
+ end
81
+
82
+ test "a new answer is lined up" do
83
+ g = AnswerEdition.new(slug: "childcare", panopticon_id: @artefact.id, title: "My new answer")
84
+ assert g.lined_up?
85
+ end
86
+
87
+ test "starting work on an answer removes it from lined up" do
88
+ g = AnswerEdition.new(slug: "childcare", panopticon_id: @artefact.id, title: "My new answer")
89
+ g.save!
90
+ user = User.create(name: "Ben")
91
+ user.start_work(g)
92
+ assert_equal false, g.lined_up?
93
+ end
94
+
95
+ test "a new guide has lined_up but isn't published" do
96
+ g = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id)
97
+ assert g.lined_up?
98
+ refute g.published?
99
+ end
100
+
101
+ test "when work started a new guide has draft but isn't published" do
102
+ g = FactoryGirl.create(:guide_edition, panopticon_id: @artefact.id)
103
+ g.start_work
104
+ assert g.draft?
105
+ refute g.published?
106
+ end
107
+
108
+ test "a guide should be marked as having reviewables if requested for review" do
109
+ guide = template_guide
110
+ user = User.create(name:"Ben")
111
+ refute guide.in_review?
112
+ user.request_review(guide, {comment: "Review this guide please."})
113
+ assert guide.in_review?
114
+ end
115
+
116
+ test "guide workflow" do
117
+ user = User.create(name: "Ben")
118
+ other_user = User.create(name: "James")
119
+
120
+ guide = user.create_edition(:guide, title: "My Title", slug: "my-title", panopticon_id: @artefact.id)
121
+ edition = guide
122
+ user.start_work(edition)
123
+ assert edition.can_request_review?
124
+ user.request_review(edition,{comment: "Review this guide please."})
125
+ refute edition.can_request_review?
126
+ assert edition.can_request_amendments?
127
+ other_user.request_amendments(edition, {comment: "I've reviewed it"})
128
+ refute edition.can_request_amendments?
129
+ user.request_review(edition,{comment: "Review this guide please."})
130
+ assert edition.can_approve_review?
131
+ other_user.approve_review(edition, {comment: "Looks good to me"})
132
+ assert edition.can_publish?
133
+ end
134
+
135
+ test "when fact check has been initiated it can be skipped" do
136
+ user = User.create(name: "Ben")
137
+ other_user = User.create(name: "James")
138
+
139
+ edition = user.create_edition(:guide, panopticon_id: @artefact.id, overview: "My Overview", title: "My Title", slug: "my-title", alternative_title: "My Other Title")
140
+
141
+ user.start_work(edition)
142
+ user.request_review(edition,{comment: "Review this guide please."})
143
+ other_user.approve_review(edition, {comment: "I've reviewed it"})
144
+ user.send_fact_check(edition,{comment: "Review this guide please.", email_addresses: "test@test.com"})
145
+
146
+ assert other_user.skip_fact_check(edition, {comment: 'Fact check not received in time'})
147
+ edition.reload
148
+ assert edition.can_publish?
149
+ assert edition.actions.detect { |e| e.request_type == 'skip_fact_check' }
150
+ end
151
+
152
+ # until we improve the validation to produce few or no false positives
153
+ test "when processing fact check, it is not validated" do
154
+ user = User.create(name: "Ben")
155
+ other_user = User.create(name: "James")
156
+
157
+ guide = user.create_edition(:guide, panopticon_id: FactoryGirl.create(:artefact).id, overview: "My Overview", title: "My Title", slug: "my-title", alternative_title: "My Other Title")
158
+ edition = guide
159
+ user.start_work(edition)
160
+ user.request_review(edition,{comment: "Review this guide please."})
161
+ other_user.approve_review(edition, {comment: "I've reviewed it"})
162
+ user.send_fact_check(edition,{comment: "Review this guide please.", email_addresses: "test@test.com"})
163
+ user.receive_fact_check(edition, {comment: "Text.<l>content that the SafeHtml validator would catch</l>"})
164
+
165
+ assert_equal "Text.<l>content that the SafeHtml validator would catch</l>", edition.actions.last.comment
166
+ end
167
+
168
+ test "check counting reviews" do
169
+ user = User.create(name: "Ben")
170
+ other_user = User.create(name: "James")
171
+
172
+ guide = user.create_edition(:guide, title: "My Title", slug: "my-title", panopticon_id: @artefact.id)
173
+ edition = guide
174
+
175
+ assert_equal 0, guide.rejected_count
176
+
177
+ user.start_work(edition)
178
+ user.request_review(edition,{comment: "Review this guide please."})
179
+ other_user.request_amendments(edition, {comment: "I've reviewed it"})
180
+
181
+ assert_equal 1, guide.rejected_count
182
+
183
+ user.request_review(edition,{comment: "Review this guide please."})
184
+ other_user.approve_review(edition, {comment: "Looks good to me"})
185
+
186
+ assert_equal 1, guide.rejected_count
187
+ end
188
+
189
+ test "user should not be able to review a guide they requested review for" do
190
+ user = User.create(name: "Ben")
191
+
192
+ guide = user.create_edition(:guide, title: "My Title", slug: "my-title", panopticon_id: @artefact.id)
193
+ edition = guide
194
+ user.start_work(edition)
195
+ assert edition.can_request_review?
196
+ user.request_review(edition,{comment: "Review this guide please."})
197
+ refute user.request_amendments(edition, {comment: "Well Done, but work harder"})
198
+ end
199
+
200
+ test "user should not be able to okay a guide they requested review for" do
201
+ user = User.create(name: "Ben")
202
+
203
+ guide = user.create_edition(:guide, title: "My Title", slug: "my-title", panopticon_id: @artefact.id)
204
+ edition = guide
205
+ user.start_work(edition)
206
+ assert edition.can_request_review?
207
+ user.request_review(edition,{comment: "Review this guide please."})
208
+ refute user.approve_review(edition, "")
209
+ end
210
+
211
+ test "a new programme has drafts but isn't published" do
212
+ p = template_programme
213
+ assert p.draft?
214
+ refute p.published?
215
+ end
216
+
217
+ test "a programme should be marked as having reviewables if requested for review" do
218
+ programme = template_programme
219
+ user, other_user = template_users
220
+
221
+ refute programme.in_review?
222
+ user.request_review(programme, {comment: "Review this programme please."})
223
+ assert programme.in_review?, "A review was not requested for this programme."
224
+ end
225
+
226
+ test "programme workflow" do
227
+ user, other_user = template_users
228
+
229
+ edition = user.create_edition(:programme, panopticon_id: @artefact.id, title: "My title", slug: "my-slug")
230
+ user.start_work(edition)
231
+ assert edition.can_request_review?
232
+ user.request_review(edition,{comment: "Review this guide please."})
233
+ refute edition.can_request_review?
234
+ assert edition.can_request_amendments?
235
+ other_user.request_amendments(edition, {comment: "I've reviewed it"})
236
+ refute edition.can_request_amendments?
237
+ user.request_review(edition,{comment: "Review this guide please."})
238
+ assert edition.can_approve_review?
239
+ other_user.approve_review(edition, {comment: "Looks good to me"})
240
+ assert edition.can_publish?
241
+ end
242
+
243
+ test "user should not be able to okay a programme they requested review for" do
244
+ user, other_user = template_users
245
+
246
+ edition = user.create_edition(:programme, panopticon_id: @artefact.id, title: "My title", slug: "my-slug")
247
+ user.start_work(edition)
248
+ assert edition.can_request_review?
249
+ user.request_review(edition,{comment: "Review this programme please."})
250
+ refute user.approve_review(edition, "")
251
+ end
252
+
253
+ test "you can only create a new edition from a published edition" do
254
+ user, other_user = template_users
255
+ edition = user.create_edition(:programme, panopticon_id: @artefact.id, title: "My title", slug: "my-slug")
256
+ refute edition.published?
257
+ refute user.new_version(edition)
258
+ end
259
+
260
+ test "a new edition of an answer creates a diff when published" do
261
+ without_metadata_denormalisation(AnswerEdition) do
262
+ edition_one = AnswerEdition.new(title: "Chucking wood", slug: "woodchuck", panopticon_id: @artefact.id)
263
+ edition_one.body = "A woodchuck would chuck all the wood he could chuck if a woodchuck could chuck wood."
264
+ edition_one.state = :ready
265
+ edition_one.save!
266
+
267
+ user = User.create name: "Michael"
268
+ user.publish edition_one, comment: "First edition"
269
+
270
+ edition_two = edition_one.build_clone
271
+ edition_two.body = "A woodchuck would chuck all the wood he could chuck if a woodchuck could chuck wood.\nAlthough no more than 361 cubic centimetres per day."
272
+ edition_two.state = :ready
273
+ edition_two.save!
274
+
275
+ user.publish edition_two, comment: "Second edition"
276
+
277
+ publish_action = edition_two.actions.where(request_type: "publish").last
278
+
279
+ assert_equal "A woodchuck would chuck all the wood he could chuck if a woodchuck could chuck wood.{+\"\\nAlthough no more than 361 cubic centimetres per day.\"}", publish_action.diff
280
+ end
281
+ end
282
+
283
+ test "handles inconsistent newlines" do
284
+ # Differ tries to be smart when calculating changes, by searching for a matching line
285
+ # later in the texts. When we have predominantly Windows-style new lines (\r\n) with
286
+ # a few Unix-style new lines (\n), a Unix-style new line later in one document will be
287
+ # matched to a Unix-style new line in the other, causing large swathes of spurious diff.
288
+
289
+ edition_one = AnswerEdition.new(title: "Chucking wood", slug: "woodchuck", panopticon_id: @artefact.id)
290
+ edition_one.body = "badger\n\nmushroom\r\n\r\nsnake\n\nend"
291
+
292
+ edition_two = AnswerEdition.new(title: "Chucking wood", slug: "woodchuck", panopticon_id: @artefact.id)
293
+ edition_two.body = "badger\r\n\r\nmushroom\r\n\r\nsnake\n\nend"
294
+ edition_two.stubs(:published_edition).returns(edition_one)
295
+
296
+ # Test that the diff output is simply the (normalised) string, with no diff markers
297
+ assert_equal "badger\n\nmushroom\n\nsnake\n\nend", edition_two.edition_changes.to_s
298
+ end
299
+
300
+ test "an edition can be moved into archive state" do
301
+ user, other_user = template_users
302
+
303
+ edition = user.create_edition(:programme, panopticon_id: @artefact.id, title: "My title", slug: "my-slug")
304
+ user.take_action!(edition, "archive")
305
+ assert_equal "archived", edition.state
306
+ end
307
+ end