curation_concerns 0.3.0 → 0.4.0

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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +1 -2
  5. data/README.md +1 -1
  6. data/Rakefile +1 -1
  7. data/VERSION +1 -1
  8. data/app/assets/javascripts/curation_concerns/curation_concerns.js +2 -0
  9. data/app/assets/javascripts/curation_concerns/uploader.js +4 -4
  10. data/app/assets/stylesheets/curation_concerns/_modules.scss +1 -0
  11. data/app/assets/stylesheets/curation_concerns/_positioning.scss +3 -0
  12. data/app/assets/stylesheets/curation_concerns/modules/icons.scss +11 -0
  13. data/app/controllers/concerns/curation_concerns/api.rb +1 -12
  14. data/app/controllers/concerns/curation_concerns/application_controller_behavior.rb +20 -6
  15. data/app/controllers/concerns/curation_concerns/curation_concern_controller.rb +44 -25
  16. data/app/controllers/concerns/curation_concerns/file_sets_controller_behavior.rb +32 -23
  17. data/app/controllers/concerns/curation_concerns/parent_container.rb +0 -11
  18. data/app/controllers/concerns/curation_concerns/single_use_links_controller_behavior.rb +1 -1
  19. data/app/controllers/concerns/curation_concerns/single_use_links_viewer_controller_behavior.rb +7 -1
  20. data/app/controllers/concerns/curation_concerns/upload_sets_controller_behavior.rb +19 -7
  21. data/app/controllers/curation_concerns/permissions_controller.rb +1 -1
  22. data/app/forms/curation_concerns/forms/collection_edit_form.rb +6 -2
  23. data/app/forms/curation_concerns/forms/work_form.rb +14 -3
  24. data/app/forms/curation_concerns/upload_set_form.rb +43 -0
  25. data/app/helpers/curation_concerns/ability_helper.rb +12 -18
  26. data/app/helpers/curation_concerns/file_set_helper.rb +1 -1
  27. data/app/helpers/curation_concerns/main_app_helpers.rb +1 -0
  28. data/app/helpers/curation_concerns/permissions_helper.rb +20 -0
  29. data/app/helpers/curation_concerns/url_helper.rb +3 -11
  30. data/app/inputs/multi_value_with_help_input.rb +8 -0
  31. data/app/inputs/select_with_help_input.rb +3 -0
  32. data/app/inputs/select_with_modal_help_input.rb +36 -0
  33. data/app/inputs/with_help_icon.rb +34 -0
  34. data/app/presenters/curation_concerns/collection_presenter.rb +9 -0
  35. data/app/presenters/curation_concerns/file_set_presenter.rb +2 -1
  36. data/app/presenters/curation_concerns/presents_attributes.rb +16 -0
  37. data/app/presenters/curation_concerns/work_show_presenter.rb +3 -2
  38. data/app/renderers/curation_concerns/attribute_renderer.rb +22 -4
  39. data/app/renderers/curation_concerns/configured_microdata.rb +40 -0
  40. data/app/services/curation_concerns/parent_service.rb +1 -1
  41. data/app/views/catalog/_action_menu_partials/_default.html.erb +2 -2
  42. data/app/views/collections/_form.html.erb +8 -9
  43. data/app/views/collections/_sort_and_per_page.html.erb +25 -23
  44. data/app/views/collections/show.html.erb +1 -1
  45. data/app/views/curation_concerns/base/_attributes.html.erb +1 -1
  46. data/app/views/curation_concerns/base/_form.html.erb +6 -7
  47. data/app/views/curation_concerns/base/_form_permission.html.erb +3 -0
  48. data/app/views/curation_concerns/base/_multiple_upload.html.erb +3 -0
  49. data/app/views/curation_concerns/base/_show_actions.html.erb +2 -2
  50. data/app/views/curation_concerns/base/_versioning.html.erb +1 -1
  51. data/app/views/curation_concerns/base/_visibility.html.erb +17 -0
  52. data/app/views/curation_concerns/base/show.html.erb +1 -1
  53. data/app/views/curation_concerns/classify_concerns/new.html.erb +1 -1
  54. data/app/views/curation_concerns/file_sets/_actions.html.erb +2 -2
  55. data/app/views/curation_concerns/file_sets/_form.html.erb +1 -1
  56. data/app/views/curation_concerns/file_sets/_rights_modal.html.erb +41 -0
  57. data/app/views/curation_concerns/file_sets/media_display/_default.html.erb +4 -1
  58. data/app/views/curation_concerns/file_sets/media_display/_image.html.erb +9 -8
  59. data/app/views/curation_concerns/file_sets/media_display/_office_document.html.erb +9 -7
  60. data/app/views/curation_concerns/file_sets/media_display/_pdf.html.erb +7 -5
  61. data/app/views/curation_concerns/file_sets/show.html.erb +2 -2
  62. data/app/views/curation_concerns/file_sets/upload/_alerts.html.erb +3 -3
  63. data/app/views/curation_concerns/file_sets/upload/_form.html.erb +1 -1
  64. data/app/views/curation_concerns/file_sets/upload/_script_templates.html.erb +1 -1
  65. data/app/views/curation_concerns/permissions/confirm.html.erb +1 -1
  66. data/app/views/curation_concerns/single_use_links_viewer/show.html.erb +1 -1
  67. data/app/views/embargoes/edit.html.erb +4 -4
  68. data/app/views/layouts/curation_concerns.html.erb +1 -1
  69. data/app/views/leases/edit.html.erb +3 -3
  70. data/app/views/shared/_add_works.html.erb +6 -3
  71. data/app/views/upload_sets/_base_metadata.html.erb +12 -0
  72. data/app/views/upload_sets/_metadata.html.erb +3 -13
  73. data/app/views/upload_sets/edit.html.erb +1 -1
  74. data/config/locales/curation_concerns.en.yml +46 -0
  75. data/curation_concerns.gemspec +5 -4
  76. data/lib/curation_concerns/engine.rb +5 -0
  77. data/lib/curation_concerns/form_builder.rb +16 -0
  78. data/lib/curation_concerns/rails/routes.rb +7 -5
  79. data/lib/generators/curation_concerns/install_generator.rb +1 -1
  80. data/lib/generators/curation_concerns/work/work_generator.rb +1 -1
  81. data/spec/actors/curation_concerns/file_set_actor_spec.rb +26 -16
  82. data/spec/controllers/curation_concerns/file_sets_controller_json_spec.rb +14 -4
  83. data/spec/controllers/curation_concerns/file_sets_controller_spec.rb +3 -3
  84. data/spec/controllers/curation_concerns/generic_works_controller_json_spec.rb +4 -4
  85. data/spec/controllers/curation_concerns/generic_works_controller_spec.rb +21 -0
  86. data/spec/controllers/curation_concerns/single_use_links_controller_spec.rb +2 -2
  87. data/spec/controllers/curation_concerns/single_use_links_viewer_controller_spec.rb +1 -1
  88. data/spec/controllers/upload_sets_controller_spec.rb +20 -27
  89. data/spec/factories/file_sets.rb +1 -0
  90. data/spec/factories/generic_works.rb +1 -0
  91. data/spec/factories/users.rb +0 -12
  92. data/spec/features/collection_spec.rb +1 -3
  93. data/spec/forms/collection_edit_form_spec.rb +16 -1
  94. data/spec/forms/upload_set_form_spec.rb +55 -0
  95. data/spec/forms/work_form_spec.rb +68 -3
  96. data/spec/helpers/curation_concerns/ability_helper_spec.rb +45 -0
  97. data/spec/helpers/curation_concerns/permissions_helper_spec.rb +12 -0
  98. data/spec/helpers/url_helper_spec.rb +0 -3
  99. data/spec/indexers/collection_indexer_spec.rb +5 -0
  100. data/spec/indexers/{file_set_indexing_service_spec.rb → file_set_indexer_spec.rb} +40 -2
  101. data/spec/indexers/{generic_work_indexing_service_spec.rb → work_indexer_spec.rb} +1 -1
  102. data/spec/inputs/multi_value_with_help_input_spec.rb +32 -0
  103. data/spec/inputs/select_with_help_input_spec.rb +43 -0
  104. data/spec/inputs/select_with_modal_help_input_spec.rb +21 -0
  105. data/spec/jobs/import_url_job_spec.rb +33 -1
  106. data/spec/jobs/ingest_file_job_spec.rb +29 -16
  107. data/spec/jobs/upload_set_update_job_spec.rb +24 -11
  108. data/spec/lib/curation_concerns/messages_spec.rb +2 -2
  109. data/spec/lib/curation_concerns/name_spec.rb +20 -0
  110. data/spec/lib/curation_concerns/null_logger_spec.rb +10 -0
  111. data/spec/models/curation_concerns/collection_behavior_spec.rb +41 -10
  112. data/spec/models/curation_concerns/work_behavior_spec.rb +1 -13
  113. data/spec/models/file_set_spec.rb +19 -4
  114. data/spec/models/generic_work_spec.rb +7 -2
  115. data/spec/models/quick_classification_query_spec.rb +35 -0
  116. data/spec/models/upload_set_spec.rb +5 -7
  117. data/spec/presenters/curation_concerns/collection_presenter_spec.rb +20 -0
  118. data/spec/presenters/curation_concerns/file_set_presenter_spec.rb +10 -3
  119. data/spec/presenters/curation_concerns/work_show_presenter_spec.rb +13 -1
  120. data/spec/renderers/curation_concerns/attribute_renderer_spec.rb +41 -8
  121. data/spec/routing/curation_concerns/routes_spec.rb +2 -2
  122. data/spec/routing/route_spec.rb +1 -1
  123. data/spec/services/file_set_audit_service_spec.rb +46 -4
  124. data/spec/spec_helper.rb +5 -7
  125. data/spec/views/collections/_sort_and_per_page.html.erb_spec.rb +32 -0
  126. data/spec/views/curation_concerns/base/_attributes.html.erb_spec.rb +8 -1
  127. data/spec/views/curation_concerns/base/show.html.erb_spec.rb +36 -2
  128. data/spec/views/curation_concerns/file_sets/_file_set.html.erb_spec.rb +3 -2
  129. data/spec/views/curation_concerns/file_sets/show.html.erb_spec.rb +56 -0
  130. data/spec/views/curation_concerns/single_use_links_viewer/show.html.erb_spec.rb +19 -0
  131. data/spec/views/shared/_add_content.html.erb_spec.rb +3 -3
  132. data/spec/views/single_use_links/new_download.html.erb_spec.rb +1 -1
  133. data/spec/views/upload_sets/_metadata.html.erb_spec.rb +28 -0
  134. metadata +80 -50
  135. data/app/assets/stylesheets/curation_concerns/help_requests.scss +0 -3
  136. data/app/controllers/concerns/curation_concerns/without_namespace.rb +0 -16
  137. data/app/controllers/registrations_controller.rb +0 -19
  138. data/app/controllers/sessions_controller.rb +0 -4
  139. data/app/views/curation_concerns/file_sets/_multiple_upload.html.erb +0 -3
  140. data/spec/fixtures/Example.ogg +0 -0
  141. data/spec/fixtures/charter.docx +0 -0
  142. data/spec/fixtures/countdown.avi +0 -0
  143. data/spec/fixtures/curation_concerns_generic_stub.txt +0 -1
  144. data/spec/fixtures/empty_file.txt +0 -0
  145. data/spec/fixtures/files/image.png +0 -0
  146. data/spec/fixtures/image.jp2 +0 -0
  147. data/spec/fixtures/image.jpg +0 -0
  148. data/spec/fixtures/piano_note.wav +0 -0
  149. data/spec/fixtures/sample_mpeg4.mp4 +0 -0
  150. data/spec/fixtures/small_file.txt +0 -1
  151. data/spec/fixtures/spoken-text.m4a +0 -0
  152. data/spec/fixtures/test.pdf +0 -0
  153. data/spec/fixtures/test4.pdf +0 -0
  154. data/spec/fixtures/test5.mp3 +0 -0
  155. data/spec/fixtures/world.png +0 -0
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe CurationConcerns::FileSetIndexingService do
3
+ describe CurationConcerns::FileSetIndexer do
4
4
  let(:file_set) do
5
5
  FileSet.new(
6
6
  id: 'foo123',
@@ -28,12 +28,21 @@ describe CurationConcerns::FileSetIndexingService do
28
28
  end
29
29
  end
30
30
 
31
+ let(:mock_file) do
32
+ mock_model("MockFile",
33
+ content: "asdf",
34
+ digest: ["urn:sha1:f794b23c0c6fe1083d0ca8b58261a078cd968967"]
35
+ )
36
+ end
37
+ let(:indexer) { described_class.new(file_set) }
38
+
31
39
  describe '#generate_solr_document' do
32
40
  before do
33
41
  allow(file_set).to receive(:label).and_return('CastoriaAd.tiff')
34
42
  allow(CurationConcerns::ThumbnailPathService).to receive(:call).and_return('/downloads/foo123?file=thumbnail')
43
+ allow(file_set).to receive(:original_file).and_return(mock_file)
35
44
  end
36
- subject { described_class.new(file_set).generate_solr_document }
45
+ subject { indexer.generate_solr_document }
37
46
 
38
47
  it 'has fields' do
39
48
  expect(subject[Solrizer.solr_name('hasRelatedMediaFragment', :symbol)]).to eq 'foo123'
@@ -64,6 +73,35 @@ describe CurationConcerns::FileSetIndexingService do
64
73
  expect(subject['all_text_timv']).to eq('abcxyz')
65
74
  expect(subject['height_is']).to eq 500
66
75
  expect(subject['width_is']).to eq 600
76
+ expect(subject[Solrizer.solr_name('digest', :symbol)]).to eq 'urn:sha1:f794b23c0c6fe1083d0ca8b58261a078cd968967'
77
+ end
78
+ end
79
+
80
+ describe '#file_format' do
81
+ subject { indexer.send(:file_format) }
82
+
83
+ context 'when both mime and format_label are present' do
84
+ before do
85
+ allow(file_set).to receive(:mime_type).and_return('image/png')
86
+ allow(file_set).to receive(:format_label).and_return(['Portable Network Graphics'])
87
+ end
88
+ it { is_expected.to eq 'png (Portable Network Graphics)' }
89
+ end
90
+
91
+ context 'when just mime type is present' do
92
+ before do
93
+ allow(file_set).to receive(:mime_type).and_return('image/png')
94
+ allow(file_set).to receive(:format_label).and_return([])
95
+ end
96
+ it { is_expected.to eq 'png' }
97
+ end
98
+
99
+ context 'when just format_label is present' do
100
+ before do
101
+ allow(file_set).to receive(:mime_type).and_return('')
102
+ allow(file_set).to receive(:format_label).and_return(['Portable Network Graphics'])
103
+ end
104
+ it { is_expected.to eq ['Portable Network Graphics'] }
67
105
  end
68
106
  end
69
107
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe CurationConcerns::WorkIndexingService do
3
+ describe CurationConcerns::WorkIndexer do
4
4
  # TODO: file_set_ids returns an empty set unless you persist the work
5
5
  let(:user) { create(:user) }
6
6
  let!(:generic_work) { create(:work_with_one_file, user: user) }
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'MultiValueWithHelpInput', type: :input do
4
+ subject { input_for file, field, as: :multi_value_with_help, required: true }
5
+ let(:file) { FileSet.new }
6
+
7
+ context "when the field has a translation" do
8
+ let(:field) { :language }
9
+ before do
10
+ allow_any_instance_of(MultiValueWithHelpInput).to receive(:raw_label_text).and_return('Language')
11
+ allow_any_instance_of(MultiValueWithHelpInput).to receive(:translate_from_namespace).and_return('default translation')
12
+ allow_any_instance_of(MultiValueWithHelpInput).to receive(:translate_from_namespace).with(:metadata_help).and_return(
13
+ 'The language of the file content.'
14
+ )
15
+ end
16
+
17
+ it 'renders help icon' do
18
+ expect(subject).to have_selector('a[data-toggle=popover][data-original-title=Language]')
19
+ expect(subject).to have_selector('a[data-toggle=popover][data-content="The language of the file content."]')
20
+ expect(subject).to have_selector('i.help-icon')
21
+ end
22
+ end
23
+
24
+ context "when the field doesn't have a translation" do
25
+ let(:field) { :date_modified }
26
+ it 'renders help icon' do
27
+ expect(subject).to have_selector('a[data-toggle=popover][data-original-title="Date modified"]')
28
+ expect(subject).to have_selector('a[data-toggle=popover][data-content="Date modified"]')
29
+ expect(subject).to have_selector('i.help-icon')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SelectWithHelpInput', type: :input do
4
+ subject { input_for form, :resource_type, options }
5
+ let(:file) { FileSet.new }
6
+ let(:form_class) do
7
+ Class.new do
8
+ include HydraEditor::Form
9
+ self.model_class = FileSet
10
+ self.terms = [:resource_type]
11
+ end
12
+ end
13
+ let(:form) { form_class.new(FileSet.new) }
14
+ let(:collection) { CurationConcerns.config.resource_types }
15
+ let(:base_options) do
16
+ { as: :select_with_help, collection: collection,
17
+ input_html: { class: 'form-control', multiple: true } }
18
+ end
19
+ let(:options) { base_options }
20
+
21
+ it "does not be required by default" do
22
+ expect(subject).to have_selector 'select'
23
+ expect(subject).not_to match(/required/)
24
+ end
25
+
26
+ context 'with File Edit' do
27
+ let(:user) { create(:user) }
28
+ let(:file) { FileSet.create(label: 'f1') { |f| f.apply_depositor_metadata(user) } }
29
+ let(:form) { CurationConcerns::Forms::FileSetEditForm.new(file) }
30
+ let(:base_options) do
31
+ { as: :select_with_help, collection: collection,
32
+ input_html: { class: 'form-control', multiple: true } }
33
+ end
34
+ let(:options) { base_options }
35
+
36
+ subject { input_for form, :resource_type, options }
37
+
38
+ it "is not required by default" do
39
+ expect(subject).to have_selector 'select'
40
+ expect(subject).not_to match(/required/)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SelectWithModalHelpInput', type: :input do
4
+ subject { input_for file, :rights, options }
5
+ let(:file) { FileSet.new }
6
+ let(:base_options) { { as: :select_with_modal_help, required: true, collection: RightsService.select_options } }
7
+ let(:options) { base_options }
8
+
9
+ context "when a blank is requested" do
10
+ let(:options) { base_options.merge(include_blank: true) }
11
+ it 'renders a blank option' do
12
+ expect(subject).to have_selector 'select option[value=""]'
13
+ end
14
+ end
15
+
16
+ context "when a blank is not requested" do
17
+ it 'has no blanks' do
18
+ expect(subject).to have_selector 'select option:first-child', text: 'Attribution 3.0 United States'
19
+ end
20
+ end
21
+ end
@@ -13,7 +13,6 @@ describe ImportUrlJob do
13
13
  end
14
14
 
15
15
  let(:file_set_id) { 'abc123' }
16
- let(:actor) { double }
17
16
 
18
17
  let(:mock_response) do
19
18
  double('response').tap do |http_res|
@@ -24,8 +23,10 @@ describe ImportUrlJob do
24
23
  end
25
24
 
26
25
  context 'after running the job' do
26
+ let(:actor) { double }
27
27
  before do
28
28
  allow(ActiveFedora::Base).to receive(:find).with(file_set_id).and_return(file_set)
29
+ allow(file_set).to receive(:reload)
29
30
  allow(CurationConcerns::FileSetActor).to receive(:new).with(file_set, user).and_return(actor)
30
31
  end
31
32
 
@@ -35,4 +36,35 @@ describe ImportUrlJob do
35
36
  described_class.perform_now(file_set_id)
36
37
  end
37
38
  end
39
+
40
+ context "when a batch update job is running too" do
41
+ let(:title) { { file_set.id => ['File One'] } }
42
+ let(:metadata) { {} }
43
+ let(:visibility) { nil }
44
+
45
+ let(:upload_set) { UploadSet.create }
46
+ let(:upload_set_job) { UploadSetUpdateJob.perform_now(user.user_key, upload_set.id, title, metadata, visibility) }
47
+ let(:file_set_id) { file_set.id }
48
+
49
+ before do
50
+ file_set.save!
51
+ allow(ActiveFedora::Base).to receive(:find).and_call_original
52
+ allow(ActiveFedora::Base).to receive(:find).with(file_set_id).and_return(file_set)
53
+ allow_any_instance_of(CurationConcerns::FileSetActor).to receive(:create_content)
54
+ allow_any_instance_of(Ability).to receive(:can?).and_return(true)
55
+ expect_any_instance_of(Net::HTTP).to receive(:request_get).with(file_hash).and_yield(mock_response)
56
+ end
57
+
58
+ it "does not kill all the metadata set by other processes" do
59
+ # run the batch job to set the title
60
+ file_set.update(title: ['File One'])
61
+
62
+ # run the import job
63
+ described_class.perform_now(file_set_id)
64
+
65
+ # import job should not override the title set another process
66
+ file = FileSet.find(file_set_id)
67
+ expect(file.title).to eq(['File One'])
68
+ end
69
+ end
38
70
  end
@@ -3,24 +3,34 @@ require 'spec_helper'
3
3
  describe IngestFileJob do
4
4
  let(:file_set) { create(:file_set) }
5
5
  let(:filename) { fixture_file_path('/world.png') }
6
+ let(:user) { create(:user) }
6
7
 
7
- it 'uses the provided mime_type' do
8
- described_class.perform_now(file_set.id, filename, 'image/png', 'bob')
9
- expect(file_set.reload.original_file.mime_type).to eq 'image/png'
8
+ context 'when givin a mime_type' do
9
+ it 'uses a provided mime_type' do
10
+ described_class.perform_now(file_set.id, filename, 'image/png', 'bob')
11
+ expect(file_set.reload.original_file.mime_type).to eq 'image/png'
12
+ end
10
13
  end
11
14
 
12
- context 'with two existing versions from different users' do
13
- let(:file1) { fixture_file_path 'world.png' }
14
- let(:file2) { fixture_file_path 'small_file.txt' }
15
- let(:actor1) { described_class.new(file_set, user) }
16
- let(:actor2) { described_class.new(file_set, second_user) }
15
+ context 'when not given a mime_type' do
16
+ it 'does not decorate File when not given mime_type' do
17
+ # Mocking CC Versioning here as it will be the versioning machinery called by the job.
18
+ # The parameter versioning: false instructs the machinery in Hydra::Works NOT to do versioning. So it can be handled later on.
19
+ allow(CurationConcerns::VersioningService).to receive(:create)
20
+ expect(Hydra::Works::AddFileToFileSet).to receive(:call).with(file_set, instance_of(::File), :original_file, versioning: false)
21
+ described_class.perform_now(file_set.id, filename, nil, 'bob')
22
+ end
23
+ end
17
24
 
18
- let(:second_user) { create(:user) }
25
+ context 'with two existing versions from different users' do
26
+ let(:file1) { fixture_file_path 'world.png' }
27
+ let(:file2) { fixture_file_path 'small_file.txt' }
19
28
  let(:versions) { file_set.reload.original_file.versions }
29
+ let(:user2) { create(:user) }
20
30
 
21
31
  before do
22
- described_class.perform_now(file_set.id, file1, 'image/png', 'bob')
23
- described_class.perform_now(file_set.id, file2, 'text/plain', 'bess')
32
+ described_class.perform_now(file_set.id, file1, 'image/png', user.user_key)
33
+ described_class.perform_now(file_set.id, file2, 'text/plain', user2.user_key)
24
34
  end
25
35
 
26
36
  it 'has two versions' do
@@ -33,13 +43,16 @@ describe IngestFileJob do
33
43
  expect(file_set.original_file.original_name).to eq 'small_file.txt'
34
44
 
35
45
  # the user for each version
36
- expect(VersionCommitter.where(version_id: versions.first.uri).pluck(:committer_login)).to eq ['bob']
37
- expect(VersionCommitter.where(version_id: versions.last.uri).pluck(:committer_login)).to eq ['bess']
46
+ expect(VersionCommitter.where(version_id: versions.first.uri).pluck(:committer_login)).to eq [user.user_key]
47
+ expect(VersionCommitter.where(version_id: versions.last.uri).pluck(:committer_login)).to eq [user2.user_key]
38
48
  end
39
49
  end
40
50
 
41
- it 'runs the after_create_content callback with file_set and user arguments' do
42
- expect(CurationConcerns.config.callback).to receive(:run).with(:after_create_content, file_set, 'bob').exactly(1).times
43
- described_class.perform_now(file_set.id, filename, 'image/png', 'bob')
51
+ describe "the after_create_contentcallback" do
52
+ subject { CurationConcerns.config.callback }
53
+ it 'runs with file_set and user arguments' do
54
+ expect(subject).to receive(:run).with(:after_create_content, file_set, user)
55
+ described_class.perform_now(file_set.id, filename, 'image/png', user.user_key)
56
+ end
44
57
  end
45
58
  end
@@ -4,27 +4,40 @@ describe UploadSetUpdateJob do
4
4
  let(:user) { create(:user) }
5
5
  let(:upload_set) { UploadSet.create }
6
6
 
7
- let!(:file) { create(:file_set, user: user, upload_set: upload_set) }
8
- let!(:file2) { create(:file_set, user: user, upload_set: upload_set) }
7
+ let(:work) { create(:work, user: user, upload_set: upload_set) }
8
+ let(:work2) { create(:work, user: user, upload_set: upload_set) }
9
+
10
+ before do
11
+ allow(CurationConcerns.config.callback).to receive(:run)
12
+ allow(CurationConcerns.config.callback).to receive(:set?)
13
+ .with(:after_upload_set_update_success)
14
+ .and_return(true)
15
+ allow(CurationConcerns.config.callback).to receive(:set?)
16
+ .with(:after_upload_set_update_failure)
17
+ .and_return(true)
18
+ end
9
19
 
10
20
  describe "#perform" do
11
- let(:title) { { file.id => ['File One'], file2.id => ['File Two'] } }
21
+ let(:title) { { work.id => ['File One'], work2.id => ['File Two'] } }
12
22
  let(:metadata) { { tag: [''] } }
13
23
  let(:visibility) { nil }
14
24
 
15
25
  subject { described_class.perform_now(user.user_key, upload_set.id, title, metadata, visibility) }
16
26
 
17
- it "updates file metadata" do
18
- expect(subject).to be true
19
- expect(file.reload.title).to eq ['File One']
27
+ it "updates work metadata" do
28
+ expect(CurationConcerns.config.callback).to receive(:run).with(:after_upload_set_update_success, user, upload_set)
29
+ subject
30
+ expect(work.reload.title).to eq ['File One']
31
+ expect(work2.reload.title).to eq ['File Two']
20
32
  end
21
33
 
22
- context "when user does not have permission to edit all of the files" do
23
- before do
24
- expect_any_instance_of(User).to receive(:can?).with(:edit, file).and_return(true)
25
- expect_any_instance_of(User).to receive(:can?).with(:edit, file2).and_return(false)
34
+ context "when user does not have permission to edit all of the works" do
35
+ it "sends the failure message" do
36
+ expect_any_instance_of(User).to receive(:can?).with(:edit, work).and_return(true)
37
+ expect_any_instance_of(User).to receive(:can?).with(:edit, work2).and_return(false)
38
+ expect(CurationConcerns.config.callback).to receive(:run).with(:after_upload_set_update_failure, user, upload_set)
39
+ subject
26
40
  end
27
- it { is_expected.to be false }
28
41
  end
29
42
  end
30
43
  end
@@ -41,7 +41,7 @@ describe CurationConcerns::Messages do
41
41
  it 'renders a success message for multiple files' do
42
42
  node = Capybara::Node::Simple.new(message.multiple_success(upload_set_id, multiple))
43
43
  expect(node).to have_selector("span[id=\"ss-1\"]", text: 'These files have been saved.')
44
- expect(node).to have_selector("a[data-content=\"#{file_list}\"][rel=\"popover\"][data-title=\"Files uploaded successfully\"]")
44
+ expect(node).to have_selector("a[data-content=\"#{file_list}\"][data-toggle=\"popover\"][data-title=\"Files uploaded successfully\"]")
45
45
  end
46
46
  end
47
47
 
@@ -57,7 +57,7 @@ describe CurationConcerns::Messages do
57
57
  it 'renders a failure message for multiple files' do
58
58
  node = Capybara::Node::Simple.new(message.multiple_failure(upload_set_id, multiple))
59
59
  expect(node).to have_selector("span[id=\"ss-1\"]", text: 'These files could not be updated. You do not have sufficient privileges to edit them.')
60
- expect(node).to have_selector("a[data-content=\"#{file_list}\"][rel=\"popover\"][data-title=\"Files failed\"]")
60
+ expect(node).to have_selector("a[data-content=\"#{file_list}\"][data-toggle=\"popover\"][data-title=\"Files failed\"]")
61
61
  end
62
62
  end
63
63
 
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe CurationConcerns::Name do
4
+ let(:name) { described_class.new(GenericWork) }
5
+
6
+ describe "route_key" do
7
+ subject { name.route_key }
8
+ it { is_expected.to eq 'curation_concerns_generic_works' }
9
+ end
10
+
11
+ describe "singular_route_key" do
12
+ subject { name.singular_route_key }
13
+ it { is_expected.to eq 'curation_concerns_generic_work' }
14
+ end
15
+
16
+ describe "param_key" do
17
+ subject { name.param_key }
18
+ it { is_expected.to eq 'generic_work' }
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe CurationConcerns::NullLogger do
4
+ subject { described_class.new }
5
+ its(:debug) { is_expected.to be_nil }
6
+ its(:info) { is_expected.to be_nil }
7
+ its(:warn) { is_expected.to be_nil }
8
+ its(:error) { is_expected.to be_nil }
9
+ its(:fatal) { is_expected.to be_nil }
10
+ end
@@ -17,19 +17,49 @@ describe CurationConcerns::CollectionBehavior do
17
17
  it { is_expected.to eq CurationConcerns::CollectionIndexer }
18
18
  end
19
19
 
20
- describe '::bytes' do
20
+ describe '.bytes' do
21
21
  subject { collection.bytes }
22
22
 
23
23
  context 'with no items' do
24
24
  before { collection.save }
25
- it { is_expected.to eq 0 }
25
+ it "gets zero without querying solr" do
26
+ expect(ActiveFedora::SolrService).not_to receive(:query)
27
+ is_expected.to eq 0
28
+ end
26
29
  end
27
30
 
28
- context 'with two 50 byte files' do
29
- let(:bitstream) { double('content', size: '50') }
30
- let(:file) { mock_model ::FileSet, content: bitstream }
31
- before { allow(collection).to receive(:members).and_return([file, file]) }
32
- it { is_expected.to eq 100 }
31
+ # Calculating the size of the Collection should only hit Solr.
32
+ # This base case querries solr in an integration test
33
+ context 'with indexed Works and FileSets', :integration do
34
+ let(:file1) { FactoryGirl.build(:file_set, file_size: ['100']) }
35
+ let(:file2) { FactoryGirl.build(:file_set, file_size: ['100']) }
36
+ let(:file3) { FactoryGirl.build(:file_set, file_size: ['9000'], id: 'fumid') }
37
+ let(:work1) { FactoryGirl.build(:generic_work) }
38
+ let(:work2) { FactoryGirl.build(:generic_work) }
39
+ let(:work3) { FactoryGirl.build(:generic_work, id: 'dumid') }
40
+ before do
41
+ # Save collection to get ids
42
+ collection.save
43
+ # Create relationships so member_ids are created
44
+ collection.members = [work1, work2]
45
+ work1.members = [file1]
46
+ work2.members = [file2]
47
+ # Create a relatinship not in the collection.
48
+ work3.members = [file3]
49
+
50
+ # Manually Call Indexing to put the data in Solr
51
+ ActiveFedora::SolrService.add(collection.to_solr)
52
+ ActiveFedora::SolrService.add(work1.to_solr, softCommit: true)
53
+ ActiveFedora::SolrService.add(work2.to_solr, softCommit: true)
54
+ ActiveFedora::SolrService.add(work3.to_solr, softCommit: true)
55
+ ActiveFedora::SolrService.add(file1.to_solr, softCommit: true)
56
+ ActiveFedora::SolrService.add(file2.to_solr, softCommit: true)
57
+ ActiveFedora::SolrService.add(file3.to_solr, softCommit: true)
58
+ end
59
+
60
+ it "is the correct aggregate size" do
61
+ is_expected.to eq 200
62
+ end
33
63
  end
34
64
  end
35
65
 
@@ -46,7 +76,7 @@ describe CurationConcerns::CollectionBehavior do
46
76
  end
47
77
 
48
78
  context 'with itself' do
49
- it 'does not add it to the collection\'s members' do
79
+ it 'does not add it to the collection members' do
50
80
  expect do
51
81
  subject.add_member(subject)
52
82
  end.to_not change { subject.members.size }
@@ -75,7 +105,7 @@ describe CurationConcerns::CollectionBehavior do
75
105
  end
76
106
  end
77
107
 
78
- context 'is a pcdm:Collection instance' do
108
+ describe 'intrinsic properties' do
79
109
  let(:collection1) { FactoryGirl.build(:collection) }
80
110
  let(:work1) { FactoryGirl.build(:work) }
81
111
 
@@ -83,7 +113,8 @@ describe CurationConcerns::CollectionBehavior do
83
113
  expect(subject.pcdm_collection?).to be true
84
114
  expect(subject.type).to include Hydra::PCDM::Vocab::PCDMTerms.Collection
85
115
  end
86
- it 'does not be a pcdm:Object' do
116
+
117
+ it 'is not a pcdm:Object' do
87
118
  expect(subject.pcdm_object?).to be false
88
119
  expect(subject.type).to_not include Hydra::PCDM::Vocab::PCDMTerms.Object
89
120
  end
@@ -4,7 +4,6 @@ describe CurationConcerns::WorkBehavior do
4
4
  before do
5
5
  class EssentialWork < ActiveFedora::Base
6
6
  include CurationConcerns::WorkBehavior
7
- include CurationConcerns::BasicMetadata
8
7
  end
9
8
  end
10
9
  after do
@@ -23,19 +22,8 @@ describe CurationConcerns::WorkBehavior do
23
22
  subject.title = %w(Hello World)
24
23
  expect(subject.to_s).to eq('Hello | World')
25
24
  end
26
-
27
- it 'falls back on label if no titles are given' do
28
- subject.title = []
29
- subject.label = 'Spam'
30
- expect(subject.to_s).to eq('Spam')
31
- end
32
-
33
- it 'with no label or titles it is "No Title"' do
34
- subject.title = []
35
- subject.label = nil
36
- expect(subject.to_s).to eq('No Title')
37
- end
38
25
  end
26
+
39
27
  describe 'human_readable_type' do
40
28
  it 'has a default' do
41
29
  expect(subject.human_readable_type).to eq 'Essential Work'
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  # It includes the CurationConcerns::FileSetBehavior module and nothing else
5
5
  # So this test covers both the FileSetBehavior module and the generated FileSet model
6
6
  describe FileSet do
7
- let(:user) { FactoryGirl.find_or_create(:jill) }
7
+ let(:user) { create(:user) }
8
8
 
9
9
  describe 'rdf type' do
10
10
  subject { described_class.new.type }
@@ -147,7 +147,7 @@ describe FileSet do
147
147
 
148
148
  describe '#indexer' do
149
149
  subject { described_class.indexer }
150
- it { is_expected.to eq CurationConcerns::FileSetIndexingService }
150
+ it { is_expected.to eq CurationConcerns::FileSetIndexer }
151
151
  end
152
152
 
153
153
  it 'supports multi-valued fields in solr' do
@@ -361,10 +361,25 @@ describe FileSet do
361
361
  end
362
362
  end
363
363
 
364
+ describe '#where_digest_is' do
365
+ let(:file) { create(:file_set) }
366
+ let(:file_path) { fixture_path + '/small_file.txt' }
367
+ let(:digest_string) { '88fb4e88c15682c18e8b19b8a7b6eaf8770d33cf' }
368
+ before do
369
+ allow(file).to receive(:warn) # suppress virus warnings
370
+ of = file.build_original_file
371
+ of.content = File.open(file_path)
372
+ file.save
373
+ file.update_index
374
+ end
375
+ subject { described_class.where_digest_is(digest_string).first }
376
+ it { is_expected.to eq(file) }
377
+ end
378
+
364
379
  describe 'to_solr' do
365
380
  let(:indexer) { double(generate_solr_document: {}) }
366
381
  before do
367
- allow(CurationConcerns::FileSetIndexingService).to receive(:new)
382
+ allow(CurationConcerns::FileSetIndexer).to receive(:new)
368
383
  .with(subject).and_return(indexer)
369
384
  end
370
385
 
@@ -374,7 +389,7 @@ describe FileSet do
374
389
  end
375
390
 
376
391
  it 'has human readable type' do
377
- expect(subject.to_solr.fetch('human_readable_type_tesim')).to eq 'File Set'
392
+ expect(subject.to_solr.fetch('human_readable_type_tesim')).to eq 'File'
378
393
  end
379
394
  end
380
395
 
@@ -9,6 +9,11 @@ describe GenericWork do
9
9
  expect(subject.title).to eq ['foo']
10
10
  end
11
11
 
12
+ describe '.model_name' do
13
+ subject { described_class.model_name.singular_route_key }
14
+ it { is_expected.to eq 'curation_concerns_generic_work' }
15
+ end
16
+
12
17
  context 'with attached files' do
13
18
  subject { FactoryGirl.create(:work_with_files) }
14
19
 
@@ -20,7 +25,7 @@ describe GenericWork do
20
25
 
21
26
  describe '#indexer' do
22
27
  subject { described_class.indexer }
23
- it { is_expected.to eq CurationConcerns::WorkIndexingService }
28
+ it { is_expected.to eq CurationConcerns::WorkIndexer }
24
29
  end
25
30
 
26
31
  describe 'to_solr' do
@@ -39,6 +44,6 @@ describe GenericWork do
39
44
  describe '#to_partial_path' do
40
45
  let(:work) { described_class.new }
41
46
  subject { work.to_partial_path }
42
- it { is_expected.to eq 'curation_concerns/generic_works/generic_work' }
47
+ it { is_expected.to eq 'generic_works/generic_work' }
43
48
  end
44
49
  end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe CurationConcerns::QuickClassificationQuery do
4
+ let(:user) { create(:user) }
5
+
6
+ context "with no options" do
7
+ let(:query) { described_class.new(user) }
8
+ describe "#all?" do
9
+ subject { query.all? }
10
+ it { is_expected.to be true }
11
+ end
12
+
13
+ describe '#each' do
14
+ let(:thing) { double }
15
+ before do
16
+ # Ensure that no other test has altered the configuration:
17
+ allow(CurationConcerns.config).to receive(:registered_curation_concern_types).and_return(['GenericWork'])
18
+ end
19
+ it "calls the block once for every model" do
20
+ expect(thing).to receive(:test).with(GenericWork)
21
+ query.each do |f|
22
+ thing.test(f)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ context "with models" do
29
+ let(:query) { described_class.new(user, models: ['dataset']) }
30
+ describe "#all?" do
31
+ subject { query.all? }
32
+ it { is_expected.to be false }
33
+ end
34
+ end
35
+ end