1 require 'integration_helper'
3 class CollectionsTest < ActionDispatch::IntegrationTest
8 # check_checkboxes_state asserts that the page holds at least one
9 # checkbox matching 'selector', and that all matching checkboxes
10 # are in state 'checkbox_status' (i.e. checked if true, unchecked otherwise)
11 def assert_checkboxes_state(selector, checkbox_status, msg=nil)
12 assert page.has_selector?(selector)
13 page.all(selector).each do |checkbox|
14 assert(checkbox.checked? == checkbox_status, msg)
18 test "Can copy a collection to a project" do
19 collection_uuid = api_fixture('collections')['foo_file']['uuid']
20 collection_name = api_fixture('collections')['foo_file']['name']
21 project_uuid = api_fixture('groups')['aproject']['uuid']
22 project_name = api_fixture('groups')['aproject']['name']
23 visit page_with_token('active', "/collections/#{collection_uuid}")
24 click_link 'Copy to project...'
25 find('.selectable', text: project_name).click
26 find('.modal-footer a,button', text: 'Copy').click
27 # Should navigate to the Data collections tab of the project after copying
28 assert_text project_name
29 assert_text "Copy of #{collection_name}"
32 test "Collection page renders name" do
33 Capybara.current_driver = :rack_test
34 uuid = api_fixture('collections')['foo_file']['uuid']
35 coll_name = api_fixture('collections')['foo_file']['name']
36 visit page_with_token('active', "/collections/#{uuid}")
37 assert(page.has_text?(coll_name), "Collection page did not include name")
38 # Now check that the page is otherwise normal, and the collection name
39 # isn't only showing up in an error message.
40 assert(page.has_link?('foo'), "Collection page did not include file link")
43 def check_sharing(want_state, link_regexp)
44 # We specifically want to click buttons. See #4291.
46 click_button "Unshare"
47 text_assertion = :assert_no_text
48 link_assertion = :assert_empty
50 click_button "Create sharing link"
51 text_assertion = :assert_text
52 link_assertion = :refute_empty
54 using_wait_time(Capybara.default_wait_time * 3) do
55 send(text_assertion, "Shared at:")
57 send(link_assertion, all("a").select { |a| a[:href] =~ link_regexp })
60 test "creating and uncreating a sharing link" do
61 coll_uuid = api_fixture("collections", "collection_owned_by_active", "uuid")
63 Regexp.new(Regexp.escape("/collections/download/#{coll_uuid}/"))
64 visit page_with_token("active_trustedclient", "/collections/#{coll_uuid}")
65 within "#sharing-button" do
66 check_sharing(:on, download_link_re)
67 check_sharing(:off, download_link_re)
71 test "can download an entire collection with a reader token" do
72 Capybara.current_driver = :rack_test
73 CollectionsController.any_instance.
74 stubs(:file_enumerator).returns(["foo\n", "file\n"])
75 uuid = api_fixture('collections')['foo_file']['uuid']
76 token = api_fixture('api_client_authorizations')['active_all_collections']['api_token']
77 url_head = "/collections/download/#{uuid}/#{token}/"
79 # It seems that Capybara can't inspect tags outside the body, so this is
80 # a very blunt approach.
81 assert_no_match(/<\s*meta[^>]+\bnofollow\b/i, page.html,
82 "wget prohibited from recursing the collection page")
83 # Look at all the links that wget would recurse through using our
84 # recommended options, and check that it's exactly the file list.
85 hrefs = page.all('a').map do |anchor|
86 link = anchor[:href] || ''
87 if link.start_with? url_head
88 link[url_head.size .. -1]
89 elsif link.start_with? '/'
95 assert_equal(['foo'], hrefs.compact.sort,
96 "download page did provide strictly file links")
97 within "#collection_files" do
99 assert_equal("foo\nfile\n", page.html)
103 test "can view empty collection" do
104 Capybara.current_driver = :rack_test
105 uuid = 'd41d8cd98f00b204e9800998ecf8427e+0'
106 visit page_with_token('active', "/collections/#{uuid}")
107 assert page.has_text?(/This collection is empty|The following collections have this content/)
110 test "combine selected collections into new collection" do
111 foo_collection = api_fixture('collections')['foo_file']
112 bar_collection = api_fixture('collections')['bar_file']
114 visit page_with_token('active', "/collections")
116 assert(page.has_text?(foo_collection['uuid']), "Collection page did not include foo file")
117 assert(page.has_text?(bar_collection['uuid']), "Collection page did not include bar file")
119 within('tr', text: foo_collection['uuid']) do
120 find('input[type=checkbox]').click
123 within('tr', text: bar_collection['uuid']) do
124 find('input[type=checkbox]').click
127 click_button 'Selection...'
128 within('.selection-action-container') do
129 click_link 'Create new collection with selected collections'
132 # now in the newly created collection page
133 assert(page.has_text?('Copy to project'), "Copy to project text not found in new collection page")
134 assert(page.has_no_text?(foo_collection['name']), "Collection page did not include foo file")
135 assert(page.has_text?('foo'), "Collection page did not include foo file")
136 assert(page.has_no_text?(bar_collection['name']), "Collection page did not include foo file")
137 assert(page.has_text?('bar'), "Collection page did not include bar file")
138 assert(page.has_text?('Created new collection in your Home project'),
139 'Not found flash message that new collection is created in Home project')
143 ['active', 'foo_file', false],
144 ['active', 'foo_collection_in_aproject', true],
145 ['project_viewer', 'foo_file', false],
146 ['project_viewer', 'foo_collection_in_aproject', false], #aproject not writable
147 ].each do |user, collection, expect_collection_in_aproject|
148 test "combine selected collection files into new collection #{user} #{collection} #{expect_collection_in_aproject}" do
149 my_collection = api_fixture('collections')[collection]
151 visit page_with_token(user, "/collections")
153 # choose file from foo collection
154 within('tr', text: my_collection['uuid']) do
158 # now in collection page
159 find('input[type=checkbox]').click
161 click_button 'Selection...'
162 within('.selection-action-container') do
163 click_link 'Create new collection with selected files'
166 # now in the newly created collection page
167 assert(page.has_text?('Copy to project'), "Copy to project text not found in new collection page")
168 assert(page.has_no_text?(my_collection['name']), "Collection page did not include foo file")
169 assert(page.has_text?('foo'), "Collection page did not include foo file")
170 if expect_collection_in_aproject
171 aproject = api_fixture('groups')['aproject']
172 assert page.has_text?("Created new collection in the project #{aproject['name']}"),
173 'Not found flash message that new collection is created in aproject'
175 assert page.has_text?("Created new collection in your Home project"),
176 'Not found flash message that new collection is created in Home project'
181 test "combine selected collection files from collection subdirectory" do
182 visit page_with_token('user1_with_load', "/collections/zzzzz-4zz18-filesinsubdir00")
184 # now in collection page
185 input_files = page.all('input[type=checkbox]')
186 (0..input_files.count-1).each do |i|
190 click_button 'Selection...'
191 within('.selection-action-container') do
192 click_link 'Create new collection with selected files'
195 # now in the newly created collection page
196 assert(page.has_text?('file_in_subdir1'), 'file not found - file_in_subdir1')
197 assert(page.has_text?('file1_in_subdir3.txt'), 'file not found - file1_in_subdir3.txt')
198 assert(page.has_text?('file2_in_subdir3.txt'), 'file not found - file2_in_subdir3.txt')
199 assert(page.has_text?('file1_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
200 assert(page.has_text?('file2_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
203 test "Collection portable data hash redirect" do
204 di = api_fixture('collections')['docker_image']
205 visit page_with_token('active', "/collections/#{di['portable_data_hash']}")
208 assert current_path.end_with?("/collections/#{di['uuid']}")
209 assert page.has_text?("docker_image")
210 assert page.has_text?("Activity")
211 assert page.has_text?("Sharing and permissions")
214 test "Collection portable data hash with multiple matches" do
215 pdh = api_fixture('collections')['baz_file']['portable_data_hash']
216 visit page_with_token('admin', "/collections/#{pdh}")
218 matches = api_fixture('collections').select {|k,v| v["portable_data_hash"] == pdh}
219 assert matches.size > 1
221 matches.each do |k,v|
222 assert page.has_link?(v["name"]), "Page /collections/#{pdh} should contain link '#{v['name']}'"
224 assert page.has_no_text?("Activity")
225 assert page.has_no_text?("Sharing and permissions")
228 test "Filtering collection files by regexp" do
229 col = api_fixture('collections', 'multilevel_collection_1')
230 visit page_with_token('active', "/collections/#{col['uuid']}")
232 # Filter file list to some but not all files in the collection
233 page.find_field('file_regex').set('file[12]')
234 assert page.has_text?("file1")
235 assert page.has_text?("file2")
236 assert page.has_no_text?("file3")
238 # Filter file list with a regex matching all files
239 page.find_field('file_regex').set('.*')
240 assert page.has_text?("file1")
241 assert page.has_text?("file2")
242 assert page.has_text?("file3")
244 # Filter file list to a regex matching no files
245 page.find_field('file_regex').set('file9')
246 assert page.has_no_text?("file1")
247 assert page.has_no_text?("file2")
248 assert page.has_no_text?("file3")
249 # make sure that we actually are looking at the collections
250 # page and not e.g. a fiddlesticks
251 assert page.has_text?("multilevel_collection_1")
252 assert page.has_text?(col["name"] || col["uuid"])
254 # Set filename filter to a syntactically invalid regex
255 # Page loads, but stops filtering after the last valid regex parse
256 page.find_field('file_regex').set('file[2')
257 assert page.has_text?("multilevel_collection_1")
258 assert page.has_text?(col["name"] || col["uuid"])
259 assert page.has_text?("file1")
260 assert page.has_text?("file2")
261 assert page.has_text?("file3")
263 # Test the "Select all" button
265 # Note: calling .set('') on a Selenium element is not sufficient
266 # to reset the field for this test, as it does not send any key
267 # events to the browser. To clear the field, we must instead send
268 # a backspace character.
269 # See https://selenium.googlecode.com/svn/trunk/docs/api/rb/Selenium/WebDriver/Element.html#clear-instance_method
270 page.find_field('file_regex').set("\b") # backspace
271 find('button#select-all').click
272 assert_checkboxes_state('input[type=checkbox]', true, '"select all" should check all checkboxes')
274 # Test the "Unselect all" button
275 page.find_field('file_regex').set("\b") # backspace
276 find('button#unselect-all').click
277 assert_checkboxes_state('input[type=checkbox]', false, '"unselect all" should clear all checkboxes')
279 # Filter files, then "select all", then unfilter
280 page.find_field('file_regex').set("\b") # backspace
281 find('button#unselect-all').click
282 page.find_field('file_regex').set('file[12]')
283 find('button#select-all').click
284 page.find_field('file_regex').set("\b") # backspace
286 # all "file1" and "file2" checkboxes must be selected
287 # all "file3" checkboxes must be clear
288 assert_checkboxes_state('[value*="file1"]', true, 'checkboxes for file1 should be selected after filtering')
289 assert_checkboxes_state('[value*="file2"]', true, 'checkboxes for file2 should be selected after filtering')
290 assert_checkboxes_state('[value*="file3"]', false, 'checkboxes for file3 should be clear after filtering')
292 # Select all files, then filter, then "unselect all", then unfilter
293 page.find_field('file_regex').set("\b") # backspace
294 find('button#select-all').click
295 page.find_field('file_regex').set('file[12]')
296 find('button#unselect-all').click
297 page.find_field('file_regex').set("\b") # backspace
299 # all "file1" and "file2" checkboxes must be clear
300 # all "file3" checkboxes must be selected
301 assert_checkboxes_state('[value*="file1"]', false, 'checkboxes for file1 should be clear after filtering')
302 assert_checkboxes_state('[value*="file2"]', false, 'checkboxes for file2 should be clear after filtering')
303 assert_checkboxes_state('[value*="file3"]', true, 'checkboxes for file3 should be selected after filtering')
306 test "Creating collection from list of filtered files" do
307 col = api_fixture('collections', 'collection_with_files_in_subdir')
308 visit page_with_token('user1_with_load', "/collections/#{col['uuid']}")
309 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not found'
310 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not found'
311 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not found'
312 assert page.has_text?('file1_in_subdir4'), 'expected file1_in_subdir4 not found'
313 assert page.has_text?('file2_in_subdir4'), 'expected file2_in_subdir4 not found'
315 # Select all files but then filter them to files in subdir1, subdir2 or subdir3
316 find('button#select-all').click
317 page.find_field('file_regex').set('_in_subdir[123]')
318 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not in filtered files'
319 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not in filtered files'
320 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not in filtered files'
321 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in filtered files'
322 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in filtered files'
324 # Create a new collection
325 click_button 'Selection...'
326 within('.selection-action-container') do
327 click_link 'Create new collection with selected files'
330 # now in the newly created collection page
331 # must have files in subdir1 and subdir3 but not subdir4
332 assert page.has_text?('file_in_subdir1'), 'file_in_subdir1 missing from new collection'
333 assert page.has_text?('file1_in_subdir3'), 'file1_in_subdir3 missing from new collection'
334 assert page.has_text?('file2_in_subdir3'), 'file2_in_subdir3 missing from new collection'
335 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in new collection'
336 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in new collection'
338 # Make sure we're not still on the old collection page.
339 refute_match(%r{/collections/#{col['uuid']}}, page.current_url)