summaryrefslogtreecommitdiff
path: root/test/models/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'test/models/helpers')
-rw-r--r--test/models/helpers/content_helper_test.rb78
-rw-r--r--test/models/helpers/node_actions_helper_test.rb146
2 files changed, 222 insertions, 2 deletions
diff --git a/test/models/helpers/content_helper_test.rb b/test/models/helpers/content_helper_test.rb
index a7ed478..d6c7b43 100644
--- a/test/models/helpers/content_helper_test.rb
+++ b/test/models/helpers/content_helper_test.rb
@@ -2,7 +2,81 @@ require 'test_helper'
2 2
3class ContentHelperTest < ActionView::TestCase 3class ContentHelperTest < ActionView::TestCase
4 test "weekday_abbr delegates through the current I18n locale" do 4 test "weekday_abbr delegates through the current I18n locale" do
5 I18n.locale = :de 5 I18n.with_locale(:de) do
6 assert_equal "Mo", weekday_abbr(Time.parse("2026-07-06")) 6 assert_equal "Mo", weekday_abbr(Time.parse("2026-07-06"))
7 end
8 end
9
10 test "asset_credit returns nil for a nil asset" do
11 assert_nil asset_credit(nil)
12 end
13
14 test "asset_credit returns nil when creator, source, and license are all blank" do
15 assert_nil asset_credit(Asset.new(:name => "blank"))
16 end
17
18 test "asset_credit renders creator, source link, and license link when all are present" do
19 asset = Asset.new(:name => "demo", :creator => "Jane Doe",
20 :source_url => "https://example.org/photo", :license_key => "cc_by_4")
21
22 result = I18n.with_locale(:en) { asset_credit(asset) }
23
24 assert_match %r{<a href="https://example.org/photo">Photo demo</a>}, result
25 assert_match "by Jane Doe", result
26 assert_match %r{<a href="https://creativecommons.org/licenses/by/4.0/">Licensed under CC BY 4.0</a>}, result
27 end
28
29 test "asset_credit falls back to plain text when source_url is blank" do
30 asset = Asset.new(:name => "demo", :creator => "Jane Doe", :license_key => "cc_by_4")
31 assert_no_match %r{<a href="[^"]*">Photo demo</a>}, I18n.with_locale(:en) { asset_credit(asset) }
32 end
33
34 test "asset_credit omits the 'by' clause when creator is blank" do
35 asset = Asset.new(:name => "demo", :source_url => "https://example.org/photo", :license_key => "cc_by_4")
36 assert_no_match "by ", I18n.with_locale(:en) { asset_credit(asset) }
37 end
38
39 test "a note-style license renders with no 'Licensed under' prefix and no link" do
40 asset = Asset.new(:name => "demo", :creator => "CCC", :license_key => "own_work")
41 result = I18n.with_locale(:en) { asset_credit(asset) }
42
43 assert_match "Own work", result
44 assert_no_match "Licensed under", result
45 assert_no_match "<a", result
46 end
47
48 test "asset_credit degrades gracefully when the license_key is no longer in the dictionary" do
49 asset = Asset.new(:name => "demo", :creator => "Jane Doe")
50 asset.license_key = "a_retired_key"
51
52 result = I18n.with_locale(:en) { asset_credit(asset) }
53
54 assert_match "Photo demo by Jane Doe", result
55 assert_no_match "Licensed under", result
56 end
57
58 test "headline_image renders nothing when no images are attached" do
59 node = Node.root.children.create!(:slug => "headline_image_empty_test")
60 @page = node.draft
61 assert_nil headline_image
62 end
63
64 test "headline_image renders the flagged headline asset" do
65 node = Node.root.children.create!(:slug => "headline_image_flagged_test")
66 asset = Asset.create!(:name => "flagged", :upload_content_type => "image/png")
67 node.draft.assets << asset
68 node.draft.related_assets.find_by(:asset_id => asset.id).update!(:headline => true)
69 @page = node.draft
70
71 assert_match "glightbox", headline_image
72 end
73
74 test "headline_image falls back to a gallery-open caption when no headline is flagged" do
75 node = Node.root.children.create!(:slug => "headline_image_no_flag_test")
76 asset = Asset.create!(:name => "unflagged", :upload_content_type => "image/png")
77 node.draft.assets << asset
78 @page = node.draft
79
80 I18n.with_locale(:en) { assert_match t(:open_gallery), headline_image }
7 end 81 end
8end 82end
diff --git a/test/models/helpers/node_actions_helper_test.rb b/test/models/helpers/node_actions_helper_test.rb
new file mode 100644
index 0000000..1b72ec9
--- /dev/null
+++ b/test/models/helpers/node_actions_helper_test.rb
@@ -0,0 +1,146 @@
1require 'test_helper'
2
3class NodeActionsHelperTest < ActionView::TestCase
4 def setup
5 @original_locale = I18n.locale
6 I18n.locale = :en
7 end
8
9 def default_url_options
10 { :locale => nil }
11 end
12
13 def icon(_name, **)
14 '<svg class="stub-icon"></svg>'.html_safe
15 end
16
17 def teardown
18 I18n.locale = @original_locale
19 end
20
21 def entry action, metadata = {}, node: nil, user: nil, page: nil
22 NodeAction.create!(:node => node, :user => user, :page => page,
23 :action => action, :occurred_at => Time.now,
24 :metadata => { "username" => "quentin",
25 "human_readable_node_name" => "Subject" }.merge(metadata))
26 end
27
28 test "publish renders the revision sentence, not the titles" do
29 out = action_summary(entry("publish",
30 { "via" => "draft", "title" => { "from" => "Old", "to" => "New" } }))
31
32 assert_includes out, "quentin"
33 assert_includes out, "new revision"
34 assert_not_includes out, "Old"
35 end
36
37 test "first publish uses its own sentence" do
38 out = action_summary(entry("publish",
39 { "via" => "draft", "title" => { "from" => nil, "to" => "New" } }))
40
41 assert_includes out, "for the first time"
42 end
43
44 test "rollback publishes get the rollback sentence" do
45 out = action_summary(entry("publish",
46 { "via" => "revision", "title" => { "from" => "Now", "to" => "Then" } }))
47
48 assert_includes out, "rolled"
49 end
50
51 test "move renders the path pair" do
52 out = action_summary(entry("move",
53 { "path" => { "from" => "a/b", "to" => "a/c" } }))
54
55 assert_includes out, "a/b"
56 assert_includes out, "a/c"
57 end
58
59 test "unknown verbs degrade to a generic sentence, never an error" do
60 out = action_summary(entry("frobnicate"))
61
62 assert_includes out, "frobnicate"
63 assert_includes out, "quentin"
64 end
65
66 test "dead references render as plain names from metadata, no links" do
67 out = action_summary(entry("publish",
68 { "title" => { "from" => "Old", "to" => "New" } }))
69
70 assert_not_includes out, "<a "
71 assert_includes out, "Subject"
72 end
73
74 test "metadata values are escaped" do
75 out = action_summary(entry("publish",
76 { "human_readable_node_name" => "<b>bold</b>" }))
77
78 assert_not_includes out, "<b>"
79 end
80
81 test "live associations upgrade names to links" do
82 out = action_summary(entry("publish",
83 { "title" => { "from" => "Old", "to" => "New" } },
84 :user => users(:quentin)))
85
86 assert_includes out, "<a "
87 end
88
89 test "details are guarded off when nothing but an unchanged title is present" do
90 unchanged = entry("publish", { "title" => { "from" => "Same", "to" => "Same" } })
91 changed = entry("publish", { "title" => { "from" => "Old", "to" => "New" } })
92
93 assert_not action_details?(unchanged)
94 assert action_details?(changed)
95 end
96
97 test "first publish with a byline names the author" do
98 out = action_summary(entry("publish",
99 { "title" => { "from" => nil, "to" => "New" },
100 "author" => { "from" => nil, "to" => "quentin" } }))
101
102 assert_includes out, "author"
103 end
104
105 test "create entries with their flat title render and are guarded off details" do
106 e = entry("create", { "title" => "Initial", "path" => "a/b" })
107
108 assert_includes action_summary(e), "a/b"
109 assert_not action_details?(e)
110 end
111
112 test "trash, restore, and destroy render their paths" do
113 trash = entry("trash", { "path" => { "from" => "club/old", "to" => "trash/old" } })
114 restore = entry("restore_from_trash", { "path" => { "from" => "trash/old", "to" => "club/new" } })
115 doomed = entry("destroy", { "path" => "trash/old" })
116
117 assert_includes action_summary(trash), "club/old"
118 assert_includes action_summary(restore), "club/new"
119 assert_includes action_summary(doomed), "trash/old"
120 end
121
122 test "revision lifecycle badges cover create, publish, rollback, and inference" do
123 created = entry("create", { "title" => "x", "path" => "a/b" })
124 published = entry("publish", { "via" => "draft", "title" => { "from" => nil, "to" => "x" } })
125 restored = entry("publish", { "via" => "revision", "title" => { "from" => "y", "to" => "x" } })
126 restored.update!(:inferred_from => "from_page_revision")
127
128 out = revision_lifecycle_badges([created, published, restored])
129
130 assert_includes out, "created"
131 assert_includes out, "published"
132 assert_includes out, "restored"
133 assert_includes out, "quentin"
134 assert_includes out, "node_action_inferred"
135 assert_includes out, "<span"
136 assert_not_includes out, "&lt;span"
137
138 assert_equal "", revision_lifecycle_badges(nil)
139 end
140
141 test "verb icons map known verbs, distinguish rollbacks, and fall back" do
142 assert_includes verb_icon(entry("trash", { "path" => { "from" => "a", "to" => "t/a" } })), "node_action_icon--trash"
143 assert_includes verb_icon(entry("publish", { "via" => "revision" })), "node_action_icon--history"
144 assert_includes verb_icon(entry("frobnicate")), "node_action_icon--circle-dashed"
145 end
146end