summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-08-09 03:33:55 +0200
committererdgeist <erdgeist@erdgeist.org>2026-08-09 03:33:55 +0200
commit20c735b0c5a2db9b8984848253ad99332d6211a8 (patch)
treea4ae71c53c403c1a7740db624e43fd3163e37ab7 /test
parent5203b80f47786b8adc169e80d89cd69159c44b62 (diff)
Attach assets to the draft instead of to every lifecycle row
Node#attach_asset! writes to the node's draft alone, creating one from the head when none is pending. It refuses when another user holds the lock, and when an autosave already exists The asset_attach verb goes with it. create_new_draft names the editor on the draft it creates and the publish entry's asset delta reports the attachment.
Diffstat (limited to 'test')
-rw-r--r--test/controllers/assets_controller_test.rb34
-rw-r--r--test/controllers/content_controller_test.rb2
-rw-r--r--test/models/node_attach_asset_test.rb83
3 files changed, 80 insertions, 39 deletions
diff --git a/test/controllers/assets_controller_test.rb b/test/controllers/assets_controller_test.rb
index 467e1a68..aa3e00e6 100644
--- a/test/controllers/assets_controller_test.rb
+++ b/test/controllers/assets_controller_test.rb
@@ -94,7 +94,7 @@ class AssetsControllerTest < ActionController::TestCase
94 94
95 # --- create with attach --- 95 # --- create with attach ---
96 96
97 test "create with node_id attaches the asset to the node's draft" do 97 test "create with node_id attaches the asset to an existing draft" do
98 node = Node.root.children.create!(:slug => "asset_attach_target") 98 node = Node.root.children.create!(:slug => "asset_attach_target")
99 99
100 post :create, params: { asset: { name: 'Attach me' }, node_id: node.id } 100 post :create, params: { asset: { name: 'Attach me' }, node_id: node.id }
@@ -102,7 +102,21 @@ class AssetsControllerTest < ActionController::TestCase
102 assert_response :redirect 102 assert_response :redirect
103 asset = Asset.last 103 asset = Asset.last
104 assert_includes node.draft.assets.reload, asset 104 assert_includes node.draft.assets.reload, asset
105 assert_equal I18n.t("flash.assets.attached", :title => node.title), flash[:notice] 105 assert_equal I18n.t("flash.assets.attached_to_draft", :title => node.title), flash[:notice]
106 end
107
108 test "create with node_id creates a draft when none is pending" do
109 node = Node.root.children.create!(:slug => "asset_attach_no_draft")
110 node.publish_draft!(users(:quentin))
111 assert_nil node.reload.draft
112
113 post :create, params: { asset: { name: 'Attach me too' }, node_id: node.id }
114
115 node.reload
116 assert_includes node.draft.assets.reload, Asset.last
117 assert_empty node.head.assets.reload
118 assert_equal users(:quentin), node.draft.editor
119 assert_equal I18n.t("flash.assets.attached_new_draft", :title => node.title), flash[:notice]
106 end 120 end
107 121
108 test "create against a foreign-locked node keeps the asset but refuses the attach" do 122 test "create against a foreign-locked node keeps the asset but refuses the attach" do
@@ -133,14 +147,16 @@ class AssetsControllerTest < ActionController::TestCase
133 assert_equal node_path(node), flash[:headline_kept_path] 147 assert_equal node_path(node), flash[:headline_kept_path]
134 end 148 end
135 149
136 test "create with node_id writes an asset_create and an asset_attach entry" do 150 test "create with node_id writes only an asset_create entry" do
137 node = Node.root.children.create!(:slug => "asset_log_pair") 151 node = Node.root.children.create!(:slug => "asset_log_single")
138 assert_difference 'NodeAction.where(:action => "asset_create").count' do 152
139 assert_difference 'NodeAction.where(:action => "asset_attach").count' do 153 assert_difference 'NodeAction.count', 1 do
140 post :create, params: { asset: { name: 'Logged twice' }, node_id: node.id } 154 post :create, params: { asset: { name: 'Logged once' }, node_id: node.id }
141 end
142 end 155 end
143 assert_equal users(:quentin), NodeAction.last.user 156
157 action = NodeAction.last
158 assert_equal "asset_create", action.action
159 assert_equal users(:quentin), action.user
144 end 160 end
145 161
146 # --- edit --- 162 # --- edit ---
diff --git a/test/controllers/content_controller_test.rb b/test/controllers/content_controller_test.rb
index 39fe276b..482c1ddf 100644
--- a/test/controllers/content_controller_test.rb
+++ b/test/controllers/content_controller_test.rb
@@ -170,6 +170,8 @@ class ContentControllerTest < ActionController::TestCase
170 :upload_content_type => "image/png", 170 :upload_content_type => "image/png",
171 :upload_updated_at => Time.at(1_700_000_000)) 171 :upload_updated_at => Time.at(1_700_000_000))
172 node.attach_asset!(asset, :user => @user1, :headline => true) 172 node.attach_asset!(asset, :user => @user1, :headline => true)
173 node.publish_draft!
174 node.reload
173 175
174 # has_variant? only tests File.exist?, so touching the path is enough 176 # has_variant? only tests File.exist?, so touching the path is enough
175 # and no ImageMagick runs in the suite. image/png takes .jpg for the 177 # and no ImageMagick runs in the suite. image/png takes .jpg for the
diff --git a/test/models/node_attach_asset_test.rb b/test/models/node_attach_asset_test.rb
index 2df2cfbb..9ab38158 100644
--- a/test/models/node_attach_asset_test.rb
+++ b/test/models/node_attach_asset_test.rb
@@ -9,49 +9,67 @@ class NodeAttachAssetTest < ActiveSupport::TestCase
9 @image = create_image_asset 9 @image = create_image_asset
10 end 10 end
11 11
12 test "attaches to a draft-only node" do 12 test "attaches to an existing draft" do
13 result = @node.attach_asset!(@image, :user => @user) 13 result = @node.attach_asset!(@image, :user => @user)
14 assert_equal 1, result[:attached] 14 assert_equal 1, result[:attached]
15 assert_not result[:draft_created]
15 assert_includes @node.draft.assets, @image 16 assert_includes @node.draft.assets, @image
16 end 17 end
17 18
18 test "attaches to head when no draft is pending" do 19 test "creates a draft when none is pending and leaves head untouched" do
19 @node.publish_draft!(@user) 20 @node.publish_draft!(@user)
20 result = @node.attach_asset!(@image, :user => @user) 21 result = @node.attach_asset!(@image, :user => @user)
21 assert_equal 1, result[:attached] 22 assert_equal 1, result[:attached]
22 assert_includes @node.head.assets, @image 23 assert result[:draft_created]
24 assert_includes @node.draft.assets, @image
25 assert_empty @node.head.assets.reload
23 end 26 end
24 27
25 test "attaches to head and pending draft alike" do 28 test "attaches to a pending draft and leaves head untouched" do
26 @node.publish_draft!(@user) 29 @node.publish_draft!(@user)
27 @node.lock_for_editing!(@user) 30 @node.lock_for_editing!(@user)
28 @node.create_new_draft(@user) 31 @node.create_new_draft(@user)
29 result = @node.attach_asset!(@image, :user => @user) 32 result = @node.attach_asset!(@image, :user => @user)
30 assert_equal 2, result[:attached] 33 assert_equal 1, result[:attached]
31 assert_includes @node.head.assets, @image 34 assert_not result[:draft_created]
32 assert_includes @node.draft.assets, @image 35 assert_includes @node.draft.assets, @image
36 assert_empty @node.head.assets.reload
33 end 37 end
34 38
35 test "attaches to all three lifecycle rows" do 39 test "refuses when an autosave exists and writes nothing" do
36 @node.publish_draft!(@user) 40 @node.publish_draft!(@user)
37 @node.lock_for_editing!(@user) 41 @node.lock_for_editing!(@user)
38 @node.create_new_draft(@user) 42 @node.create_new_draft(@user)
39 @node.autosave!({ :title => "wip" }, @user) 43 @node.autosave!({ :title => "wip" }, @user)
44 assert_raises(ActiveRecord::RecordInvalid) { @node.attach_asset!(@image, :user => @user) }
45 assert_empty @node.draft.assets.reload
46 assert_empty @node.autosave.assets.reload
47 end
48
49 test "reports an asset the draft already carries without duplicating it" do
50 @node.draft.related_assets.create!(:asset => @image)
40 result = @node.attach_asset!(@image, :user => @user) 51 result = @node.attach_asset!(@image, :user => @user)
41 assert_equal 3, result[:attached] 52 assert_equal 0, result[:attached]
42 [@node.head, @node.draft, @node.autosave].each do |row| 53 assert_equal 1, result[:already]
43 assert_includes row.assets, @image 54 assert_not result[:draft_created]
44 end 55 assert_equal 1, @node.draft.related_assets.where(:asset_id => @image.id).count
45 end 56 end
46 57
47 test "skips rows that already carry the asset" do 58 test "creates no draft when head already carries the asset" do
48 @node.draft.related_assets.create!(:asset => @image) 59 @node.draft.related_assets.create!(:asset => @image)
49 @node.publish_draft!(@user) 60 @node.publish_draft!(@user)
50 @node.lock_for_editing!(@user) 61 assert_nil @node.draft
51 @node.create_new_draft(@user) 62
63 result = @node.attach_asset!(@image, :user => @user)
64 assert_equal 0, result[:attached]
65 assert_not result[:draft_created]
66 assert_nil @node.reload.draft
67 end
68
69 test "attaching twice leaves one join row" do
70 @node.attach_asset!(@image, :user => @user)
52 result = @node.attach_asset!(@image, :user => @user) 71 result = @node.attach_asset!(@image, :user => @user)
53 assert_equal 0, result[:attached] 72 assert_equal 0, result[:attached]
54 assert_equal 2, result[:already]
55 assert_equal 1, @node.draft.related_assets.where(:asset_id => @image.id).count 73 assert_equal 1, @node.draft.related_assets.where(:asset_id => @image.id).count
56 end 74 end
57 75
@@ -82,6 +100,17 @@ class NodeAttachAssetTest < ActiveSupport::TestCase
82 assert_includes @node.draft.assets, @image 100 assert_includes @node.draft.assets, @image
83 end 101 end
84 102
103 test "keeps a headline the new draft inherited from head" do
104 incumbent = create_image_asset
105 @node.draft.related_assets.create!(:asset => incumbent, :headline => true)
106 @node.publish_draft!(@user)
107
108 result = @node.attach_asset!(@image, :user => @user, :headline => true)
109 assert result[:draft_created]
110 assert_equal :kept_existing, result[:headline]
111 assert_equal incumbent, @node.draft.reload.headline_asset
112 end
113
85 test "declines the headline flag for ineligible asset types" do 114 test "declines the headline flag for ineligible asset types" do
86 plain = create_plain_asset 115 plain = create_plain_asset
87 result = @node.attach_asset!(plain, :user => @user, :headline => true) 116 result = @node.attach_asset!(plain, :user => @user, :headline => true)
@@ -95,25 +124,19 @@ class NodeAttachAssetTest < ActiveSupport::TestCase
95 assert_raises(ActiveRecord::RecordInvalid) { @node.attach_asset!(@image, :user => @user) } 124 assert_raises(ActiveRecord::RecordInvalid) { @node.attach_asset!(@image, :user => @user) }
96 end 125 end
97 126
98 test "attaching writes an asset_attach entry with node and asset participants" do 127 test "attaching writes no log entry -- publish carries the witnessing" do
99 result = @node.attach_asset!(@image, :user => @user, :headline => true) 128 assert_no_difference "NodeAction.count" do
100 assert_equal :set, result[:headline]
101
102 action = NodeAction.where(:action => "asset_attach").last
103 assert_equal @node, action.node
104 subjects = action.action_participants.map { |p| [p.subject_type, p.subject_id] }
105 assert_includes subjects, ["Node", @node.id]
106 assert_includes subjects, ["Asset", @image.id]
107 assert action.metadata["headline"]
108 end
109
110 test "a fully redundant attach writes no entry" do
111 @node.attach_asset!(@image, :user => @user)
112 assert_no_difference 'NodeAction.count' do
113 @node.attach_asset!(@image, :user => @user) 129 @node.attach_asset!(@image, :user => @user)
114 end 130 end
115 end 131 end
116 132
133 test "attaching under a restricted surface needs no redaktion role" do
134 updates = Node.root.children.create!(:slug => "updates")
135 node = updates.children.create!(:slug => "gated-attachment")
136 result = node.reload.attach_asset!(@image, :user => @user)
137 assert_equal 1, result[:attached]
138 end
139
117 private 140 private
118 141
119 def create_image_asset 142 def create_image_asset