hyrax 2.0.0.beta1 → 2.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -2
  3. data/app/actors/hyrax/actors/file_set_actor.rb +12 -15
  4. data/app/assets/javascripts/hyrax.js +6 -5
  5. data/app/assets/javascripts/hyrax/{app.js → app.js.erb} +12 -8
  6. data/app/assets/javascripts/hyrax/channels/notifications.js +0 -0
  7. data/app/assets/javascripts/hyrax/notification.es6 +19 -31
  8. data/app/channels/hyrax/application_cable/channel.rb +6 -0
  9. data/app/channels/hyrax/application_cable/connection.rb +30 -0
  10. data/app/channels/hyrax/notifications_channel.rb +15 -0
  11. data/app/controllers/hyrax/depositors_controller.rb +2 -2
  12. data/app/controllers/hyrax/notifications_controller.rb +2 -0
  13. data/app/controllers/hyrax/users_controller.rb +0 -7
  14. data/app/helpers/hyrax/hyrax_helper_behavior.rb +27 -0
  15. data/app/jobs/import_url_job.rb +3 -1
  16. data/app/jobs/stream_notifications_job.rb +10 -0
  17. data/app/models/proxy_deposit_request.rb +2 -2
  18. data/app/models/user_mailbox.rb +19 -0
  19. data/app/services/hyrax/{message_user_service.rb → abstract_message_service.rb} +7 -4
  20. data/app/services/hyrax/batch_create_failure_service.rb +1 -1
  21. data/app/services/hyrax/batch_create_success_service.rb +1 -1
  22. data/app/services/hyrax/fixity_check_failure_service.rb +1 -1
  23. data/app/services/hyrax/import_url_failure_service.rb +1 -1
  24. data/app/services/hyrax/messenger_service.rb +8 -0
  25. data/app/services/hyrax/workflow/abstract_notification.rb +1 -1
  26. data/app/views/_user_util_links.html.erb +1 -1
  27. data/app/views/hyrax/homepage/index.html.erb +1 -1
  28. data/config/locales/hyrax.de.yml +5 -2
  29. data/config/locales/hyrax.en.yml +4 -1
  30. data/config/locales/hyrax.es.yml +4 -1
  31. data/config/locales/hyrax.fr.yml +5 -2
  32. data/config/locales/hyrax.it.yml +4 -1
  33. data/config/locales/hyrax.pt-BR.yml +5 -2
  34. data/config/locales/hyrax.zh.yml +5 -2
  35. data/config/routes.rb +4 -2
  36. data/db/migrate/20170905135339_add_preferred_locale_to_users.rb +5 -0
  37. data/lib/generators/hyrax/templates/config/authorities/licenses.yml +28 -10
  38. data/lib/generators/hyrax/templates/config/hyrax.rb +0 -3
  39. data/lib/hyrax/configuration.rb +0 -5
  40. data/lib/hyrax/engine.rb +5 -0
  41. data/lib/hyrax/version.rb +1 -1
  42. data/spec/actors/hyrax/actors/file_set_actor_spec.rb +74 -0
  43. data/spec/channels/hyrax/application_cable/channel_spec.rb +14 -0
  44. data/spec/channels/hyrax/application_cable/connection_spec.rb +31 -0
  45. data/spec/channels/hyrax/notifications_channel_spec.rb +45 -0
  46. data/spec/controllers/hyrax/notifications_controller_spec.rb +1 -0
  47. data/spec/helpers/blacklight_helper_spec.rb +4 -2
  48. data/spec/helpers/hyrax_helper_spec.rb +34 -4
  49. data/spec/jobs/import_url_job_spec.rb +1 -1
  50. data/spec/jobs/stream_notifications_job_spec.rb +30 -0
  51. data/spec/models/collection_spec.rb +13 -19
  52. data/spec/models/proxy_deposit_request_spec.rb +2 -1
  53. data/spec/models/user_mailbox_spec.rb +73 -0
  54. data/spec/services/hyrax/abstract_message_service_spec.rb +25 -0
  55. data/spec/services/hyrax/messenger_service_spec.rb +15 -0
  56. data/spec/test_app_templates/lib/generators/test_app_generator.rb +6 -0
  57. data/spec/views/_user_util_links.html.erb_spec.rb +3 -2
  58. data/spec/views/hyrax/homepage/index.html.erb_spec.rb +4 -0
  59. data/template.rb +1 -1
  60. metadata +23 -14
  61. data/app/assets/javascripts/hyrax/notifications.es6 +0 -63
  62. data/app/views/hyrax/users/_notify_number.html.erb +0 -8
  63. data/app/views/hyrax/users/notifications_number.json.jbuilder +0 -1
  64. data/app/views/kaminari/blacklight/_first_page.html.erb +0 -9
  65. data/app/views/kaminari/blacklight/_gap.html.erb +0 -8
  66. data/app/views/kaminari/blacklight/_last_page.html.erb +0 -9
  67. data/app/views/kaminari/blacklight/_next_page.html.erb +0 -9
  68. data/app/views/kaminari/blacklight/_page.html.erb +0 -10
  69. data/app/views/kaminari/blacklight/_paginator.html.erb +0 -19
  70. data/app/views/kaminari/blacklight/_prev_page.html.erb +0 -9
@@ -0,0 +1,31 @@
1
+ RSpec.describe Hyrax::ApplicationCable::Connection, no_clean: true do
2
+ subject { described_class.new(server, env) }
3
+
4
+ let(:server) { ActionCable::Server::Base.new }
5
+ let(:env) { {} }
6
+
7
+ describe '#connect' do
8
+ # rubocop:disable RSpec/SubjectStub
9
+ before do
10
+ allow(subject).to receive(:user_id).and_return(user_id)
11
+ end
12
+ # rubocop:enable RSpec/SubjectStub
13
+
14
+ context 'when user is found' do
15
+ let(:user) { create(:user) }
16
+ let(:user_id) { user.id }
17
+
18
+ it 'sets #current_user to the found user instance' do
19
+ expect { subject.connect }.to change { subject.current_user }.from(nil).to(user)
20
+ end
21
+ end
22
+
23
+ context 'when user is not found' do
24
+ let(:user_id) { nil }
25
+
26
+ it 'rejects the unauthorized connection' do
27
+ expect { subject.connect }.to raise_error(ActionCable::Connection::Authorization::UnauthorizedError)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ RSpec.describe Hyrax::NotificationsChannel, no_clean: true do
2
+ subject { described_class.new(connection, nil) }
3
+
4
+ let(:connection) { Hyrax::ApplicationCable::Connection.new(server, {}) }
5
+ let(:server) { ActionCable::Server::Base.new }
6
+ let(:user) { create(:user) }
7
+
8
+ before do
9
+ allow(connection).to receive(:find_verified_user).and_return(user)
10
+ connection.connect
11
+ end
12
+
13
+ describe '#current_user' do
14
+ it 'has a current user instance from its connection' do
15
+ expect(subject.current_user).to eq user
16
+ end
17
+ end
18
+
19
+ describe '#update_locale' do
20
+ let(:data) { { 'locale' => 'zh' } }
21
+
22
+ it 'updates the current user instance with the locale' do
23
+ expect { subject.update_locale(data) }.to change { user.preferred_locale }
24
+ .from(nil).to(data['locale'])
25
+ end
26
+ end
27
+
28
+ describe '#subscribed' do
29
+ # rubocop:disable RSpec/SubjectStub
30
+ it 'calls #stream_for with the current user instance' do
31
+ expect(subject).to receive(:stream_for).with(user).once
32
+ subject.subscribed
33
+ end
34
+ # rubocop:enable RSpec/SubjectStub
35
+ end
36
+
37
+ describe '#unsubscribed' do
38
+ # rubocop:disable RSpec/SubjectStub
39
+ it 'calls #stop_all_streams' do
40
+ expect(subject).to receive(:stop_all_streams).once
41
+ subject.unsubscribed
42
+ end
43
+ # rubocop:enable RSpec/SubjectStub
44
+ end
45
+ end
@@ -9,6 +9,7 @@ RSpec.describe Hyrax::NotificationsController, type: :controller do
9
9
  describe "#index" do
10
10
  it "shows message" do
11
11
  expect(mock_box).to receive(:inbox).and_return(["test"])
12
+ expect(StreamNotificationsJob).to receive(:perform_later).once
12
13
  get :index
13
14
  expect(response).to be_success
14
15
  expect(assigns[:messages]).to eq(["test"])
@@ -1,3 +1,5 @@
1
+ # coding: utf-8
2
+
1
3
  RSpec.describe BlacklightHelper, type: :helper do
2
4
  let(:blacklight_config) { CatalogController.blacklight_config }
3
5
  let(:attributes) do
@@ -49,8 +51,8 @@ RSpec.describe BlacklightHelper, type: :helper do
49
51
  let(:field_name) { 'rights_tesim' }
50
52
 
51
53
  it do
52
- is_expected.to eq "<a href=\"http://creativecommons.org/publicdomain/zero/1.0/\">CC0 1.0 Universal</a>, " \
53
- "<a href=\"http://creativecommons.org/publicdomain/mark/1.0/\">Public Domain Mark 1.0</a>, " \
54
+ is_expected.to eq "<a href=\"http://creativecommons.org/publicdomain/zero/1.0/\">Creative Commons CC0 1.0 Universal</a>, " \
55
+ "<a href=\"http://creativecommons.org/publicdomain/mark/1.0/\">Creative Commons Public Domain Mark 1.0</a>, " \
54
56
  "and <a href=\"http://www.europeana.eu/portal/rights/rr-r.html\">All rights reserved</a>"
55
57
  end
56
58
  end
@@ -23,6 +23,36 @@ RSpec.describe HyraxHelper, type: :helper do
23
23
  end
24
24
  end
25
25
 
26
+ describe '#render_notifications' do
27
+ let(:mailbox) { double('mailbox', unread_count: unread_count, label: 'Foobar') }
28
+
29
+ subject { helper.render_notifications(user: nil) }
30
+
31
+ before do
32
+ allow(UserMailbox).to receive(:new).and_return(mailbox)
33
+ end
34
+
35
+ context 'with unread messages' do
36
+ let(:unread_count) { 10 }
37
+
38
+ it 'renders with label-danger and is visible' do
39
+ expect(subject).to eq '<a aria-label="Foobar" class="notify-number" href="/notifications"><span class="fa fa-bell"></span>' \
40
+ "\n" \
41
+ '<span class="count label label-danger">10</span></a>'
42
+ end
43
+ end
44
+
45
+ context 'with no unread messages' do
46
+ let(:unread_count) { 0 }
47
+
48
+ it 'renders with label-default and is invisible' do
49
+ expect(subject).to eq '<a aria-label="Foobar" class="notify-number" href="/notifications"><span class="fa fa-bell"></span>' \
50
+ "\n" \
51
+ '<span class="count label invisible label-default">0</span></a>'
52
+ end
53
+ end
54
+ end
55
+
26
56
  describe '#available_translations' do
27
57
  subject { helper.available_translations }
28
58
 
@@ -321,16 +351,16 @@ RSpec.describe HyraxHelper, type: :helper do
321
351
  it "maps the url to a link with a label" do
322
352
  expect(helper.license_links(
323
353
  value: ["http://creativecommons.org/publicdomain/zero/1.0/"]
324
- )).to eq("<a href=\"http://creativecommons.org/publicdomain/zero/1.0/\">CC0 1.0 Universal</a>")
354
+ )).to eq("<a href=\"http://creativecommons.org/publicdomain/zero/1.0/\">Creative Commons CC0 1.0 Universal</a>")
325
355
  end
326
356
 
327
- it "converts multiple rights statements to a sentence" do
357
+ it "converts multiple licenses to a sentence" do
328
358
  expect(helper.license_links(
329
359
  value: ["http://creativecommons.org/publicdomain/zero/1.0/",
330
360
  "http://creativecommons.org/publicdomain/mark/1.0/",
331
361
  "http://www.europeana.eu/portal/rights/rr-r.html"]
332
- )).to eq("<a href=\"http://creativecommons.org/publicdomain/zero/1.0/\">CC0 1.0 Universal</a>, " \
333
- "<a href=\"http://creativecommons.org/publicdomain/mark/1.0/\">Public Domain Mark 1.0</a>, " \
362
+ )).to eq("<a href=\"http://creativecommons.org/publicdomain/zero/1.0/\">Creative Commons CC0 1.0 Universal</a>, " \
363
+ "<a href=\"http://creativecommons.org/publicdomain/mark/1.0/\">Creative Commons Public Domain Mark 1.0</a>, " \
334
364
  "and <a href=\"http://www.europeana.eu/portal/rights/rr-r.html\">All rights reserved</a>")
335
365
  end
336
366
  end
@@ -29,7 +29,7 @@ RSpec.describe ImportUrlJob do
29
29
  end
30
30
 
31
31
  it 'creates the content and updates the associated operation' do
32
- expect(actor).to receive(:create_content).with(File).and_return(true)
32
+ expect(actor).to receive(:create_content).with(File, from_url: true).and_return(true)
33
33
  described_class.perform_now(file_set, operation)
34
34
  expect(operation).to be_success
35
35
  end
@@ -0,0 +1,30 @@
1
+ RSpec.describe StreamNotificationsJob do
2
+ describe '#perform' do
3
+ context 'with zero users' do
4
+ let(:users) { nil }
5
+
6
+ it 'does not broadcast' do
7
+ expect(Hyrax::NotificationsChannel).not_to receive(:broadcast_to)
8
+ described_class.perform_now(users)
9
+ end
10
+ end
11
+
12
+ context 'with a user' do
13
+ let(:users) { create(:user) }
14
+ let(:mailbox) { double('mailbox', unread_count: 7, label: "You've got mail!") }
15
+
16
+ before do
17
+ allow(UserMailbox).to receive(:new).and_return(mailbox)
18
+ end
19
+
20
+ it 'broadcasts to the user' do
21
+ expect(Hyrax::NotificationsChannel).to receive(:broadcast_to)
22
+ .once
23
+ .with(users,
24
+ notifications_count: 7,
25
+ notifications_label: "You've got mail!")
26
+ described_class.perform_now(users)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -14,18 +14,15 @@ RSpec.describe Collection do
14
14
  end
15
15
 
16
16
  describe "#to_solr" do
17
- let(:user) { create(:user) }
17
+ let(:user) { build(:user) }
18
18
  let(:collection) { build(:collection, user: user, title: ['A good title']) }
19
19
 
20
20
  let(:solr_document) { collection.to_solr }
21
21
 
22
- it "has title information" do
22
+ it "has title information and depositor information" do
23
23
  expect(solr_document).to include 'title_tesim' => ['A good title'],
24
- 'title_sim' => ['A good title']
25
- end
26
-
27
- it "has depositor information" do
28
- expect(solr_document).to include 'depositor_tesim' => [user.user_key],
24
+ 'title_sim' => ['A good title'],
25
+ 'depositor_tesim' => [user.user_key],
29
26
  'depositor_ssim' => [user.user_key]
30
27
  end
31
28
  end
@@ -42,7 +39,7 @@ RSpec.describe Collection do
42
39
  end
43
40
  end
44
41
 
45
- describe "#members_objects" do
42
+ describe "#members_objects", clean_repo: true do
46
43
  let(:collection) { create(:collection) }
47
44
 
48
45
  it "is empty by default" do
@@ -52,43 +49,40 @@ RSpec.describe Collection do
52
49
  context "adding members" do
53
50
  let(:work1) { create(:work) }
54
51
  let(:work2) { create(:work) }
55
- let(:work3) { create(:work) }
56
52
 
57
53
  it "allows multiple files to be added" do
58
- collection.add_member_objects [work1.id, work2.id, work3.id]
54
+ collection.add_member_objects [work1.id, work2.id]
59
55
  collection.save!
60
- expect(collection.reload.member_objects).to match_array [work1, work2, work3]
56
+ expect(collection.reload.member_objects).to match_array [work1, work2]
61
57
  end
62
58
  end
63
59
  end
64
60
 
65
- it "has a title" do
61
+ it "has a title", clean_repo: true do
66
62
  subject.title = ["title"]
67
63
  subject.save!
68
64
  expect(subject.reload.title).to eq ["title"]
69
65
  end
70
66
 
71
- it "has a description" do
72
- subject.title = ["title"]
67
+ it "has a description", clean_repo: true do
68
+ subject.title = ["title"] # Because the title is required
73
69
  subject.description = ["description"]
74
70
  subject.save!
75
71
  expect(subject.reload.description).to eq ["description"]
76
72
  end
77
73
 
78
- describe "#destroy" do
74
+ describe "#destroy", clean_repo: true do
79
75
  let(:collection) { build(:collection) }
80
76
  let(:work1) { create(:work) }
81
- let(:work2) { create(:work) }
82
77
 
83
78
  before do
84
- collection.add_member_objects [work1.id, work2.id]
79
+ collection.add_member_objects [work1.id]
85
80
  collection.save!
86
81
  collection.destroy
87
82
  end
88
83
 
89
84
  it "does not delete member files when deleted" do
90
85
  expect(GenericWork.exists?(work1.id)).to be true
91
- expect(GenericWork.exists?(work2.id)).to be true
92
86
  end
93
87
  end
94
88
 
@@ -111,7 +105,7 @@ RSpec.describe Collection do
111
105
  let(:member) { Member.create }
112
106
  let(:collection) { OtherCollection.create(title: ['test title']) }
113
107
 
114
- it "have members that know about the collection" do
108
+ it "have members that know about the collection", clean_repo: true do
115
109
  member.reload
116
110
  expect(member.member_of_collections).to eq [collection]
117
111
  end
@@ -112,7 +112,8 @@ RSpec.describe ProxyDepositRequest, type: :model do
112
112
  context 'when the transfer_to user is found' do
113
113
  it 'creates a transfer_request' do
114
114
  subject.transfer_to = receiver.user_key
115
- subject.save!
115
+ expect { subject.save! }.to change { receiver.mailbox.inbox(unread: true).count }
116
+ .from(0).to(1)
116
117
  proxy_request = receiver.proxy_deposit_requests.first
117
118
  expect(proxy_request.work_id).to eq(work_id)
118
119
  expect(proxy_request.sending_user).to eq(sender)
@@ -1,3 +1,5 @@
1
+ # coding: utf-8
2
+
1
3
  RSpec.describe UserMailbox do
2
4
  let(:user) { create(:user) }
3
5
  let(:another_user) { create(:user) }
@@ -19,6 +21,77 @@ RSpec.describe UserMailbox do
19
21
  end
20
22
  end
21
23
 
24
+ describe '#unread_count' do
25
+ it 'returns the number of unread messages for a user' do
26
+ expect { another_user.send_message(user, 'Another Test', '[subj]') }
27
+ .to change { subject.unread_count }.from(1).to(2)
28
+ end
29
+ end
30
+
31
+ describe '#label' do
32
+ # rubocop:disable RSpec/SubjectStub
33
+ before do
34
+ allow(subject).to receive(:unread_count).and_return(count)
35
+ end
36
+ # rubocop:enable RSpec/SubjectStub
37
+
38
+ context 'with zero unread messages' do
39
+ let(:count) { 0 }
40
+
41
+ it 'returns the appropriate label' do
42
+ expect(subject.label).to eq 'You have no unread notifications'
43
+ end
44
+ end
45
+
46
+ context 'with one unread message' do
47
+ let(:count) { 1 }
48
+
49
+ it 'returns the appropriate label' do
50
+ expect(subject.label).to eq 'You have one unread notification'
51
+ end
52
+ end
53
+
54
+ context 'with multiple unread messages' do
55
+ let(:count) { 5 }
56
+
57
+ it 'returns the appropriate label' do
58
+ expect(subject.label).to eq 'You have 5 unread notifications'
59
+ end
60
+ end
61
+
62
+ describe 'locales' do
63
+ let(:count) { 3 }
64
+
65
+ context 'when param is passed' do
66
+ it 'returns the label in the specified locale' do
67
+ expect(subject.label('es')).to eq 'Tienes notificaciones no leídas de 3'
68
+ end
69
+ end
70
+
71
+ context 'when param is not passed' do
72
+ before { allow(user).to receive(:preferred_locale).and_return(preferred_locale) }
73
+
74
+ context 'when user has a preferred locale' do
75
+ let(:preferred_locale) { 'it' }
76
+
77
+ it 'returns the label in the user-preferred locale' do
78
+ expect(I18n).not_to receive(:default_locale)
79
+ expect(subject.label).to eq 'Hai notifiche non letti 3'
80
+ end
81
+ end
82
+
83
+ context 'when user lacks a preferred locale' do
84
+ let(:preferred_locale) { nil }
85
+
86
+ it 'returns the system default locale' do
87
+ expect(I18n).to receive(:default_locale).once.and_return('de')
88
+ expect(subject.label).to eq 'Sie haben 3 ungelesene Benachrichtigungen'
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
22
95
  describe "#delete_all" do
23
96
  before do
24
97
  another_user.send_message(user, 'message 2', 'subject 2')
@@ -0,0 +1,25 @@
1
+ RSpec.describe Hyrax::AbstractMessageService do
2
+ let(:file_set) { double }
3
+ let(:user) { build(:user) }
4
+ let(:klass) do
5
+ Class.new(described_class) do
6
+ def message
7
+ 'You have won!'
8
+ end
9
+
10
+ def subject
11
+ 'Attention!'
12
+ end
13
+ end
14
+ end
15
+
16
+ subject { klass.new(file_set, user) }
17
+
18
+ describe '#call' do
19
+ it 'invokes Hyrax::MessengerService to deliver the message' do
20
+ expect(Hyrax::MessengerService).to receive(:deliver)
21
+ .with(::User.audit_user, user, 'You have won!', 'Attention!').once
22
+ subject.call
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ RSpec.describe Hyrax::MessengerService do
2
+ describe '#deliver' do
3
+ let(:sender) { create(:user) }
4
+ let(:recipients) { create(:user) }
5
+ let(:body) { 'Quite an excellent message' }
6
+ let(:subject) { 'IMPORTANT' }
7
+ let(:other_arg) { 'Did I make it?' }
8
+
9
+ it 'invokes Hyrax::MessengerService to deliver the message' do
10
+ expect(sender).to receive(:send_message).with(recipients, body, subject, other_arg)
11
+ expect(StreamNotificationsJob).to receive(:perform_later).with(recipients)
12
+ described_class.deliver(sender, recipients, body, subject, other_arg)
13
+ end
14
+ end
15
+ end
@@ -76,4 +76,10 @@ class TestAppGenerator < Rails::Generators::Base
76
76
  end
77
77
  copy_file 'disable_animations_in_test_environment.rb', 'app/middleware/disable_animations_in_test_environment.rb'
78
78
  end
79
+
80
+ def configure_action_cable_to_use_redis
81
+ gsub_file 'config/cable.yml',
82
+ "development:\n adapter: async",
83
+ "development:\n adapter: redis\n url: redis://localhost:6379"
84
+ end
79
85
  end