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
28 # It should navigate to the project after copying...
29 assert(page.has_text?(project_name))
30 assert(page.has_text?("Copy of #{collection_name}"))
33 test "Collection page renders name" do
34 Capybara.current_driver = :rack_test
35 uuid = api_fixture('collections')['foo_file']['uuid']
36 coll_name = api_fixture('collections')['foo_file']['name']
37 visit page_with_token('active', "/collections/#{uuid}")
38 assert(page.has_text?(coll_name), "Collection page did not include name")
39 # Now check that the page is otherwise normal, and the collection name
40 # isn't only showing up in an error message.
41 assert(page.has_link?('foo'), "Collection page did not include file link")
44 def check_sharing(want_state, link_regexp)
45 # We specifically want to click buttons. See #4291.
47 click_button "Unshare"
48 text_assertion = :assert_no_text
49 link_assertion = :assert_empty
51 click_button "Create sharing link"
52 text_assertion = :assert_text
53 link_assertion = :refute_empty
55 using_wait_time(Capybara.default_wait_time * 3) do
56 send(text_assertion, "Shared at:")
58 send(link_assertion, all("a").select { |a| a[:href] =~ link_regexp })
61 test "creating and uncreating a sharing link" do
62 coll_uuid = api_fixture("collections", "collection_owned_by_active", "uuid")
64 Regexp.new(Regexp.escape("/collections/download/#{coll_uuid}/"))
65 visit page_with_token("active_trustedclient", "/collections/#{coll_uuid}")
66 within "#sharing-button" do
67 check_sharing(:on, download_link_re)
68 check_sharing(:off, download_link_re)
72 test "can download an entire collection with a reader token" do
73 Capybara.current_driver = :rack_test
74 CollectionsController.any_instance.
75 stubs(:file_enumerator).returns(["foo\n", "file\n"])
76 uuid = api_fixture('collections')['foo_file']['uuid']
77 token = api_fixture('api_client_authorizations')['active_all_collections']['api_token']
78 url_head = "/collections/download/#{uuid}/#{token}/"
80 # It seems that Capybara can't inspect tags outside the body, so this is
81 # a very blunt approach.
82 assert_no_match(/<\s*meta[^>]+\bnofollow\b/i, page.html,
83 "wget prohibited from recursing the collection page")
84 # Look at all the links that wget would recurse through using our
85 # recommended options, and check that it's exactly the file list.
86 hrefs = page.all('a').map do |anchor|
87 link = anchor[:href] || ''
88 if link.start_with? url_head
89 link[url_head.size .. -1]
90 elsif link.start_with? '/'
96 assert_equal(['foo'], hrefs.compact.sort,
97 "download page did provide strictly file links")
98 within "#collection_files" do
100 assert_equal("foo\nfile\n", page.html)
104 test "can view empty collection" do
105 Capybara.current_driver = :rack_test
106 uuid = 'd41d8cd98f00b204e9800998ecf8427e+0'
107 visit page_with_token('active', "/collections/#{uuid}")
108 assert page.has_text?(/This collection is empty|The following collections have this content/)
111 test "combine selected collections into new collection" do
112 foo_collection = api_fixture('collections')['foo_file']
113 bar_collection = api_fixture('collections')['bar_file']
115 visit page_with_token('active', "/collections")
117 assert(page.has_text?(foo_collection['uuid']), "Collection page did not include foo file")
118 assert(page.has_text?(bar_collection['uuid']), "Collection page did not include bar file")
120 within('tr', text: foo_collection['uuid']) do
121 find('input[type=checkbox]').click
124 within('tr', text: bar_collection['uuid']) do
125 find('input[type=checkbox]').click
128 click_button 'Selection...'
129 within('.selection-action-container') do
130 click_link 'Create new collection with selected collections'
133 # now in the newly created collection page
134 assert(page.has_text?('Copy to project'), "Copy to project text not found in new collection page")
135 assert(page.has_no_text?(foo_collection['name']), "Collection page did not include foo file")
136 assert(page.has_text?('foo'), "Collection page did not include foo file")
137 assert(page.has_no_text?(bar_collection['name']), "Collection page did not include foo file")
138 assert(page.has_text?('bar'), "Collection page did not include bar file")
139 assert(page.has_text?('Created new collection in your Home project'),
140 'Not found flash message that new collection is created in Home project')
144 ['active', 'foo_file', false],
145 ['active', 'foo_collection_in_aproject', true],
146 ['project_viewer', 'foo_file', false],
147 ['project_viewer', 'foo_collection_in_aproject', false], #aproject not writable
148 ].each do |user, collection, expect_collection_in_aproject|
149 test "combine selected collection files into new collection #{user} #{collection} #{expect_collection_in_aproject}" do
150 my_collection = api_fixture('collections')[collection]
152 visit page_with_token(user, "/collections")
154 # choose file from foo collection
155 within('tr', text: my_collection['uuid']) do
159 # now in collection page
160 find('input[type=checkbox]').click
162 click_button 'Selection...'
163 within('.selection-action-container') do
164 click_link 'Create new collection with selected files'
167 # now in the newly created collection page
168 assert(page.has_text?('Copy to project'), "Copy to project text not found in new collection page")
169 assert(page.has_no_text?(my_collection['name']), "Collection page did not include foo file")
170 assert(page.has_text?('foo'), "Collection page did not include foo file")
171 if expect_collection_in_aproject
172 aproject = api_fixture('groups')['aproject']
173 assert page.has_text?("Created new collection in the project #{aproject['name']}"),
174 'Not found flash message that new collection is created in aproject'
176 assert page.has_text?("Created new collection in your Home project"),
177 'Not found flash message that new collection is created in Home project'
182 test "combine selected collection files from collection subdirectory" do
183 visit page_with_token('user1_with_load', "/collections/zzzzz-4zz18-filesinsubdir00")
185 # now in collection page
186 input_files = page.all('input[type=checkbox]')
187 (0..input_files.count-1).each do |i|
191 click_button 'Selection...'
192 within('.selection-action-container') do
193 click_link 'Create new collection with selected files'
196 # now in the newly created collection page
197 assert(page.has_text?('file_in_subdir1'), 'file not found - file_in_subdir1')
198 assert(page.has_text?('file1_in_subdir3.txt'), 'file not found - file1_in_subdir3.txt')
199 assert(page.has_text?('file2_in_subdir3.txt'), 'file not found - file2_in_subdir3.txt')
200 assert(page.has_text?('file1_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
201 assert(page.has_text?('file2_in_subdir4.txt'), 'file not found - file1_in_subdir4.txt')
204 test "Collection portable data hash redirect" do
205 di = api_fixture('collections')['docker_image']
206 visit page_with_token('active', "/collections/#{di['portable_data_hash']}")
209 assert current_path.end_with?("/collections/#{di['uuid']}")
210 assert page.has_text?("docker_image")
211 assert page.has_text?("Activity")
212 assert page.has_text?("Sharing and permissions")
215 test "Collection portable data hash with multiple matches" do
216 pdh = api_fixture('collections')['baz_file']['portable_data_hash']
217 visit page_with_token('admin', "/collections/#{pdh}")
219 matches = api_fixture('collections').select {|k,v| v["portable_data_hash"] == pdh}
220 assert matches.size > 1
222 matches.each do |k,v|
223 assert page.has_link?(v["name"]), "Page /collections/#{pdh} should contain link '#{v['name']}'"
225 assert page.has_no_text?("Activity")
226 assert page.has_no_text?("Sharing and permissions")
229 test "Filtering collection files by regexp" do
230 col = api_fixture('collections', 'multilevel_collection_1')
231 visit page_with_token('active', "/collections/#{col['uuid']}")
233 # Filter file list to some but not all files in the collection
234 page.find_field('file_regex').set('file[12]')
235 assert page.has_text?("file1")
236 assert page.has_text?("file2")
237 assert page.has_no_text?("file3")
239 # Filter file list with a regex matching all files
240 page.find_field('file_regex').set('.*')
241 assert page.has_text?("file1")
242 assert page.has_text?("file2")
243 assert page.has_text?("file3")
245 # Filter file list to a regex matching no files
246 page.find_field('file_regex').set('file9')
247 assert page.has_no_text?("file1")
248 assert page.has_no_text?("file2")
249 assert page.has_no_text?("file3")
250 # make sure that we actually are looking at the collections
251 # page and not e.g. a fiddlesticks
252 assert page.has_text?("multilevel_collection_1")
253 assert page.has_text?(col['portable_data_hash'])
255 # Set filename filter to a syntactically invalid regex
256 # Page loads, but stops filtering after the last valid regex parse
257 page.find_field('file_regex').set('file[2')
258 assert page.has_text?("multilevel_collection_1")
259 assert page.has_text?(col['portable_data_hash'])
260 assert page.has_text?("file1")
261 assert page.has_text?("file2")
262 assert page.has_text?("file3")
264 # Test the "Select all" button
266 # Note: calling .set('') on a Selenium element is not sufficient
267 # to reset the field for this test, as it does not send any key
268 # events to the browser. To clear the field, we must instead send
269 # a backspace character.
270 # See https://selenium.googlecode.com/svn/trunk/docs/api/rb/Selenium/WebDriver/Element.html#clear-instance_method
271 page.find_field('file_regex').set("\b") # backspace
272 find('button#select-all').click
273 assert_checkboxes_state('input[type=checkbox]', true, '"select all" should check all checkboxes')
275 # Test the "Unselect all" button
276 page.find_field('file_regex').set("\b") # backspace
277 find('button#unselect-all').click
278 assert_checkboxes_state('input[type=checkbox]', false, '"unselect all" should clear all checkboxes')
280 # Filter files, then "select all", then unfilter
281 page.find_field('file_regex').set("\b") # backspace
282 find('button#unselect-all').click
283 page.find_field('file_regex').set('file[12]')
284 find('button#select-all').click
285 page.find_field('file_regex').set("\b") # backspace
287 # all "file1" and "file2" checkboxes must be selected
288 # all "file3" checkboxes must be clear
289 assert_checkboxes_state('[value*="file1"]', true, 'checkboxes for file1 should be selected after filtering')
290 assert_checkboxes_state('[value*="file2"]', true, 'checkboxes for file2 should be selected after filtering')
291 assert_checkboxes_state('[value*="file3"]', false, 'checkboxes for file3 should be clear after filtering')
293 # Select all files, then filter, then "unselect all", then unfilter
294 page.find_field('file_regex').set("\b") # backspace
295 find('button#select-all').click
296 page.find_field('file_regex').set('file[12]')
297 find('button#unselect-all').click
298 page.find_field('file_regex').set("\b") # backspace
300 # all "file1" and "file2" checkboxes must be clear
301 # all "file3" checkboxes must be selected
302 assert_checkboxes_state('[value*="file1"]', false, 'checkboxes for file1 should be clear after filtering')
303 assert_checkboxes_state('[value*="file2"]', false, 'checkboxes for file2 should be clear after filtering')
304 assert_checkboxes_state('[value*="file3"]', true, 'checkboxes for file3 should be selected after filtering')
307 test "Creating collection from list of filtered files" do
308 col = api_fixture('collections', 'collection_with_files_in_subdir')
309 visit page_with_token('user1_with_load', "/collections/#{col['uuid']}")
310 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not found'
311 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not found'
312 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not found'
313 assert page.has_text?('file1_in_subdir4'), 'expected file1_in_subdir4 not found'
314 assert page.has_text?('file2_in_subdir4'), 'expected file2_in_subdir4 not found'
316 # Select all files but then filter them to files in subdir1, subdir2 or subdir3
317 find('button#select-all').click
318 page.find_field('file_regex').set('_in_subdir[123]')
319 assert page.has_text?('file_in_subdir1'), 'expected file_in_subdir1 not in filtered files'
320 assert page.has_text?('file1_in_subdir3'), 'expected file1_in_subdir3 not in filtered files'
321 assert page.has_text?('file2_in_subdir3'), 'expected file2_in_subdir3 not in filtered files'
322 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in filtered files'
323 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in filtered files'
325 # Create a new collection
326 click_button 'Selection...'
327 within('.selection-action-container') do
328 click_link 'Create new collection with selected files'
331 # now in the newly created collection page
332 assert page.has_text?('Content hash:'), 'not on new collection page'
333 assert page.has_no_text?(col['uuid']), 'new collection page has old collection uuid'
334 assert page.has_no_text?(col['portable_data_hash']), 'new collection page has old portable_data_hash'
336 # must have files in subdir1 and subdir3 but not subdir4
337 assert page.has_text?('file_in_subdir1'), 'file_in_subdir1 missing from new collection'
338 assert page.has_text?('file1_in_subdir3'), 'file1_in_subdir3 missing from new collection'
339 assert page.has_text?('file2_in_subdir3'), 'file2_in_subdir3 missing from new collection'
340 assert page.has_no_text?('file1_in_subdir4'), 'file1_in_subdir4 found in new collection'
341 assert page.has_no_text?('file2_in_subdir4'), 'file2_in_subdir4 found in new collection'