1 require 'integration_helper'
2 require_relative 'integration_test_utils'
4 class CollectionsTest < ActionDispatch::IntegrationTest
9 test "Can copy a collection to a project" do
10 collection_uuid = api_fixture('collections')['foo_file']['uuid']
11 collection_name = api_fixture('collections')['foo_file']['name']
12 project_uuid = api_fixture('groups')['aproject']['uuid']
13 project_name = api_fixture('groups')['aproject']['name']
14 visit page_with_token('active', "/collections/#{collection_uuid}")
15 click_link 'Copy to project...'
16 find('.selectable', text: project_name).click
17 find('.modal-footer a,button', text: 'Copy').click
18 # Should navigate to the Data collections tab of the project after copying
19 assert_text project_name
20 assert_text "Copy of #{collection_name}"
23 def check_sharing(want_state, link_regexp)
24 # We specifically want to click buttons. See #4291.
26 click_button "Unshare"
27 text_assertion = :assert_no_text
28 link_assertion = :assert_empty
30 click_button "Create sharing link"
31 text_assertion = :assert_text
32 link_assertion = :refute_empty
34 using_wait_time(Capybara.default_max_wait_time * 3) do
35 send(text_assertion, "Shared at:")
37 send(link_assertion, all("a").select { |a| a[:href] =~ link_regexp })
40 test "creating and uncreating a sharing link" do
41 coll_uuid = api_fixture("collections", "collection_owned_by_active", "uuid")
43 Regexp.new(Regexp.escape("/collections/download/#{coll_uuid}/"))
44 visit page_with_token("active_trustedclient", "/collections/#{coll_uuid}")
45 within "#sharing-button" do
46 check_sharing(:on, download_link_re)
47 check_sharing(:off, download_link_re)
51 test "can download an entire collection with a reader token" do
52 Capybara.current_driver = :rack_test
53 CollectionsController.any_instance.
54 stubs(:file_enumerator).returns(["foo\n", "file\n"])
55 uuid = api_fixture('collections')['foo_file']['uuid']
56 token = api_fixture('api_client_authorizations')['active_all_collections']['api_token']
57 url_head = "/collections/download/#{uuid}/#{token}/"
59 # It seems that Capybara can't inspect tags outside the body, so this is
60 # a very blunt approach.
61 assert_no_match(/<\s*meta[^>]+\bnofollow\b/i, page.html,
62 "wget prohibited from recursing the collection page")
63 # Look at all the links that wget would recurse through using our
64 # recommended options, and check that it's exactly the file list.
65 hrefs = page.all('a').map do |anchor|
66 link = anchor[:href] || ''
67 if link.start_with? url_head
68 link[url_head.size .. -1]
69 elsif link.start_with? '/'
75 assert_equal(['foo'], hrefs.compact.sort,
76 "download page did provide strictly file links")
77 within "#collection_files" do
79 assert_equal("foo\nfile\n", page.html)
83 test "combine selected collections into new collection" do
84 foo_collection = api_fixture('collections')['foo_file']
85 bar_collection = api_fixture('collections')['bar_file']
87 visit page_with_token('active', "/collections")
89 assert(page.has_text?(foo_collection['uuid']), "Collection page did not include foo file")
90 assert(page.has_text?(bar_collection['uuid']), "Collection page did not include bar file")
92 within('tr', text: foo_collection['uuid']) do
93 find('input[type=checkbox]').click
96 within('tr', text: bar_collection['uuid']) do
97 find('input[type=checkbox]').click
100 click_button 'Selection...'
101 within('.selection-action-container') do
102 click_link 'Create new collection with selected collections'
105 # now in the newly created collection page
106 assert(page.has_text?('Copy to project'), "Copy to project text not found in new collection page")
107 assert(page.has_no_text?(foo_collection['name']), "Collection page did not include foo file")
108 assert(page.has_text?('foo'), "Collection page did not include foo file")
109 assert(page.has_no_text?(bar_collection['name']), "Collection page did not include foo file")
110 assert(page.has_text?('bar'), "Collection page did not include bar file")
111 assert(page.has_text?('Created new collection in your Home project'),
112 'Not found flash message that new collection is created in Home project')
116 ['active', 'foo_file', false],
117 ['active', 'foo_collection_in_aproject', true],
118 ['project_viewer', 'foo_file', false],
119 ['project_viewer', 'foo_collection_in_aproject', false], #aproject not writable
120 ].each do |user, collection, expect_collection_in_aproject|
121 test "combine selected collection files into new collection #{user} #{collection} #{expect_collection_in_aproject}" do
122 my_collection = api_fixture('collections')[collection]
124 visit page_with_token(user, "/collections")
126 # choose file from foo collection
127 within('tr', text: my_collection['uuid']) do
131 # now in collection page
132 find('input[type=checkbox]').click
134 click_button 'Selection...'
135 within('.selection-action-container') do
136 click_link 'Create new collection with selected files'
139 # now in the newly created collection page
140 assert(page.has_text?('Copy to project'), "Copy to project text not found in new collection page")
141 assert(page.has_no_text?(my_collection['name']), "Collection page did not include foo file")
142 assert(page.has_text?('foo'), "Collection page did not include foo file")
143 if expect_collection_in_aproject
144 aproject = api_fixture('groups')['aproject']
145 assert page.has_text?("Created new collection in the project #{aproject['name']}"),
146 'Not found flash message that new collection is created in aproject'
148 assert page.has_text?("Created new collection in your Home project"),
149 'Not found flash message that new collection is created in Home project'
154 test "combine selected collection files from collection subdirectory" do
155 visit page_with_token('user1_with_load', "/collections/zzzzz-4zz18-filesinsubdir00")
157 # now in collection page
158 input_files = page.all('input[type=checkbox]')
159 (0..input_files.count-1).each do |i|
163 click_button 'Selection...'
164 within('.selection-action-container') do
165 click_link 'Create new collection with selected files'
168 # now in the newly created collection page
169 assert(page.has_text?('file_in_subdir1'), 'file not found - file_in_subdir1')
170 assert(page.has_text?('file1_in_subdir3.txt'), 'file not found - file1_in_subdir3.txt')
171 assert(page.has_text?('file2_in_subdir3.txt'), 'file not found - file2_in_subdir3.txt')
172 assert(page.has_text?('file1_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
173 assert(page.has_text?('file2_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
176 test "Collection portable data hash with multiple matches with more than one page of results" do
177 pdh = api_fixture('collections')['baz_file']['portable_data_hash']
178 visit page_with_token('admin', "/collections/#{pdh}")
180 assert_selector 'a', text: 'Collection_1'
182 assert_text 'The following collections have this content:'
183 assert_text 'more results are not shown'
184 assert_no_text 'Activity'
185 assert_no_text 'Sharing and permissions'
188 test "Filtering collection files by regexp" do
189 col = api_fixture('collections', 'multilevel_collection_1')
190 visit page_with_token('active', "/collections/#{col['uuid']}")
192 # Filter file list to some but not all files in the collection
193 page.find_field('file_regex').set('file[12]')
194 assert page.has_text?("file1")
195 assert page.has_text?("file2")
196 assert page.has_no_text?("file3")
198 # Filter file list with a regex matching all files
199 page.find_field('file_regex').set('.*')
200 assert page.has_text?("file1")
201 assert page.has_text?("file2")
202 assert page.has_text?("file3")
204 # Filter file list to a regex matching no files
205 page.find_field('file_regex').set('file9')
206 assert page.has_no_text?("file1")
207 assert page.has_no_text?("file2")
208 assert page.has_no_text?("file3")
209 # make sure that we actually are looking at the collections
210 # page and not e.g. a fiddlesticks
211 assert page.has_text?("multilevel_collection_1")
212 assert page.has_text?(col["name"] || col["uuid"])
214 # Set filename filter to a syntactically invalid regex
215 # Page loads, but stops filtering after the last valid regex parse
216 page.find_field('file_regex').set('file[2')
217 assert page.has_text?("multilevel_collection_1")
218 assert page.has_text?(col["name"] || col["uuid"])
219 assert page.has_text?("file1")
220 assert page.has_text?("file2")
221 assert page.has_text?("file3")
223 # Test the "Select all" button
225 # Note: calling .set('') on a Selenium element is not sufficient
226 # to reset the field for this test, as it does not send any key
227 # events to the browser. To clear the field, we must instead send
228 # a backspace character.
229 # See https://selenium.googlecode.com/svn/trunk/docs/api/rb/Selenium/WebDriver/Element.html#clear-instance_method
230 page.find_field('file_regex').set("\b") # backspace
231 find('button#select-all').click
232 assert_checkboxes_state('input[type=checkbox]', true, '"select all" should check all checkboxes')
234 # Test the "Unselect all" button
235 page.find_field('file_regex').set("\b") # backspace
236 find('button#unselect-all').click
237 assert_checkboxes_state('input[type=checkbox]', false, '"unselect all" should clear all checkboxes')
239 # Filter files, then "select all", then unfilter
240 page.find_field('file_regex').set("\b") # backspace
241 find('button#unselect-all').click
242 page.find_field('file_regex').set('file[12]')
243 find('button#select-all').click
244 page.find_field('file_regex').set("\b") # backspace
246 # all "file1" and "file2" checkboxes must be selected
247 # all "file3" checkboxes must be clear
248 assert_checkboxes_state('[value*="file1"]', true, 'checkboxes for file1 should be selected after filtering')
249 assert_checkboxes_state('[value*="file2"]', true, 'checkboxes for file2 should be selected after filtering')
250 assert_checkboxes_state('[value*="file3"]', false, 'checkboxes for file3 should be clear after filtering')
252 # Select all files, then filter, then "unselect all", then unfilter
253 page.find_field('file_regex').set("\b") # backspace
254 find('button#select-all').click
255 page.find_field('file_regex').set('file[12]')
256 find('button#unselect-all').click
257 page.find_field('file_regex').set("\b") # backspace
259 # all "file1" and "file2" checkboxes must be clear
260 # all "file3" checkboxes must be selected
261 assert_checkboxes_state('[value*="file1"]', false, 'checkboxes for file1 should be clear after filtering')
262 assert_checkboxes_state('[value*="file2"]', false, 'checkboxes for file2 should be clear after filtering')
263 assert_checkboxes_state('[value*="file3"]', true, 'checkboxes for file3 should be selected after filtering')
266 test "Creating collection from list of filtered files" do
267 col = api_fixture('collections', 'collection_with_files_in_subdir')
268 visit page_with_token('user1_with_load', "/collections/#{col['uuid']}")
269 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not found'
270 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not found'
271 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not found'
272 assert page.has_text?('file1_in_subdir4'), 'expected file1_in_subdir4 not found'
273 assert page.has_text?('file2_in_subdir4'), 'expected file2_in_subdir4 not found'
275 # Select all files but then filter them to files in subdir1, subdir2 or subdir3
276 find('button#select-all').click
277 page.find_field('file_regex').set('_in_subdir[123]')
278 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not in filtered files'
279 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not in filtered files'
280 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not in filtered files'
281 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in filtered files'
282 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in filtered files'
284 # Create a new collection
285 click_button 'Selection...'
286 within('.selection-action-container') do
287 click_link 'Create new collection with selected files'
290 # now in the newly created collection page
291 # must have files in subdir1 and subdir3 but not subdir4
292 assert page.has_text?('file_in_subdir1'), 'file_in_subdir1 missing from new collection'
293 assert page.has_text?('file1_in_subdir3'), 'file1_in_subdir3 missing from new collection'
294 assert page.has_text?('file2_in_subdir3'), 'file2_in_subdir3 missing from new collection'
295 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in new collection'
296 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in new collection'
298 # Make sure we're not still on the old collection page.
299 refute_match(%r{/collections/#{col['uuid']}}, page.current_url)
302 test "remove a file from collection using checkbox and dropdown option" do
303 need_selenium 'to confirm unlock'
305 visit page_with_token('active', '/collections/zzzzz-4zz18-a21ux3541sxa8sf')
306 assert(page.has_text?('file1'), 'file not found - file1')
311 input_files = page.all('input[type=checkbox]')
314 click_button 'Selection...'
315 within('.selection-action-container') do
316 click_link 'Remove selected files'
319 assert(page.has_no_text?('file1'), 'file found - file')
320 assert(page.has_text?('file2'), 'file not found - file2')
323 test "remove a file in collection using trash icon" do
324 need_selenium 'to confirm unlock'
326 visit page_with_token('active', '/collections/zzzzz-4zz18-a21ux3541sxa8sf')
327 assert(page.has_text?('file1'), 'file not found - file1')
331 first('.fa-trash-o').click
334 assert(page.has_no_text?('file1'), 'file found - file')
335 assert(page.has_text?('file2'), 'file not found - file2')
338 test "rename a file in collection" do
339 need_selenium 'to confirm unlock'
341 visit page_with_token('active', '/collections/zzzzz-4zz18-a21ux3541sxa8sf')
345 within('.collection_files') do
346 first('.fa-pencil').click
347 find('.editable-input input').set('file1renamed')
348 find('.editable-submit').click
351 assert(page.has_text?('file1renamed'), 'file not found - file1renamed')
354 test "remove/rename file options not presented if user cannot update a collection" do
355 # visit a publicly accessible collection as 'spectator'
356 visit page_with_token('spectator', '/collections/zzzzz-4zz18-uukreo9rbgwsujr')
358 click_button 'Selection'
359 within('.selection-action-container') do
360 assert_selector 'li', text: 'Create new collection with selected files'
361 assert_no_selector 'li', text: 'Remove selected files'
364 within('.collection_files') do
365 assert(page.has_text?('GNU_General_Public_License'), 'file not found - GNU_General_Public_License')
366 assert_nil first('.fa-pencil')
367 assert_nil first('.fa-trash-o')
371 test "unlock collection to modify files" do
372 need_selenium 'to confirm remove'
374 collection = api_fixture('collections')['collection_owned_by_active']
376 # On load, collection is locked, and upload tab, rename and remove options are disabled
377 visit page_with_token('active', "/collections/#{collection['uuid']}")
379 assert_selector 'a[data-toggle="disabled"]', text: 'Upload'
381 within('.collection_files') do
382 file_ctrls = page.all('.btn-collection-file-control')
383 assert_equal 2, file_ctrls.size
384 assert_equal true, file_ctrls[0]['class'].include?('disabled')
385 assert_equal true, file_ctrls[1]['class'].include?('disabled')
386 find('input[type=checkbox]').click
389 click_button 'Selection'
390 within('.selection-action-container') do
391 assert_selector 'li.disabled', text: 'Remove selected files'
392 assert_selector 'li', text: 'Create new collection with selected files'
397 assert_no_selector 'a[data-toggle="disabled"]', text: 'Upload'
398 assert_selector 'a', text: 'Upload'
400 within('.collection_files') do
401 file_ctrls = page.all('.btn-collection-file-control')
402 assert_equal 2, file_ctrls.size
403 assert_equal false, file_ctrls[0]['class'].include?('disabled')
404 assert_equal false, file_ctrls[1]['class'].include?('disabled')
406 # previous checkbox selection won't result in firing a new event;
407 # undo and redo checkbox to fire the selection event again
408 find('input[type=checkbox]').click
409 find('input[type=checkbox]').click
412 click_button 'Selection'
413 within('.selection-action-container') do
414 assert_no_selector 'li.disabled', text: 'Remove selected files'
415 assert_selector 'li', text: 'Remove selected files'
419 def unlock_collection
420 first('.lock-collection-btn').click