diff options
| -rw-r--r-- | app/helpers/node_actions_helper.rb | 74 | ||||
| -rw-r--r-- | app/models/node_action.rb | 25 | ||||
| -rw-r--r-- | app/views/node_actions/_change_details.html.erb | 30 | ||||
| -rw-r--r-- | app/views/node_actions/index.html.erb | 25 | ||||
| -rw-r--r-- | config/locales/de.yml | 13 | ||||
| -rw-r--r-- | config/locales/en.yml | 44 | ||||
| -rw-r--r-- | public/stylesheets/admin.css | 34 | ||||
| -rw-r--r-- | test/models/helpers/node_actions_helper_test.rb | 32 | ||||
| -rw-r--r-- | test/models/node_action_test.rb | 16 |
9 files changed, 222 insertions, 71 deletions
diff --git a/app/helpers/node_actions_helper.rb b/app/helpers/node_actions_helper.rb index 55ca982..996f98d 100644 --- a/app/helpers/node_actions_helper.rb +++ b/app/helpers/node_actions_helper.rb | |||
| @@ -16,8 +16,57 @@ module NodeActionsHelper | |||
| 16 | :action => h(action.action), :subject => subject_ref(action)).html_safe | 16 | :action => h(action.action), :subject => subject_ref(action)).html_safe |
| 17 | end | 17 | end |
| 18 | 18 | ||
| 19 | |||
| 20 | def action_details? action | ||
| 21 | m = action.metadata | ||
| 22 | return true if m["translation_diff"].present? | ||
| 23 | return true if m["title"].is_a?(Hash) && m.dig("title", "from") != m.dig("title", "to") | ||
| 24 | %w[author tags template_changed assets_changed | ||
| 25 | abstract_changed body_changed].any? { |key| m[key].present? } | ||
| 26 | end | ||
| 27 | |||
| 28 | # Plain strings by design -- safe_join in the template escapes them. | ||
| 29 | def default_locale_changes action | ||
| 30 | m = action.metadata | ||
| 31 | items = [] | ||
| 32 | if m["title"].is_a?(Hash) && m.dig("title", "from") && m.dig("title", "from") != m.dig("title", "to") | ||
| 33 | items << t("node_actions.detail_title", | ||
| 34 | :from => m.dig("title", "from"), :to => m.dig("title", "to")) | ||
| 35 | end | ||
| 36 | items << t("node_actions.detail_author", | ||
| 37 | :from => m.dig("author", "from"), :to => m.dig("author", "to")) if m["author"] | ||
| 38 | items << t("node_actions.detail_tags", | ||
| 39 | :from => Array(m.dig("tags", "from")).join(", "), | ||
| 40 | :to => Array(m.dig("tags", "to")).join(", ")) if m["tags"] | ||
| 41 | items << t("node_actions.abstract_changed") if m["abstract_changed"] | ||
| 42 | items << t("node_actions.body_changed") if m["body_changed"] | ||
| 43 | items << t("node_actions.template_changed") if m["template_changed"] | ||
| 44 | items << t("node_actions.assets_changed") if m["assets_changed"] | ||
| 45 | items | ||
| 46 | end | ||
| 47 | |||
| 48 | def translation_changes diff | ||
| 49 | case diff["status"] | ||
| 50 | when "added" then [t("node_actions.locale_added", :title => diff.dig("title", "to"))] | ||
| 51 | when "removed" then [t("node_actions.locale_removed", :title => diff.dig("title", "from"))] | ||
| 52 | else | ||
| 53 | items = [] | ||
| 54 | items << t("node_actions.detail_title", | ||
| 55 | :from => diff.dig("title", "from"), :to => diff.dig("title", "to")) if diff["title"] | ||
| 56 | items << t("node_actions.abstract_changed") if diff["abstract_changed"] | ||
| 57 | items << t("node_actions.body_changed") if diff["body_changed"] | ||
| 58 | items | ||
| 59 | end | ||
| 60 | end | ||
| 61 | |||
| 19 | private | 62 | private |
| 20 | 63 | ||
| 64 | def revision_ref action, key | ||
| 65 | label = t(key) | ||
| 66 | return label unless action.node && action.page | ||
| 67 | link_to(label, node_revision_path(action.node, action.page)) | ||
| 68 | end | ||
| 69 | |||
| 21 | def actor_ref action | 70 | def actor_ref action |
| 22 | action.user ? link_to(h(action.actor_name), admin_log_path(:user_id => action.user_id)) | 71 | action.user ? link_to(h(action.actor_name), admin_log_path(:user_id => action.user_id)) |
| 23 | : h(action.actor_name) | 72 | : h(action.actor_name) |
| @@ -29,17 +78,20 @@ module NodeActionsHelper | |||
| 29 | end | 78 | end |
| 30 | 79 | ||
| 31 | def summarize_publish action | 80 | def summarize_publish action |
| 32 | key = if action.metadata["via"] == "revision" | 81 | if action.metadata["via"] == "revision" |
| 33 | "node_actions.publish_rollback" | 82 | t("node_actions.publish_rollback", |
| 34 | elsif action.metadata.dig("title", "from").nil? | 83 | :actor => actor_ref(action), :subject => subject_ref(action), |
| 35 | "node_actions.publish_first" | 84 | :revision => revision_ref(action, "node_actions.revision_earlier")).html_safe |
| 36 | else | 85 | elsif action.metadata.dig("title", "from").nil? |
| 37 | "node_actions.publish" | 86 | author = action.metadata.dig("author", "to") |
| 38 | end | 87 | key = author ? "node_actions.publish_first_with_author" : "node_actions.publish_first" |
| 39 | 88 | t(key, :actor => actor_ref(action), :subject => subject_ref(action), | |
| 40 | t(key, :actor => actor_ref(action), :subject => subject_ref(action), | 89 | :author => h(author)).html_safe |
| 41 | :from => h(action.metadata.dig("title", "from")), | 90 | else |
| 42 | :to => h(action.metadata.dig("title", "to"))).html_safe | 91 | t("node_actions.publish", |
| 92 | :actor => actor_ref(action), :subject => subject_ref(action), | ||
| 93 | :revision => revision_ref(action, "node_actions.revision_new")).html_safe | ||
| 94 | end | ||
| 43 | end | 95 | end |
| 44 | 96 | ||
| 45 | def summarize_move action | 97 | def summarize_move action |
diff --git a/app/models/node_action.rb b/app/models/node_action.rb index 39935c7..792ae1e 100644 --- a/app/models/node_action.rb +++ b/app/models/node_action.rb | |||
| @@ -82,21 +82,23 @@ class NodeAction < ApplicationRecord | |||
| 82 | # user agent, ever. Success only -- rejected attempts are not | 82 | # user agent, ever. Success only -- rejected attempts are not |
| 83 | # logged. | 83 | # logged. |
| 84 | 84 | ||
| 85 | def self.record!(node:, action:, user: nil, page: nil, locale: nil, **extra) | 85 | def self.record!(node:, action:, user: nil, page: nil, locale: nil, |
| 86 | occurred_at: nil, inferred_from: nil, **extra) | ||
| 86 | create!( | 87 | create!( |
| 87 | :node => node, | 88 | :node => node, |
| 88 | :page => page, | 89 | :page => page, |
| 89 | :user => user, | 90 | :user => user, |
| 90 | :action => action, | 91 | :action => action, |
| 91 | :locale => locale, | 92 | :locale => locale, |
| 92 | :occurred_at => Time.now, | 93 | :occurred_at => occurred_at || Time.now, |
| 93 | :metadata => { | 94 | :inferred_from => inferred_from, |
| 95 | :metadata => { | ||
| 94 | "username" => user&.login, | 96 | "username" => user&.login, |
| 95 | "human_readable_node_name" => Globalize.with_locale(I18n.default_locale) { | 97 | "human_readable_node_name" => Globalize.with_locale(I18n.default_locale) { |
| 96 | node&.head&.title || node&.draft&.title | 98 | node&.head&.title || node&.draft&.title |
| 97 | }, | 99 | }, |
| 98 | }.merge(extra.stringify_keys) | 100 | }.merge(extra.stringify_keys) |
| 99 | ) | 101 | ) |
| 100 | end | 102 | end |
| 101 | 103 | ||
| 102 | # Computes the publish-entry diff between an outgoing head and the | 104 | # Computes the publish-entry diff between an outgoing head and the |
| @@ -113,7 +115,10 @@ class NodeAction < ApplicationRecord | |||
| 113 | title_of = ->(page) { page&.translations&.find_by(:locale => default)&.title } | 115 | title_of = ->(page) { page&.translations&.find_by(:locale => default)&.title } |
| 114 | diff = { :title => { "from" => title_of.call(old_page), | 116 | diff = { :title => { "from" => title_of.call(old_page), |
| 115 | "to" => title_of.call(new_page) } } | 117 | "to" => title_of.call(new_page) } } |
| 116 | return diff unless old_page | 118 | unless old_page |
| 119 | diff[:author] = { "from" => nil, "to" => new_page.user&.login } if new_page.user | ||
| 120 | return diff | ||
| 121 | end | ||
| 117 | 122 | ||
| 118 | old_author, new_author = old_page.user&.login, new_page.user&.login | 123 | old_author, new_author = old_page.user&.login, new_page.user&.login |
| 119 | diff[:author] = { "from" => old_author, "to" => new_author } if old_author != new_author | 124 | diff[:author] = { "from" => old_author, "to" => new_author } if old_author != new_author |
diff --git a/app/views/node_actions/_change_details.html.erb b/app/views/node_actions/_change_details.html.erb index 383f53a..2583e8b 100644 --- a/app/views/node_actions/_change_details.html.erb +++ b/app/views/node_actions/_change_details.html.erb | |||
| @@ -1,27 +1,27 @@ | |||
| 1 | <details class="node_action_details"> | 1 | <details class="node_action_details"> |
| 2 | <summary><%= t("node_actions.show_changes") %></summary> | 2 | <summary><%= t("node_actions.show_changes") %></summary> |
| 3 | <table> | 3 | <table> |
| 4 | <% action_entry.metadata["translation_diff"].each do |locale, diff| %> | 4 | <% if (default_items = default_locale_changes(action_entry)).any? %> |
| 5 | <tr> | ||
| 6 | <th><%= I18n.default_locale.to_s.upcase %></th> | ||
| 7 | <td> | ||
| 8 | <%= safe_join(default_items, ", ") %> | ||
| 9 | <% if action_entry.page && action_entry.node %> | ||
| 10 | <%= link_to t("node_actions.view_revision"), node_revision_path(action_entry.node, action_entry.page) %> | ||
| 11 | <% end %> | ||
| 12 | </td> | ||
| 13 | </tr> | ||
| 14 | <% end %> | ||
| 15 | <% (action_entry.metadata["translation_diff"] || {}).each do |locale, diff| %> | ||
| 5 | <tr> | 16 | <tr> |
| 6 | <th><%= locale.upcase %></th> | 17 | <th><%= locale.upcase %></th> |
| 7 | <td> | 18 | <td> |
| 8 | <% case diff["status"] %> | 19 | <%= safe_join(translation_changes(diff), ", ") %> |
| 9 | <% when "added" %> | 20 | <% if action_entry.page && action_entry.node %> |
| 10 | <%= t("node_actions.locale_added", :title => diff.dig("title", "to")) %> | 21 | <%= link_to t("node_actions.view_revision"), node_revision_path(action_entry.node, action_entry.page, :locale => locale) %> |
| 11 | <% when "removed" %> | ||
| 12 | <%= t("node_actions.locale_removed", :title => diff.dig("title", "from")) %> | ||
| 13 | <% else %> | ||
| 14 | <% if diff["title"] %> | ||
| 15 | <%= diff.dig("title", "from") %> → <%= diff.dig("title", "to") %> | ||
| 16 | <% end %> | ||
| 17 | <%= t("node_actions.abstract_changed") if diff["abstract_changed"] %> | ||
| 18 | <%= t("node_actions.body_changed") if diff["body_changed"] %> | ||
| 19 | <% end %> | 22 | <% end %> |
| 20 | </td> | 23 | </td> |
| 21 | </tr> | 24 | </tr> |
| 22 | <% end %> | 25 | <% end %> |
| 23 | </table> | 26 | </table> |
| 24 | <% if action_entry.page && action_entry.node %> | ||
| 25 | <%= link_to t("node_actions.view_revision"), node_revision_path(action_entry.node, action_entry.page) %> | ||
| 26 | <% end %> | ||
| 27 | </details> | 27 | </details> |
diff --git a/app/views/node_actions/index.html.erb b/app/views/node_actions/index.html.erb index 92740cd..ee06213 100644 --- a/app/views/node_actions/index.html.erb +++ b/app/views/node_actions/index.html.erb | |||
| @@ -6,17 +6,22 @@ | |||
| 6 | 6 | ||
| 7 | <%= will_paginate @actions %> | 7 | <%= will_paginate @actions %> |
| 8 | 8 | ||
| 9 | <ul id="node_action_list"> | 9 | <table id="node_action_list"> |
| 10 | <% @actions.each do |action| %> | 10 | <% @actions.each do |action| %> |
| 11 | <li class="node_action node_action--<%= action.action %>"> | 11 | <tr class="node_action node_action--<%= action.action %>"> |
| 12 | <span class="node_action_time"><%= l(action.occurred_at, :format => :ccc) %></span> | 12 | <td class="node_action_time"><%= action.occurred_at.strftime("%Y-%m-%d %H:%M") %></td> |
| 13 | <% if action.inferred_from %> | 13 | <td class="node_action_body"> |
| 14 | <span class="node_action_inferred" title="<%= action.inferred_from %>"><%= t("node_actions.backfilled") %></span> | 14 | <%= action_summary(action) %> |
| 15 | <% end %> | 15 | <% if action.node_id && params[:node_id].blank? %> |
| 16 | <span class="node_action_summary"><%= action_summary(action) %></span> | 16 | <%= link_to t("node_actions.node_history"), admin_log_path(:node_id => action.node_id), :class => "node_action_zoom" %> |
| 17 | <%= render "change_details", :action_entry => action if action.metadata["translation_diff"].present? %> | 17 | <% end %> |
| 18 | </li> | 18 | <% if action.inferred_from %> |
| 19 | <span class="node_action_inferred" title="<%= action.inferred_from %>"><%= t("node_actions.backfilled") %></span> | ||
| 20 | <% end %> | ||
| 21 | <%= render "change_details", :action_entry => action if action_details?(action) %> | ||
| 22 | </td> | ||
| 23 | </tr> | ||
| 19 | <% end %> | 24 | <% end %> |
| 20 | </ul> | 25 | </table> |
| 21 | 26 | ||
| 22 | <%= will_paginate @actions %> | 27 | <%= will_paginate @actions %> |
diff --git a/config/locales/de.yml b/config/locales/de.yml index 795e4d0..9de6aac 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml | |||
| @@ -90,9 +90,10 @@ de: | |||
| 90 | show_changes: "Änderungen an Übersetzungen" | 90 | show_changes: "Änderungen an Übersetzungen" |
| 91 | view_revision: "Diese Revision ansehen" | 91 | view_revision: "Diese Revision ansehen" |
| 92 | unknown: "%{actor} hat %{action} auf %{subject} aus" | 92 | unknown: "%{actor} hat %{action} auf %{subject} aus" |
| 93 | publish: "%{actor} hat %{subject} veröffentlicht, (vorher: %{from})" | 93 | publish: "%{actor} hat %{revision} von %{subject} veröffentlicht" |
| 94 | publish_rollback: "%{actor} hat %{subject} auf %{revision} zurückgesetzt" | ||
| 94 | publish_first: "%{actor} hat %{subject} zum ersten Mal veröffentlicht" | 95 | publish_first: "%{actor} hat %{subject} zum ersten Mal veröffentlicht" |
| 95 | publish_rollback: "%{actor} hat %{subject} auf eine frühere Revision zurückgesetzt (vorher: %{from})" | 96 | publish_first_with_author: "%{actor} hat %{subject} zum ersten Mal veröffentlicht (Autor: %{author})" |
| 96 | create: "%{actor} hat %{subject} unter %{path} angelegt" | 97 | create: "%{actor} hat %{subject} unter %{path} angelegt" |
| 97 | move: "%{actor} hat %{subject} von %{from} nach %{to} verschoben" | 98 | move: "%{actor} hat %{subject} von %{from} nach %{to} verschoben" |
| 98 | discard_autosave: "%{actor} hat ungespeicherte Änderungen an %{subject} verschoben" | 99 | discard_autosave: "%{actor} hat ungespeicherte Änderungen an %{subject} verschoben" |
| @@ -101,3 +102,11 @@ de: | |||
| 101 | locale_removed: "Übersetzung entfernt, letzter Titel \"%{title}\"" | 102 | locale_removed: "Übersetzung entfernt, letzter Titel \"%{title}\"" |
| 102 | abstract_changed: "Abstract geändert" | 103 | abstract_changed: "Abstract geändert" |
| 103 | body_changed: "Text geändert" | 104 | body_changed: "Text geändert" |
| 105 | revision_new: "eine neue Revision" | ||
| 106 | revision_earlier: "eine frühere Revision" | ||
| 107 | node_history: "Chronik" | ||
| 108 | detail_title: "Titel „%{from}“ → „%{to}“" | ||
| 109 | detail_author: "Autor %{from} → %{to}" | ||
| 110 | detail_tags: "Tags %{from} → %{to}" | ||
| 111 | template_changed: "Template geändert" | ||
| 112 | assets_changed: "Bildliste geändert" | ||
diff --git a/config/locales/en.yml b/config/locales/en.yml index 8470778..f1856c1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml | |||
| @@ -36,21 +36,29 @@ en: | |||
| 36 | page_aria_label: "Page %{page}" | 36 | page_aria_label: "Page %{page}" |
| 37 | 37 | ||
| 38 | node_actions: | 38 | node_actions: |
| 39 | heading: "Action log" | 39 | heading: "Action log" |
| 40 | show_all: "Show all entries" | 40 | show_all: "Show all entries" |
| 41 | backfilled: "backfilled" | 41 | backfilled: "backfilled" |
| 42 | show_changes: "translation changes" | 42 | show_changes: "translation changes" |
| 43 | view_revision: "view this revision" | 43 | view_revision: "view this revision" |
| 44 | actor_self: "you" | 44 | unknown: "%{actor} did %{action} on %{subject}" |
| 45 | unknown: "%{actor} did %{action} on %{subject}" | 45 | publish: "%{actor} published %{revision} of %{subject}" |
| 46 | publish: "%{actor} published %{subject} (was: %{from})" | 46 | publish_rollback: "%{actor} rolled %{subject} back to %{revision}" |
| 47 | publish_first: "%{actor} published %{subject} for the first time" | 47 | publish_first: "%{actor} published %{subject} for the first time" |
| 48 | publish_rollback: "%{actor} rolled %{subject} back to an earlier revision (was: %{from})" | 48 | publish_first_with_author: "%{actor} published %{subject} for the first time (author: %{author})" |
| 49 | create: "%{actor} created %{subject} at %{path}" | 49 | create: "%{actor} created %{subject} at %{path}" |
| 50 | move: "%{actor} moved %{subject} from %{from} to %{to}" | 50 | move: "%{actor} moved %{subject} from %{from} to %{to}" |
| 51 | discard_autosave: "%{actor} discarded unsaved changes on %{subject}" | 51 | discard_autosave: "%{actor} discarded unsaved changes on %{subject}" |
| 52 | destroy_draft: "%{actor} discarded the draft of %{subject}" | 52 | destroy_draft: "%{actor} discarded the draft of %{subject}" |
| 53 | locale_added: "translation added, titled \"%{title}\"" | 53 | locale_added: "translation added, titled \"%{title}\"" |
| 54 | locale_removed: "translation removed, last titled \"%{title}\"" | 54 | locale_removed: "translation removed, last titled \"%{title}\"" |
| 55 | abstract_changed: "abstract changed" | 55 | abstract_changed: "abstract changed" |
| 56 | body_changed: "body changed" | 56 | body_changed: "body changed" |
| 57 | revision_new: "a new revision" | ||
| 58 | revision_earlier: "an earlier revision" | ||
| 59 | node_history: "node history" | ||
| 60 | detail_title: "title \"%{from}\" → \"%{to}\"" | ||
| 61 | detail_author: "author %{from} → %{to}" | ||
| 62 | detail_tags: "tags %{from} → %{to}" | ||
| 63 | template_changed: "template changed" | ||
| 64 | assets_changed: "attached images changed" | ||
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 5f0b165..c1273c6 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css | |||
| @@ -1494,3 +1494,37 @@ div#image_browser ul li { | |||
| 1494 | gap: 8px; | 1494 | gap: 8px; |
| 1495 | flex-wrap: wrap; | 1495 | flex-wrap: wrap; |
| 1496 | } | 1496 | } |
| 1497 | |||
| 1498 | /* ============================================================ | ||
| 1499 | Action log | ||
| 1500 | ============================================================ */ | ||
| 1501 | |||
| 1502 | #node_action_list td.node_action_time { | ||
| 1503 | white-space: nowrap; | ||
| 1504 | vertical-align: top; | ||
| 1505 | font-family: monospace; | ||
| 1506 | font-size: 0.8em; | ||
| 1507 | color: #777; | ||
| 1508 | padding-right: 1em; | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | #node_action_list td.node_action_body { | ||
| 1512 | vertical-align: top; | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | .node_action_inferred { | ||
| 1516 | opacity: 0.5; | ||
| 1517 | font-size: smaller; | ||
| 1518 | margin-left: 0.5em; | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | .node_action_zoom { | ||
| 1522 | font-size: smaller; | ||
| 1523 | margin-left: 0.5em; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | .node_action_details summary { | ||
| 1527 | cursor: pointer; | ||
| 1528 | font-size: smaller; | ||
| 1529 | color: #777; | ||
| 1530 | } | ||
diff --git a/test/models/helpers/node_actions_helper_test.rb b/test/models/helpers/node_actions_helper_test.rb index 93bbdf6..5244c19 100644 --- a/test/models/helpers/node_actions_helper_test.rb +++ b/test/models/helpers/node_actions_helper_test.rb | |||
| @@ -21,12 +21,13 @@ class NodeActionsHelperTest < ActionView::TestCase | |||
| 21 | "human_readable_node_name" => "Subject" }.merge(metadata)) | 21 | "human_readable_node_name" => "Subject" }.merge(metadata)) |
| 22 | end | 22 | end |
| 23 | 23 | ||
| 24 | test "publish renders the title pair" do | 24 | test "publish renders the revision sentence, not the titles" do |
| 25 | out = action_summary(entry("publish", | 25 | out = action_summary(entry("publish", |
| 26 | { "via" => "draft", "title" => { "from" => "Old", "to" => "New" } })) | 26 | { "via" => "draft", "title" => { "from" => "Old", "to" => "New" } })) |
| 27 | 27 | ||
| 28 | assert_includes out, "quentin" | 28 | assert_includes out, "quentin" |
| 29 | assert_includes out, "Old" | 29 | assert_includes out, "new revision" |
| 30 | assert_not_includes out, "Old" | ||
| 30 | end | 31 | end |
| 31 | 32 | ||
| 32 | test "first publish uses its own sentence" do | 33 | test "first publish uses its own sentence" do |
| @@ -68,10 +69,8 @@ class NodeActionsHelperTest < ActionView::TestCase | |||
| 68 | 69 | ||
| 69 | test "metadata values are escaped" do | 70 | test "metadata values are escaped" do |
| 70 | out = action_summary(entry("publish", | 71 | out = action_summary(entry("publish", |
| 71 | { "human_readable_node_name" => "<b>bold</b>", | 72 | { "human_readable_node_name" => "<b>bold</b>" })) |
| 72 | "title" => { "from" => "<script>alert(1)</script>", "to" => "x" } })) | ||
| 73 | 73 | ||
| 74 | assert_not_includes out, "<script>" | ||
| 75 | assert_not_includes out, "<b>" | 74 | assert_not_includes out, "<b>" |
| 76 | end | 75 | end |
| 77 | 76 | ||
| @@ -82,4 +81,27 @@ class NodeActionsHelperTest < ActionView::TestCase | |||
| 82 | 81 | ||
| 83 | assert_includes out, "<a " | 82 | assert_includes out, "<a " |
| 84 | end | 83 | end |
| 84 | |||
| 85 | test "details are guarded off when nothing but an unchanged title is present" do | ||
| 86 | unchanged = entry("publish", { "title" => { "from" => "Same", "to" => "Same" } }) | ||
| 87 | changed = entry("publish", { "title" => { "from" => "Old", "to" => "New" } }) | ||
| 88 | |||
| 89 | assert_not action_details?(unchanged) | ||
| 90 | assert action_details?(changed) | ||
| 91 | end | ||
| 92 | |||
| 93 | test "first publish with a byline names the author" do | ||
| 94 | out = action_summary(entry("publish", | ||
| 95 | { "title" => { "from" => nil, "to" => "New" }, | ||
| 96 | "author" => { "from" => nil, "to" => "quentin" } })) | ||
| 97 | |||
| 98 | assert_includes out, "author" | ||
| 99 | end | ||
| 100 | |||
| 101 | test "create entries with their flat title render and are guarded off details" do | ||
| 102 | e = entry("create", { "title" => "Initial", "path" => "a/b" }) | ||
| 103 | |||
| 104 | assert_includes action_summary(e), "a/b" | ||
| 105 | assert_not action_details?(e) | ||
| 106 | end | ||
| 85 | end | 107 | end |
diff --git a/test/models/node_action_test.rb b/test/models/node_action_test.rb index 24d8245..b177cca 100644 --- a/test/models/node_action_test.rb +++ b/test/models/node_action_test.rb | |||
| @@ -18,6 +18,12 @@ class NodeActionTest < ActiveSupport::TestCase | |||
| 18 | assert_equal({ :title => { "from" => nil, "to" => "Erstausgabe" } }, diff) | 18 | assert_equal({ :title => { "from" => nil, "to" => "Erstausgabe" } }, diff) |
| 19 | end | 19 | end |
| 20 | 20 | ||
| 21 | test "first publish carries the byline when the page has one" do | ||
| 22 | diff = NodeAction.head_diff(nil, build_page(:user => users(:quentin))) | ||
| 23 | |||
| 24 | assert_equal({ "from" => nil, "to" => users(:quentin).login }, diff[:author]) | ||
| 25 | end | ||
| 26 | |||
| 21 | test "title pair is always present, even when unchanged" do | 27 | test "title pair is always present, even when unchanged" do |
| 22 | diff = NodeAction.head_diff(build_page, build_page) | 28 | diff = NodeAction.head_diff(build_page, build_page) |
| 23 | 29 | ||
| @@ -109,4 +115,14 @@ class NodeActionTest < ActiveSupport::TestCase | |||
| 109 | 115 | ||
| 110 | assert_nil NodeAction.head_diff(old_page, new_page)[:translation_diff] | 116 | assert_nil NodeAction.head_diff(old_page, new_page)[:translation_diff] |
| 111 | end | 117 | end |
| 118 | |||
| 119 | test "record! passes provenance and historical timestamps through" do | ||
| 120 | long_ago = 2.years.ago | ||
| 121 | action = NodeAction.record!(:node => nil, :action => "publish", | ||
| 122 | :occurred_at => long_ago, | ||
| 123 | :inferred_from => "from_page_revision") | ||
| 124 | |||
| 125 | assert_equal "from_page_revision", action.inferred_from | ||
| 126 | assert_in_delta long_ago.to_f, action.occurred_at.to_f, 1.0 | ||
| 127 | end | ||
| 112 | end | 128 | end |
