1 require 'integration_helper'
2 require 'selenium-webdriver'
5 class CollectionsTest < ActionDispatch::IntegrationTest
7 Capybara.current_driver = :rack_test
10 # check_checkboxes_state asserts that the page holds at least one
11 # checkbox matching 'selector', and that all matching checkboxes
12 # are in state 'checkbox_status' (i.e. checked if true, unchecked otherwise)
13 def assert_checkboxes_state(selector, checkbox_status, msg=nil)
14 assert page.has_selector?(selector)
15 page.all(selector).each do |checkbox|
16 assert(checkbox.checked? == checkbox_status, msg)
20 test "Can copy a collection to a project" do
21 Capybara.current_driver = Capybara.javascript_driver
23 collection_uuid = api_fixture('collections')['foo_file']['uuid']
24 collection_name = api_fixture('collections')['foo_file']['name']
25 project_uuid = api_fixture('groups')['aproject']['uuid']
26 project_name = api_fixture('groups')['aproject']['name']
27 visit page_with_token('active', "/collections/#{collection_uuid}")
28 click_link 'Copy to project...'
29 find('.selectable', text: project_name).click
30 find('.modal-footer a,button', text: 'Copy').click
32 # It should navigate to the project after copying...
33 assert(page.has_text?(project_name))
34 assert(page.has_text?("Copy of #{collection_name}"))
37 test "Collection page renders name" do
38 uuid = api_fixture('collections')['foo_file']['uuid']
39 coll_name = api_fixture('collections')['foo_file']['name']
40 visit page_with_token('active', "/collections/#{uuid}")
41 assert(page.has_text?(coll_name), "Collection page did not include name")
42 # Now check that the page is otherwise normal, and the collection name
43 # isn't only showing up in an error message.
44 assert(page.has_link?('foo'), "Collection page did not include file link")
47 def check_sharing(want_state, link_regexp)
48 # We specifically want to click buttons. See #4291.
50 click_button "Unshare"
51 text_assertion = :assert_no_text
52 link_assertion = :assert_empty
54 click_button "Create sharing link"
55 text_assertion = :assert_text
56 link_assertion = :refute_empty
58 using_wait_time(Capybara.default_wait_time * 3) do
59 send(text_assertion, "Shared at:")
61 send(link_assertion, all("a").select { |a| a[:href] =~ link_regexp })
64 test "creating and uncreating a sharing link" do
65 Capybara.current_driver = Capybara.javascript_driver
66 coll_uuid = api_fixture("collections", "collection_owned_by_active", "uuid")
68 Regexp.new(Regexp.escape("/collections/download/#{coll_uuid}/"))
69 visit page_with_token("active_trustedclient", "/collections/#{coll_uuid}")
70 within "#sharing-button" do
71 check_sharing(:on, download_link_re)
72 check_sharing(:off, download_link_re)
76 test "can download an entire collection with a reader token" do
77 CollectionsController.any_instance.
78 stubs(:file_enumerator).returns(["foo\n", "file\n"])
79 uuid = api_fixture('collections')['foo_file']['uuid']
80 token = api_fixture('api_client_authorizations')['active_all_collections']['api_token']
81 url_head = "/collections/download/#{uuid}/#{token}/"
83 # It seems that Capybara can't inspect tags outside the body, so this is
84 # a very blunt approach.
85 assert_no_match(/<\s*meta[^>]+\bnofollow\b/i, page.html,
86 "wget prohibited from recursing the collection page")
87 # Look at all the links that wget would recurse through using our
88 # recommended options, and check that it's exactly the file list.
89 hrefs = page.all('a').map do |anchor|
90 link = anchor[:href] || ''
91 if link.start_with? url_head
92 link[url_head.size .. -1]
93 elsif link.start_with? '/'
99 assert_equal(['foo'], hrefs.compact.sort,
100 "download page did provide strictly file links")
101 within "#collection_files" do
103 assert_equal("foo\nfile\n", page.html)
107 test "can view empty collection" do
108 uuid = 'd41d8cd98f00b204e9800998ecf8427e+0'
109 visit page_with_token('active', "/collections/#{uuid}")
110 assert page.has_text?(/This collection is empty|The following collections have this content/)
113 test "combine selected collections into new collection" do
114 headless = Headless.new
116 Capybara.current_driver = :selenium
118 foo_collection = api_fixture('collections')['foo_file']
119 bar_collection = api_fixture('collections')['bar_file']
121 visit page_with_token('active', "/collections")
123 assert(page.has_text?(foo_collection['uuid']), "Collection page did not include foo file")
124 assert(page.has_text?(bar_collection['uuid']), "Collection page did not include bar file")
126 within('tr', text: foo_collection['uuid']) do
127 find('input[type=checkbox]').click
130 within('tr', text: bar_collection['uuid']) do
131 find('input[type=checkbox]').click
134 click_button 'Selection...'
135 within('.selection-action-container') do
136 click_link 'Create new collection with selected collections'
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?(foo_collection['name']), "Collection page did not include foo file")
142 assert(page.has_text?('foo'), "Collection page did not include foo file")
143 assert(page.has_no_text?(bar_collection['name']), "Collection page did not include foo file")
144 assert(page.has_text?('bar'), "Collection page did not include bar file")
145 assert(page.has_text?('Created new collection in your Home project'),
146 'Not found flash message that new collection is created in Home project')
151 ['active', 'foo_file', false],
152 ['active', 'foo_collection_in_aproject', true],
153 ['project_viewer', 'foo_file', false],
154 ['project_viewer', 'foo_collection_in_aproject', false], #aproject not writable
155 ].each do |user, collection, expect_collection_in_aproject|
156 test "combine selected collection files into new collection #{user} #{collection} #{expect_collection_in_aproject}" do
157 headless = Headless.new
159 Capybara.current_driver = :selenium
161 my_collection = api_fixture('collections')[collection]
163 visit page_with_token(user, "/collections")
165 # choose file from foo collection
166 within('tr', text: my_collection['uuid']) do
170 # now in collection page
171 find('input[type=checkbox]').click
173 click_button 'Selection...'
174 within('.selection-action-container') do
175 click_link 'Create new collection with selected files'
178 # now in the newly created collection page
179 assert(page.has_text?('Copy to project'), "Copy to project text not found in new collection page")
180 assert(page.has_no_text?(my_collection['name']), "Collection page did not include foo file")
181 assert(page.has_text?('foo'), "Collection page did not include foo file")
182 if expect_collection_in_aproject
183 aproject = api_fixture('groups')['aproject']
184 assert page.has_text?("Created new collection in the project #{aproject['name']}"),
185 'Not found flash message that new collection is created in aproject'
187 assert page.has_text?("Created new collection in your Home project"),
188 'Not found flash message that new collection is created in Home project'
195 test "combine selected collection files from collection subdirectory" do
196 headless = Headless.new
198 Capybara.current_driver = :selenium
200 visit page_with_token('user1_with_load', "/collections/zzzzz-4zz18-filesinsubdir00")
202 # now in collection page
203 input_files = page.all('input[type=checkbox]')
204 (0..input_files.count-1).each do |i|
208 click_button 'Selection...'
209 within('.selection-action-container') do
210 click_link 'Create new collection with selected files'
213 # now in the newly created collection page
214 assert(page.has_text?('file_in_subdir1'), 'file not found - file_in_subdir1')
215 assert(page.has_text?('file1_in_subdir3.txt'), 'file not found - file1_in_subdir3.txt')
216 assert(page.has_text?('file2_in_subdir3.txt'), 'file not found - file2_in_subdir3.txt')
217 assert(page.has_text?('file1_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
218 assert(page.has_text?('file2_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
223 test "Collection portable data hash redirect" do
224 di = api_fixture('collections')['docker_image']
225 visit page_with_token('active', "/collections/#{di['portable_data_hash']}")
228 assert current_path.end_with?("/collections/#{di['uuid']}")
229 assert page.has_text?("docker_image")
230 assert page.has_text?("Activity")
231 assert page.has_text?("Sharing and permissions")
234 test "Collection portable data hash with multiple matches" do
235 pdh = api_fixture('collections')['baz_file']['portable_data_hash']
236 visit page_with_token('admin', "/collections/#{pdh}")
238 matches = api_fixture('collections').select {|k,v| v["portable_data_hash"] == pdh}
239 assert matches.size > 1
241 matches.each do |k,v|
242 assert page.has_link?(v["name"]), "Page /collections/#{pdh} should contain link '#{v['name']}'"
244 assert page.has_no_text?("Activity")
245 assert page.has_no_text?("Sharing and permissions")
248 test "Filtering collection files by regexp" do
249 headless = Headless.new
251 Capybara.current_driver = :selenium
252 col = api_fixture('collections', 'multilevel_collection_1')
253 visit page_with_token('active', "/collections/#{col['uuid']}")
255 # Filter file list to some but not all files in the collection
256 page.find_field('file_regex').set('file[12]')
257 assert page.has_text?("file1")
258 assert page.has_text?("file2")
259 assert page.has_no_text?("file3")
261 # Filter file list with a regex matching all files
262 page.find_field('file_regex').set('.*')
263 assert page.has_text?("file1")
264 assert page.has_text?("file2")
265 assert page.has_text?("file3")
267 # Filter file list to a regex matching no files
268 page.find_field('file_regex').set('file9')
269 assert page.has_no_text?("file1")
270 assert page.has_no_text?("file2")
271 assert page.has_no_text?("file3")
272 # make sure that we actually are looking at the collections
273 # page and not e.g. a fiddlesticks
274 assert page.has_text?("multilevel_collection_1")
275 assert page.has_text?(col['portable_data_hash'])
277 # Set filename filter to a syntactically invalid regex
278 # Page loads, but stops filtering after the last valid regex parse
279 page.find_field('file_regex').set('file[2')
280 assert page.has_text?("multilevel_collection_1")
281 assert page.has_text?(col['portable_data_hash'])
282 assert page.has_text?("file1")
283 assert page.has_text?("file2")
284 assert page.has_text?("file3")
286 # Test the "Select all" button
288 # Note: calling .set('') on a Selenium element is not sufficient
289 # to reset the field for this test, as it does not send any key
290 # events to the browser. To clear the field, we must instead send
291 # a backspace character.
292 # See https://selenium.googlecode.com/svn/trunk/docs/api/rb/Selenium/WebDriver/Element.html#clear-instance_method
293 page.find_field('file_regex').set("\b") # backspace
294 find('button#select-all').click
295 assert_checkboxes_state('input[type=checkbox]', true, '"select all" should check all checkboxes')
297 # Test the "Unselect all" button
298 page.find_field('file_regex').set("\b") # backspace
299 find('button#unselect-all').click
300 assert_checkboxes_state('input[type=checkbox]', false, '"unselect all" should clear all checkboxes')
302 # Filter files, then "select all", then unfilter
303 page.find_field('file_regex').set("\b") # backspace
304 find('button#unselect-all').click
305 page.find_field('file_regex').set('file[12]')
306 find('button#select-all').click
307 page.find_field('file_regex').set("\b") # backspace
309 # all "file1" and "file2" checkboxes must be selected
310 # all "file3" checkboxes must be clear
311 assert_checkboxes_state('[value*="file1"]', true, 'checkboxes for file1 should be selected after filtering')
312 assert_checkboxes_state('[value*="file2"]', true, 'checkboxes for file2 should be selected after filtering')
313 assert_checkboxes_state('[value*="file3"]', false, 'checkboxes for file3 should be clear after filtering')
315 # Select all files, then filter, then "unselect all", then unfilter
316 page.find_field('file_regex').set("\b") # backspace
317 find('button#select-all').click
318 page.find_field('file_regex').set('file[12]')
319 find('button#unselect-all').click
320 page.find_field('file_regex').set("\b") # backspace
322 # all "file1" and "file2" checkboxes must be clear
323 # all "file3" checkboxes must be selected
324 assert_checkboxes_state('[value*="file1"]', false, 'checkboxes for file1 should be clear after filtering')
325 assert_checkboxes_state('[value*="file2"]', false, 'checkboxes for file2 should be clear after filtering')
326 assert_checkboxes_state('[value*="file3"]', true, 'checkboxes for file3 should be selected after filtering')
329 test "Creating collection from list of filtered files" do
330 headless = Headless.new
332 Capybara.current_driver = :selenium
334 col = api_fixture('collections', 'collection_with_files_in_subdir')
335 visit page_with_token('user1_with_load', "/collections/#{col['uuid']}")
336 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not found'
337 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not found'
338 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not found'
339 assert page.has_text?('file1_in_subdir4'), 'expected file1_in_subdir4 not found'
340 assert page.has_text?('file2_in_subdir4'), 'expected file2_in_subdir4 not found'
342 # Select all files but then filter them to files in subdir1, subdir2 or subdir3
343 find('button#select-all').click
344 page.find_field('file_regex').set('_in_subdir[123]')
345 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not in filtered files'
346 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not in filtered files'
347 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not in filtered files'
348 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in filtered files'
349 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in filtered files'
351 # Create a new collection
352 click_button 'Selection...'
353 within('.selection-action-container') do
354 click_link 'Create new collection with selected files'
357 # now in the newly created collection page
358 assert page.has_text?('Content hash:'), 'not on new collection page'
359 assert page.has_no_text?(col['uuid']), 'new collection page has old collection uuid'
360 assert page.has_no_text?(col['portable_data_hash']), 'new collection page has old portable_data_hash'
362 # must have files in subdir1 and subdir3 but not subdir4
363 assert page.has_text?('file_in_subdir1'), 'file_in_subdir1 missing from new collection'
364 assert page.has_text?('file1_in_subdir3'), 'file1_in_subdir3 missing from new collection'
365 assert page.has_text?('file2_in_subdir3'), 'file2_in_subdir3 missing from new collection'
366 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in new collection'
367 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in new collection'