summaryrefslogtreecommitdiff
path: root/test/controllers
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-13 16:36:38 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-13 16:36:38 +0200
commit0b6ae26f3b4c3c8278e569fa6644a544e996c25d (patch)
tree6c0e8dd23fa243e6bf7e6473aebae3f13ea20dea /test/controllers
parente2705119ba718d40ff4f29c00027c2dfecef01ce (diff)
Add per-node translation management: list, edit, destroy, compare
Replaces the old locale-switch-and-edit-the-same-screen workflow, which conflated presentation locale with content locale and let an editor silently drift into editing the wrong language with no persistent signal that anything had changed. Non-default-locale content now has its own explicit routes and screens, never sharing a route param with the ambient chrome locale. - PageTranslationsController: index/show/edit/update/destroy, scoped to Page.non_default_locales; update handles first-time creation too, so there's no separate new/create step. - Reads go through the actual PageTranslation row (Page#translation_summary), never through the Globalize fallback-bearing accessor -- fallback is correct for public rendering but wrong for editing, where a missing translation needs to look empty, not borrowed from another locale. - Translations ride on the page's own draft/head cycle; no independent publish state. - nodes#show gains a Translations section (per-locale Lock+Edit / Create+Lock, Destroy, a link into the read-only Compare view) and a locale indicator on its own default-locale content; nodes#edit, nodes#update, and nodes#autosave are pinned to the default locale via Globalize.with_locale regardless of the ambient route locale. - nodes#show no longer double-loads the node or calls wipe_draft! on every view (see previous commit for why that's now safe). - .preview_link_row is renamed .aligned_action_row now that it has a second real consumer.
Diffstat (limited to 'test/controllers')
-rw-r--r--test/controllers/page_translations_controller_test.rb78
1 files changed, 78 insertions, 0 deletions
diff --git a/test/controllers/page_translations_controller_test.rb b/test/controllers/page_translations_controller_test.rb
new file mode 100644
index 0000000..d84ac45
--- /dev/null
+++ b/test/controllers/page_translations_controller_test.rb
@@ -0,0 +1,78 @@
1require 'test_helper'
2
3class PageTranslationsControllerTest < ActionController::TestCase
4 test "index lists the default locale's existing translation and flags a missing one" do
5 login_as :quentin
6 node = Node.root.children.create!(:slug => "translations_index_test")
7 node.publish_draft!
8
9 get :index, params: { :node_id => node.id }
10
11 assert_response :success
12 assert_equal [:en], assigns(:translations).map { |t| t[:locale] }
13 assert_equal false, assigns(:translations).first[:exists]
14 end
15
16 test "update creates a first-time translation on a fresh draft, leaving head untouched" do
17 login_as :quentin
18 node = Node.root.children.create!(:slug => "translations_create_test")
19 Globalize.with_locale(:de) { node.draft.update!(:title => "Deutscher Titel") }
20 node.publish_draft!
21
22 patch :update, params: { :node_id => node.id, :translation_locale => "en", :page => { :title => "English Title" } }
23
24 node.reload
25 assert_not_nil node.draft
26 assert_includes node.draft.translated_locales, :en
27 assert_not_includes node.head.translated_locales, :en
28 end
29
30 test "no route exists for the default locale under the translations resource" do
31 login_as :quentin
32 node = Node.root.children.create!(:slug => "translations_route_constraint_test")
33
34 assert_raises(ActionController::UrlGenerationError) do
35 patch :update, params: { :node_id => node.id, :translation_locale => "de", :page => { :title => "x" } }
36 end
37 end
38
39 test "update with Save + Unlock + Exit unlocks the node and redirects to nodes#show" do
40 login_as :quentin
41 node = Node.root.children.create!(:slug => "translations_exit_test")
42
43 patch :update, params: { :node_id => node.id, :translation_locale => "en", :page => { :title => "x" }, :commit => "Save + Unlock + Exit" }
44
45 assert_nil node.reload.lock_owner
46 assert_redirected_to node_path(node)
47 end
48
49 test "update saves the translation onto the draft" do
50 login_as :quentin
51 node = Node.root.children.create!(:slug => "translations_update_test")
52 Globalize.with_locale(:en) { node.draft.update!(:title => "Original") }
53
54 patch :update, params: { :node_id => node.id, :translation_locale => "en", :page => { :title => "Revised" } }
55
56 assert_equal "Revised", Globalize.with_locale(:en) { node.draft.reload.title }
57 end
58
59 test "destroy refuses to remove the only remaining translation" do
60 login_as :quentin
61 node = Node.root.children.create!(:slug => "translations_destroy_last_test")
62 Globalize.with_locale(:en) { node.draft.update!(:title => "Only translation") }
63 node.draft.translations.where(:locale => :de).delete_all
64
65 delete :destroy, params: { :node_id => node.id, :translation_locale => "en" }
66
67 assert_equal "Can't remove the only remaining translation.", flash[:error]
68 end
69
70 test "destroy is a safe no-op, not a false success, when the translation doesn't exist" do
71 login_as :quentin
72 node = Node.root.children.create!(:slug => "translations_destroy_missing_test")
73
74 delete :destroy, params: { :node_id => node.id, :translation_locale => "en" }
75
76 assert_match(/No EN translation exists/, flash[:error])
77 end
78end