hyrax 2.0.0.beta1 → 2.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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