sufia 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +5 -2
  5. data/History.md +6 -0
  6. data/README.md +40 -0
  7. data/Rakefile +4 -0
  8. data/app/assets/javascripts/sufia.js +3 -115
  9. data/app/assets/javascripts/sufia/batch_select_all.js +179 -0
  10. data/app/assets/javascripts/sufia/edit_metadata.js +86 -0
  11. data/app/assets/javascripts/sufia/multiForm.js +57 -0
  12. data/app/assets/javascripts/terms_of_service.js +7 -0
  13. data/app/assets/stylesheets/audio-js.css +3 -0
  14. data/app/assets/stylesheets/dashboard.css.scss +51 -0
  15. data/app/assets/stylesheets/generic_files.css +36 -0
  16. data/app/assets/stylesheets/sufia.css.scss +2 -0
  17. data/app/controllers/batch_controller.rb +11 -0
  18. data/app/controllers/batch_edits_controller.rb +1 -77
  19. data/app/controllers/generic_files_controller.rb +1 -0
  20. data/app/controllers/mailbox_controller.rb +1 -1
  21. data/app/controllers/single_use_link_controller.rb +11 -7
  22. data/app/helpers/generic_file_helper.rb +11 -3
  23. data/app/helpers/sufia_helper.rb +13 -10
  24. data/app/models/batch.rb +1 -1
  25. data/app/models/datastreams/fits_datastream.rb +2 -2
  26. data/app/models/datastreams/generic_file_rdf_datastream.rb +22 -18
  27. data/app/models/datastreams/properties_datastream.rb +2 -2
  28. data/app/views/_user_util_links.html.erb +2 -2
  29. data/app/views/batch/_metadata.html.erb +82 -0
  30. data/app/views/batch/_more_metadata.html.erb +6 -0
  31. data/app/views/batch/edit.html.erb +1 -8
  32. data/app/views/batch_edits/_check_all.html.erb +0 -157
  33. data/app/views/batch_edits/edit.html.erb +0 -29
  34. data/app/views/catalog/_index_partials/_list_files.html.erb +8 -10
  35. data/app/views/catalog/_recent_document.html.erb +9 -18
  36. data/app/views/catalog/_results_pagination.html.erb +1 -1
  37. data/app/views/contact_form/new.html.erb +1 -1
  38. data/app/views/dashboard/_index_partials/_default_group.html.erb +1 -1
  39. data/app/views/dashboard/_index_partials/_list_files.html.erb +12 -14
  40. data/app/views/dashboard/_index_partials/_thumbnail_display.html.erb +9 -19
  41. data/app/views/dashboard/_results_pagination.html.erb +1 -1
  42. data/app/views/dashboard/index.html.erb +6 -82
  43. data/app/views/error/single_use_error.html.erb +35 -0
  44. data/app/views/generic_files/_descriptions.html.erb +2 -2
  45. data/app/views/generic_files/_extra_fields_modal.html.erb +1 -1
  46. data/app/views/generic_files/_field_form.html.erb +2 -5
  47. data/app/views/generic_files/_media_display.html.erb +8 -6
  48. data/app/views/generic_files/_permission.html.erb +2 -2
  49. data/app/views/generic_files/_rights_modal.html.erb +1 -1
  50. data/app/views/generic_files/_show_actions.html.erb +1 -1
  51. data/app/views/generic_files/_show_details.html.erb +11 -6
  52. data/app/views/generic_files/edit.html.erb +0 -8
  53. data/app/views/generic_files/edit_fields/_type.html.erb +1 -1
  54. data/app/views/generic_files/show.html.erb +5 -8
  55. data/app/views/generic_files/show_fields/_based_near.html.erb +4 -1
  56. data/app/views/generic_files/show_fields/_contributor.html.erb +4 -1
  57. data/app/views/generic_files/show_fields/_creator.html.erb +4 -1
  58. data/app/views/generic_files/show_fields/_date_created.html.erb +4 -1
  59. data/app/views/generic_files/show_fields/_description.html.erb +4 -1
  60. data/app/views/generic_files/show_fields/_language.html.erb +1 -1
  61. data/app/views/generic_files/show_fields/_publisher.html.erb +4 -1
  62. data/app/views/generic_files/show_fields/_related_url.html.erb +3 -1
  63. data/app/views/generic_files/show_fields/_resource_type.html.erb +1 -1
  64. data/app/views/generic_files/show_fields/_subject.html.erb +4 -1
  65. data/app/views/generic_files/show_fields/_tag.html.erb +1 -1
  66. data/app/views/generic_files/show_fields/_title.html.erb +4 -1
  67. data/app/views/layouts/error.html.erb +0 -4
  68. data/app/views/layouts/hydra-head.html.erb +2 -6
  69. data/app/views/single_use_link/show.html.erb +1 -1
  70. data/app/views/users/index.html.erb +1 -1
  71. data/app/views/users/show.html.erb +1 -1
  72. data/config/locales/sufia.en.yml +1 -0
  73. data/config/routes.rb +11 -4
  74. data/lib/generators/sufia/sufia_generator.rb +2 -1
  75. data/lib/generators/sufia/templates/catalog_controller.rb +143 -117
  76. data/lib/generators/sufia/templates/config/resque_admin.rb +10 -0
  77. data/lib/generators/sufia/templates/config/sufia.rb +8 -0
  78. data/lib/sufia.rb +4 -14
  79. data/lib/sufia/batch_edits_controller_behavior.rb +89 -0
  80. data/lib/sufia/controller.rb +7 -5
  81. data/lib/sufia/downloads_controller_behavior.rb +14 -19
  82. data/lib/sufia/file_content/extract_metadata.rb +11 -4
  83. data/lib/sufia/files_controller_behavior.rb +63 -44
  84. data/lib/sufia/generic_file.rb +29 -11
  85. data/lib/sufia/generic_file/audit.rb +1 -1
  86. data/lib/sufia/generic_file/thumbnail.rb +51 -26
  87. data/lib/sufia/id_service.rb +28 -11
  88. data/lib/sufia/jobs/batch_update_job.rb +2 -2
  89. data/lib/sufia/jobs/characterize_job.rb +11 -3
  90. data/lib/sufia/jobs/ffmpeg_transcode_job.rb +61 -0
  91. data/lib/sufia/jobs/resolrize_job.rb +1 -1
  92. data/lib/sufia/jobs/transcode_audio_job.rb +40 -0
  93. data/lib/sufia/jobs/transcode_video_job.rb +9 -49
  94. data/lib/sufia/queue/resque.rb +2 -2
  95. data/lib/sufia/single_use_error.rb +4 -0
  96. data/lib/sufia/solr_document_behavior.rb +108 -1
  97. data/lib/sufia/version.rb +1 -1
  98. data/solr_conf/conf/schema.xml +332 -652
  99. data/solr_conf/conf/solrconfig.xml +60 -196
  100. data/spec/controllers/batch_controller_spec.rb +4 -5
  101. data/spec/controllers/catalog_controller_spec.rb +13 -13
  102. data/spec/controllers/dashboard_controller_spec.rb +2 -2
  103. data/spec/controllers/downloads_controller_spec.rb +74 -62
  104. data/spec/controllers/generic_files_controller_spec.rb +10 -8
  105. data/spec/controllers/single_use_link_controller_spec.rb +12 -4
  106. data/spec/fixtures/Example.ogg +0 -0
  107. data/spec/fixtures/piano_note.wav +0 -0
  108. data/spec/fixtures/sufia_generic_stub.descMeta.txt +1 -1
  109. data/spec/helpers/sufia_helper_spec.rb +12 -0
  110. data/spec/models/characterize_job_spec.rb +89 -0
  111. data/spec/models/checksum_audit_log_spec.rb +1 -0
  112. data/spec/models/event_jobs_spec.rb +9 -9
  113. data/spec/models/file_content_datastream_spec.rb +16 -10
  114. data/spec/models/fits_datastream_spec.rb +2 -8
  115. data/spec/models/generic_file_spec.rb +131 -60
  116. data/spec/models/solr_document_spec.rb +21 -0
  117. data/spec/models/transcode_audio_job_spec.rb +81 -0
  118. data/spec/models/transcode_video_job_spec.rb +2 -2
  119. data/spec/models/unzip_job_spec.rb +3 -3
  120. data/spec/spec_helper.rb +21 -0
  121. data/spec/support/Gemfile +7 -3
  122. data/sufia.gemspec +8 -11
  123. data/tasks/cucumber.rake +1 -2
  124. data/tasks/sufia-dev.rake +13 -2
  125. data/tasks/sufia.rake +1 -1
  126. metadata +77 -118
  127. data/app/views/batch_edits/_metadata.html.erb +0 -180
  128. data/lib/generators/sufia/templates/config/hydra_config.rb +0 -32
  129. data/lib/kaminari/helpers/tag.rb +0 -11
@@ -74,6 +74,8 @@ describe GenericFilesController do
74
74
  end
75
75
 
76
76
  it "should create and save a file asset from the given params" do
77
+ date_today = Date.today
78
+ Date.stub(:today).and_return(date_today)
77
79
  file = fixture_file_upload('/world.png','image/png')
78
80
  xhr :post, :create, :files=>[file], :Filename=>"The world", :batch_id => "sample:batch_id", :permission=>{"group"=>{"public"=>"read"} }, :terms_of_service => '1'
79
81
  response.should be_success
@@ -87,8 +89,8 @@ describe GenericFilesController do
87
89
  saved_file.content.dsChecksumValid.should be_true
88
90
 
89
91
  # Confirming that date_uploaded and date_modified were set
90
- saved_file.date_uploaded.should have_at_least(1).items
91
- saved_file.date_modified.should have_at_least(1).items
92
+ saved_file.date_uploaded.should == date_today
93
+ saved_file.date_modified.should == date_today
92
94
  end
93
95
 
94
96
  it "should record what user created the first version of content" do
@@ -124,12 +126,12 @@ describe GenericFilesController do
124
126
  #TODO make sure this is moved to scholarsphere:
125
127
  #saved_file.depositor.should == 'jilluser'
126
128
  saved_file.depositor.should == 'jilluser@example.com'
127
- saved_file.properties.to_solr.keys.should include('depositor_t')
129
+ saved_file.properties.to_solr.keys.should include('depositor_tesim')
128
130
  #TODO make sure this is moved to scholarsphere:
129
131
  #saved_file.properties.to_solr['depositor_t'].should == ['jilluser']
130
- saved_file.properties.to_solr['depositor_t'].should == ['jilluser@example.com']
131
- saved_file.to_solr.keys.should include('depositor_t')
132
- saved_file.to_solr['depositor_t'].should == ['jilluser@example.com']
132
+ saved_file.properties.to_solr['depositor_tesim'].should == ['jilluser@example.com']
133
+ saved_file.to_solr.keys.should include('depositor_tesim')
134
+ saved_file.to_solr['depositor_tesim'].should == ['jilluser@example.com']
133
135
  end
134
136
  it "Should call virus check" do
135
137
  controller.should_receive(:virus_check).and_return(0)
@@ -284,7 +286,7 @@ describe GenericFilesController do
284
286
  CharacterizeJob.should_receive(:new).with(@generic_file.pid).and_return(s2)
285
287
  Sufia.queue.should_receive(:push).with(s2).once
286
288
  file = fixture_file_upload('/image.jp2','image/jp2')
287
- post :update, :id=>@generic_file.pid, :filedata=>file, :Filename=>"The world", :generic_file=>{:tag=>[''] }
289
+ post :update, :id=>@generic_file.pid, :filedata=>file, :Filename=>"The world"
288
290
 
289
291
  edited_file = GenericFile.find(@generic_file.pid)
290
292
  version2 = edited_file.content.latest_version
@@ -302,7 +304,7 @@ describe GenericFilesController do
302
304
  s2 = stub('one')
303
305
  CharacterizeJob.should_receive(:new).with(@generic_file.pid).and_return(s2)
304
306
  Sufia.queue.should_receive(:push).with(s2).once
305
- post :update, :id=>@generic_file.pid, :revision=>'content.0', :generic_file=>{:tag=>['']}
307
+ post :update, :id=>@generic_file.pid, :revision=>'content.0'
306
308
 
307
309
  restored_file = GenericFile.find(@generic_file.pid)
308
310
  version3 = restored_file.content.latest_version
@@ -92,10 +92,14 @@ describe SingleUseLinkController do
92
92
  it "and_return 404 on second attempt" do
93
93
  get :download, id:@dhash
94
94
  response.should be_success
95
- lambda {get :download, id:@dhash}.should raise_error ActionController::RoutingError
95
+ get :download, id:@dhash
96
+ response.should render_template('error/single_use_error')
96
97
  end
97
98
  it "and_return 404 on attempt to get download with show" do
98
- lambda {get :download, id:@shash}.should raise_error ActionController::RoutingError
99
+ get :download, id:@dhash
100
+ response.should be_success
101
+ get :download, id:@dhash
102
+ response.should render_template('error/single_use_error')
99
103
  end
100
104
  end
101
105
 
@@ -108,10 +112,14 @@ describe SingleUseLinkController do
108
112
  it "and_return 404 on second attempt" do
109
113
  get :show, id:@shash
110
114
  response.should be_success
111
- lambda {get :show, id:@shash}.should raise_error ActionController::RoutingError
115
+ get :show, id:@shash
116
+ response.should render_template('error/single_use_error')
112
117
  end
113
118
  it "and_return 404 on attempt to get show with download" do
114
- lambda {get :show, id:@dhash}.should raise_error ActionController::RoutingError
119
+ get :show, id:@shash
120
+ response.should be_success
121
+ get :show, id:@shash
122
+ response.should render_template('error/single_use_error')
115
123
  end
116
124
  end
117
125
  end
Binary file
@@ -1,6 +1,6 @@
1
1
  <info:fedora/sufia:<%= @id %>> <http://purl.org/dc/terms/publisher> "<%= @user %>" .
2
2
  <info:fedora/sufia:<%= @id %>> <http://purl.org/dc/terms/description> "<%= @title %> Description" .
3
- <info:fedora/sufia:<%= @id %>> <http://purl.org/dc/terms/created> "<%= Time.now.strftime("%m/%d/%Y") %>" .
3
+ <info:fedora/sufia:<%= @id %>> <http://purl.org/dc/terms/created> "<%= Time.now.ctime %>" .
4
4
  <info:fedora/sufia:<%= @id %>> <http://purl.org/dc/terms/contributor> "<%= @user %>" .
5
5
  <info:fedora/sufia:<%= @id %>> <http://purl.org/dc/terms/title> "<%= @title %>" .
6
6
  <info:fedora/sufia:<%= @id %>> <http://purl.org/dc/terms/relation> "test" .
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe SufiaHelper do
4
+ describe "link_to_profile" do
5
+ it "should use User#to_params" do
6
+ u = User.new
7
+ u.stub(:user_key).and_return('justin@example.com')
8
+ User.should_receive(:find_by_user_key).with('justin@example.com').and_return(u)
9
+ helper.link_to_profile('justin@example.com').should == "<a href=\"/users/justin@example-dot-com\">justin@example.com</a>"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe CharacterizeJob do
4
+ before do
5
+ @generic_file = GenericFile.new
6
+ @generic_file.apply_depositor_metadata('jcoyne@example.com')
7
+ @generic_file.save!
8
+ end
9
+
10
+ after do
11
+ @generic_file.delete
12
+ end
13
+
14
+ subject { CharacterizeJob.new(@generic_file.id)}
15
+
16
+ describe "with a AVI (video) file" do
17
+ before do
18
+ @generic_file.add_file_datastream(File.new(fixture_path + '/countdown.avi'), :dsid=>'content', :mime_type=>'video/avi')
19
+ @generic_file.stub(:characterize_if_changed).and_yield
20
+ @generic_file.save!
21
+ end
22
+ it "should create a transcode job" do
23
+ job = stub("stub video job")
24
+ if $in_travis
25
+ @generic_file.stub(:video?).and_return(true)
26
+ GenericFile.should_receive(:find).with(@generic_file.id).and_return(@generic_file)
27
+ end
28
+ TranscodeVideoJob.should_receive(:new).with(@generic_file.id, 'content').and_return(job)
29
+ Sufia.queue.should_receive(:push).with(job)
30
+ subject.run
31
+ end
32
+ it "should create a thumbnail" do
33
+ GenericFile.any_instance.should_receive(:create_thumbnail)
34
+ subject.run
35
+ end
36
+ end
37
+
38
+ describe "with a WAV (audio) file" do
39
+ before do
40
+ @generic_file.add_file_datastream(File.new(fixture_path + '/piano_note.wav'), :dsid=>'content', :mime_type=>'audio/wav')
41
+ @generic_file.stub(:characterize_if_changed).and_yield
42
+ @generic_file.save!
43
+ end
44
+ it "should create a transcode job" do
45
+ job = stub("stub audio job")
46
+ if $in_travis
47
+ @generic_file.stub(:audio?).and_return(true)
48
+ GenericFile.should_receive(:find).with(@generic_file.id).and_return(@generic_file)
49
+ end
50
+ TranscodeAudioJob.should_receive(:new).with(@generic_file.id, 'content').and_return(job)
51
+ Sufia.queue.should_receive(:push).with(job)
52
+ subject.run
53
+ end
54
+ end
55
+
56
+ describe "with an mp3 (audio) file" do
57
+ before do
58
+ @generic_file.add_file_datastream(File.new(fixture_path + '/sufia/sufia_test5.mp3'), :dsid=>'content', :mime_type=>'audio/mp3')
59
+ @generic_file.stub(:characterize_if_changed).and_yield
60
+ @generic_file.save!
61
+ end
62
+ it "should create a transcode job. (we'd like ogg too)" do
63
+ # TODO just copy the 'content' datastream to the mp3 datastream if it's an mp3, and then transcode to ogg
64
+ job = stub("stub audio job")
65
+ if $in_travis
66
+ @generic_file.stub(:audio?).and_return(true)
67
+ GenericFile.should_receive(:find).with(@generic_file.id).and_return(@generic_file)
68
+ end
69
+ TranscodeAudioJob.should_receive(:new).with(@generic_file.id, 'content').and_return(job)
70
+ Sufia.queue.should_receive(:push).with(job)
71
+ subject.run
72
+ end
73
+ end
74
+
75
+ describe "with an jpeg2000 (image) file" do
76
+ before do
77
+ @generic_file.add_file_datastream(File.new(fixture_path + '/image.jp2'), :dsid=>'content', :mime_type=>'image/jp2')
78
+ @generic_file.stub(:characterize_if_changed).and_yield
79
+ @generic_file.save!
80
+ end
81
+
82
+ it "should create a thumbnail" do
83
+ GenericFile.any_instance.should_receive(:create_thumbnail)
84
+ subject.run
85
+ end
86
+ end
87
+ end
88
+
89
+
@@ -19,6 +19,7 @@ describe ChecksumAuditLog do
19
19
  @f = GenericFile.new
20
20
  @f.add_file_datastream(File.new(fixture_path + '/world.png'), :dsid=>'content')
21
21
  @f.apply_depositor_metadata('mjg36')
22
+ @f.stub(:characterize_if_changed).and_yield #don't run characterization
22
23
  @f.save!
23
24
  @version = @f.datastreams['content'].versions.first
24
25
  @old = ChecksumAuditLog.create(:pid=>@f.pid, :dsid=>@version.dsid, :version=>@version.versionID, :pass=>1, :created_at=>2.minutes.ago)
@@ -40,7 +40,7 @@ describe 'event jobs' do
40
40
  count_user = @user.events.length
41
41
  count_another = @another_user.events.length
42
42
  Time.should_receive(:now).at_least(:once).and_return(1)
43
- event = { action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has edited his or her profile', timestamp: '1' }
43
+ event = { action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has edited his or her profile', timestamp: '1' }
44
44
  UserEditProfileEventJob.new(@user.user_key).run
45
45
  @user.events.length.should == count_user + 1
46
46
  @user.events.first.should == event
@@ -54,7 +54,7 @@ describe 'event jobs' do
54
54
  @another_user.events.length.should == 0
55
55
  @third_user.events.length.should == 0
56
56
  Time.should_receive(:now).at_least(:once).and_return(1)
57
- event = { action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> is now following <a href="/users/archivist1@example.com">archivist1@example.com</a>', timestamp: '1' }
57
+ event = { action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> is now following <a href="/users/archivist1@example-dot-com">archivist1@example.com</a>', timestamp: '1' }
58
58
  UserFollowEventJob.new(@user.user_key, @another_user.user_key).run
59
59
  @user.events.length.should == 1
60
60
  @user.events.first.should == event
@@ -71,7 +71,7 @@ describe 'event jobs' do
71
71
  @another_user.events.length.should == 0
72
72
  @third_user.events.length.should == 0
73
73
  Time.should_receive(:now).at_least(:once).and_return(1)
74
- event = { action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has unfollowed <a href="/users/archivist1@example.com">archivist1@example.com</a>', timestamp: '1' }
74
+ event = { action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has unfollowed <a href="/users/archivist1@example-dot-com">archivist1@example.com</a>', timestamp: '1' }
75
75
  UserUnfollowEventJob.new(@user.user_key, @another_user.user_key).run
76
76
  @user.events.length.should == 1
77
77
  @user.events.first.should == event
@@ -90,7 +90,7 @@ describe 'event jobs' do
90
90
  @third_user.events.length.should == 0
91
91
  @gf.events.length.should == 0
92
92
  Time.should_receive(:now).at_least(:once).and_return(1)
93
- event = {action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has deposited <a href="/files/123">Hamlet</a>', timestamp: '1' }
93
+ event = {action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has deposited <a href="/files/123">Hamlet</a>', timestamp: '1' }
94
94
  ContentDepositEventJob.new('test:123', @user.user_key).run
95
95
  @user.profile_events.length.should == 1
96
96
  @user.profile_events.first.should == event
@@ -111,7 +111,7 @@ describe 'event jobs' do
111
111
  @third_user.events.length.should == 0
112
112
  @gf.events.length.should == 0
113
113
  Time.should_receive(:now).at_least(:once).and_return(1)
114
- event = {action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has updated <a href="/files/123">Hamlet</a>', timestamp: '1' }
114
+ event = {action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has updated <a href="/files/123">Hamlet</a>', timestamp: '1' }
115
115
  ContentUpdateEventJob.new('test:123', @user.user_key).run
116
116
  @user.profile_events.length.should == 1
117
117
  @user.profile_events.first.should == event
@@ -132,7 +132,7 @@ describe 'event jobs' do
132
132
  @third_user.events.length.should == 0
133
133
  @gf.events.length.should == 0
134
134
  Time.should_receive(:now).at_least(:once).and_return(1)
135
- event = {action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has added a new version of <a href="/files/123">Hamlet</a>', timestamp: '1' }
135
+ event = {action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has added a new version of <a href="/files/123">Hamlet</a>', timestamp: '1' }
136
136
  ContentNewVersionEventJob.new('test:123', @user.user_key).run
137
137
  @user.profile_events.length.should == 1
138
138
  @user.profile_events.first.should == event
@@ -153,7 +153,7 @@ describe 'event jobs' do
153
153
  @third_user.events.length.should == 0
154
154
  @gf.events.length.should == 0
155
155
  Time.should_receive(:now).at_least(:once).and_return(1)
156
- event = {action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has restored a version \'content.0\' of <a href="/files/123">Hamlet</a>', timestamp: '1' }
156
+ event = {action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has restored a version \'content.0\' of <a href="/files/123">Hamlet</a>', timestamp: '1' }
157
157
  ContentRestoredVersionEventJob.new('test:123', @user.user_key, 'content.0').run
158
158
  @user.profile_events.length.should == 1
159
159
  @user.profile_events.first.should == event
@@ -172,7 +172,7 @@ describe 'event jobs' do
172
172
  @another_user.events.length.should == 0
173
173
  @third_user.events.length.should == 0
174
174
  Time.should_receive(:now).at_least(:once).and_return(1)
175
- event = {action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has deleted file \'test:123\'', timestamp: '1' }
175
+ event = {action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has deleted file \'test:123\'', timestamp: '1' }
176
176
  ContentDeleteEventJob.new('test:123', @user.user_key).run
177
177
  @user.profile_events.length.should == 1
178
178
  @user.profile_events.first.should == event
@@ -191,7 +191,7 @@ describe 'event jobs' do
191
191
  @gf.events.length.should == 0
192
192
  @now = Time.now
193
193
  Time.should_receive(:now).at_least(:once).and_return(@now)
194
- event = {action: 'User <a href="/users/jilluser@example.com">jilluser@example.com</a> has updated <a href="/files/123">Hamlet</a>', timestamp: @now.to_i.to_s }
194
+ event = {action: 'User <a href="/users/jilluser@example-dot-com">jilluser@example.com</a> has updated <a href="/files/123">Hamlet</a>', timestamp: @now.to_i.to_s }
195
195
  ContentUpdateEventJob.new('test:123', @user.user_key).run
196
196
  @user.profile_events.length.should == 1
197
197
  @user.profile_events.first.should == event
@@ -16,19 +16,18 @@ require 'spec_helper'
16
16
 
17
17
  describe FileContentDatastream do
18
18
  before do
19
- @subject = FileContentDatastream.new(nil, 'content')
20
- @subject.stub(:pid=>'my_pid')
21
- @subject.stub(:dsVersionID=>'content.7')
19
+ Sufia.queue.stub(:push).with(an_instance_of CharacterizeJob) #don't run characterization
22
20
  end
23
21
  describe "version control" do
24
- before(:all) do
22
+ before do
25
23
  f = GenericFile.new
26
24
  f.add_file_datastream(File.new(fixture_path + '/world.png'), :dsid=>'content')
27
25
  f.apply_depositor_metadata('mjg36')
26
+ f.stub(:characterize_if_changed).and_yield #don't run characterization
28
27
  f.save
29
- @file = GenericFile.find(f.pid)
28
+ @file = f.reload
30
29
  end
31
- after(:all) do
30
+ after do
32
31
  @file.delete
33
32
  end
34
33
  it "should have a list of versions with one entry" do
@@ -47,8 +46,9 @@ describe FileContentDatastream do
47
46
  @file.content.get_version("foobar").should be_nil
48
47
  end
49
48
  describe "add a version" do
50
- before(:all) do
49
+ before do
51
50
  @file.add_file_datastream(File.new(fixture_path + '/world.png'), :dsid=>'content')
51
+ @file.stub(:characterize_if_changed).and_yield #don't run characterization
52
52
  @file.save
53
53
  end
54
54
  it "should return two versions" do
@@ -63,10 +63,15 @@ describe FileContentDatastream do
63
63
  end
64
64
  end
65
65
  describe "extract_metadata" do
66
+ before do
67
+ @subject = FileContentDatastream.new(nil, 'content')
68
+ @subject.stub(:pid=>'my_pid')
69
+ @subject.stub(:dsVersionID=>'content.7')
70
+ end
66
71
  it "should have the path" do
67
72
  @subject.send(:fits_path).should be_present
68
73
  end
69
- it "should return an xml document" do
74
+ it "should return an xml document", :unless => $in_travis do
70
75
  repo = mock("repo")
71
76
  repo.stub(:config=>{})
72
77
  f = File.new(fixture_path + '/world.png')
@@ -78,7 +83,7 @@ describe FileContentDatastream do
78
83
  doc = Nokogiri::XML.parse(xml)
79
84
  doc.root.xpath('//ns:imageWidth/text()', {'ns'=>'http://hul.harvard.edu/ois/xml/ns/fits/fits_output'}).inner_text.should == '50'
80
85
  end
81
- it "should return expected results when invoked via HTTP" do
86
+ it "should return expected results when invoked via HTTP", :unless => $in_travis do
82
87
  repo = mock("repo")
83
88
  repo.stub(:config=>{})
84
89
  f = ActionDispatch::Http::UploadedFile.new(:tempfile => File.new(fixture_path + '/world.png'),
@@ -96,6 +101,7 @@ describe FileContentDatastream do
96
101
  before do
97
102
  @generic_file = GenericFile.new
98
103
  @generic_file.apply_depositor_metadata('mjg36')
104
+ @generic_file.stub(:characterize_if_changed).and_yield #don't run characterization
99
105
  end
100
106
  after do
101
107
  @generic_file.delete
@@ -111,7 +117,7 @@ describe FileContentDatastream do
111
117
  @generic_file.thumbnail.changed?.should be_true
112
118
  @generic_file.content.changed?.should be_false
113
119
 
114
- retrieved_file = GenericFile.find(@generic_file.pid)
120
+ retrieved_file = @generic_file.reload
115
121
  retrieved_file.content.changed?.should be_false
116
122
  end
117
123
  end
@@ -14,17 +14,11 @@
14
14
 
15
15
  require 'spec_helper'
16
16
 
17
- describe FitsDatastream do
17
+ describe FitsDatastream, :unless => $in_travis do
18
18
  before(:all) do
19
- GenericFile.any_instance.stub(:terms_of_service).and_return('1')
20
19
  @file = GenericFile.new
21
20
  @file.add_file_datastream(File.new(fixture_path + '/world.png'), :dsid=>'content')
22
- @file.apply_depositor_metadata('mjg36')
23
- @file.save
24
- @file = GenericFile.find(@file.pid)
25
- end
26
- after(:all) do
27
- @file.delete
21
+ @file.characterize
28
22
  end
29
23
  it "should have a format label" do
30
24
  @file.format_label.should == ["Portable Network Graphics"]
@@ -16,14 +16,14 @@ require 'spec_helper'
16
16
 
17
17
  describe GenericFile do
18
18
  before do
19
- @file = GenericFile.new
20
- @file.apply_depositor_metadata('jcoyne')
19
+ subject.apply_depositor_metadata('jcoyne')
20
+ @file = subject #TODO remove this line someday (use subject instead)
21
21
  end
22
22
 
23
23
  describe "terms_for_editing" do
24
24
  it "should return a list" do
25
25
  @file.terms_for_editing.should == [ :contributor, :creator, :title, :description, :publisher,
26
- :date_created, :subject, :language, :rights, :identifier, :based_near, :tag, :related_url]
26
+ :date_created, :subject, :language, :rights, :resource_type, :identifier, :based_near, :tag, :related_url]
27
27
  end
28
28
  end
29
29
  describe "terms_for_display" do
@@ -34,6 +34,71 @@ describe GenericFile do
34
34
  end
35
35
  end
36
36
 
37
+ describe "mime type recognition" do
38
+ describe "image?" do
39
+ it "should be true for jpeg2000" do
40
+ subject.mime_type = 'image/jp2'
41
+ subject.should be_image
42
+ end
43
+ it "should be true for jpeg" do
44
+ subject.mime_type = 'image/jpg'
45
+ subject.should be_image
46
+ end
47
+ it "should be true for png" do
48
+ subject.mime_type = 'image/png'
49
+ subject.should be_image
50
+ end
51
+ end
52
+ describe "pdf?" do
53
+ it "should be true for pdf" do
54
+ subject.mime_type = 'application/pdf'
55
+ subject.should be_pdf
56
+ end
57
+ end
58
+ describe "audio?" do
59
+ it "should be true for wav" do
60
+ subject.mime_type = 'audio/x-wave'
61
+ subject.should be_audio
62
+ subject.mime_type = 'audio/x-wav'
63
+ subject.should be_audio
64
+ end
65
+ it "should be true for mpeg" do
66
+ subject.mime_type = 'audio/mpeg'
67
+ subject.should be_audio
68
+ subject.mime_type = 'audio/mp3'
69
+ subject.should be_audio
70
+ end
71
+ it "should be true for ogg" do
72
+ subject.mime_type = 'audio/ogg'
73
+ subject.should be_audio
74
+ end
75
+ end
76
+ describe "video?" do
77
+ it "should be true for avi" do
78
+ subject.mime_type = 'video/avi'
79
+ subject.should be_video
80
+ end
81
+ it "should be true for webm" do
82
+ subject.mime_type = 'video/webm'
83
+ subject.should be_video
84
+ end
85
+ it "should be true for mpeg" do
86
+ subject.mime_type = 'video/mp4'
87
+ subject.should be_video
88
+ subject.mime_type = 'video/mpeg'
89
+ subject.should be_video
90
+ end
91
+ it "should be true for quicktime" do
92
+ subject.mime_type = 'video/quicktime'
93
+ subject.should be_video
94
+ end
95
+ it "should be true for mxf" do
96
+ subject.mime_type = 'application/mxf'
97
+ subject.should be_video
98
+ end
99
+ end
100
+ end
101
+
37
102
  describe "attributes" do
38
103
  it "should have rightsMetadata" do
39
104
  @file.rightsMetadata.should be_instance_of ParanoidRightsDatastream
@@ -158,7 +223,7 @@ describe GenericFile do
158
223
  end
159
224
  it "should have activity stream-related methods defined" do
160
225
  @file.save
161
- f = GenericFile.find(@file.pid)
226
+ f = @file.reload
162
227
  f.should respond_to(:stream)
163
228
  f.should respond_to(:events)
164
229
  f.should respond_to(:create_event)
@@ -169,7 +234,7 @@ describe GenericFile do
169
234
  @file.creator = "John Doe"
170
235
  @file.title = "New work"
171
236
  @file.save
172
- f = GenericFile.find(@file.pid)
237
+ f = @file.reload
173
238
  f.related_url.should == ["http://example.org/"]
174
239
  f.creator.should == ["John Doe"]
175
240
  f.title.should == ["New work"]
@@ -178,13 +243,13 @@ describe GenericFile do
178
243
  @file.creator = "John Doe"
179
244
  @file.title = "New work"
180
245
  @file.save
181
- f = GenericFile.find(@file.pid)
246
+ f = @file.reload
182
247
  f.creator.should == ["John Doe"]
183
248
  f.title.should == ["New work"]
184
249
  f.creator = "Jane Doe"
185
250
  f.title << "Newer work"
186
251
  f.save
187
- f = GenericFile.find(@file.pid)
252
+ f = @file.reload
188
253
  f.creator.should == ["Jane Doe"]
189
254
  f.title.should == ["New work", "Newer work"]
190
255
  end
@@ -198,8 +263,8 @@ describe GenericFile do
198
263
  @file.description = "The work by Allah"
199
264
  @file.publisher = "Vertigo Comics"
200
265
  @file.date_created = "1200-01-01"
201
- @file.date_uploaded = "2011-01-01"
202
- @file.date_modified = "2012-01-01"
266
+ @file.date_uploaded = Date.parse("2011-01-01")
267
+ @file.date_modified = Date.parse("2012-01-01")
203
268
  @file.subject = "Theology"
204
269
  @file.language = "Arabic"
205
270
  @file.rights = "Wide open, buddy."
@@ -211,25 +276,27 @@ describe GenericFile do
211
276
  @file.format_label = "JPEG Image"
212
277
  local = @file.to_solr
213
278
  local.should_not be_nil
214
- local["desc_metadata__part_of_t"].should be_nil
215
- local["desc_metadata__date_uploaded_t"].should be_nil
216
- local["desc_metadata__date_modified_t"].should be_nil
217
- local["desc_metadata__rights_t"].should == ["Wide open, buddy."]
218
- local["desc_metadata__related_url_t"].should be_nil
219
- local["desc_metadata__contributor_t"].should == ["Mohammad"]
220
- local["desc_metadata__creator_t"].should == ["Allah"]
221
- local["desc_metadata__title_t"].should == ["The Work"]
222
- local["desc_metadata__description_t"].should == ["The work by Allah"]
223
- local["desc_metadata__publisher_t"].should == ["Vertigo Comics"]
224
- local["desc_metadata__subject_t"].should == ["Theology"]
225
- local["desc_metadata__language_t"].should == ["Arabic"]
226
- local["desc_metadata__date_created_t"].should == ["1200-01-01"]
227
- local["desc_metadata__resource_type_t"].should == ["Book"]
228
- local["file_format_t"].should == "jpeg (JPEG Image)"
229
- local["desc_metadata__identifier_t"].should == ["urn:isbn:1234567890"]
230
- local["desc_metadata__based_near_t"].should == ["Medina, Saudi Arabia"]
231
- local["mime_type_t"].should == ["image/jpeg"]
232
- local["noid_s"].should == "__DO_NOT_USE__"
279
+ local[Solrizer.solr_name("desc_metadata__part_of")].should be_nil
280
+ local[Solrizer.solr_name("desc_metadata__date_uploaded")].should be_nil
281
+ local[Solrizer.solr_name("desc_metadata__date_modified")].should be_nil
282
+ local[Solrizer.solr_name("desc_metadata__date_uploaded", :stored_sortable, type: :date)].should == ['2011-01-01T00:00:00Z']
283
+ local[Solrizer.solr_name("desc_metadata__date_modified", :stored_sortable, type: :date)].should == ['2012-01-01T00:00:00Z']
284
+ local[Solrizer.solr_name("desc_metadata__rights")].should == ["Wide open, buddy."]
285
+ local[Solrizer.solr_name("desc_metadata__related_url")].should be_nil
286
+ local[Solrizer.solr_name("desc_metadata__contributor")].should == ["Mohammad"]
287
+ local[Solrizer.solr_name("desc_metadata__creator")].should == ["Allah"]
288
+ local[Solrizer.solr_name("desc_metadata__title")].should == ["The Work"]
289
+ local[Solrizer.solr_name("desc_metadata__description")].should == ["The work by Allah"]
290
+ local[Solrizer.solr_name("desc_metadata__publisher")].should == ["Vertigo Comics"]
291
+ local[Solrizer.solr_name("desc_metadata__subject")].should == ["Theology"]
292
+ local[Solrizer.solr_name("desc_metadata__language")].should == ["Arabic"]
293
+ local[Solrizer.solr_name("desc_metadata__date_created")].should == ["1200-01-01"]
294
+ local[Solrizer.solr_name("desc_metadata__resource_type")].should == ["Book"]
295
+ local[Solrizer.solr_name("file_format")].should == "jpeg (JPEG Image)"
296
+ local[Solrizer.solr_name("desc_metadata__identifier")].should == ["urn:isbn:1234567890"]
297
+ local[Solrizer.solr_name("desc_metadata__based_near")].should == ["Medina, Saudi Arabia"]
298
+ local[Solrizer.solr_name("mime_type")].should == ["image/jpeg"]
299
+ local["noid_tsi"].should == "__DO_NOT_USE__"
233
300
  end
234
301
  it "should support multi-valued fields in solr" do
235
302
  @file.tag = ["tag1", "tag2"]
@@ -241,24 +308,41 @@ describe GenericFile do
241
308
  @file.relative_path.should == "documents/research/NSF/2010"
242
309
  end
243
310
  describe "create_thumbnail" do
311
+ before do
312
+ @f = GenericFile.new
313
+ #@f.stub(:characterize_if_changed).and_yield #don't run characterization
314
+ @f.apply_depositor_metadata('mjg36')
315
+ end
316
+ after do
317
+ @f.delete
318
+ end
319
+ describe "with a video", :if => Sufia::Engine.config.enable_ffmpeg do
320
+ before do
321
+ @f.stub(:mime_type=>'video/quicktime') #Would get set by the characterization job
322
+ @f.add_file_datastream(File.new("#{fixture_path}/countdown.avi", 'rb'), :dsid=>'content')
323
+ @f.save
324
+ end
325
+ it "should make a png thumbnail" do
326
+ @f.create_thumbnail
327
+ @f.thumbnail.content.size.should == 4768 # this is a bad test. I just want to show that it did something.
328
+ @f.thumbnail.mimeType.should == 'image/png'
329
+ end
330
+ end
331
+
244
332
  describe "with an image that doesn't get resized" do
245
333
  before do
246
- @f = GenericFile.new
247
334
  @f.stub(:mime_type=>'image/png', :width=>['50'], :height=>['50']) #Would get set by the characterization job
248
335
  @f.add_file_datastream(File.new("#{fixture_path}/world.png", 'rb'), :dsid=>'content')
249
- @f.apply_depositor_metadata('mjg36')
250
336
  @f.save
337
+ end
338
+ it "should keep the thumbnail at the original size (but transform to png)" do
251
339
  @mock_image = mock("image", :from_blob=>true)
340
+ @mock_image.should_not_receive(:scale)
341
+ @mock_image.should_receive(:to_blob).and_return('fake content')
252
342
  Magick::ImageList.should_receive(:new).and_return(@mock_image)
253
- end
254
- after do
255
- @f.delete
256
- end
257
- it "should scale the thumbnail to original size" do
258
- @mock_image.should_receive(:scale).with(50, 50).and_return(stub(:to_blob=>'fake content'))
259
343
  @f.create_thumbnail
260
- @f.content.changed?.should be_false
261
344
  @f.thumbnail.content.should == 'fake content'
345
+ @f.thumbnail.mimeType.should == 'image/png'
262
346
  end
263
347
  end
264
348
  end
@@ -266,12 +350,11 @@ describe GenericFile do
266
350
  before(:each) do
267
351
  u = FactoryGirl.create(:user)
268
352
  f = GenericFile.new
269
- f.stub(:characterize).and_return(true)
270
353
  f.add_file_datastream(File.new(fixture_path + '/world.png'), :dsid=>'content')
271
354
  f.apply_depositor_metadata(u.user_key)
355
+ f.stub(:characterize_if_changed).and_yield #don't run characterization
272
356
  f.save!
273
- @f = GenericFile.find(f.pid)
274
- @f.stub(:characterize).and_return(true)
357
+ @f = f.reload
275
358
  end
276
359
  it "should schedule a audit job for each datastream" do
277
360
  s1 = stub('one')
@@ -289,12 +372,6 @@ describe GenericFile do
289
372
  s5 = stub('five')
290
373
  AuditJob.should_receive(:new).with(@f.pid, 'content', "content.0").and_return(s5)
291
374
  Sufia.queue.should_receive(:push).with(s5)
292
- s6 = stub('six')
293
- AuditJob.should_receive(:new).with(@f.pid, 'characterization', "characterization.0").and_return(s6)
294
- Sufia.queue.should_receive(:push).with(s6)
295
- s7 = stub('seven')
296
- AuditJob.should_receive(:new).with(@f.pid, 'thumbnail', "thumbnail.0").and_return(s7)
297
- Sufia.queue.should_receive(:push).with(s7)
298
375
  @f.audit!
299
376
  end
300
377
  it "should log a failing audit" do
@@ -319,6 +396,7 @@ describe GenericFile do
319
396
  @f = GenericFile.new
320
397
  @f.add_file_datastream(File.new(fixture_path + '/world.png'), :dsid=>'content')
321
398
  @f.apply_depositor_metadata('mjg36')
399
+ @f.stub(:characterize_if_changed).and_yield #don't run characterization
322
400
  @f.save!
323
401
  @version = @f.datastreams['content'].versions.first
324
402
  @old = ChecksumAuditLog.create(:pid=>@f.pid, :dsid=>@version.dsid, :version=>@version.versionID, :pass=>1, :created_at=>2.minutes.ago)
@@ -455,7 +533,7 @@ describe GenericFile do
455
533
  end
456
534
  end
457
535
  describe "characterize" do
458
- it "should return expected results when called" do
536
+ it "should return expected results when called", :unless => $in_travis do
459
537
  @file.add_file_datastream(File.new(fixture_path + '/world.png'), :dsid=>'content')
460
538
  @file.characterize
461
539
  doc = Nokogiri::XML.parse(@file.characterization.content)
@@ -475,19 +553,12 @@ describe GenericFile do
475
553
  myfile = GenericFile.new
476
554
  myfile.add_file_datastream(File.new(fixture_path + '/sufia/sufia_test4.pdf'), :dsid=>'content')
477
555
  myfile.label = 'label123'
478
- myfile.thumbnail.size.nil?.should be_true
479
556
  myfile.apply_depositor_metadata('mjg36')
480
557
  myfile.save
481
- @myfile = GenericFile.find(myfile.pid)
558
+ @myfile = myfile.reload
482
559
  end
483
560
  after(:all) do
484
- unless @myfile.inner_object.kind_of? ActiveFedora::UnsavedDigitalObject
485
- begin
486
- @myfile.delete
487
- rescue ActiveFedora::ObjectNotFoundError
488
- # do nothing
489
- end
490
- end
561
+ @myfile.delete
491
562
  end
492
563
  it "should return expected results after a save" do
493
564
  @myfile.file_size.should == ['218882']
@@ -506,7 +577,7 @@ describe GenericFile do
506
577
  @myfile.filename[0].should == @myfile.label
507
578
  end
508
579
  it "should include thumbnail generation in characterization job" do
509
- @myfile.thumbnail.size.nil?.should be_false
580
+ @myfile.thumbnail.size.should_not be_nil
510
581
  end
511
582
  it "should append each term only once" do
512
583
  @myfile.append_metadata
@@ -537,19 +608,19 @@ describe GenericFile do
537
608
  it "should have read groups writer" do
538
609
  subject.read_groups = ['group-2', 'group-3']
539
610
  subject.rightsMetadata.groups.should == {'group-2' => 'read', 'group-3'=>'read', 'group-8' => 'edit'}
540
- subject.rightsMetadata.individuals.should == {"person1"=>"read","person2"=>"read"}
611
+ subject.rightsMetadata.individuals.should == {"person1"=>"read","person2"=>"read", 'jcoyne' => 'edit'}
541
612
  end
542
613
 
543
614
  it "should have read groups string writer" do
544
615
  subject.read_groups_string = 'umg/up.dlt.staff, group-3'
545
616
  subject.rightsMetadata.groups.should == {'umg/up.dlt.staff' => 'read', 'group-3'=>'read', 'group-8' => 'edit'}
546
- subject.rightsMetadata.individuals.should == {"person1"=>"read","person2"=>"read"}
617
+ subject.rightsMetadata.individuals.should == {"person1"=>"read","person2"=>"read", 'jcoyne' => 'edit'}
547
618
  end
548
619
  it "should only revoke eligible groups" do
549
620
  subject.set_read_groups(['group-2', 'group-3'], ['group-6'])
550
621
  # 'group-7' is not eligible to be revoked
551
622
  subject.rightsMetadata.groups.should == {'group-2' => 'read', 'group-3'=>'read', 'group-7' => 'read', 'group-8' => 'edit'}
552
- subject.rightsMetadata.individuals.should == {"person1"=>"read","person2"=>"read"}
623
+ subject.rightsMetadata.individuals.should == {"person1"=>"read","person2"=>"read", 'jcoyne' => 'edit'}
553
624
  end
554
625
  end
555
626
  describe "permissions validation" do