Skip to content

Commit 21f7fdd

Browse files
Update social media accounts validations to include title logic
- We now validate for unique title as well (URL must also be unique from before). - Channel names can now be repeated, provided their titles are distinct. - The "Other" channel does not behave in any way differently from the rest of the channels. We won't allow multiple "Other" entries unless they have different titles. A valid scenario is if one "Other" channel has no title and the other does. - We do not validate title uniqueness scoped to the channel, but globally - we will not allow a repeated title even if it is across different channels. This is because it could still be confusing on the screen if the title is repeated. - If there are channels that match, and their titles match, we'll only render a single error for the titles matching.
1 parent c4ab88b commit 21f7fdd

2 files changed

Lines changed: 95 additions & 18 deletions

File tree

app/validators/social_media_links_validator.rb

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ def initialize(opts = {})
33
@attributes = opts[:attributes]
44
@channel_field = opts[:fields]["service_field"]
55
@url_field = opts[:fields]["url_field"]
6+
@title_field = opts[:fields]["title_field"]
7+
68
super
79
end
810

@@ -11,34 +13,52 @@ def validate(record)
1113
arr = record.send(attribute_name.to_sym) || []
1214
@channels_seen = []
1315
@urls_seen = []
16+
@titles_seen = []
1417

1518
arr.each_with_index do |social_media_account, index|
1619
channel_name = social_media_account[@channel_field]
1720
url = social_media_account[@url_field]
21+
title = social_media_account["title"]
22+
channel = { channel_name: channel_name, title: title }
1823

19-
validate_social_media_channel(channel_name, index, record, attribute_name)
24+
validate_social_media_title(title, index, record, attribute_name)
2025
validate_social_media_url(url, index, record, attribute_name)
26+
validate_social_media_channel(channel, index, record, attribute_name)
2127
end
2228
end
2329
end
2430

2531
private
2632

27-
def validate_social_media_channel(channel_name, index, record, attribute_name)
28-
if channel_name.blank?
33+
def validate_social_media_channel(channel, index, record, attribute_name)
34+
if channel[:channel_name].blank?
2935
record.errors.add(
3036
:"#{attribute_name}.#{index}.#{@channel_field}",
3137
:blank,
3238
message: "cannot be blank",
3339
)
34-
elsif channel_name != "Other" && @channels_seen.include?(channel_name)
40+
elsif @channels_seen.select { |c| c[:channel_name] == channel[:channel_name] && c[:title] == channel[:title] && c[:title].blank? }.any?
3541
record.errors.add(
3642
:"#{attribute_name}.#{index}.#{@channel_field}",
3743
:taken,
3844
message: "must be unique",
3945
)
4046
else
41-
@channels_seen << channel_name
47+
@channels_seen << channel
48+
end
49+
end
50+
51+
def validate_social_media_title(title, index, record, attribute_name)
52+
return if title.blank?
53+
54+
if @titles_seen.include?(title)
55+
record.errors.add(
56+
:"#{attribute_name}.#{index}.#{@title_field}",
57+
:taken,
58+
message: "must be unique",
59+
)
60+
else
61+
@titles_seen << title
4262
end
4363
end
4464

test/unit/app/validators/social_media_links_validator_test.rb

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class SocialMediaLinksValidatorTest < ActiveSupport::TestCase
77
fields: {
88
"service_field" => "social_media_service_name",
99
"url_field" => "url",
10+
"title_field" => "title",
1011
},
1112
})
1213
end
@@ -78,46 +79,102 @@ class SocialMediaLinksValidatorTestClass
7879
assert_includes block_content.errors["social_media_links.0.url".to_sym], "is invalid - use the full URL, including https://"
7980
end
8081

81-
test "social media links are invalid if two of the same channel are provided" do
82+
test "social media links are invalid if two channels have the same URL" do
8283
block_content = SocialMediaLinksValidatorTestClass.new
8384
block_content.social_media_links = [
85+
{ "social_media_service_name" => "Twitter", "url" => "http://facebook.com/govuk" },
8486
{ "social_media_service_name" => "Facebook", "url" => "http://facebook.com/govuk" },
85-
{ "social_media_service_name" => "Facebook", "url" => "http://facebook.com/govukpage2" },
8687
]
8788
@validator.validate(block_content)
8889

89-
assert_empty block_content.errors["social_media_links.0.social_media_service_name".to_sym]
90-
assert_includes block_content.errors["social_media_links.1.social_media_service_name".to_sym], "must be unique"
90+
assert_empty block_content.errors["social_media_links.0.url".to_sym]
91+
assert_includes block_content.errors["social_media_links.1.url".to_sym], "must be unique"
9192
end
9293

93-
test "social media links are invalid if two channels have the same URL" do
94+
test "social media links are valid when a channel is chosen and a well-formed URL is provided" do
9495
block_content = SocialMediaLinksValidatorTestClass.new
9596
block_content.social_media_links = [
96-
{ "social_media_service_name" => "Twitter", "url" => "http://facebook.com/govuk" },
9797
{ "social_media_service_name" => "Facebook", "url" => "http://facebook.com/govuk" },
98+
{ "social_media_service_name" => "LinkedIn", "url" => "https://linkedin.com/company/govuk" },
9899
]
99100
@validator.validate(block_content)
100101

101-
assert_empty block_content.errors["social_media_links.0.url".to_sym]
102-
assert_includes block_content.errors["social_media_links.1.url".to_sym], "must be unique"
102+
assert block_content.errors.empty?
103103
end
104104

105-
test "social media links are valid when multiple 'Other' channels are provided with different URLs" do
105+
test "social media links are valid when titles are unique" do
106106
block_content = SocialMediaLinksValidatorTestClass.new
107107
block_content.social_media_links = [
108-
{ "social_media_service_name" => "Other", "url" => "http://example.com/one" },
109-
{ "social_media_service_name" => "Other", "url" => "http://example.com/two" },
108+
{ "social_media_service_name" => "Facebook", "url" => "http://facebook.com/govuk", "title" => "GOV.UK on Facebook" },
109+
{ "social_media_service_name" => "Twitter", "url" => "http://twitter.com/govuk", "title" => "GOV.UK on Twitter" },
110110
]
111111
@validator.validate(block_content)
112112

113113
assert block_content.errors.empty?
114114
end
115115

116-
test "social media links are valid when a channel is chosen and a well-formed URL is provided" do
116+
test "social media links are valid when titles are blank" do
117+
block_content = SocialMediaLinksValidatorTestClass.new
118+
block_content.social_media_links = [
119+
{ "social_media_service_name" => "Facebook", "url" => "http://facebook.com/govuk", "title" => "" },
120+
{ "social_media_service_name" => "Twitter", "url" => "http://twitter.com/govuk", "title" => "" },
121+
]
122+
@validator.validate(block_content)
123+
124+
assert block_content.errors.empty?
125+
end
126+
127+
test "social media links are invalid when any two accounts have the same title" do
128+
block_content = SocialMediaLinksValidatorTestClass.new
129+
block_content.social_media_links = [
130+
{ "social_media_service_name" => "Facebook", "title" => "Our updates", "url" => "http://facebook.com/govuk" },
131+
{ "social_media_service_name" => "Twitter", "title" => "Our updates", "url" => "http://twitter.com/govuk" },
132+
]
133+
@validator.validate(block_content)
134+
135+
assert_includes block_content.errors["social_media_links.1.title".to_sym], "must be unique"
136+
end
137+
138+
test "social media links are invalid when multiple instances of the same channel are provided, with no distinct titles" do
117139
block_content = SocialMediaLinksValidatorTestClass.new
118140
block_content.social_media_links = [
119141
{ "social_media_service_name" => "Facebook", "url" => "http://facebook.com/govuk" },
120-
{ "social_media_service_name" => "LinkedIn", "url" => "https://linkedin.com/company/govuk" },
142+
{ "social_media_service_name" => "Facebook", "url" => "http://facebook.com/govukpage2" },
143+
]
144+
@validator.validate(block_content)
145+
146+
assert_empty block_content.errors["social_media_links.0.social_media_service_name".to_sym]
147+
assert_includes block_content.errors["social_media_links.1.social_media_service_name".to_sym], "must be unique"
148+
end
149+
150+
test "social media links are invalid when multiple 'Other' channels are provided, with no distinct titles" do
151+
block_content = SocialMediaLinksValidatorTestClass.new
152+
block_content.social_media_links = [
153+
{ "social_media_service_name" => "Other", "url" => "http://example.com/one" },
154+
{ "social_media_service_name" => "Other", "url" => "http://example.com/two" },
155+
]
156+
@validator.validate(block_content)
157+
158+
assert_includes block_content.errors["social_media_links.1.social_media_service_name".to_sym], "must be unique"
159+
end
160+
161+
test "social media links are invalid and only display title uniqueness error, if multiple instances of the same channel are provided, and their titles match" do
162+
block_content = SocialMediaLinksValidatorTestClass.new
163+
block_content.social_media_links = [
164+
{ "social_media_service_name" => "Facebook", "title" => "Facebook", "url" => "http://facebook.com/govuk" },
165+
{ "social_media_service_name" => "Facebook", "title" => "Facebook", "url" => "http://facebook.com/govukpage2" },
166+
]
167+
@validator.validate(block_content)
168+
169+
assert_includes block_content.errors["social_media_links.1.title".to_sym], "must be unique"
170+
assert block_content.errors["social_media_links.1.social_media_service_name".to_sym].empty?
171+
end
172+
173+
test "social media links are valid when multiple instances of the same channel are provided with different titles and different URLs" do
174+
block_content = SocialMediaLinksValidatorTestClass.new
175+
block_content.social_media_links = [
176+
{ "social_media_service_name" => "Facebook", "title" => "Facebook Corporate", "url" => "http://example.com/one" },
177+
{ "social_media_service_name" => "Facebook", "title" => "Facebook Fun", "url" => "http://example.com/two" },
121178
]
122179
@validator.validate(block_content)
123180

0 commit comments

Comments
 (0)