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.
- data/.gitignore +17 -0
- data/.ruby-version +1 -0
- data/.travis.yml +14 -0
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +5 -0
- data/Rakefile +46 -0
- data/app/models/action.rb +60 -0
- data/app/models/answer_edition.rb +13 -0
- data/app/models/artefact.rb +341 -0
- data/app/models/artefact_action.rb +27 -0
- data/app/models/artefact_external_link.rb +15 -0
- data/app/models/business_support/business_size.rb +14 -0
- data/app/models/business_support/business_type.rb +14 -0
- data/app/models/business_support/location.rb +14 -0
- data/app/models/business_support/purpose.rb +14 -0
- data/app/models/business_support/sector.rb +14 -0
- data/app/models/business_support/stage.rb +14 -0
- data/app/models/business_support/support_type.rb +14 -0
- data/app/models/business_support_edition.rb +69 -0
- data/app/models/campaign_edition.rb +72 -0
- data/app/models/completed_transaction_edition.rb +14 -0
- data/app/models/curated_list.rb +32 -0
- data/app/models/edition.rb +286 -0
- data/app/models/expectant.rb +21 -0
- data/app/models/expectation.rb +12 -0
- data/app/models/guide_edition.rb +19 -0
- data/app/models/help_page_edition.rb +13 -0
- data/app/models/licence_edition.rb +35 -0
- data/app/models/local_authority.rb +58 -0
- data/app/models/local_interaction.rb +20 -0
- data/app/models/local_service.rb +49 -0
- data/app/models/local_transaction_edition.rb +49 -0
- data/app/models/overview_dashboard.rb +25 -0
- data/app/models/part.rb +28 -0
- data/app/models/parted.rb +32 -0
- data/app/models/place_edition.rb +20 -0
- data/app/models/programme_edition.rb +26 -0
- data/app/models/simple_smart_answer_edition.rb +66 -0
- data/app/models/simple_smart_answer_edition/node.rb +40 -0
- data/app/models/simple_smart_answer_edition/node/option.rb +31 -0
- data/app/models/tag.rb +88 -0
- data/app/models/transaction_edition.rb +28 -0
- data/app/models/travel_advice_edition.rb +177 -0
- data/app/models/user.rb +54 -0
- data/app/models/video_edition.rb +24 -0
- data/app/models/workflow.rb +217 -0
- data/app/models/workflow_actor.rb +141 -0
- data/app/traits/attachable.rb +60 -0
- data/app/traits/govspeak_smart_quotes_fixer.rb +19 -0
- data/app/traits/taggable.rb +113 -0
- data/app/validators/safe_html.rb +33 -0
- data/app/validators/slug_validator.rb +53 -0
- data/config/mongoid.yml +5 -0
- data/govuk_content_models.gemspec +42 -0
- data/jenkins.sh +7 -0
- data/lib/fact_check_address.rb +36 -0
- data/lib/govuk_content_models.rb +12 -0
- data/lib/govuk_content_models/require_all.rb +14 -0
- data/lib/govuk_content_models/test_helpers/factories.rb +213 -0
- data/lib/govuk_content_models/test_helpers/local_services.rb +24 -0
- data/lib/govuk_content_models/version.rb +4 -0
- data/test/fixtures/contactotron_api_response.json +1 -0
- data/test/fixtures/uploads/image.jpg +0 -0
- data/test/models/artefact_action_test.rb +123 -0
- data/test/models/artefact_external_link_test.rb +32 -0
- data/test/models/artefact_tag_test.rb +52 -0
- data/test/models/artefact_test.rb +583 -0
- data/test/models/business_support/business_size_test.rb +25 -0
- data/test/models/business_support/business_type_test.rb +25 -0
- data/test/models/business_support/location_test.rb +25 -0
- data/test/models/business_support/purpose_test.rb +29 -0
- data/test/models/business_support/sector_test.rb +25 -0
- data/test/models/business_support/stage_test.rb +25 -0
- data/test/models/business_support/support_type_test.rb +25 -0
- data/test/models/business_support_edition_test.rb +186 -0
- data/test/models/campaign_edition_test.rb +90 -0
- data/test/models/curated_list_test.rb +32 -0
- data/test/models/edition_test.rb +826 -0
- data/test/models/fact_check_address_test.rb +36 -0
- data/test/models/help_page_edition_test.rb +38 -0
- data/test/models/licence_edition_test.rb +104 -0
- data/test/models/local_authority_test.rb +113 -0
- data/test/models/local_service_test.rb +199 -0
- data/test/models/local_transaction_edition_test.rb +78 -0
- data/test/models/overview_dashboard_test.rb +47 -0
- data/test/models/simple_smart_answer_edition_test.rb +169 -0
- data/test/models/simple_smart_answer_node_test.rb +134 -0
- data/test/models/simple_smart_answer_option_test.rb +90 -0
- data/test/models/tag_test.rb +92 -0
- data/test/models/time_zone_test.rb +48 -0
- data/test/models/transaction_edition_test.rb +20 -0
- data/test/models/travel_advice_edition_test.rb +480 -0
- data/test/models/user_test.rb +114 -0
- data/test/models/video_edition_test.rb +64 -0
- data/test/models/workflow_actor_test.rb +61 -0
- data/test/models/workflow_test.rb +307 -0
- data/test/test_helper.rb +47 -0
- data/test/traits/attachable_test.rb +143 -0
- data/test/traits/taggable_test.rb +114 -0
- data/test/validators/safe_html_validator_test.rb +86 -0
- data/test/validators/slug_validator_test.rb +42 -0
- 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
|