blacklight-spotlight 1.5.1 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -3
  3. data/app/assets/javascripts/spotlight/translation_progress.js +23 -0
  4. data/app/assets/stylesheets/spotlight/_spotlight.scss +2 -0
  5. data/app/assets/stylesheets/spotlight/_translations.scss +47 -0
  6. data/app/assets/stylesheets/spotlight/_utilities.scss +3 -0
  7. data/app/assets/stylesheets/spotlight/_variables.scss +5 -0
  8. data/app/controllers/concerns/spotlight/controller.rb +12 -1
  9. data/app/controllers/spotlight/about_pages_controller.rb +6 -0
  10. data/app/controllers/spotlight/browse_controller.rb +1 -1
  11. data/app/controllers/spotlight/catalog_controller.rb +6 -1
  12. data/app/controllers/spotlight/exhibits_controller.rb +10 -2
  13. data/app/controllers/spotlight/feature_pages_controller.rb +6 -0
  14. data/app/controllers/spotlight/filters_controller.rb +2 -2
  15. data/app/controllers/spotlight/home_pages_controller.rb +10 -0
  16. data/app/controllers/spotlight/languages_controller.rb +46 -0
  17. data/app/controllers/spotlight/pages_controller.rb +57 -3
  18. data/app/controllers/spotlight/solr_controller.rb +3 -3
  19. data/app/controllers/spotlight/translations_controller.rb +34 -0
  20. data/app/helpers/spotlight/application_helper.rb +1 -0
  21. data/app/helpers/spotlight/languages_helper.rb +33 -0
  22. data/app/helpers/spotlight/translations_helper.rb +13 -0
  23. data/app/models/concerns/spotlight/custom_translation_extension.rb +4 -0
  24. data/app/models/concerns/spotlight/translatables.rb +30 -0
  25. data/app/models/spotlight/ability.rb +5 -2
  26. data/app/models/spotlight/about_page.rb +1 -1
  27. data/app/models/spotlight/exhibit.rb +14 -6
  28. data/app/models/spotlight/feature_page.rb +1 -2
  29. data/app/models/spotlight/home_page.rb +1 -3
  30. data/app/models/spotlight/language.rb +24 -0
  31. data/app/models/spotlight/main_navigation.rb +12 -0
  32. data/app/models/spotlight/page.rb +53 -1
  33. data/app/models/spotlight/resources/upload.rb +6 -1
  34. data/app/models/spotlight/search.rb +4 -0
  35. data/app/services/spotlight/clone_translated_page_from_locale.rb +32 -0
  36. data/app/views/_user_util_links.html.erb +1 -0
  37. data/app/views/devise/mailer/invitation_instructions.html.erb +2 -2
  38. data/app/views/layouts/spotlight/spotlight.html.erb +2 -2
  39. data/app/views/shared/_curated_features_navbar.html.erb +2 -2
  40. data/app/views/spotlight/about_pages/_sidebar.html.erb +1 -1
  41. data/app/views/spotlight/admin_users/index.html.erb +1 -1
  42. data/app/views/spotlight/catalog/_edit_default.html.erb +1 -1
  43. data/app/views/spotlight/exhibits/_export.html.erb +1 -1
  44. data/app/views/spotlight/exhibits/_form.html.erb +1 -1
  45. data/app/views/spotlight/exhibits/_import.html.erb +2 -1
  46. data/app/views/spotlight/exhibits/_languages.html.erb +56 -0
  47. data/app/views/spotlight/exhibits/edit.html.erb +11 -5
  48. data/app/views/spotlight/feature_pages/_sidebar.html.erb +1 -1
  49. data/app/views/spotlight/filters/_form.html.erb +2 -1
  50. data/app/views/spotlight/resources/upload/_form.html.erb +1 -1
  51. data/app/views/spotlight/shared/_curation_sidebar.html.erb +5 -0
  52. data/app/views/spotlight/shared/_locale_picker.html.erb +14 -0
  53. data/app/views/spotlight/translations/_browse_categories.html.erb +67 -0
  54. data/app/views/spotlight/translations/_general.html.erb +176 -0
  55. data/app/views/spotlight/translations/_metadata.html.erb +67 -0
  56. data/app/views/spotlight/translations/_page.html.erb +45 -0
  57. data/app/views/spotlight/translations/_pages.html.erb +37 -0
  58. data/app/views/spotlight/translations/_pages_table.html.erb +15 -0
  59. data/app/views/spotlight/translations/_search_fields.html.erb +97 -0
  60. data/app/views/spotlight/translations/edit.html.erb +55 -0
  61. data/config/i18n-tasks.yml +81 -0
  62. data/config/locales/devise.en.yml +2 -1
  63. data/config/locales/spotlight.en.yml +657 -614
  64. data/config/routes.rb +19 -1
  65. data/db/migrate/20180308203409_create_spotlight_languages.rb +12 -0
  66. data/db/migrate/20180403130857_translation_uniqueness.rb +5 -0
  67. data/db/migrate/20180405044000_add_locale_to_pages.rb +6 -0
  68. data/db/migrate/20180406212516_add_default_locale_reference_to_spotlight_pages.rb +7 -0
  69. data/lib/generators/spotlight/templates/catalog_controller.rb +2 -2
  70. data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +14 -4
  71. data/lib/generators/spotlight/templates/config/initializers/translation.rb +4 -2
  72. data/lib/migration/page_language.rb +27 -0
  73. data/lib/spotlight/engine.rb +32 -4
  74. data/lib/spotlight/upload_field_config.rb +27 -0
  75. data/lib/spotlight/version.rb +1 -1
  76. data/lib/tasks/spotlight_tasks.rake +6 -0
  77. data/spec/controllers/spotlight/about_pages_controller_spec.rb +67 -1
  78. data/spec/controllers/spotlight/feature_pages_controller_spec.rb +50 -0
  79. data/spec/controllers/spotlight/filters_controller_spec.rb +4 -4
  80. data/spec/controllers/spotlight/home_pages_controller_spec.rb +25 -0
  81. data/spec/controllers/spotlight/languages_controller_spec.rb +66 -0
  82. data/spec/controllers/spotlight/pages_controller_spec.rb +45 -0
  83. data/spec/controllers/spotlight/solr_controller_spec.rb +1 -1
  84. data/spec/controllers/spotlight/translations_controller_spec.rb +67 -0
  85. data/spec/examples.txt +1171 -1281
  86. data/spec/factories/exhibits.rb +1 -1
  87. data/spec/factories/language.rb +6 -0
  88. data/spec/factories/main_navigation.rb +7 -0
  89. data/spec/factories/searches.rb +1 -0
  90. data/spec/factories/tags.rb +1 -0
  91. data/spec/features/exhibits/language_create_edit_spec.rb +53 -0
  92. data/spec/features/exhibits/translation_editing_spec.rb +397 -0
  93. data/spec/features/javascript/locale_selector_spec.rb +61 -0
  94. data/spec/helpers/spotlight/languages_helper_spec.rb +73 -0
  95. data/spec/helpers/spotlight/translations_helper_spec.rb +16 -0
  96. data/spec/i18n_spec.rb +29 -0
  97. data/spec/lib/migration/page_language_spec.rb +21 -0
  98. data/spec/lib/spotlight/upload_field_config_spec.rb +24 -0
  99. data/spec/models/spotlight/ability_spec.rb +17 -4
  100. data/spec/models/spotlight/exhibit_spec.rb +49 -0
  101. data/spec/models/spotlight/language_spec.rb +41 -0
  102. data/spec/models/spotlight/page_spec.rb +109 -0
  103. data/spec/models/translation_spec.rb +11 -0
  104. data/spec/services/spotlight/clone_translated_page_from_locale_spec.rb +29 -0
  105. data/spec/spec_helper.rb +1 -13
  106. data/spec/support/disable_friendly_id_deprecation_warnings.rb +7 -6
  107. data/spec/test_app_templates/Gemfile.extra +3 -0
  108. data/spec/test_app_templates/catalog_controller.rb +31 -31
  109. data/spec/test_app_templates/lib/generators/test_app_generator.rb +9 -6
  110. data/spec/views/spotlight/contacts/edit.html.erb_spec.rb +13 -0
  111. data/spec/views/spotlight/exhibits/_form.html.erb_spec.rb +33 -0
  112. data/spec/views/spotlight/exhibits/edit.html.erb_spec.rb +4 -1
  113. data/spec/views/spotlight/resources/_external_resources_form.html.erb_spec.rb +13 -0
  114. data/spec/views/spotlight/resources/new.html.erb_spec.rb +10 -4
  115. data/spec/views/spotlight/translations/_page.html.erb_spec.rb +75 -0
  116. metadata +88 -28
  117. data/app/assets/javascripts/spotlight/sir-trevor.js +0 -0
  118. data/app/views/shared/_share_follow.html.erb +0 -5
  119. data/config/locales/social_share_button.en.yml +0 -18
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'Locale Selector', js: true do
4
+ let(:exhibit) { FactoryBot.create(:exhibit, published: true) }
5
+ let!(:language_es) { FactoryBot.create(:language, exhibit: exhibit, locale: 'es', public: true) }
6
+ let!(:language_zh) { FactoryBot.create(:language, exhibit: exhibit, locale: 'zh') }
7
+
8
+ before { login_as user }
9
+
10
+ context 'with an anonymous user' do
11
+ let(:user) { FactoryBot.create(:exhibit_visitor) }
12
+
13
+ it 'only sees public languages' do
14
+ visit spotlight.exhibit_path(exhibit)
15
+
16
+ expect(page).to have_css('li.dropdown', text: 'English')
17
+ click_link 'English'
18
+
19
+ within('.dropdown-menu', visible: true) do
20
+ expect(page).to have_css('li', count: 1)
21
+ expect(page).to have_css('li', text: 'Español')
22
+ end
23
+ end
24
+ end
25
+
26
+ context 'with an exhibit curator' do
27
+ let(:user) { FactoryBot.create(:exhibit_curator, exhibit: exhibit) }
28
+
29
+ it 'can see any saved languages' do
30
+ visit spotlight.exhibit_path(exhibit)
31
+
32
+ expect(page).to have_css('li.dropdown', text: 'English')
33
+ click_link 'English'
34
+
35
+ within('.dropdown-menu', visible: true) do
36
+ expect(page).to have_css('li', count: 2)
37
+ expect(page).to have_css('li', text: '中文')
38
+ expect(page).to have_css('li', text: 'Español')
39
+ end
40
+ end
41
+ end
42
+
43
+ describe 'switching locales' do
44
+ let(:user) { FactoryBot.create(:exhibit_visitor) }
45
+
46
+ it 'works' do
47
+ visit spotlight.exhibit_path(exhibit)
48
+
49
+ expect(page).to have_css('input[placeholder="Search..."]')
50
+
51
+ click_link 'English'
52
+
53
+ within('.dropdown-menu', visible: true) do
54
+ click_link 'Español'
55
+ end
56
+
57
+ expect(page).not_to have_css('input[placeholder="Search..."]')
58
+ expect(page).to have_css('input[placeholder="Buscar..."]')
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,73 @@
1
+ describe Spotlight::LanguagesHelper, type: :helper do
2
+ let(:current_exhibit) { FactoryBot.create(:exhibit) }
3
+ describe '#add_exhibit_language_dropdown_options' do
4
+ it 'returns a sorted Array of locales and their names' do
5
+ allow(helper).to receive_messages(current_exhibit: current_exhibit)
6
+ expect(helper.add_exhibit_language_dropdown_options).to match_array(
7
+ [
8
+ ['Albanian', :sq],
9
+ ['Chinese', :zh],
10
+ ['Dutch', :nl],
11
+ ['French', :fr],
12
+ ['German', :de],
13
+ ['Hungarian', :hu],
14
+ ['Italian', :it],
15
+ ['Portugese - Brazil', :'pt-br'],
16
+ ['Spanish', :es]
17
+ ]
18
+ )
19
+ end
20
+ end
21
+
22
+ describe '#locale_selecter_dropown_options' do
23
+ before do
24
+ allow(helper).to receive_messages(current_ability: Ability.new(nil))
25
+ allow(helper).to receive_messages(current_exhibit: current_exhibit)
26
+
27
+ current_exhibit.languages = [
28
+ FactoryBot.create(:language, public: true, locale: 'es'),
29
+ FactoryBot.create(:language, public: true, locale: 'de')
30
+ ]
31
+ current_exhibit.save
32
+ end
33
+
34
+ it 'includes the default locale (when it is not current)' do
35
+ allow(I18n).to receive(:locale).and_return(:es)
36
+ expect(helper.locale_selecter_dropown_options.last).to be_a(Spotlight::Language)
37
+ expect(helper.locale_selecter_dropown_options.last).not_to be_persisted
38
+ expect(helper.locale_selecter_dropown_options.last.locale).to eq 'en'
39
+ end
40
+
41
+ it 'does not include the current locale' do
42
+ expect(
43
+ helper.locale_selecter_dropown_options.map(&:locale)
44
+ ).not_to include(I18n.locale.to_s)
45
+ end
46
+
47
+ it 'sorts by the native translation' do
48
+ allow(I18n).to receive(:locale).and_return(:it)
49
+
50
+ expect(
51
+ helper.locale_selecter_dropown_options.map(&:to_native)
52
+ ).to eq %w[Deutsch English Español]
53
+ end
54
+ end
55
+
56
+ describe '#default_language?' do
57
+ context 'when using default locale' do
58
+ it do
59
+ expect(helper.default_language?).to eq true
60
+ end
61
+ it do
62
+ expect(helper).to receive_messages(params: { locale: :en })
63
+ expect(helper.default_language?).to eq true
64
+ end
65
+ end
66
+ context 'when using a different locale' do
67
+ it do
68
+ expect(helper).to receive_messages(params: { locale: :it })
69
+ expect(helper.default_language?).to eq false
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Spotlight::TranslationsHelper do
4
+ describe '#non_custom_metadata_fields' do
5
+ let(:exhibit) { FactoryBot.create(:exhibit) }
6
+ let!(:custom_field) { FactoryBot.create(:custom_field, exhibit: exhibit) }
7
+
8
+ before { allow(helper).to receive(:current_exhibit).and_return(exhibit) }
9
+
10
+ it "is an array of the current exhibit's metadata fields with the custom fields removed" do
11
+ expect(exhibit.blacklight_config.show_fields.keys).to include custom_field.field
12
+
13
+ expect(helper.non_custom_metadata_fields.keys).not_to include custom_field.field
14
+ end
15
+ end
16
+ end
data/spec/i18n_spec.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/tasks'
4
+
5
+ # rubocop:disable RSpec/DescribeClass
6
+ RSpec.describe 'I18n' do
7
+ let(:i18n) { I18n::Tasks::BaseTask.new }
8
+ let(:missing_keys) { i18n.missing_keys }
9
+ let(:unused_keys) { i18n.unused_keys }
10
+
11
+ pending 'does not have missing keys' do
12
+ expect(missing_keys).to be_empty,
13
+ "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
14
+ end
15
+
16
+ it 'does not have unused keys' do
17
+ expect(unused_keys).to be_empty,
18
+ "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
19
+ end
20
+
21
+ it 'files are normalized' do
22
+ non_normalized = i18n.non_normalized_paths
23
+ error_message = "The following files need to be normalized:\n" \
24
+ "#{non_normalized.map { |path| " #{path}" }.join("\n")}\n" \
25
+ 'Please run `i18n-tasks normalize` to fix'
26
+ expect(non_normalized).to be_empty, error_message
27
+ end
28
+ end
29
+ # rubocop:enable RSpec/DescribeClass
@@ -0,0 +1,21 @@
1
+ require 'migration/page_language'
2
+
3
+ RSpec.describe Migration::PageLanguage do
4
+ describe '#migrate_pages' do
5
+ let(:exhibit) { FactoryBot.create(:exhibit) }
6
+ let(:page) { FactoryBot.create(:feature_page, exhibit: exhibit) }
7
+ let(:slug) { FriendlyId::Slug.find(page.id) }
8
+ before do
9
+ # Remove the locale scope (anticipating pre translation state of scope)
10
+ slug.scope = slug.scope.sub(',locale:en', '')
11
+ slug.save
12
+ slug.reload
13
+ end
14
+ it 'sets the scope to the default locale' do
15
+ expect(slug.scope).not_to include(',locale:en')
16
+ subject.run
17
+ slug.reload
18
+ expect(slug.scope).to eq "exhibit_id:#{page.exhibit.id},locale:en"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Spotlight::UploadFieldConfig do
4
+ describe '#label' do
5
+ it 'accepts a proc and calls it' do
6
+ label = -> { 'returned string' }
7
+ expect(described_class.new(field_name: 'something', label: label).label).to eq 'returned string'
8
+ end
9
+
10
+ it 'returns any non-proc value' do
11
+ expect(described_class.new(field_name: 'something', label: 'String').label).to eq 'String'
12
+ end
13
+
14
+ it 'falls back to the field name when no label is given' do
15
+ expect(described_class.new(field_name: 'something').label).to eq 'something'
16
+ end
17
+ end
18
+
19
+ describe '#solr_field' do
20
+ it 'is an alias of the #solr_field method so it can be polymorphic with other Blacklight configurations' do
21
+ expect(described_class.new(field_name: 'something').solr_field).to eq 'something'
22
+ end
23
+ end
24
+ end
@@ -4,10 +4,13 @@ describe Spotlight::Ability, type: :model do
4
4
  before do
5
5
  allow_any_instance_of(Spotlight::Search).to receive(:set_default_featured_image)
6
6
  end
7
- let(:exhibit) { FactoryBot.build_stubbed(:exhibit) }
8
- let(:search) { FactoryBot.build_stubbed(:published_search, exhibit: exhibit) }
9
- let(:unpublished_search) { FactoryBot.build_stubbed(:search, exhibit: exhibit) }
10
- let(:page) { FactoryBot.build_stubbed(:feature_page, exhibit: exhibit) }
7
+ let(:exhibit) { FactoryBot.create(:exhibit) }
8
+ let(:search) { FactoryBot.create(:published_search, exhibit: exhibit) }
9
+ let(:unpublished_search) { FactoryBot.create(:search, exhibit: exhibit) }
10
+ let(:page) { FactoryBot.create(:feature_page, exhibit: exhibit) }
11
+ let(:language) { FactoryBot.create(:language, exhibit: exhibit) }
12
+ let(:public_language) { FactoryBot.create(:language, exhibit: exhibit, public: true) }
13
+ let(:translation) { FactoryBot.create(:translation, exhibit: exhibit) }
11
14
  subject { Ability.new(user) }
12
15
 
13
16
  describe 'a user with no roles' do
@@ -17,6 +20,8 @@ describe Spotlight::Ability, type: :model do
17
20
  it { is_expected.to be_able_to(:read, page) }
18
21
  it { is_expected.not_to be_able_to(:create, Spotlight::Page.new(exhibit: exhibit)) }
19
22
  it { is_expected.to be_able_to(:read, search) }
23
+ it { is_expected.to be_able_to(:read, public_language) }
24
+ it { is_expected.not_to be_able_to(:read, language) }
20
25
  it { is_expected.not_to be_able_to(:read, unpublished_search) }
21
26
  it { is_expected.not_to be_able_to(:tag, exhibit) }
22
27
  end
@@ -42,6 +47,7 @@ describe Spotlight::Ability, type: :model do
42
47
  it { is_expected.to be_able_to(:import, exhibit) }
43
48
  it { is_expected.to be_able_to(:process_import, exhibit) }
44
49
  it { is_expected.to be_able_to(:destroy, exhibit) }
50
+ it { is_expected.to be_able_to(:manage, language) }
45
51
  end
46
52
 
47
53
  describe 'a user with curate role' do
@@ -63,11 +69,18 @@ describe Spotlight::Ability, type: :model do
63
69
  it { is_expected.to be_able_to(:update, page) }
64
70
  it { is_expected.to be_able_to(:destroy, page) }
65
71
 
72
+ it { is_expected.to be_able_to(:create, Translation) }
73
+ it { is_expected.to be_able_to(:update_all, Translation) }
74
+ it { is_expected.to be_able_to(:update, translation) }
75
+ it { is_expected.to be_able_to(:destroy, translation) }
76
+
66
77
  it { is_expected.to be_able_to(:tag, exhibit) }
67
78
 
68
79
  it { is_expected.to be_able_to(:edit, contact) }
69
80
  it { is_expected.to be_able_to(:new, contact) }
70
81
  it { is_expected.to be_able_to(:create, contact) }
71
82
  it { is_expected.to be_able_to(:destroy, contact) }
83
+ it { is_expected.not_to be_able_to(:manage, language) }
84
+ it { is_expected.to be_able_to(:read, language) }
72
85
  end
73
86
  end
@@ -16,6 +16,24 @@ describe Spotlight::Exhibit, type: :model do
16
16
  subject.save!
17
17
  expect(subject.description).to eq 'Test description'
18
18
  end
19
+
20
+ describe 'validations' do
21
+ it 'validates the presence of the title' do
22
+ exhibit.title = ''
23
+ expect do
24
+ exhibit.save
25
+ end.to change { exhibit.errors[:title].count }.by(1)
26
+ end
27
+
28
+ it 'does not validate the presence of the title under a non-default locale' do
29
+ expect(I18n).to receive(:locale).and_return(:fr)
30
+ exhibit.title = ''
31
+ expect do
32
+ exhibit.save
33
+ end.not_to(change { exhibit.errors[:title].count })
34
+ end
35
+ end
36
+
19
37
  describe 'contact_emails' do
20
38
  before do
21
39
  subject.contact_emails_attributes = [{ 'email' => 'chris@example.com' }, { 'email' => 'jesse@stanford.edu' }]
@@ -299,4 +317,35 @@ describe Spotlight::Exhibit, type: :model do
299
317
  it 'is expected to be versioned' do
300
318
  is_expected.to be_versioned
301
319
  end
320
+ describe 'translatable fields' do
321
+ let(:persisted_exhibit) { FactoryBot.create(:exhibit, title: 'Sample', subtitle: 'SubSample', description: 'Description') }
322
+ before do
323
+ FactoryBot.create(:translation, locale: 'fr', exhibit: persisted_exhibit, key: "#{persisted_exhibit.slug}.title", value: 'Titre français')
324
+ FactoryBot.create(:translation, locale: 'fr', exhibit: persisted_exhibit, key: "#{persisted_exhibit.slug}.subtitle", value: 'Sous-titre français')
325
+ FactoryBot.create(:translation, locale: 'fr', exhibit: persisted_exhibit, key: "#{persisted_exhibit.slug}.description", value: 'Description français')
326
+ Translation.current_exhibit = persisted_exhibit
327
+ end
328
+ after do
329
+ I18n.locale = 'en'
330
+ end
331
+ it 'has a translatable title' do
332
+ expect(persisted_exhibit.title).to eq 'Sample'
333
+ I18n.locale = 'fr'
334
+ persisted_exhibit.reload
335
+ expect(persisted_exhibit.title).to eq 'Titre français'
336
+ end
337
+ it 'has a translatable subtitle' do
338
+ expect(persisted_exhibit.subtitle).to eq 'SubSample'
339
+ I18n.locale = 'fr'
340
+ persisted_exhibit.reload
341
+ expect(persisted_exhibit.subtitle).to eq 'Sous-titre français'
342
+ end
343
+
344
+ it 'has a translatable description' do
345
+ expect(persisted_exhibit.description).to eq 'Description'
346
+ I18n.locale = 'fr'
347
+ persisted_exhibit.reload
348
+ expect(persisted_exhibit.description).to eq 'Description français'
349
+ end
350
+ end
302
351
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Spotlight::Language do
4
+ describe '#to_native' do
5
+ it 'is the native translation of the locale' do
6
+ expect(described_class.new(locale: 'de').to_native).to eq 'Deutsch'
7
+ end
8
+
9
+ it 'is a blank string when the locale does not exist (for string comparison)' do
10
+ expect(described_class.new(locale: 'xx').to_native).to eq ''
11
+ end
12
+ end
13
+
14
+ describe 'when being destroyed' do
15
+ let(:exhibit) { FactoryBot.create(:exhibit) }
16
+ let(:language) { described_class.create(locale: 'es', exhibit: exhibit) }
17
+ before { Translation.current_exhibit = exhibit }
18
+
19
+ it 'also destroys its locale related pages' do
20
+ page_es = exhibit.home_page.clone_for_locale('es').tap(&:save)
21
+
22
+ expect(Spotlight::Page.exists?(page_es.id)).to be true
23
+
24
+ expect do
25
+ language.destroy
26
+ end.to change(Spotlight::Page, :count).by(-1)
27
+
28
+ expect(Spotlight::Page.exists?(page_es.id)).to be false
29
+ end
30
+
31
+ it 'also destroys its locale related translations' do
32
+ translation = FactoryBot.create(:translation, key: 'some.key', exhibit: exhibit, locale: 'es')
33
+
34
+ expect do
35
+ language.destroy
36
+ end.to change(Translation, :count).by(-1)
37
+
38
+ expect(Translation.exists?(translation.id)).to be false
39
+ end
40
+ end
41
+ end
@@ -111,4 +111,113 @@ describe Spotlight::Page, type: :model do
111
111
  expect(page.thumbnail_image_url).to eq thumbnail.iiif_url
112
112
  end
113
113
  end
114
+
115
+ describe 'updated_after?' do
116
+ let!(:old_page) { FactoryBot.create(:feature_page, updated_at: 10.seconds.ago) }
117
+ let!(:new_page) { FactoryBot.create(:feature_page) }
118
+
119
+ it 'compares the updated_at of the two objects' do
120
+ expect(new_page).to be_updated_after(old_page)
121
+ end
122
+ end
123
+
124
+ describe 'translated_pages' do
125
+ let!(:page_es) { FactoryBot.create(:feature_page, exhibit: exhibit, locale: 'es', default_locale_page: page) }
126
+ subject!(:page) { FactoryBot.create(:feature_page, exhibit: exhibit) }
127
+
128
+ it 'is a relation of the other pages that indicate they belong to this page' do
129
+ expect(page.translated_pages.length).to eq 1
130
+ expect(page.translated_pages.first).to eq page_es
131
+ end
132
+ end
133
+
134
+ describe 'clone_for_locale' do
135
+ let(:page) { FactoryBot.create(:feature_page, exhibit: exhibit, published: true) }
136
+ subject!(:cloned_page) { page.clone_for_locale('es') }
137
+
138
+ it 'creates a new page' do
139
+ expect do
140
+ cloned_page.save
141
+ end.to change(described_class, :count).by(1)
142
+ end
143
+
144
+ it 'has the given locale' do
145
+ expect(cloned_page.locale).to eq 'es'
146
+ end
147
+
148
+ it 'sets the default_locale_page to self' do
149
+ expect(cloned_page.default_locale_page).to eq page
150
+ end
151
+
152
+ it 'does not copy the published attribute to the cloned page' do
153
+ expect(page).to be_published
154
+ expect(cloned_page).not_to be_published
155
+ end
156
+
157
+ context 'when cloning a child page' do
158
+ let(:parent_page) { FactoryBot.create(:feature_page, exhibit: exhibit) }
159
+ let(:parent_cloned_page) { parent_page.clone_for_locale('es') }
160
+
161
+ before do
162
+ parent_cloned_page.save
163
+ page.update(parent_page_id: parent_page.id)
164
+ end
165
+
166
+ it 'associates the page with the translated version (if present)' do
167
+ expect(page.clone_for_locale('es').parent_page.id).to eq parent_cloned_page.id
168
+ end
169
+ end
170
+
171
+ context 'when cloning a parent page whose children pages have already been cloned' do
172
+ let(:parent_page_es) { parent_page.clone_for_locale('es') }
173
+ let(:child_page_es) { child_page.clone_for_locale('es') }
174
+
175
+ before { child_page_es.save }
176
+
177
+ it 'updates the translated child pages with the correct parent association' do
178
+ expect(child_page_es.parent_page).to eq parent_page
179
+ parent_page_es.save
180
+ expect(child_page_es.reload.parent_page).to eq parent_page_es
181
+ end
182
+ end
183
+ end
184
+
185
+ describe 'syncing data between translated pages' do
186
+ let(:parent_page_es) do
187
+ FactoryBot.create(
188
+ :feature_page,
189
+ exhibit: exhibit,
190
+ locale: 'es',
191
+ default_locale_page: parent_page
192
+ )
193
+ end
194
+ let(:child_page_es) do
195
+ FactoryBot.create(
196
+ :feature_page,
197
+ exhibit: exhibit,
198
+ locale: 'es',
199
+ default_locale_page: child_page,
200
+ parent_page: parent_page_es
201
+ )
202
+ end
203
+
204
+ it 'updates the translated pages weight' do
205
+ expect(parent_page_es.weight).not_to be 5
206
+ parent_page.update(weight: 5)
207
+ expect(parent_page_es.reload.weight).to be 5
208
+ end
209
+
210
+ it 'updates the parent page id' do
211
+ expect(child_page_es.parent_page).to eq parent_page_es
212
+ child_page.update(parent_page: nil)
213
+ expect(child_page_es.reload.parent_page).to be_nil
214
+ end
215
+
216
+ it 'updates the attributes separately' do
217
+ expect(child_page_es.parent_page).to eq parent_page_es
218
+ child_page.update(weight: 5)
219
+ expect(child_page_es.reload.weight).to eq 5
220
+ expect(child_page_es.reload.parent_page).to eq parent_page_es
221
+ end
222
+ end
114
223
  end