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,92 @@
1
+ require "test_helper"
2
+
3
+ class TagTest < ActiveSupport::TestCase
4
+ test "should return a hash of the fields" do
5
+ tag = Tag.new(
6
+ tag_id: "crime",
7
+ tag_type: "section",
8
+ title: "Crime"
9
+ )
10
+ expected_hash = {
11
+ id: "crime",
12
+ title: "Crime",
13
+ type: "section",
14
+ description: nil,
15
+ short_description: nil
16
+ }
17
+ assert_equal expected_hash, tag.as_json
18
+ end
19
+
20
+ setup do
21
+ %w(crime business housing).each do |section|
22
+ FactoryGirl.create(:tag, :tag_id => section, :title => section.capitalize)
23
+ end
24
+
25
+ %w(pie mash chips).each do |keyword|
26
+ FactoryGirl.create(
27
+ :tag,
28
+ :tag_id => keyword,
29
+ :title => keyword.capitalize,
30
+ :tag_type => "keyword"
31
+ )
32
+ end
33
+ end
34
+
35
+ test "should load by tag ID" do
36
+ assert_equal "Crime", Tag.by_tag_id("crime").title
37
+ end
38
+
39
+ test "should load by tag ID and type" do
40
+ assert_equal "Crime", Tag.by_tag_id("crime", "section").title
41
+ end
42
+
43
+ test "should not load an incorrectly-typed tag" do
44
+ assert_nil Tag.by_tag_id("crime", "keyword")
45
+ end
46
+
47
+ test "should return nil if tag does not exist" do
48
+ assert_nil Tag.by_tag_id("batman")
49
+ end
50
+
51
+ test "should return multiple tags" do
52
+ assert_equal(
53
+ %w(Crime Business),
54
+ Tag.by_tag_ids(%w(crime business)).map(&:title)
55
+ )
56
+ end
57
+
58
+ test "should return nil for missing tags" do
59
+ tag_ids = %w(crime business batman housing)
60
+ tags = Tag.by_tag_ids(tag_ids)
61
+ assert_nil tags[2]
62
+ [0, 1, 3].each do |i|
63
+ assert_equal tag_ids[i], tags[i].tag_id
64
+ end
65
+ end
66
+
67
+ test "should return nil for tags of the wrong type" do
68
+ tag_ids = %w(crime business pie batman)
69
+ tags = Tag.by_tag_ids(tag_ids, "section")
70
+ [2, 3].each do |i| assert_nil tags[i] end
71
+ [0, 1].each do |i| assert_equal tag_ids[i], tags[i].tag_id end
72
+ end
73
+
74
+ test "should return multiple tags from the bang method" do
75
+ assert_equal(
76
+ %w(Crime Business),
77
+ Tag.by_tag_ids!(%w(crime business)).map(&:title)
78
+ )
79
+ end
80
+
81
+ test "should raise an exception if any tags are missing" do
82
+ assert_raises Tag::MissingTags do
83
+ Tag.by_tag_ids!(%w(crime business batman))
84
+ end
85
+ end
86
+
87
+ test "should raise an exception with the wrong tag type" do
88
+ assert_raises Tag::MissingTags do
89
+ Tag.by_tag_ids!(%w(crime business pie chips), "section")
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,48 @@
1
+ require 'test_helper'
2
+
3
+ class TimeZoneTest < ActiveSupport::TestCase
4
+ def first_day_of_summer_time
5
+ Time.zone.parse("2013-04-01")
6
+ end
7
+
8
+ def wintertime
9
+ Time.zone.parse("2013-01-01")
10
+ end
11
+
12
+ context "use_activesupport_time_zone is set to true, Time.zone is set to 'London'" do
13
+ setup do
14
+ # This context has already been set in the local mongoid.yml, and in test_helper.rb
15
+ end
16
+
17
+ should "still store the date in UTC" do
18
+ Timecop.freeze(wintertime) do
19
+ FactoryGirl.create(:artefact)
20
+ assert_equal 'UTC', Artefact.last[:created_at].zone
21
+ assert_equal 'GMT', Artefact.last.created_at.zone
22
+ end
23
+ end
24
+
25
+ should "use the Time.zone time zone for dot-methods" do
26
+ Timecop.freeze(wintertime) do
27
+ FactoryGirl.create(:artefact)
28
+ assert_equal 'GMT', Artefact.last.created_at.zone
29
+ end
30
+ end
31
+
32
+ context "it is currently British Summer Time" do
33
+ should "still store the date in UTC" do
34
+ Timecop.freeze(first_day_of_summer_time) do
35
+ FactoryGirl.create(:artefact)
36
+ assert_equal 'UTC', Artefact.last[:created_at].zone
37
+ end
38
+ end
39
+
40
+ should "use the time zone with offset for dot-methods" do
41
+ Timecop.freeze(first_day_of_summer_time) do
42
+ FactoryGirl.create(:artefact)
43
+ assert_equal 'BST', Artefact.last.created_at.zone
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class TransactionEditionTest < ActiveSupport::TestCase
4
+
5
+ setup do
6
+ @artefact = FactoryGirl.create(:artefact)
7
+ end
8
+
9
+ context "indexable_content" do
10
+ should "include the introduction without markup" do
11
+ transaction = FactoryGirl.create(:transaction_edition, introduction: "## introduction", more_information: "", panopticon_id: @artefact.id)
12
+ assert_equal "introduction", transaction.indexable_content
13
+ end
14
+
15
+ should "include the more_information without markup" do
16
+ transaction = FactoryGirl.create(:transaction_edition, more_information: "## more info", introduction: "", panopticon_id: @artefact.id)
17
+ assert_equal "more info", transaction.indexable_content
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,480 @@
1
+ # encoding: UTF-8
2
+
3
+ require "test_helper"
4
+
5
+ class TravelAdviceEditionTest < ActiveSupport::TestCase
6
+
7
+ should "have correct fields" do
8
+ ed = TravelAdviceEdition.new
9
+ ed.title = "Travel advice for Aruba"
10
+ ed.overview = "This gives travel advice for Aruba"
11
+ ed.country_slug = 'aruba'
12
+ ed.alert_status = [ 'avoid_all_but_essential_travel_to_parts', 'avoid_all_travel_to_parts' ]
13
+ ed.summary = "This is the summary of stuff going on in Aruba"
14
+ ed.version_number = 4
15
+ ed.image_id = "id_from_the_asset_manager_for_an_image"
16
+ ed.document_id = "id_from_the_asset_manager_for_a_document"
17
+ ed.published_at = Time.zone.parse('2013-02-21T14:56:22Z')
18
+ ed.minor_update = true
19
+ ed.change_description = "Some things"
20
+ ed.synonyms = ["Foo", "Bar"]
21
+ ed.parts.build(:title => "Part One", :slug => "one")
22
+ ed.safely.save!
23
+
24
+ ed = TravelAdviceEdition.first
25
+ assert_equal "Travel advice for Aruba", ed.title
26
+ assert_equal "This gives travel advice for Aruba", ed.overview
27
+ assert_equal 'aruba', ed.country_slug
28
+ assert_equal [ 'avoid_all_but_essential_travel_to_parts', 'avoid_all_travel_to_parts' ], ed.alert_status
29
+ assert_equal "This is the summary of stuff going on in Aruba", ed.summary
30
+ assert_equal 4, ed.version_number
31
+ assert_equal "id_from_the_asset_manager_for_an_image", ed.image_id
32
+ assert_equal "id_from_the_asset_manager_for_a_document", ed.document_id
33
+ assert_equal Time.zone.parse('2013-02-21T14:56:22Z'), ed.published_at
34
+ assert_equal true, ed.minor_update
35
+ assert_equal ["Foo", "Bar"], ed.synonyms
36
+ assert_equal "Some things", ed.change_description
37
+ assert_equal "Part One", ed.parts.first.title
38
+ end
39
+
40
+ context "validations" do
41
+ setup do
42
+ @ta = FactoryGirl.build(:travel_advice_edition)
43
+ end
44
+
45
+ should "require a country slug" do
46
+ @ta.country_slug = ''
47
+ assert ! @ta.valid?
48
+ assert_includes @ta.errors.messages[:country_slug], "can't be blank"
49
+ end
50
+
51
+ should "require a title" do
52
+ @ta.title = ''
53
+ assert ! @ta.valid?
54
+ assert_includes @ta.errors.messages[:title], "can't be blank"
55
+ end
56
+
57
+ context "on state" do
58
+ should "only allow one edition in draft per slug" do
59
+ another_edition = FactoryGirl.create(:travel_advice_edition,
60
+ :country_slug => @ta.country_slug)
61
+ @ta.state = 'draft'
62
+ assert ! @ta.valid?
63
+ assert_includes @ta.errors.messages[:state], "is already taken"
64
+ end
65
+
66
+ should "only allow one edition in published per slug" do
67
+ another_edition = FactoryGirl.create(:published_travel_advice_edition,
68
+ :country_slug => @ta.country_slug)
69
+ @ta.state = 'published'
70
+ assert ! @ta.valid?
71
+ assert_includes @ta.errors.messages[:state], "is already taken"
72
+ end
73
+
74
+ should "allow multiple editions in archived per slug" do
75
+ another_edition = FactoryGirl.create(:archived_travel_advice_edition,
76
+ :country_slug => @ta.country_slug)
77
+ @ta.save!
78
+ @ta.state = 'archived'
79
+ assert @ta.valid?
80
+ end
81
+
82
+ should "not conflict with itself when validating uniqueness" do
83
+ @ta.state = 'draft'
84
+ @ta.save!
85
+ assert @ta.valid?
86
+ end
87
+ end
88
+
89
+ context "preventing editing of non-draft" do
90
+ should "not allow published editions to be edited" do
91
+ ta = FactoryGirl.create(:published_travel_advice_edition)
92
+ ta.title = "Fooey"
93
+ assert ! ta.valid?
94
+ assert_includes ta.errors.messages[:state], "must be draft to modify"
95
+ end
96
+
97
+ should "not allow archived editions to be edited" do
98
+ ta = FactoryGirl.create(:archived_travel_advice_edition)
99
+ ta.title = "Fooey"
100
+ assert ! ta.valid?
101
+ assert_includes ta.errors.messages[:state], "must be draft to modify"
102
+ end
103
+
104
+ should "allow publishing draft editions" do
105
+ ta = FactoryGirl.create(:travel_advice_edition)
106
+ assert ta.publish
107
+ end
108
+
109
+ should "allow 'save & publish'" do
110
+ ta = FactoryGirl.create(:travel_advice_edition)
111
+ ta.title = 'Foo'
112
+ assert ta.publish
113
+ end
114
+
115
+ should "allow archiving published editions" do
116
+ ta = FactoryGirl.create(:published_travel_advice_edition)
117
+ assert ta.archive
118
+ end
119
+
120
+ should "NOT allow 'save & archive'" do
121
+ ta = FactoryGirl.create(:published_travel_advice_edition)
122
+ ta.title = 'Foo'
123
+ assert ! ta.archive
124
+ assert_includes ta.errors.messages[:state], "must be draft to modify"
125
+ end
126
+ end
127
+
128
+ context "on alert status" do
129
+ should "not permit invalid values in the array" do
130
+ @ta.alert_status = [ 'avoid_all_but_essential_travel_to_parts', 'something_else', 'blah' ]
131
+ assert ! @ta.valid?
132
+ assert_includes @ta.errors.messages[:alert_status], "is not in the list"
133
+ end
134
+
135
+ should "permit an empty array" do
136
+ @ta.alert_status = [ ]
137
+ assert @ta.valid?
138
+ end
139
+ end
140
+
141
+ context "on version_number" do
142
+ should "require a version_number" do
143
+ @ta.save # version_number is automatically populated on create, so save it first.
144
+ @ta.version_number = ''
145
+ refute @ta.valid?
146
+ assert_includes @ta.errors.messages[:version_number], "can't be blank"
147
+ end
148
+
149
+ should "require a unique version_number per slug" do
150
+ another_edition = FactoryGirl.create(:archived_travel_advice_edition,
151
+ :country_slug => @ta.country_slug,
152
+ :version_number => 3)
153
+ @ta.version_number = 3
154
+ refute @ta.valid?
155
+ assert_includes @ta.errors.messages[:version_number], "is already taken"
156
+ end
157
+
158
+ should "allow matching version_numbers for different slugs" do
159
+ another_edition = FactoryGirl.create(:archived_travel_advice_edition,
160
+ :country_slug => 'wibble',
161
+ :version_number => 3)
162
+ @ta.version_number = 3
163
+ assert @ta.valid?
164
+ end
165
+ end
166
+
167
+ context "on minor update" do
168
+ should "not allow first version to be minor update" do
169
+ @ta.minor_update = true
170
+ refute @ta.valid?
171
+ assert_includes @ta.errors.messages[:minor_update], "can't be set for first version"
172
+ end
173
+
174
+ should "allow other versions to be minor updates" do
175
+ FactoryGirl.create(:published_travel_advice_edition, :country_slug => @ta.country_slug)
176
+ @ta.minor_update = true
177
+ assert @ta.valid?
178
+ end
179
+ end
180
+
181
+ context "on change_description" do
182
+ should "be required on publish" do
183
+ @ta.save! # Can't save directly as published, have to save as draft first
184
+ @ta.change_description = ""
185
+ @ta.state = "published"
186
+ refute @ta.valid?
187
+ assert_includes @ta.errors.messages[:change_description], "can't be blank on publish"
188
+ end
189
+
190
+ should "not be required on publish for a minor update" do
191
+ FactoryGirl.create(:archived_travel_advice_edition, :country_slug => @ta.country_slug)
192
+ @ta.version_number = 2 # version one can't be minor update
193
+ @ta.save! # Can't save directly as published, have to save as draft first
194
+ @ta.change_description = ""
195
+ @ta.minor_update = true
196
+ @ta.state = "published"
197
+ assert @ta.valid?
198
+ end
199
+
200
+ should "not be required when just saving a draft" do
201
+ @ta.change_description = ""
202
+ assert @ta.valid?
203
+ end
204
+ end
205
+ end
206
+
207
+ context "fixing user input" do
208
+ setup do
209
+ @ed = FactoryGirl.build(:travel_advice_edition)
210
+ end
211
+
212
+ should "convert smart quotes in the summary field" do
213
+ @ed.summary = "This is a [link](https://www.gov.uk/ “link”)"
214
+ @ed.save!
215
+
216
+ @ed.reload
217
+ assert_equal 'This is a [link](https://www.gov.uk/ "link")', @ed.summary
218
+ end
219
+
220
+ should "convert smart quotes in part bodies" do
221
+ @ed.parts.build(:title => 'One', :slug => 'one', :body => "This is a [link](https://www.gov.uk/ “link”)")
222
+ @ed.save!
223
+
224
+ @ed.reload
225
+ assert_equal 'This is a [link](https://www.gov.uk/ "link")', @ed.parts.first.body
226
+ end
227
+ end
228
+
229
+ should "have a published scope" do
230
+ e1 = FactoryGirl.create(:draft_travel_advice_edition)
231
+ e2 = FactoryGirl.create(:published_travel_advice_edition)
232
+ e3 = FactoryGirl.create(:archived_travel_advice_edition)
233
+ e4 = FactoryGirl.create(:published_travel_advice_edition)
234
+
235
+ assert_equal [e2, e4].sort, TravelAdviceEdition.published.to_a.sort
236
+ end
237
+
238
+ context "fields on a new edition" do
239
+ should "be in draft state" do
240
+ assert TravelAdviceEdition.new.draft?
241
+ end
242
+
243
+ context "populating version_number" do
244
+ should "set version_number to 1 if there are no existing versions for the country" do
245
+ ed = TravelAdviceEdition.new(:country_slug => 'foo')
246
+ ed.valid?
247
+ assert_equal 1, ed.version_number
248
+ end
249
+
250
+ should "set version_number to the next available version" do
251
+ FactoryGirl.create(:archived_travel_advice_edition, :country_slug => 'foo', :version_number => 1)
252
+ FactoryGirl.create(:archived_travel_advice_edition, :country_slug => 'foo', :version_number => 2)
253
+ FactoryGirl.create(:published_travel_advice_edition, :country_slug => 'foo', :version_number => 4)
254
+
255
+ ed = TravelAdviceEdition.new(:country_slug => 'foo')
256
+ ed.valid?
257
+ assert_equal 5, ed.version_number
258
+ end
259
+
260
+ should "do nothing if version_number is already set" do
261
+ ed = TravelAdviceEdition.new(:country_slug => 'foo', :version_number => 42)
262
+ ed.valid?
263
+ assert_equal 42, ed.version_number
264
+ end
265
+
266
+ should "do nothing if country_slug is not set" do
267
+ ed = TravelAdviceEdition.new(:country_slug => '')
268
+ ed.valid?
269
+ assert_equal nil, ed.version_number
270
+ end
271
+ end
272
+
273
+ should "not be minor_update" do
274
+ assert_equal false, TravelAdviceEdition.new.minor_update
275
+ end
276
+ end
277
+
278
+ context "building a new version" do
279
+ setup do
280
+ @ed = FactoryGirl.create(:travel_advice_edition,
281
+ :title => "Aruba",
282
+ :overview => "Aruba is not near Wales",
283
+ :country_slug => "aruba",
284
+ :summary => "## The summary",
285
+ :alert_status => ["avoid_all_but_essential_travel_to_whole_country", "avoid_all_travel_to_parts"],
286
+ :image_id => "id_from_the_asset_manager_for_an_image",
287
+ :document_id => "id_from_the_asset_manager_for_a_document")
288
+ @ed.parts.build(:title => "Fooey", :slug => 'fooey', :body => "It's all about Fooey")
289
+ @ed.parts.build(:title => "Gooey", :slug => 'gooey', :body => "It's all about Gooey")
290
+ @ed.save!
291
+ @ed.publish!
292
+ end
293
+
294
+ should "build a new instance with the same fields" do
295
+ new_ed = @ed.build_clone
296
+ assert new_ed.new_record?
297
+ assert new_ed.valid?
298
+ assert_equal @ed.title, new_ed.title
299
+ assert_equal @ed.country_slug, new_ed.country_slug
300
+ assert_equal @ed.overview, new_ed.overview
301
+ assert_equal @ed.summary, new_ed.summary
302
+ assert_equal @ed.image_id, new_ed.image_id
303
+ assert_equal @ed.document_id, new_ed.document_id
304
+ assert_equal @ed.alert_status, new_ed.alert_status
305
+ end
306
+
307
+ should "copy the edition's parts" do
308
+ new_ed = @ed.build_clone
309
+ assert_equal ['Fooey', 'Gooey'], new_ed.parts.map(&:title)
310
+ end
311
+ end
312
+
313
+ context "previous_version" do
314
+ setup do
315
+ @ed1 = FactoryGirl.create(:archived_travel_advice_edition, :country_slug => 'foo')
316
+ @ed2 = FactoryGirl.create(:archived_travel_advice_edition, :country_slug => 'foo')
317
+ @ed3 = FactoryGirl.create(:archived_travel_advice_edition, :country_slug => 'foo')
318
+ end
319
+
320
+ should "return the previous version" do
321
+ assert_equal @ed2, @ed3.previous_version
322
+ assert_equal @ed1, @ed2.previous_version
323
+ end
324
+
325
+ should "return nil if there is no previous version" do
326
+ assert_equal nil, @ed1.previous_version
327
+ end
328
+ end
329
+
330
+ context "publishing" do
331
+ setup do
332
+ @published = FactoryGirl.create(:published_travel_advice_edition, :country_slug => 'aruba',
333
+ :published_at => 3.days.ago, :change_description => 'Stuff changed')
334
+ @ed = FactoryGirl.create(:travel_advice_edition, :country_slug => 'aruba')
335
+ end
336
+
337
+ should "publish the edition and archive related editions" do
338
+ @ed.publish!
339
+ @published.reload
340
+ assert @ed.published?
341
+ assert @published.archived?
342
+ end
343
+
344
+ context "setting the published date" do
345
+ should "set the published_at to now for a normal update" do
346
+ Timecop.freeze(1.day.from_now) do
347
+ @ed.publish!
348
+ # The to_i is necessary to account for the difference in milliseconds
349
+ # Time from the db only has a resolution in seconds, whereas Time.zone.now is more accurate
350
+ assert_equal Time.zone.now.utc.to_i, @ed.published_at.to_i
351
+ end
352
+ end
353
+
354
+ should "set the published_at to the previous version's published_at for a minor update" do
355
+ @ed.minor_update = true
356
+ @ed.publish!
357
+ assert_equal @published.published_at, @ed.published_at
358
+ end
359
+ end
360
+
361
+ should "set the change_description to the previous version's change_description for a minor update" do
362
+ @ed.minor_update = true
363
+ @ed.publish!
364
+ assert_equal @published.change_description, @ed.change_description
365
+ end
366
+ end
367
+
368
+ context "setting the reviewed at date" do
369
+ setup do
370
+ @published = FactoryGirl.create(:published_travel_advice_edition, :country_slug => 'aruba',
371
+ :published_at => 3.days.ago, :change_description => 'Stuff changed')
372
+ @published.reviewed_at = 2.days.ago
373
+ @published.save!
374
+
375
+ Timecop.freeze(1.days.ago) do
376
+ # this is done to make sure there's a significant difference in time
377
+ # between creating the edition and it being published
378
+ @ed = FactoryGirl.create(:travel_advice_edition, :country_slug => 'aruba')
379
+ end
380
+ end
381
+
382
+ should "be updated to published time when edition is published" do
383
+ @ed.change_description = "Did some stuff"
384
+ @ed.publish!
385
+ assert_equal @ed.published_at, @ed.reviewed_at
386
+ end
387
+
388
+ should "be set to the previous version's reviewed_at when a minor update is published" do
389
+ @ed.minor_update = true
390
+ @ed.publish!
391
+ assert_equal @published.reviewed_at, @ed.reviewed_at
392
+ end
393
+
394
+ should "be able to be updated without affecting other dates" do
395
+ published_at = @ed.published_at
396
+ Timecop.freeze(1.day.from_now) do
397
+ @ed.reviewed_at = Time.zone.now
398
+ assert_equal published_at, @ed.published_at
399
+ end
400
+ end
401
+
402
+ should "be able to update reviewed_at on a published edition" do
403
+ @ed.minor_update = true
404
+ @ed.publish!
405
+ Timecop.freeze(1.day.from_now) do
406
+ new_time = Time.zone.now
407
+ @ed.reviewed_at = new_time
408
+ @ed.save!
409
+ assert_equal new_time.utc.to_i, @ed.reviewed_at.to_i
410
+ end
411
+ end
412
+ end
413
+
414
+ context "indexable content" do
415
+ setup do
416
+ @edition = FactoryGirl.build(:travel_advice_edition)
417
+ end
418
+
419
+ should "return summary and all part titles and bodies" do
420
+ @edition.summary = "The Summary"
421
+ @edition.parts << Part.new(:title => "Part One", :body => "Some text")
422
+ @edition.parts << Part.new(:title => "More info", :body => "Some more information")
423
+ assert_equal "The Summary Part One Some text More info Some more information", @edition.indexable_content
424
+ end
425
+
426
+ should "convert govspeak to plain text" do
427
+ @edition.summary = "## The Summary"
428
+ @edition.parts << Part.new(:title => "Part One", :body => "* Some text")
429
+ assert_equal "The Summary Part One Some text", @edition.indexable_content
430
+ end
431
+ end
432
+
433
+ context "actions" do
434
+ setup do
435
+ @user = FactoryGirl.create(:user)
436
+ @old = FactoryGirl.create(:archived_travel_advice_edition, :country_slug => 'foo')
437
+ @edition = FactoryGirl.create(:draft_travel_advice_edition, :country_slug => 'foo')
438
+ end
439
+
440
+ should "not have any actions by default" do
441
+ assert_equal 0, @edition.actions.size
442
+ end
443
+
444
+ should "add a 'create' action" do
445
+ @edition.build_action_as(@user, Action::CREATE)
446
+ assert_equal 1, @edition.actions.size
447
+ assert_equal Action::CREATE, @edition.actions.first.request_type
448
+ assert_equal @user, @edition.actions.first.requester
449
+ end
450
+
451
+ should "add a 'new' action with a comment" do
452
+ @edition.build_action_as(@user, Action::NEW_VERSION, "a comment for the new version")
453
+ assert_equal 1, @edition.actions.size
454
+ assert_equal "a comment for the new version", @edition.actions.first.comment
455
+ end
456
+
457
+ context "publish_as" do
458
+ should "add a 'publish' action with change_description as comment on publish" do
459
+ @edition.change_description = "## My hovercraft is full of eels!"
460
+ @edition.publish_as(@user)
461
+ @edition.reload
462
+ assert_equal 1, @edition.actions.size
463
+ action = @edition.actions.last
464
+ assert_equal Action::PUBLISH, action.request_type
465
+ assert_equal @user, action.requester
466
+ assert_equal "My hovercraft is full of eels!", action.comment
467
+ end
468
+
469
+ should "add a 'publish' action with 'Minor update' as comment on publish of a minor_update" do
470
+ @edition.minor_update = true
471
+ @edition.publish_as(@user)
472
+ @edition.reload
473
+ assert_equal 1, @edition.actions.size
474
+ action = @edition.actions.last
475
+ assert_equal Action::PUBLISH, action.request_type
476
+ assert_equal "Minor update", action.comment
477
+ end
478
+ end
479
+ end
480
+ end