sufia 6.3.0 → 6.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.rubocop.yml +10 -0
- data/Gemfile +16 -7
- data/History.md +43 -0
- data/README.md +26 -19
- data/SUFIA_VERSION +1 -1
- data/app/assets/javascripts/notifications_check.js.erb +46 -0
- data/app/assets/javascripts/sufia.js +1 -2
- data/app/assets/javascripts/sufia/uploader.js +3 -3
- data/app/assets/stylesheets/sufia/_collections.scss +5 -0
- data/app/assets/stylesheets/sufia/_dashboard.scss +6 -1
- data/app/assets/stylesheets/sufia/_file-listing.scss +44 -6
- data/app/assets/stylesheets/sufia/_file-show.scss +4 -0
- data/app/assets/stylesheets/sufia/_settings.scss +3 -0
- data/app/controllers/api/items_controller.rb +7 -3
- data/app/controllers/concerns/sufia/admin/depositor_stats.rb +1 -1
- data/app/controllers/concerns/sufia/admin/stats_behavior.rb +6 -76
- data/app/controllers/concerns/sufia/batch_controller_behavior.rb +10 -2
- data/app/controllers/concerns/sufia/contact_form_controller_behavior.rb +1 -0
- data/app/controllers/concerns/sufia/files_controller_behavior.rb +11 -1
- data/app/controllers/concerns/sufia/homepage_controller.rb +1 -1
- data/app/controllers/concerns/sufia/my_controller_behavior.rb +2 -0
- data/app/controllers/concerns/sufia/users_controller_behavior.rb +2 -2
- data/app/helpers/generic_file_helper.rb +8 -5
- data/app/jobs/content_delete_event_job.rb +16 -11
- data/app/jobs/content_deposit_event_job.rb +4 -16
- data/app/jobs/content_depositor_change_event_job.rb +32 -20
- data/app/jobs/content_event_job.rb +39 -0
- data/app/jobs/content_new_version_event_job.rb +4 -16
- data/app/jobs/content_restored_version_event_job.rb +6 -19
- data/app/jobs/content_update_event_job.rb +4 -16
- data/app/jobs/event_job.rb +48 -4
- data/app/jobs/user_edit_profile_event_job.rb +4 -17
- data/app/jobs/user_follow_event_job.rb +10 -12
- data/app/jobs/user_unfollow_event_job.rb +10 -15
- data/app/models/concerns/sufia/solr_document_behavior.rb +11 -1
- data/app/models/system_stats.rb +108 -0
- data/app/presenters/sufia/admin_stats_presenter.rb +49 -0
- data/app/views/_controls.html.erb +1 -1
- data/app/views/_footer.html.erb +1 -1
- data/app/views/_logo.html.erb +1 -3
- data/app/views/admin/stats/_date_form.html.erb +8 -0
- data/app/views/admin/stats/_deposits.html.erb +2 -10
- data/app/views/admin/stats/_files.html.erb +6 -14
- data/app/views/admin/stats/_new_users.html.erb +7 -14
- data/app/views/admin/stats/_stats_by_date.html.erb +8 -0
- data/app/views/admin/stats/_top_data.html.erb +24 -0
- data/app/views/admin/stats/index.html.erb +5 -31
- data/app/views/collections/_form_for_select_collection.html.erb +5 -4
- data/app/views/collections/_show_actions.html.erb +7 -2
- data/app/views/collections/_show_document_list_row.html.erb +1 -9
- data/app/views/generic_files/_browse_everything.html.erb +3 -0
- data/app/views/generic_files/_descriptions.html.erb +1 -1
- data/app/views/generic_files/_generic_file.html.erb +1 -1
- data/app/views/generic_files/_local_file_import.html.erb +3 -0
- data/app/views/generic_files/_show_actions.html.erb +4 -0
- data/app/views/generic_files/upload/_form.html.erb +3 -0
- data/app/views/generic_files/upload/_to_collection.html.erb +5 -0
- data/app/views/homepage/_recent_document.html.erb +1 -7
- data/app/views/my/_index_partials/_default_group.html.erb +1 -1
- data/app/views/my/_index_partials/_list_collections.html.erb +3 -10
- data/app/views/my/_index_partials/_list_files.html.erb +13 -22
- data/app/views/my/_sort_and_per_page.html.erb +3 -3
- data/app/views/records/edit_fields/_rights.html.erb +2 -1
- data/app/views/static/terms.html.erb +1 -1
- data/config/locales/sufia.en.yml +13 -0
- data/lib/generators/sufia/templates/catalog_controller.rb +2 -2
- data/lib/sufia/version.rb +1 -1
- data/spec/actors/generic_file/actor_spec.rb +35 -0
- data/spec/controllers/admin_stats_controller_spec.rb +53 -23
- data/spec/controllers/api/items_controller_spec.rb +47 -41
- data/spec/controllers/batch_controller_spec.rb +1 -0
- data/spec/controllers/generic_files_controller_spec.rb +35 -1
- data/spec/controllers/my/files_controller_spec.rb +5 -0
- data/spec/factories/generic_files.rb +3 -0
- data/spec/features/collection_spec.rb +91 -0
- data/spec/features/contact_form_spec.rb +1 -0
- data/spec/forms/collection_edit_form_spec.rb +3 -3
- data/spec/forms/generic_file_edit_form_spec.rb +1 -1
- data/spec/jobs/create_derivatives_job_spec.rb +6 -0
- data/spec/models/file_content_datastream_spec.rb +1 -1
- data/spec/models/file_download_stat_spec.rb +4 -4
- data/spec/models/file_usage_spec.rb +2 -2
- data/spec/models/file_view_stat_spec.rb +4 -4
- data/spec/models/generic_file_spec.rb +15 -3
- data/spec/models/geo_names_resource_spec.rb +10 -0
- data/spec/models/solr_document_spec.rb +28 -0
- data/spec/models/system_stats_spec.rb +184 -0
- data/spec/models/user_spec.rb +1 -1
- data/spec/models/user_usage_stats_spec.rb +1 -1
- data/spec/services/generic_file_csv_service_spec.rb +66 -0
- data/spec/services/generic_file_indexing_service_spec.rb +35 -0
- data/spec/services/lock_manager_spec.rb +12 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/views/admin/stats/index.html.erb_spec.rb +11 -10
- data/spec/views/catalog/sort_and_per_page.html.erb_spec.rb +1 -1
- data/spec/views/collections/_form_for_select_collection.html.erb_spec.rb +51 -0
- data/spec/views/generic_file/_browse_everything.html.erb_spec.rb +4 -0
- data/spec/views/generic_file/edit.html.erb_spec.rb +31 -24
- data/spec/views/generic_file/new.html.erb_spec.rb +70 -0
- data/spec/views/generic_file/show.html.erb_spec.rb +23 -0
- data/sufia.gemspec +3 -2
- data/tasks/sufia-dev.rake +2 -0
- metadata +42 -9
- data/lib/sufia/role_mapper.rb +0 -7
|
@@ -17,6 +17,7 @@ describe BatchController do
|
|
|
17
17
|
it "is successful" do
|
|
18
18
|
expect(Sufia.queue).to receive(:push).with(batch_update_message).once
|
|
19
19
|
post :update, id: batch.id, title: { '1' => 'foo' }, visibility: 'open', generic_file: { tag: [""] }
|
|
20
|
+
expect(assigns(:batch_update_job)).to eq(batch_update_message)
|
|
20
21
|
expect(response).to redirect_to routes.url_helpers.dashboard_files_path
|
|
21
22
|
expect(flash[:notice]).to include("Your files are being processed")
|
|
22
23
|
end
|
|
@@ -15,6 +15,14 @@ describe GenericFilesController do
|
|
|
15
15
|
let(:mock) { GenericFile.new(id: 'test123') }
|
|
16
16
|
let(:batch) { Batch.create }
|
|
17
17
|
let(:batch_id) { batch.id }
|
|
18
|
+
let(:collection) {
|
|
19
|
+
Collection.create(title: 'test collection') do |c|
|
|
20
|
+
c.apply_depositor_metadata(user.user_key)
|
|
21
|
+
end
|
|
22
|
+
}
|
|
23
|
+
let(:collection_id) { collection.id }
|
|
24
|
+
let(:collection_noedit) { Collection.create(title: 'test collection - NO EDIT') }
|
|
25
|
+
let(:collection_noedit_id) { collection_noedit.id }
|
|
18
26
|
let(:file) { fixture_file_upload('/world.png', 'image/png') }
|
|
19
27
|
|
|
20
28
|
before do
|
|
@@ -39,10 +47,22 @@ describe GenericFilesController do
|
|
|
39
47
|
end
|
|
40
48
|
end
|
|
41
49
|
|
|
50
|
+
context "when user tries to upload to a collection they can't edit" do
|
|
51
|
+
# This shouldn't happen via the UI which will only present to the user collections they can edit.
|
|
52
|
+
it "adds new file but does not put the file in the collection" do
|
|
53
|
+
xhr :post, :create, files: [file], Filename: "The world", batch_id: batch_id, permission: { "group" => { "public" => "read" } }, terms_of_service: "1", collection: collection_noedit_id
|
|
54
|
+
expect(response).to be_success
|
|
55
|
+
|
|
56
|
+
updated_collection = Collection.find(collection_id)
|
|
57
|
+
# This is confirming that the file was NOT added to the collection the user cannot edit
|
|
58
|
+
expect(updated_collection.member_ids).to eq []
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
42
62
|
context "when everything is perfect" do
|
|
43
63
|
render_views
|
|
44
64
|
it "spawns a content deposit event job" do
|
|
45
|
-
expect_any_instance_of(Sufia::GenericFile::Actor).to receive(:create_content).with(file, 'world.png', 'content', 'image/png').and_return(true)
|
|
65
|
+
expect_any_instance_of(Sufia::GenericFile::Actor).to receive(:create_content).with(file, 'world.png', 'content', 'image/png', nil).and_return(true)
|
|
46
66
|
xhr :post, :create, files: [file], 'Filename' => 'The world', batch_id: batch_id, permission: { group: { public: 'read' } }, terms_of_service: '1'
|
|
47
67
|
expect(response.body).to eq '[{"name":null,"size":null,"url":"/files/test123","thumbnail_url":"test123","delete_url":"deleteme","delete_type":"DELETE"}]'
|
|
48
68
|
expect(flash[:error]).to be_nil
|
|
@@ -82,6 +102,20 @@ describe GenericFilesController do
|
|
|
82
102
|
expect(saved_file.depositor).to eq 'jilluser@example.com'
|
|
83
103
|
expect(saved_file.to_solr['depositor_tesim']).to eq ['jilluser@example.com']
|
|
84
104
|
end
|
|
105
|
+
|
|
106
|
+
it "adds new file when collection is instructions id" do
|
|
107
|
+
xhr :post, :create, files: [file], Filename: "The world", batch_id: batch_id, permission: { "group" => { "public" => "read" } }, terms_of_service: "1", collection: '-1'
|
|
108
|
+
expect(response).to be_success
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "adds new file to collection" do
|
|
112
|
+
xhr :post, :create, files: [file], Filename: "The world", batch_id: batch_id, permission: { "group" => { "public" => "read" } }, terms_of_service: "1", collection: collection_id
|
|
113
|
+
expect(response).to be_success
|
|
114
|
+
|
|
115
|
+
updated_collection = Collection.find(collection_id)
|
|
116
|
+
# This is confirming that the file was added to the collection
|
|
117
|
+
expect(updated_collection.member_ids).to eq ['test123']
|
|
118
|
+
end
|
|
85
119
|
end
|
|
86
120
|
|
|
87
121
|
context "when the file has a virus" do
|
|
@@ -87,4 +87,9 @@ describe My::FilesController, type: :controller do
|
|
|
87
87
|
expect(assigns(:batches)).to include("ss-" + batch_id2)
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
|
+
|
|
91
|
+
it "sets add_files_to_collection when provided in params" do
|
|
92
|
+
get :index, add_files_to_collection: '12345'
|
|
93
|
+
expect(assigns(:add_files_to_collection)).to eql('12345')
|
|
94
|
+
end
|
|
90
95
|
end
|
|
@@ -25,6 +25,7 @@ FactoryGirl.define do
|
|
|
25
25
|
resource_type ["Dissertation"]
|
|
26
26
|
subject %w(lorem ipsum dolor sit amet)
|
|
27
27
|
title ["fake_document.pdf"]
|
|
28
|
+
mime_type 'application/pdf'
|
|
28
29
|
before(:create) do |gf|
|
|
29
30
|
gf.title = ["Fake PDF Title"]
|
|
30
31
|
end
|
|
@@ -36,6 +37,7 @@ FactoryGirl.define do
|
|
|
36
37
|
initialize_with { new(id: id) }
|
|
37
38
|
subject %w(consectetur adipisicing elit)
|
|
38
39
|
title ["Test Document MP3.mp3"]
|
|
40
|
+
mime_type 'audio/mpeg'
|
|
39
41
|
read_groups ["public"]
|
|
40
42
|
end
|
|
41
43
|
factory :public_wav do
|
|
@@ -46,6 +48,7 @@ FactoryGirl.define do
|
|
|
46
48
|
resource_type ["Audio", "Dataset"]
|
|
47
49
|
read_groups ["public"]
|
|
48
50
|
title ["Fake Wav File.wav"]
|
|
51
|
+
mime_type 'audio/wav'
|
|
49
52
|
subject %w(sed do eiusmod tempor incididunt ut labore)
|
|
50
53
|
end
|
|
51
54
|
end
|
|
@@ -25,6 +25,15 @@ describe 'collection', type: :feature do
|
|
|
25
25
|
let(:title2) { "Test Collection 2" }
|
|
26
26
|
let(:description2) { "Description for collection 2 we are testing." }
|
|
27
27
|
|
|
28
|
+
let(:collection1) do
|
|
29
|
+
Collection.create(title: title1, description: description1,
|
|
30
|
+
members: []) { |c| c.apply_depositor_metadata(user.user_key) }
|
|
31
|
+
end
|
|
32
|
+
let(:collection2) do
|
|
33
|
+
Collection.create(title: title2, description: description2,
|
|
34
|
+
members: []) { |c| c.apply_depositor_metadata(user.user_key) }
|
|
35
|
+
end
|
|
36
|
+
|
|
28
37
|
let(:user) { FactoryGirl.create(:user) }
|
|
29
38
|
|
|
30
39
|
let(:gfs) do
|
|
@@ -140,6 +149,88 @@ describe 'collection', type: :feature do
|
|
|
140
149
|
end
|
|
141
150
|
end
|
|
142
151
|
|
|
152
|
+
describe 'collection sorting' do
|
|
153
|
+
before do
|
|
154
|
+
collection1 # create the collections by referencing them
|
|
155
|
+
sleep(1) # make sure the timestamps aren't equal
|
|
156
|
+
collection2
|
|
157
|
+
sleep(1)
|
|
158
|
+
collection1.title += 'changed'
|
|
159
|
+
collection1.save
|
|
160
|
+
# collection 1 is now earlier when sorting by create date but later
|
|
161
|
+
# when sorting by modified date
|
|
162
|
+
|
|
163
|
+
sign_in user
|
|
164
|
+
visit '/dashboard/collections'
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "has creation date for collections" do
|
|
168
|
+
expect(page).to have_content(collection1.create_date.to_date.to_formatted_s(:standard))
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "allows changing sort order" do
|
|
172
|
+
find(:xpath, "//select[@id='sort']/option[contains(., 'date modified')][contains(@value, 'asc')]") \
|
|
173
|
+
.select_option
|
|
174
|
+
click_button('Refresh')
|
|
175
|
+
expect(page).to have_css("#document_#{collection1.id}")
|
|
176
|
+
expect(page).to have_css("#document_#{collection2.id}")
|
|
177
|
+
expect(page.body.index("id=\"document_#{collection1.id}")).to be > page.body.index("id=\"document_#{collection2.id}")
|
|
178
|
+
|
|
179
|
+
find(:xpath, "//select[@id='sort']/option[contains(., 'date modified')][contains(@value, 'desc')]") \
|
|
180
|
+
.select_option
|
|
181
|
+
click_button('Refresh')
|
|
182
|
+
expect(page).to have_css("#document_#{collection1.id}")
|
|
183
|
+
expect(page).to have_css("#document_#{collection2.id}")
|
|
184
|
+
expect(page.body.index("id=\"document_#{collection1.id}")).to be < page.body.index("id=\"document_#{collection2.id}")
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
describe 'add files to collection' do
|
|
189
|
+
let!(:gf1) { gfs[0] }
|
|
190
|
+
let!(:gf2) { gfs[1] }
|
|
191
|
+
|
|
192
|
+
before do
|
|
193
|
+
collection1 # create collections by referencing them
|
|
194
|
+
collection2
|
|
195
|
+
sign_in user
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "preselects the collection we are adding files to" do
|
|
199
|
+
visit "/collections/#{collection1.id}"
|
|
200
|
+
click_link 'Add files'
|
|
201
|
+
first('input#check_all').click
|
|
202
|
+
click_button "Add to Collection"
|
|
203
|
+
expect(page).to have_css("input#id_#{collection1.id}[checked='checked']")
|
|
204
|
+
expect(page).not_to have_css("input#id_#{collection2.id}[checked='checked']")
|
|
205
|
+
|
|
206
|
+
visit "/collections/#{collection2.id}"
|
|
207
|
+
click_link 'Add files'
|
|
208
|
+
first('input#check_all').click
|
|
209
|
+
click_button "Add to Collection"
|
|
210
|
+
expect(page).not_to have_css("input#id_#{collection1.id}[checked='checked']")
|
|
211
|
+
expect(page).to have_css("input#id_#{collection2.id}[checked='checked']")
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
describe 'upload files to collection' do
|
|
216
|
+
let(:upload_to_collection) { true }
|
|
217
|
+
let!(:gf1) { gfs[0] }
|
|
218
|
+
let!(:gf2) { gfs[1] }
|
|
219
|
+
|
|
220
|
+
before do
|
|
221
|
+
Sufia.config.upload_to_collection = upload_to_collection
|
|
222
|
+
collection1 # create collections by referencing them
|
|
223
|
+
collection2
|
|
224
|
+
sign_in user
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it "preselects the collection we are uploading files to" do
|
|
228
|
+
visit "/collections/#{collection1.id}"
|
|
229
|
+
click_link 'Upload files'
|
|
230
|
+
expect(page).to have_select('collection', selected: title1)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
143
234
|
describe 'edit collection' do
|
|
144
235
|
let!(:collection) do
|
|
145
236
|
Collection.create(title: 'collection title', description: 'collection description',
|
|
@@ -17,6 +17,7 @@ describe "Sending an email via the contact form", type: :feature do
|
|
|
17
17
|
select "Depositing content", from: "contact_form_category"
|
|
18
18
|
click_button "Send"
|
|
19
19
|
expect(page).to have_content "Thank you"
|
|
20
|
+
expect(page).not_to have_content "I am contacting you regarding ScholarSphere."
|
|
20
21
|
# this step allows the delivery to go back to normal
|
|
21
22
|
allow_any_instance_of(ContactForm).to receive(:deliver).and_call_original
|
|
22
23
|
end
|
|
@@ -11,10 +11,10 @@ describe Sufia::Forms::CollectionEditForm do
|
|
|
11
11
|
:identifier, :based_near, :related_url] }
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
describe "
|
|
14
|
+
describe "multiple?" do
|
|
15
15
|
context "with :title" do
|
|
16
|
-
subject { described_class.
|
|
17
|
-
it { is_expected.to be
|
|
16
|
+
subject { described_class.multiple?(:title) }
|
|
17
|
+
it { is_expected.to be false }
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -23,7 +23,7 @@ describe Sufia::Forms::GenericFileEditForm do
|
|
|
23
23
|
let(:params) { ActionController::Parameters.new(title: ['foo'], description: [''], "permissions_attributes" => { "2" => { "access" => "edit", "_destroy" => "true", "id" => "a987551e-b87f-427a-8721-3e5942273125" } }) }
|
|
24
24
|
subject { described_class.model_attributes(params) }
|
|
25
25
|
|
|
26
|
-
it "
|
|
26
|
+
it "only changes title" do
|
|
27
27
|
expect(subject['title']).to eq ["foo"]
|
|
28
28
|
expect(subject['description']).to be_empty
|
|
29
29
|
expect(subject['permissions_attributes']).to eq("2" => { "access" => "edit", "id" => "a987551e-b87f-427a-8721-3e5942273125", "_destroy" => "true" })
|
|
@@ -45,7 +45,7 @@ describe FileContentDatastream, type: :model do
|
|
|
45
45
|
@generic_file.apply_depositor_metadata('mjg36')
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
it "
|
|
48
|
+
it "only returns true when the datastream has actually changed" do
|
|
49
49
|
@generic_file.add_file(File.open(fixture_path + '/world.png', 'rb'), path: 'content', original_name: 'world.png')
|
|
50
50
|
expect(@generic_file.content).to be_changed
|
|
51
51
|
@generic_file.save!
|
|
@@ -46,7 +46,7 @@ RSpec.describe FileDownloadStat, type: :model do
|
|
|
46
46
|
describe "cache empty" do
|
|
47
47
|
let(:stats) do
|
|
48
48
|
expect(described_class).to receive(:ga_statistics).and_return(sample_download_statistics)
|
|
49
|
-
described_class.statistics(file_id, Date.today - 4.
|
|
49
|
+
described_class.statistics(file_id, Date.today - 4.days)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
it "includes cached ga data" do
|
|
@@ -59,17 +59,17 @@ RSpec.describe FileDownloadStat, type: :model do
|
|
|
59
59
|
# at this point all data should be cached
|
|
60
60
|
allow(described_class).to receive(:ga_statistics).with(Date.today, file_id).and_raise("We should not call Google Analytics All data should be cached!")
|
|
61
61
|
|
|
62
|
-
stats2 = described_class.statistics(file_id, Date.today - 4.
|
|
62
|
+
stats2 = described_class.statistics(file_id, Date.today - 4.days)
|
|
63
63
|
expect(described_class.to_flots stats2).to include(*download_output)
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
describe "cache loaded" do
|
|
68
|
-
let!(:file_download_stat) { described_class.create(date: (Date.today - 5.
|
|
68
|
+
let!(:file_download_stat) { described_class.create(date: (Date.today - 5.days).to_datetime, file_id: file_id, downloads: "25") }
|
|
69
69
|
|
|
70
70
|
let(:stats) do
|
|
71
71
|
expect(described_class).to receive(:ga_statistics).and_return(sample_download_statistics)
|
|
72
|
-
described_class.statistics(file_id, Date.today - 5.
|
|
72
|
+
described_class.statistics(file_id, Date.today - 5.days)
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
it "includes cached data" do
|
|
@@ -55,7 +55,7 @@ describe FileUsage, type: :model do
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
let(:usage) do
|
|
58
|
-
allow_any_instance_of(GenericFile).to receive(:create_date).and_return((Date.today - 4.
|
|
58
|
+
allow_any_instance_of(GenericFile).to receive(:create_date).and_return((Date.today - 4.days).to_s)
|
|
59
59
|
expect(FileDownloadStat).to receive(:ga_statistics).and_return(sample_download_statistics)
|
|
60
60
|
expect(FileViewStat).to receive(:ga_statistics).and_return(sample_pageview_statistics)
|
|
61
61
|
described_class.new(file.id)
|
|
@@ -123,7 +123,7 @@ describe FileUsage, type: :model do
|
|
|
123
123
|
|
|
124
124
|
describe "create date after earliest" do
|
|
125
125
|
let(:usage) do
|
|
126
|
-
allow_any_instance_of(GenericFile).to receive(:create_date).and_return((Date.today - 4.
|
|
126
|
+
allow_any_instance_of(GenericFile).to receive(:create_date).and_return((Date.today - 4.days).to_s)
|
|
127
127
|
expect(FileDownloadStat).to receive(:ga_statistics).and_return(sample_download_statistics)
|
|
128
128
|
expect(FileViewStat).to receive(:ga_statistics).and_return(sample_pageview_statistics)
|
|
129
129
|
Sufia.config.analytic_start_date = earliest
|
|
@@ -47,7 +47,7 @@ RSpec.describe FileViewStat, type: :model do
|
|
|
47
47
|
describe "cache empty" do
|
|
48
48
|
let(:stats) do
|
|
49
49
|
expect(described_class).to receive(:ga_statistics).and_return(sample_pageview_statistics)
|
|
50
|
-
described_class.statistics(file_id, Date.today - 4.
|
|
50
|
+
described_class.statistics(file_id, Date.today - 4.days, user_id)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
it "includes cached ga data" do
|
|
@@ -61,17 +61,17 @@ RSpec.describe FileViewStat, type: :model do
|
|
|
61
61
|
# at this point all data should be cached
|
|
62
62
|
allow(described_class).to receive(:ga_statistics).with(Date.today, file_id).and_raise("We should not call Google Analytics All data should be cached!")
|
|
63
63
|
|
|
64
|
-
stats2 = described_class.statistics(file_id, Date.today - 5.
|
|
64
|
+
stats2 = described_class.statistics(file_id, Date.today - 5.days)
|
|
65
65
|
expect(described_class.to_flots stats2).to include(*view_output)
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
describe "cache loaded" do
|
|
70
|
-
let!(:file_view_stat) { described_class.create(date: (Date.today - 5.
|
|
70
|
+
let!(:file_view_stat) { described_class.create(date: (Date.today - 5.days).to_datetime, file_id: file_id, views: "25") }
|
|
71
71
|
|
|
72
72
|
let(:stats) do
|
|
73
73
|
expect(described_class).to receive(:ga_statistics).and_return(sample_pageview_statistics)
|
|
74
|
-
described_class.statistics(file_id, Date.today - 5.
|
|
74
|
+
described_class.statistics(file_id, Date.today - 5.days)
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
it "includes cached data" do
|
|
@@ -491,7 +491,7 @@ describe GenericFile, type: :model do
|
|
|
491
491
|
expect(subject.edit_users).to eq ['jcoyne']
|
|
492
492
|
end
|
|
493
493
|
|
|
494
|
-
it "
|
|
494
|
+
it "only revokes eligible groups" do
|
|
495
495
|
subject.set_read_groups(['group-2', 'group-3'], ['group-6'])
|
|
496
496
|
# 'group-7' is not eligible to be revoked
|
|
497
497
|
expect(subject.read_groups).to match_array ['group-2', 'group-3', 'group-7']
|
|
@@ -643,7 +643,7 @@ describe GenericFile, type: :model do
|
|
|
643
643
|
end
|
|
644
644
|
|
|
645
645
|
context "with no end date" do
|
|
646
|
-
let(:start_date) { 1.
|
|
646
|
+
let(:start_date) { 1.day.ago }
|
|
647
647
|
let(:end_date) { nil }
|
|
648
648
|
before do
|
|
649
649
|
@file.save
|
|
@@ -652,7 +652,7 @@ describe GenericFile, type: :model do
|
|
|
652
652
|
end
|
|
653
653
|
|
|
654
654
|
context "with an end date" do
|
|
655
|
-
let(:start_date) { 1.
|
|
655
|
+
let(:start_date) { 1.day.ago }
|
|
656
656
|
let(:end_date) { DateTime.now }
|
|
657
657
|
before do
|
|
658
658
|
@file.save
|
|
@@ -661,6 +661,18 @@ describe GenericFile, type: :model do
|
|
|
661
661
|
end
|
|
662
662
|
end
|
|
663
663
|
|
|
664
|
+
describe '#where_digest_is' do
|
|
665
|
+
subject { described_class.where_digest_is digest_string }
|
|
666
|
+
let(:digest_string) { 'f794b23c0c6fe1083d0ca8b58261a078cd968967' }
|
|
667
|
+
before do
|
|
668
|
+
@file.add_file(File.open(fixture_path + '/world.png'), path: 'content', original_name: 'world.png')
|
|
669
|
+
@file.save
|
|
670
|
+
end
|
|
671
|
+
it 'returns a list of files' do
|
|
672
|
+
expect(subject).to eq [@file]
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
|
|
664
676
|
describe "where_access_is" do
|
|
665
677
|
subject { described_class.where_access_is access_level }
|
|
666
678
|
before do
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe GeoNamesResource, type: :model do
|
|
4
|
+
before do
|
|
5
|
+
state = {
|
|
6
|
+
"totalResultsCount" => 1, "geonames" => [{
|
|
7
|
+
"countryId" => "1327865", "adminCode1" => "11", "countryName" => "Myanmar [Burma]", "fclName" => "country, state, region,...", "countryCode" => "MM", "lng" => "98", "fcodeName" => "first-order administrative division", "toponymName" => "Shan State", "fcl" => "A", "name" => "Shan State", "fcode" => "ADM1", "geonameId" => 1_297_099, "lat" => "22", "adminName1" => "Shan", "population" => 5_815_384
|
|
8
|
+
}]
|
|
9
|
+
}
|
|
10
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
|
11
|
+
mock.get "/searchJSON?maxRows=10&q=State&username=", {}, state.to_json
|
|
12
|
+
end
|
|
13
|
+
end
|
|
4
14
|
it "finds locations" do
|
|
5
15
|
hits = described_class.find_location("State")
|
|
6
16
|
expect(hits).not_to be_nil
|
|
@@ -8,6 +8,34 @@ describe SolrDocument, type: :model do
|
|
|
8
8
|
it "is a date" do
|
|
9
9
|
expect(subject.date_uploaded).to eq '03/14/2013'
|
|
10
10
|
end
|
|
11
|
+
it "logs parse errors" do
|
|
12
|
+
expect(ActiveFedora::Base.logger).to receive(:info).with(/Unable to parse date.*/)
|
|
13
|
+
subject['date_uploaded_dtsi'] = 'Test'
|
|
14
|
+
subject.date_uploaded
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "create_date" do
|
|
19
|
+
before do
|
|
20
|
+
subject['system_create_dtsi'] = '2013-03-14T00:00:00Z'
|
|
21
|
+
end
|
|
22
|
+
it "is a date" do
|
|
23
|
+
expect(subject.create_date).to eq '03/14/2013'
|
|
24
|
+
end
|
|
25
|
+
it "logs parse errors" do
|
|
26
|
+
expect(ActiveFedora::Base.logger).to receive(:info).with(/Unable to parse date.*/)
|
|
27
|
+
subject['system_create_dtsi'] = 'Test'
|
|
28
|
+
subject.create_date
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "resource_type" do
|
|
33
|
+
before do
|
|
34
|
+
subject['resource_type_tesim'] = ['Image']
|
|
35
|
+
end
|
|
36
|
+
it "returns the resource type" do
|
|
37
|
+
expect(subject.resource_type).to eq ['Image']
|
|
38
|
+
end
|
|
11
39
|
end
|
|
12
40
|
|
|
13
41
|
describe '#to_param' do
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ::SystemStats, type: :model do
|
|
4
|
+
let(:user1) { FactoryGirl.find_or_create(:user) }
|
|
5
|
+
let(:morning_two_days_ago) { 2.days.ago.to_date.to_datetime.to_s }
|
|
6
|
+
let(:yesterday) { 1.day.ago.to_datetime.to_s }
|
|
7
|
+
let(:this_morning) { 0.days.ago.to_date.to_datetime.to_s }
|
|
8
|
+
|
|
9
|
+
let(:stats) { described_class.new(depositor_count, user_stats[:start_date], user_stats[:end_date]) }
|
|
10
|
+
|
|
11
|
+
describe "#top_depositors" do
|
|
12
|
+
let(:user_stats) { {} }
|
|
13
|
+
|
|
14
|
+
context "when requested count is withing bounds" do
|
|
15
|
+
let!(:user2) { FactoryGirl.find_or_create(:archivist) }
|
|
16
|
+
let(:depositor_count) { 15 }
|
|
17
|
+
|
|
18
|
+
# I am specifically creating objects in this test
|
|
19
|
+
# I am doing this for one test to make sure that the full loop works
|
|
20
|
+
before do
|
|
21
|
+
GenericFile.new(id: "abc123") do |gf|
|
|
22
|
+
gf.apply_depositor_metadata(user1)
|
|
23
|
+
gf.update_index
|
|
24
|
+
end
|
|
25
|
+
GenericFile.new(id: "def123") do |gf|
|
|
26
|
+
gf.apply_depositor_metadata(user2)
|
|
27
|
+
gf.update_index
|
|
28
|
+
end
|
|
29
|
+
GenericFile.new(id: "zzz123") do |gf|
|
|
30
|
+
gf.create_date = [2.days.ago]
|
|
31
|
+
gf.apply_depositor_metadata(user1)
|
|
32
|
+
gf.update_index
|
|
33
|
+
end
|
|
34
|
+
Collection.new(id: "ccc123") do |c|
|
|
35
|
+
c.apply_depositor_metadata(user1)
|
|
36
|
+
c.update_index
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "queries for the data" do
|
|
41
|
+
expect(stats.top_depositors).to include(display_name(user1) => 3, display_name(user2) => 1)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "when requested count is too small" do
|
|
46
|
+
let(:depositor_count) { 3 }
|
|
47
|
+
let(:actual_count) { 5 }
|
|
48
|
+
it "queries for 5 items" do
|
|
49
|
+
expect(stats).to receive(:open).with("http://127.0.0.1:8983/solr/test/terms?terms.fl=depositor_tesim&terms.sort=count&terms.limit=#{actual_count}&wt=json&omitHeader=true").and_return(StringIO.new('{"terms":{"depositor_tesim":["example.com",4,"user2",3,"archivist1",1]}}'))
|
|
50
|
+
stats.top_depositors
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "when requested count is too big" do
|
|
55
|
+
let(:depositor_count) { 99 }
|
|
56
|
+
let(:actual_count) { 20 }
|
|
57
|
+
it "queries for 20 items" do
|
|
58
|
+
expect(stats).to receive(:open).with("http://127.0.0.1:8983/solr/test/terms?terms.fl=depositor_tesim&terms.sort=count&terms.limit=#{actual_count}&wt=json&omitHeader=true").and_return(StringIO.new('{"terms":{"depositor_tesim":["example.com",4,"user2",3,"archivist1",1]}}'))
|
|
59
|
+
stats.top_depositors
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def display_name(user)
|
|
65
|
+
user.user_key.split('@')[0]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "#document_by_permission" do
|
|
69
|
+
let(:user_stats) { {} }
|
|
70
|
+
let(:depositor_count) { nil }
|
|
71
|
+
|
|
72
|
+
before do
|
|
73
|
+
FactoryGirl.build(:public_pdf, depositor: user1, id: "pdf1223").update_index
|
|
74
|
+
FactoryGirl.build(:public_wav, depositor: user1, id: "wav1223").update_index
|
|
75
|
+
FactoryGirl.build(:public_mp3, depositor: user1, id: "mp31223", create_date: [2.days.ago]).update_index
|
|
76
|
+
FactoryGirl.build(:registered_file, depositor: user1, id: "reg1223").update_index
|
|
77
|
+
FactoryGirl.build(:generic_file, depositor: user1, id: "private1223").update_index
|
|
78
|
+
Collection.new(id: "ccc123") do |c|
|
|
79
|
+
c.apply_depositor_metadata(user1)
|
|
80
|
+
c.update_index
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
it "get all documents by permissions" do
|
|
84
|
+
expect(stats.document_by_permission).to include(public: 3, private: 1, registered: 1, total: 5)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context "when passing a start date" do
|
|
88
|
+
let(:user_stats) { { start_date: yesterday } }
|
|
89
|
+
it "get documents after date by permissions" do
|
|
90
|
+
expect(stats.document_by_permission).to include(public: 2, private: 1, registered: 1, total: 4)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "when passing an end date" do
|
|
94
|
+
let(:user_stats) { { start_date: morning_two_days_ago, end_date: yesterday } }
|
|
95
|
+
it "get documents between dates by permissions" do
|
|
96
|
+
expect(stats.document_by_permission).to include(public: 1, private: 0, registered: 0, total: 1)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe "#top_formats" do
|
|
103
|
+
let(:user_stats) { {} }
|
|
104
|
+
let(:depositor_count) { nil }
|
|
105
|
+
|
|
106
|
+
before do
|
|
107
|
+
FactoryGirl.build(:public_pdf, depositor: user1, id: "pdf1111").update_index
|
|
108
|
+
FactoryGirl.build(:public_wav, depositor: user1, id: "wav1111").update_index
|
|
109
|
+
FactoryGirl.build(:public_mp3, depositor: user1, id: "mp31111", create_date: [2.days.ago]).update_index
|
|
110
|
+
FactoryGirl.build(:registered_file, depositor: user1, id: "word1111", mime_type: "application/vnd.ms-word.document").update_index
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
subject { stats.top_formats }
|
|
114
|
+
|
|
115
|
+
it { is_expected.to include("mpeg" => 1, "pdf" => 1, "wav" => 1, "vnd.ms-word.document" => 1) }
|
|
116
|
+
|
|
117
|
+
context "when more than 5 formats available" do
|
|
118
|
+
before do
|
|
119
|
+
FactoryGirl.build(:public_pdf, depositor: user1, id: "pdf2222").update_index
|
|
120
|
+
FactoryGirl.build(:public_wav, depositor: user1, id: "wav2222").update_index
|
|
121
|
+
FactoryGirl.build(:public_mp3, depositor: user1, id: "mp32222", create_date: [2.days.ago]).update_index
|
|
122
|
+
FactoryGirl.build(:registered_file, depositor: user1, id: "reg2222", mime_type: "application/vnd.ms-word.document").update_index
|
|
123
|
+
FactoryGirl.build(:generic_file, depositor: user1, id: "png1111", mime_type: "image/png").update_index
|
|
124
|
+
FactoryGirl.build(:generic_file, depositor: user1, id: "png2222", mime_type: "image/png").update_index
|
|
125
|
+
FactoryGirl.build(:generic_file, depositor: user1, id: "jpeg2222", mime_type: "image/jpeg").update_index
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it do
|
|
129
|
+
is_expected.to include("mpeg" => 2, "pdf" => 2, "wav" => 2, "vnd.ms-word.document" => 2, "png" => 2)
|
|
130
|
+
is_expected.not_to include("jpeg" => 1)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
describe "#recent_users" do
|
|
136
|
+
let!(:user2) { FactoryGirl.find_or_create(:archivist) }
|
|
137
|
+
|
|
138
|
+
let(:one_day_ago_date) { 1.day.ago.to_datetime }
|
|
139
|
+
let(:two_days_ago_date) { 2.days.ago.to_datetime.end_of_day }
|
|
140
|
+
let(:one_day_ago) { one_day_ago_date.strftime("%Y-%m-%d") }
|
|
141
|
+
let(:two_days_ago) { two_days_ago_date.strftime("%Y-%m-%d") }
|
|
142
|
+
let(:depositor_count) { nil }
|
|
143
|
+
|
|
144
|
+
subject { stats.recent_users }
|
|
145
|
+
|
|
146
|
+
context "without dates" do
|
|
147
|
+
let(:user_stats) { {} }
|
|
148
|
+
let(:mock_order) { double }
|
|
149
|
+
let(:mock_limit) { double }
|
|
150
|
+
it "defaults to latest 5 users" do
|
|
151
|
+
expect(mock_order).to receive(:limit).with(5).and_return(mock_limit)
|
|
152
|
+
expect(User).to receive(:order).with('created_at DESC').and_return(mock_order)
|
|
153
|
+
is_expected.to eq mock_limit
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context "with start date" do
|
|
158
|
+
let(:user_stats) { { start_date: one_day_ago } }
|
|
159
|
+
|
|
160
|
+
it "allows queries against user_stats without an end date " do
|
|
161
|
+
expect(User).to receive(:recent_users).with(one_day_ago_date, nil).and_return([user2])
|
|
162
|
+
is_expected.to eq([user2])
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
context "with start date and end date" do
|
|
166
|
+
let(:user_stats) { { start_date: two_days_ago, end_date: one_day_ago } }
|
|
167
|
+
it "queries" do
|
|
168
|
+
expect(User).to receive(:recent_users).with(two_days_ago_date, one_day_ago_date).and_return([user2])
|
|
169
|
+
is_expected.to eq([user2])
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
describe "#users_count" do
|
|
175
|
+
let(:user_stats) { {} }
|
|
176
|
+
let(:depositor_count) { nil }
|
|
177
|
+
let!(:user1) { FactoryGirl.find_or_create(:user) }
|
|
178
|
+
let!(:user2) { FactoryGirl.find_or_create(:archivist) }
|
|
179
|
+
|
|
180
|
+
subject { stats.users_count }
|
|
181
|
+
|
|
182
|
+
it { is_expected.to eq 2 }
|
|
183
|
+
end
|
|
184
|
+
end
|