diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-15 01:41:34 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-15 04:23:09 +0200 |
| commit | d56155231814633e04f856d22646fea24ef97011 (patch) | |
| tree | 9d5b6f8c32ee5b59783a2880388e7833278d1d87 /test/models | |
| parent | 28a6999b55cbec555696df848d6e924aae3166ee (diff) | |
node_id/page_id/user_id are lookup and ordering only -- all three
nullify on delete, so an entry outlives its actor and its subject.
Everything that must survive those deletions lives in a mandatory
metadata jsonb written once at creation: the actor's username, the
node's human-readable name (pinned to the default locale), and
action-specific extras such as publish's title from/to.
NodeAction.record! is the single constructor, so every entry gets
the same baseline metadata without each call site re-implementing
it. occurred_at is one field for live and backfilled entries alike;
inferred_from distinguishes them -- nil means witnessed at the
moment it happened, populated names how a backfilled entry was
estimated.
Instrumented so far: publish (crediting the actual publisher,
threaded through from the controller -- previously nobody had the
act of publishing recorded anywhere), revert's discard_autosave and
destroy_draft branches, and translation destroy. publish_draft! now
runs in a transaction so the promotion and its log entry land
together. The remaining verbs follow once this mechanism has proven
itself.
Diffstat (limited to 'test/models')
| -rw-r--r-- | test/models/node_test.rb | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/test/models/node_test.rb b/test/models/node_test.rb index 959387d..022fff6 100644 --- a/test/models/node_test.rb +++ b/test/models/node_test.rb | |||
| @@ -621,4 +621,87 @@ class NodeTest < ActiveSupport::TestCase | |||
| 621 | assert_equal "Edited directly on autosave", Globalize.with_locale(:en) { autosave.title } | 621 | assert_equal "Edited directly on autosave", Globalize.with_locale(:en) { autosave.title } |
| 622 | assert_equal "v2", Globalize.with_locale(:de) { autosave.title } | 622 | assert_equal "v2", Globalize.with_locale(:de) { autosave.title } |
| 623 | end | 623 | end |
| 624 | |||
| 625 | test "publish_draft! logs a NodeAction crediting the actual publisher" do | ||
| 626 | node = Node.root.children.create!(:slug => "publish_log_test") | ||
| 627 | node.draft.update!(:title => "Version one") | ||
| 628 | |||
| 629 | node.publish_draft!(@user1) | ||
| 630 | |||
| 631 | action = NodeAction.last | ||
| 632 | assert_equal node, action.node | ||
| 633 | assert_equal node.head, action.page | ||
| 634 | assert_equal @user1, action.user | ||
| 635 | assert_equal "publish", action.action | ||
| 636 | end | ||
| 637 | |||
| 638 | test "publish_draft! called with no user logs no actor, not a guessed one" do | ||
| 639 | node = Node.root.children.create!(:slug => "publish_log_no_user_test") | ||
| 640 | node.draft.update!(:title => "Version one") | ||
| 641 | |||
| 642 | node.publish_draft! | ||
| 643 | |||
| 644 | action = NodeAction.last | ||
| 645 | assert_nil action.user | ||
| 646 | assert_nil action.metadata["username"] | ||
| 647 | end | ||
| 648 | |||
| 649 | test "publish_draft! with nothing pending creates no NodeAction" do | ||
| 650 | node = Node.root.children.create!(:slug => "publish_log_noop_test") | ||
| 651 | node.publish_draft! | ||
| 652 | count_before = NodeAction.count | ||
| 653 | |||
| 654 | result = node.publish_draft! | ||
| 655 | |||
| 656 | assert_nil result | ||
| 657 | assert_equal count_before, NodeAction.count | ||
| 658 | end | ||
| 659 | |||
| 660 | test "revert! logs discard_autosave for an in-progress autosave" do | ||
| 661 | node = create_node_with_published_page | ||
| 662 | node.lock_for_editing!(@user1) | ||
| 663 | node.autosave!({:title => "in progress"}, @user1) | ||
| 664 | |||
| 665 | node.revert!(@user1) | ||
| 666 | |||
| 667 | action = NodeAction.last | ||
| 668 | assert_equal node, action.node | ||
| 669 | assert_equal @user1, action.user | ||
| 670 | assert_equal "discard_autosave", action.action | ||
| 671 | end | ||
| 672 | |||
| 673 | test "revert! logs destroy_draft for a draft with a head behind it" do | ||
| 674 | node = create_node_with_published_page | ||
| 675 | find_or_create_draft(node, @user1) | ||
| 676 | |||
| 677 | node.revert!(@user1) | ||
| 678 | |||
| 679 | action = NodeAction.last | ||
| 680 | assert_equal node, action.node | ||
| 681 | assert_equal @user1, action.user | ||
| 682 | assert_equal "destroy_draft", action.action | ||
| 683 | end | ||
| 684 | |||
| 685 | test "revert! with nothing to revert logs nothing" do | ||
| 686 | node = create_node_with_published_page | ||
| 687 | node.lock_for_editing!(@user1) | ||
| 688 | count_before = NodeAction.count | ||
| 689 | |||
| 690 | node.revert!(@user1) | ||
| 691 | |||
| 692 | assert_equal count_before, NodeAction.count | ||
| 693 | end | ||
| 694 | |||
| 695 | test "publish_draft! records the title's from/to in metadata" do | ||
| 696 | node = create_node_with_published_page | ||
| 697 | Globalize.with_locale(:de) { node.head.update!(:title => "Original Title") } | ||
| 698 | find_or_create_draft(node, @user1) | ||
| 699 | Globalize.with_locale(:de) { node.draft.update!(:title => "New Title") } | ||
| 700 | |||
| 701 | node.publish_draft!(@user1) | ||
| 702 | |||
| 703 | action = NodeAction.last | ||
| 704 | assert_equal "Original Title", action.metadata["from"] | ||
| 705 | assert_equal "New Title", action.metadata["to"] | ||
| 706 | end | ||
| 624 | end | 707 | end |
