summaryrefslogtreecommitdiff
path: root/test/models/node_action_test.rb
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-16 02:40:03 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-16 02:40:03 +0200
commitc0c9250141c2fa64fed967b8b9ad9bada3694c3d (patch)
tree8a36020521dafc0d259d5d78461c59a4635b6ba4 /test/models/node_action_test.rb
parentfb7b8233f1bbf7acb88d48f96e6f81cefe168d1c (diff)
Record the full lifecycle contract in NodeAction entries
A contract comment above NodeAction.record! now specifies every verb's metadata shape. NodeAction.head_diff computes the publish diff between an outgoing head and its replacement -- default-locale title pair always, author/tags pairs and template/assets/abstract/ body flags only when changed, and a per-locale translation_diff with added/removed/changed status. It is a pure function of its two pages, shared by publish, rollback, and the future backfill, and reads translation rows directly so fallbacks never masquerade as content. publish entries carry via ("draft" or "revision"); restore_revision! is now transactional, takes the acting user, and logs through the same diff. Staged slug/parent changes applied at publish log a move entry with the path pair. Node creation logs a create entry with initial title and path. The draft-scoped translation_destroy writer is retired -- locale removal is recorded by the publish diff, where it becomes public fact.
Diffstat (limited to 'test/models/node_action_test.rb')
-rw-r--r--test/models/node_action_test.rb112
1 files changed, 112 insertions, 0 deletions
diff --git a/test/models/node_action_test.rb b/test/models/node_action_test.rb
new file mode 100644
index 0000000..24d8245
--- /dev/null
+++ b/test/models/node_action_test.rb
@@ -0,0 +1,112 @@
1require "test_helper"
2
3class NodeActionTest < ActiveSupport::TestCase
4
5 # Standalone pages, no node -- same pattern autosave relies on.
6 # Default-locale attributes are written pinned, never ambient.
7 def build_page en: nil, **attrs
8 page = Globalize.with_locale(I18n.default_locale) do
9 Page.create!({ :title => "Titel" }.merge(attrs))
10 end
11 page.translations.create!({ :locale => "en" }.merge(en)) if en
12 page.reload
13 end
14
15 test "first publish yields exactly the title pair, from nil" do
16 diff = NodeAction.head_diff(nil, build_page(:title => "Erstausgabe"))
17
18 assert_equal({ :title => { "from" => nil, "to" => "Erstausgabe" } }, diff)
19 end
20
21 test "title pair is always present, even when unchanged" do
22 diff = NodeAction.head_diff(build_page, build_page)
23
24 assert_equal "Titel", diff[:title]["from"]
25 assert_equal "Titel", diff[:title]["to"]
26 end
27
28 test "author pair present only when the byline changed" do
29 u1, u2 = users(:quentin), users(:aaron)
30
31 assert_nil NodeAction.head_diff(build_page(:user => u1), build_page(:user => u1))[:author]
32
33 changed = NodeAction.head_diff(build_page(:user => u1), build_page(:user => u2))
34 assert_equal({ "from" => u1.login, "to" => u2.login }, changed[:author])
35 end
36
37 test "tags pair present only when the tag set changed" do
38 old_page = build_page; old_page.tag_list = "alpha, beta"; old_page.save!
39 new_page = build_page; new_page.tag_list = "beta, gamma"; new_page.save!
40
41 diff = NodeAction.head_diff(old_page.reload, new_page.reload)
42 assert_equal %w[alpha beta], diff[:tags]["from"]
43 assert_equal %w[beta gamma], diff[:tags]["to"]
44
45 same = NodeAction.head_diff(old_page, old_page)
46 assert_nil same[:tags]
47 end
48
49 test "template_changed flag only when true" do
50 old_page = build_page(:template_name => "standard_template")
51
52 assert NodeAction.head_diff(old_page, build_page(:template_name => "update"))[:template_changed]
53 assert_nil NodeAction.head_diff(old_page, build_page(:template_name => "standard_template"))[:template_changed]
54 end
55
56 test "assets_changed flag when the attached set differs" do
57 asset = Asset.create!(:name => "diff probe",
58 :upload_file_name => "test_image.png",
59 :upload_content_type => "image/png",
60 :upload_file_size => 49854,
61 :upload_updated_at => Time.current)
62 old_page, new_page = build_page, build_page
63 new_page.related_assets.create!(:asset_id => asset.id, :position => 1)
64
65
66 diff = NodeAction.head_diff(old_page, new_page.reload)
67 assert diff[:assets_changed]
68 assert_nil NodeAction.head_diff(old_page, old_page)[:assets_changed]
69 end
70
71 test "default-locale abstract and body changes become flags, only when true" do
72 diff = NodeAction.head_diff(build_page(:abstract => "a"), build_page(:abstract => "b"))
73
74 assert diff[:abstract_changed]
75 assert_nil diff[:body_changed]
76 end
77
78 test "added locale carries status and the new title" do
79 diff = NodeAction.head_diff(build_page, build_page(en: { :title => "English" }))
80
81 entry = diff[:translation_diff]["en"]
82 assert_equal "added", entry["status"]
83 assert_equal({ "from" => nil, "to" => "English" }, entry["title"])
84 end
85
86 test "removed locale keeps the vanished title" do
87 diff = NodeAction.head_diff(build_page(en: { :title => "English" }), build_page)
88
89 entry = diff[:translation_diff]["en"]
90 assert_equal "removed", entry["status"]
91 assert_equal "English", entry["title"]["from"]
92 assert_nil entry["title"]["to"]
93 end
94
95 test "changed locale carries only what actually differs" do
96 old_page = build_page(en: { :title => "Same", :body => "old" })
97 new_page = build_page(en: { :title => "Same", :body => "new" })
98
99 entry = NodeAction.head_diff(old_page, new_page)[:translation_diff]["en"]
100 assert_equal "changed", entry["status"]
101 assert_nil entry["title"]
102 assert entry["body_changed"]
103 assert_nil entry["abstract_changed"]
104 end
105
106 test "untouched locales are absent; identical pages yield no translation_diff at all" do
107 old_page = build_page(en: { :title => "Same" })
108 new_page = build_page(en: { :title => "Same" })
109
110 assert_nil NodeAction.head_diff(old_page, new_page)[:translation_diff]
111 end
112end