1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
require "test_helper"
class NodeTrashTest < ActiveSupport::TestCase
def setup
@user1 = User.create!(:login => "trasher", :email => "t@example.com",
:password => "foobar", :password_confirmation => "foobar")
end
test "trash! demotes the head into the draft slot when no draft exists" do
node = create_node_with_published_page
former_head = node.head
node.trash!(@user1)
node.reload
assert_nil node.head_id
assert_equal former_head, node.draft
assert node.in_trash?
end
test "trash! keeps an existing draft; the former head stays a plain revision" do
node = create_node_with_published_page
draft = find_or_create_draft(node, @user1)
former_head = node.head
node.trash!(@user1)
node.reload
assert_nil node.head_id
assert_equal draft, node.draft
assert_includes node.pages, former_head
end
test "trash! demotes descendant heads and counts them in the log entry" do
parent = create_node_with_published_page
child = parent.children.create!(:slug => "trashed_child")
child.draft.update!(:title => "Child")
child.publish_draft!(@user1)
parent.trash!(@user1)
action = NodeAction.where(:action => "trash").last
assert_equal parent, action.node
assert_equal 2, action.metadata["demoted_heads"]
assert action.metadata["was_published"]
assert_nil child.reload.head_id
assert child.in_trash?
end
test "trash! logs one entry with the path pair and updates unique names" do
node = create_node_with_published_page
path_before = node.unique_name
assert_difference "NodeAction.count", 1 do
node.trash!(@user1)
end
action = NodeAction.last
assert_equal path_before, action.metadata.dig("path", "from")
assert_equal node.reload.unique_name, action.metadata.dig("path", "to")
assert action.metadata.dig("path", "to").start_with?(CccConventions::TRASH_SLUG)
end
test "trash! on an already trashed node is a logged-nothing no-op" do
node = create_node_with_published_page
node.trash!(@user1)
assert_no_difference "NodeAction.count" do
assert_nil node.reload.trash!(@user1)
end
end
test "restore_from_trash! reparents as drafts without republishing" do
node = create_node_with_published_page
node.trash!(@user1)
target = Node.root.children.create!(:slug => "restore_target")
node.reload.restore_from_trash!(target, @user1)
node.reload
assert_equal target, node.parent
assert_not node.in_trash?
assert_nil node.head_id
assert_not_nil node.draft_id
assert_equal "restore_from_trash", NodeAction.last.action
end
test "restore_from_trash! refuses targets inside the Trash and the Trash itself" do
node = create_node_with_published_page
node.trash!(@user1)
other_trashed = Node.trash.children.create!(:slug => "also_trashed")
assert_raises(ActiveRecord::RecordInvalid) { node.reload.restore_from_trash!(Node.trash, @user1) }
assert_raises(ActiveRecord::RecordInvalid) { node.reload.restore_from_trash!(other_trashed, @user1) }
end
test "destroy_from_trash! refuses nodes outside the Trash" do
node = create_node_with_published_page
assert_raises(ActiveRecord::RecordInvalid) { node.destroy_from_trash!(@user1) }
assert Node.exists?(node.id)
end
test "destroy_from_trash! removes the whole subtree bottom-up with one entry" do
parent = create_node_with_published_page
child = parent.children.create!(:slug => "doomed_child")
grandchild = child.children.create!(:slug => "doomed_grandchild")
page_ids = [parent, child, grandchild].flat_map { |n| n.pages.pluck(:id) }
parent.trash!(@user1)
assert_difference "NodeAction.count", 1 do
parent.reload.destroy_from_trash!(@user1)
end
assert_not Node.exists?(parent.id)
assert_not Node.exists?(child.id)
assert_not Node.exists?(grandchild.id)
assert_equal 0, Page.where(:id => page_ids).count
action = NodeAction.where(:action => "destroy").last
assert_equal 2, action.metadata["destroyed_descendants"]
assert_nil action.node_id
end
test "destroy_from_trash! logs an entry that survives the node" do
node = create_node_with_published_page
Globalize.with_locale(I18n.default_locale) { node.head.update!(:title => "Doomed") }
node.trash!(@user1)
final_path = node.reload.unique_name
node.destroy_from_trash!(@user1)
action = NodeAction.where(:action => "destroy").last
assert_nil action.node_id
assert_equal final_path, action.metadata["path"]
assert_equal "Doomed", action.subject_name
assert_equal @user1, action.user
end
test "suggested_restore_parent finds the old parent while it lives" do
parent = Node.root.children.create!(:slug => "old_home")
node = parent.children.create!(:slug => "comes_back")
node.trash!(@user1)
assert_equal parent, node.reload.suggested_restore_parent
parent.trash!(@user1)
assert_nil node.reload.suggested_restore_parent
end
test "suggested_restore_parent is root for trashed top-level nodes" do
node = Node.root.children.create!(:slug => "was_top_level")
node.trash!(@user1)
assert_equal Node.root, node.reload.suggested_restore_parent
end
test "trashed nodes and the Trash itself stay out of the drafts surfaces" do
Node.trash
node = create_node_with_published_page
node.trash!(@user1)
ids = Node.drafts_and_autosaves.pluck(:id)
assert_not_includes ids, Node.trash.id
assert_not_includes ids, node.id
end
end
|