From d41ee504caedbe858e24ab2a23c7a804454c64c8 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sat, 18 Jul 2026 02:15:29 +0200 Subject: Add Trash affordances: cockpit, listing, dashboard entry nodes#show gains a Trash section on trashed nodes: provenance from the trash entry, a restore form whose parent picker pre-fills the old parent while it still lives, and permanent deletion. A Move-to-Trash button joins the status actions on living nodes. nodes#trashed lists trashed subtree roots with weight, provenance, and deletion; the dashboard housekeeping row links to it, and trash/destroy redirect there. Deletion from Trash now removes the whole subtree, deepest first, each node through a real destroy! so every per-node cascade runs -- amending the never-recursive rule for this one sanctioned path (both confirms state the count; the root entry carries destroyed_descendants). Bare Node#destroy still refuses children. --- test/models/node_trash_test.rb | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'test/models') diff --git a/test/models/node_trash_test.rb b/test/models/node_trash_test.rb index b72770b..07e5bc6 100644 --- a/test/models/node_trash_test.rb +++ b/test/models/node_trash_test.rb @@ -102,12 +102,25 @@ class NodeTrashTest < ActiveSupport::TestCase assert Node.exists?(node.id) end - test "destroy_from_trash! refuses nodes with children" do - node = create_node_with_published_page - node.children.create!(:slug => "still_here") - node.trash!(@user1) + 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 - assert_raises(ActiveRecord::RecordNotDestroyed) { node.reload.destroy_from_trash!(@user1) } + 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 @@ -124,4 +137,22 @@ class NodeTrashTest < ActiveSupport::TestCase 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 end -- cgit v1.3