1 require 'integration_helper'
2 require 'selenium-webdriver'
5 class ProjectsTest < ActionDispatch::IntegrationTest
7 headless = Headless.new
9 Capybara.current_driver = :selenium
11 # project tests need bigger page size to be able to see all the buttons
12 Capybara.current_session.driver.browser.manage.window.resize_to(1152, 768)
15 test 'Check collection count for A Project in the tab pane titles' do
16 project_uuid = api_fixture('groups')['aproject']['uuid']
17 visit page_with_token 'active', '/projects/' + project_uuid
19 collection_count = page.all("[data-pk*='collection']").count
20 assert_selector '#Data_collections-tab span', text: "(#{collection_count})"
23 test 'Find a project and edit its description' do
24 visit page_with_token 'active', '/'
25 find("#projects-menu").click
26 find(".dropdown-menu a", text: "A Project").click
27 within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
28 find('span', text: api_fixture('groups')['aproject']['name']).click
29 within('.arv-description-as-subtitle') do
30 find('.fa-pencil').click
31 find('.editable-input textarea').set('I just edited this.')
32 find('.editable-submit').click
37 assert(find?('.container-fluid', text: 'I just edited this.'),
38 "Description update did not survive page refresh")
41 test 'Find a project and edit description to textile description' do
42 visit page_with_token 'active', '/'
43 find("#projects-menu").click
44 find(".dropdown-menu a", text: "A Project").click
45 within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
46 find('span', text: api_fixture('groups')['aproject']['name']).click
47 within('.arv-description-as-subtitle') do
48 find('.fa-pencil').click
49 find('.editable-input textarea').set('<p>*Textile description for A project* - "take me home":/ </p><p>And a new paragraph in description.</p>')
50 find('.editable-submit').click
57 assert_no_text '*Textile description for A project*'
58 assert(find?('.container-fluid', text: 'Textile description for A project'),
59 "Description update did not survive page refresh")
60 assert(find?('.container-fluid', text: 'And a new paragraph in description'),
61 "Description did not contain the expected new paragraph")
62 assert(page.has_link?("take me home"), "link not found in description")
64 click_link 'take me home'
67 assert(page.has_text?('Active pipelines'), 'Active pipelines - not found on dashboard')
70 test 'Find a project and edit description to html description' do
71 visit page_with_token 'active', '/'
72 find("#projects-menu").click
73 find(".dropdown-menu a", text: "A Project").click
74 within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
75 find('span', text: api_fixture('groups')['aproject']['name']).click
76 within('.arv-description-as-subtitle') do
77 find('.fa-pencil').click
78 find('.editable-input textarea').set('<br>Textile description for A project</br> - <a href="/">take me home</a>')
79 find('.editable-submit').click
84 assert(find?('.container-fluid', text: 'Textile description for A project'),
85 "Description update did not survive page refresh")
86 assert(!find?('.container-fluid', text: '<br>Textile description for A project</br>'),
87 "Textile description is displayed with uninterpreted formatting characters")
88 assert(page.has_link?("take me home"),"link not found in description")
89 click_link 'take me home'
90 assert page.has_text?('Active pipelines')
93 test 'Find a project and edit description to textile description with link to object' do
94 visit page_with_token 'active', '/'
95 find("#projects-menu").click
96 find(".dropdown-menu a", text: "A Project").click
97 within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
98 find('span', text: api_fixture('groups')['aproject']['name']).click
99 within('.arv-description-as-subtitle') do
100 find('.fa-pencil').click
101 find('.editable-input textarea').set('*Textile description for A project* - "go to sub-project":' + api_fixture('groups')['asubproject']['uuid'] + "'")
102 find('.editable-submit').click
107 assert(find?('.container-fluid', text: 'Textile description for A project'),
108 "Description update did not survive page refresh")
109 assert(!find?('.container-fluid', text: '*Textile description for A project*'),
110 "Textile description is displayed with uninterpreted formatting characters")
111 assert(page.has_link?("go to sub-project"), "link not found in description")
112 click_link 'go to sub-project'
113 assert(page.has_text?(api_fixture('groups')['asubproject']['name']), 'sub-project name not found after clicking link')
116 test 'Add a new name, then edit it, without creating a duplicate' do
117 project_uuid = api_fixture('groups')['aproject']['uuid']
118 specimen_uuid = api_fixture('traits')['owned_by_aproject_with_no_name']['uuid']
119 visit page_with_token 'active', '/projects/' + project_uuid
120 click_link 'Other objects'
121 within '.selection-action-container' do
122 # Wait for the tab to load:
123 assert_selector 'tr[data-kind="arvados#trait"]'
124 within first('tr', text: 'Trait') do
125 find(".fa-pencil").click
126 find('.editable-input input').set('Now I have a name.')
127 find('.glyphicon-ok').click
128 assert_selector '.editable', text: 'Now I have a name.'
129 find(".fa-pencil").click
130 find('.editable-input input').set('Now I have a new name.')
131 find('.glyphicon-ok').click
134 assert_selector '.editable', text: 'Now I have a new name.'
137 click_link 'Other objects'
138 within '.selection-action-container' do
139 find '.editable', text: 'Now I have a new name.'
140 assert_no_selector '.editable', text: 'Now I have a name.'
144 test 'Create a project and move it into a different project' do
145 visit page_with_token 'active', '/projects'
146 find("#projects-menu").click
147 find(".dropdown-menu a", text: "Home").click
148 find('.btn', text: "Add a subproject").click
151 find('.fa-pencil').click
152 find('.editable-input input').set('Project 1234')
153 find('.glyphicon-ok').click
158 find("#projects-menu").click
159 find(".dropdown-menu a", text: "Home").click
160 find('.btn', text: "Add a subproject").click
162 find('.fa-pencil').click
163 find('.editable-input input').set('Project 5678')
164 find('.glyphicon-ok').click
168 click_link 'Move project...'
169 find('.selectable', text: 'Project 1234').click
170 find('.modal-footer a,button', text: 'Move').click
173 # Wait for the page to refresh and show the new parent in Sharing panel
175 assert(page.has_link?("Project 1234"),
176 "Project 5678 should now be inside project 1234")
179 def show_project_using(auth_key, proj_key='aproject')
180 project_uuid = api_fixture('groups')[proj_key]['uuid']
181 visit(page_with_token(auth_key, "/projects/#{project_uuid}"))
182 assert(page.has_text?("A Project"), "not on expected project page")
186 find('#project_sharing').all('tr')
189 def add_share_and_check(share_type, name, obj=nil)
190 assert(page.has_no_text?(name), "project is already shared with #{name}")
191 start_share_count = share_rows.size
192 click_on("Share with #{share_type}")
193 within(".modal-container") do
194 # Order is important here: we should find something that appears in the
195 # modal before we make any assertions about what's not in the modal.
196 # Otherwise, the not-included assertions might falsely pass because
197 # the modal hasn't loaded yet.
198 find(".selectable", text: name).click
199 assert(has_no_selector?(".modal-dialog-preview-pane"),
200 "preview pane available in sharing dialog")
201 if share_type == 'users' and obj and obj['email']
202 assert(page.has_text?(obj['email']), "Did not find user's email")
204 assert_raises(Capybara::ElementNotFound,
205 "Projects pulldown available from sharing dialog") do
206 click_on "All projects"
210 using_wait_time(Capybara.default_wait_time * 3) do
211 assert(page.has_link?(name),
212 "new share was not added to sharing table")
213 assert_equal(start_share_count + 1, share_rows.size,
214 "new share did not add row to sharing table")
218 def modify_share_and_check(name)
219 start_rows = share_rows
220 link_row = start_rows.select { |row| row.has_text?(name) }
221 assert_equal(1, link_row.size, "row with new permission not found")
222 within(link_row.first) do
224 select("Write", from: "share_change_level")
225 click_on("editable-submit")
226 assert(has_link?("Write"),
227 "failed to change access level on new share")
229 page.driver.browser.switch_to.alert.accept
232 using_wait_time(Capybara.default_wait_time * 3) do
233 assert(page.has_no_text?(name),
234 "new share row still exists after being revoked")
235 assert_equal(start_rows.size - 1, share_rows.size,
236 "revoking share did not remove row from sharing table")
240 test "project viewer can't see project sharing tab" do
241 show_project_using("project_viewer")
242 assert(page.has_no_link?("Sharing"),
243 "read-only project user sees sharing tab")
246 test "project owner can manage sharing for another user" do
247 add_user = api_fixture('users')['future_project_user']
248 new_name = ["first_name", "last_name"].map { |k| add_user[k] }.join(" ")
250 show_project_using("active")
252 add_share_and_check("users", new_name, add_user)
253 modify_share_and_check(new_name)
256 test "project owner can manage sharing for another group" do
257 new_name = api_fixture('groups')['future_project_viewing_group']['name']
259 show_project_using("active")
261 add_share_and_check("groups", new_name)
262 modify_share_and_check(new_name)
265 test "'share with group' listing does not offer projects" do
266 show_project_using("active")
268 click_on "Share with groups"
269 good_uuid = api_fixture("groups")["private"]["uuid"]
270 assert(page.has_selector?(".selectable[data-object-uuid=\"#{good_uuid}\"]"),
271 "'share with groups' listing missing owned user group")
272 bad_uuid = api_fixture("groups")["asubproject"]["uuid"]
273 assert(page.has_no_selector?(".selectable[data-object-uuid=\"#{bad_uuid}\"]"),
274 "'share with groups' listing includes project")
278 ['Move',api_fixture('collections')['collection_to_move_around_in_aproject'],
279 api_fixture('groups')['aproject'],api_fixture('groups')['asubproject']],
280 ['Remove',api_fixture('collections')['collection_to_move_around_in_aproject'],
281 api_fixture('groups')['aproject']],
282 ['Copy',api_fixture('collections')['collection_to_move_around_in_aproject'],
283 api_fixture('groups')['aproject'],api_fixture('groups')['asubproject']],
284 ['Remove',api_fixture('collections')['collection_in_aproject_with_same_name_as_in_home_project'],
285 api_fixture('groups')['aproject'],nil,true],
286 ].each do |action, my_collection, src, dest=nil, expect_name_change=nil|
287 test "selection #{action} -> #{expect_name_change.inspect} for project" do
288 perform_selection_action src, dest, my_collection, action
292 assert page.has_text?(my_collection['name']), 'Collection not found in src project after copy'
293 visit page_with_token 'active', '/'
294 find("#projects-menu").click
295 find(".dropdown-menu a", text: dest['name']).click
296 assert page.has_text?(my_collection['name']), 'Collection not found in dest project after copy'
299 assert page.has_no_text?(my_collection['name']), 'Collection still found in src project after move'
300 visit page_with_token 'active', '/'
301 find("#projects-menu").click
302 find(".dropdown-menu a", text: dest['name']).click
303 assert page.has_text?(my_collection['name']), 'Collection not found in dest project after move'
306 assert page.has_no_text?(my_collection['name']), 'Collection still found in src project after remove'
307 visit page_with_token 'active', '/'
308 find("#projects-menu").click
309 find(".dropdown-menu a", text: "Home").click
310 assert page.has_text?(my_collection['name']), 'Collection not found in home project after remove'
311 if expect_name_change
312 assert page.has_text?(my_collection['name']+' removed from ' + src['name']),
313 'Collection with update name is not found in home project after remove'
319 def perform_selection_action src, dest, item, action
320 visit page_with_token 'active', '/'
321 find("#projects-menu").click
322 find(".dropdown-menu a", text: src['name']).click
323 assert page.has_text?(item['name']), 'Collection not found in src project'
325 within('tr', text: item['name']) do
326 find('input[type=checkbox]').click
329 click_button 'Selection'
331 within('.selection-action-container') do
332 assert page.has_text?("Compare selected"), "Compare selected link text not found"
333 assert page.has_link?("Copy selected"), "Copy selected link not found"
334 assert page.has_link?("Move selected"), "Move selected link not found"
335 assert page.has_link?("Remove selected"), "Remove selected link not found"
337 click_link "#{action} selected"
340 # select the destination project if a Copy or Move action is being performed
341 if action == 'Copy' || action == 'Move'
342 within(".modal-container") do
343 find('.selectable', text: dest['name']).click
344 find('.modal-footer a,button', text: action).click
350 # Test copy action state. It should not be available when a subproject is selected.
351 test "copy action is disabled when a subproject is selected" do
352 my_project = api_fixture('groups')['aproject']
353 my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
354 my_subproject = api_fixture('groups')['asubproject']
356 # verify that selection options are disabled on the project until an item is selected
357 visit page_with_token 'active', '/'
358 find("#projects-menu").click
359 find(".dropdown-menu a", text: my_project['name']).click
361 click_button 'Selection'
362 within('.selection-action-container') do
363 assert_selector 'li.disabled', text: 'Create new collection with selected collections'
364 assert_selector 'li.disabled', text: 'Compare selected'
365 assert_selector 'li.disabled', text: 'Copy selected'
366 assert_selector 'li.disabled', text: 'Move selected'
367 assert_selector 'li.disabled', text: 'Remove selected'
370 # select collection and verify links are enabled
371 visit page_with_token 'active', '/'
372 find("#projects-menu").click
373 find(".dropdown-menu a", text: my_project['name']).click
374 assert page.has_text?(my_collection['name']), 'Collection not found in project'
376 within('tr', text: my_collection['name']) do
377 find('input[type=checkbox]').click
380 click_button 'Selection'
381 within('.selection-action-container') do
382 assert_no_selector 'li.disabled', text: 'Create new collection with selected collections'
383 assert_selector 'li', text: 'Create new collection with selected collections'
384 assert_selector 'li.disabled', text: 'Compare selected'
385 assert_no_selector 'li.disabled', text: 'Copy selected'
386 assert_selector 'li', text: 'Copy selected'
387 assert_no_selector 'li.disabled', text: 'Move selected'
388 assert_selector 'li', text: 'Move selected'
389 assert_no_selector 'li.disabled', text: 'Remove selected'
390 assert_selector 'li', text: 'Remove selected'
393 # select subproject and verify that copy action is disabled
394 visit page_with_token 'active', '/'
395 find("#projects-menu").click
396 find(".dropdown-menu a", text: my_project['name']).click
398 click_link 'Subprojects'
399 assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
401 within('tr', text: my_subproject['name']) do
402 find('input[type=checkbox]').click
405 click_button 'Selection'
406 within('.selection-action-container') do
407 assert_selector 'li.disabled', text: 'Create new collection with selected collections'
408 assert_selector 'li.disabled', text: 'Compare selected'
409 assert_selector 'li.disabled', text: 'Copy selected'
410 assert_no_selector 'li.disabled', text: 'Move selected'
411 assert_selector 'li', text: 'Move selected'
412 assert_no_selector 'li.disabled', text: 'Remove selected'
413 assert_selector 'li', text: 'Remove selected'
416 # select subproject and a collection and verify that copy action is still disabled
417 visit page_with_token 'active', '/'
418 find("#projects-menu").click
419 find(".dropdown-menu a", text: my_project['name']).click
421 click_link 'Subprojects'
422 assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
424 within('tr', text: my_subproject['name']) do
425 find('input[type=checkbox]').click
428 click_link 'Data collections'
429 assert page.has_text?(my_collection['name']), 'Collection not found in project'
431 within('tr', text: my_collection['name']) do
432 find('input[type=checkbox]').click
435 click_link 'Subprojects'
436 click_button 'Selection'
437 within('.selection-action-container') do
438 assert_selector 'li.disabled', text: 'Create new collection with selected collections'
439 assert_selector 'li.disabled', text: 'Compare selected'
440 assert_selector 'li.disabled', text: 'Copy selected'
441 assert_no_selector 'li.disabled', text: 'Move selected'
442 assert_selector 'li', text: 'Move selected'
443 assert_no_selector 'li.disabled', text: 'Remove selected'
444 assert_selector 'li', text: 'Remove selected'
448 # When project tabs are switched, only options applicable to the current tab's selections are enabled.
449 test "verify selection options when tabs are switched" do
450 my_project = api_fixture('groups')['aproject']
451 my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
452 my_subproject = api_fixture('groups')['asubproject']
454 # select subproject and a collection and verify that copy action is still disabled
455 visit page_with_token 'active', '/'
456 find("#projects-menu").click
457 find(".dropdown-menu a", text: my_project['name']).click
459 # Select a sub-project
460 click_link 'Subprojects'
461 assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
463 within('tr', text: my_subproject['name']) do
464 find('input[type=checkbox]').click
467 # Select a collection
468 click_link 'Data collections'
469 assert page.has_text?(my_collection['name']), 'Collection not found in project'
471 within('tr', text: my_collection['name']) do
472 find('input[type=checkbox]').click
475 # Go back to Subprojects tab
476 click_link 'Subprojects'
477 click_button 'Selection'
478 within('.selection-action-container') do
479 assert_selector 'li.disabled', text: 'Create new collection with selected collections'
480 assert_selector 'li.disabled', text: 'Compare selected'
481 assert_selector 'li.disabled', text: 'Copy selected'
482 assert_no_selector 'li.disabled', text: 'Move selected'
483 assert_selector 'li', text: 'Move selected'
484 assert_no_selector 'li.disabled', text: 'Remove selected'
485 assert_selector 'li', text: 'Remove selected'
488 # Go back to Data collections tab
489 click_link 'Data collections'
490 click_button 'Selection'
491 within('.selection-action-container') do
492 assert_no_selector 'li.disabled', text: 'Create new collection with selected collections'
493 assert_selector 'li', text: 'Create new collection with selected collections'
494 assert_selector 'li.disabled', text: 'Compare selected'
495 assert_no_selector 'li.disabled', text: 'Copy selected'
496 assert_selector 'li', text: 'Copy selected'
497 assert_no_selector 'li.disabled', text: 'Move selected'
498 assert_selector 'li', text: 'Move selected'
499 assert_no_selector 'li.disabled', text: 'Remove selected'
500 assert_selector 'li', text: 'Remove selected'
504 # "Move selected" and "Remove selected" options should not be available when current user cannot write to the project
505 test "move selected and remove selected actions not available when current user cannot write to project" do
506 my_project = api_fixture('groups')['anonymously_accessible_project']
507 visit page_with_token 'active', "/projects/#{my_project['uuid']}"
509 click_button 'Selection'
510 within('.selection-action-container') do
511 assert_selector 'li', text: 'Create new collection with selected collections'
512 assert_selector 'li', text: 'Compare selected'
513 assert_selector 'li', text: 'Copy selected'
514 assert_no_selector 'li', text: 'Move selected'
515 assert_no_selector 'li', text: 'Remove selected'
521 ['project_viewer', false],
522 ].each do |user, expect_collection_in_aproject|
523 test "combine selected collections into new collection #{user} #{expect_collection_in_aproject}" do
524 my_project = api_fixture('groups')['aproject']
525 my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
527 visit page_with_token user, '/'
528 find("#projects-menu").click
529 find(".dropdown-menu a", text: my_project['name']).click
530 assert page.has_text?(my_collection['name']), 'Collection not found in project'
532 within('tr', text: my_collection['name']) do
533 find('input[type=checkbox]').click
536 click_button 'Selection'
537 within('.selection-action-container') do
538 click_link 'Create new collection with selected collections'
541 # now in the new collection page
542 if expect_collection_in_aproject
543 assert page.has_text?("Created new collection in the project #{my_project['name']}"),
544 'Not found flash message that new collection is created in aproject'
546 assert page.has_text?("Created new collection in your Home project"),
547 'Not found flash message that new collection is created in Home project'
549 assert page.has_text?('Content hash'), 'Not found content hash in collection page'
555 ["pipelines", "/pipeline_instances"],
556 ["collections", "/collections"]
557 ].each do |target,path|
558 test "Test dashboard button all #{target}" do
559 visit page_with_token 'active', '/'
560 click_link "All #{target}"
561 assert_equal path, current_path
565 def scroll_setup(project_name,
569 sort_parameters = nil)
570 project_uuid = api_fixture('groups')[project_name]['uuid']
571 visit page_with_token 'user1_with_load', '/projects/' + project_uuid
573 assert(page.has_text?("#{item_list_parameter.humanize} (#{total_nbr_items})"), "Number of #{item_list_parameter.humanize} did not match the input amount")
575 click_link item_list_parameter.humanize
579 find("th[data-sort-order='#{sort_parameters.gsub(/\s/,'')}']").click
584 def scroll_items_check(nbr_items,
590 for i in 1..nbr_items
591 items << "#{fixture_prefix}#{i}"
594 verify_items = items.dup
595 unexpected_items = []
597 within(".arv-project-#{item_list_parameter}") do
598 page.execute_script "window.scrollBy(0,999000)"
604 # Visit all rows. If not all expected items are found, retry
605 found_items = page.all(item_selector)
606 item_count = found_items.count
609 (0..item_count-1).each do |i|
610 # Found row text using the fixture string e.g. "Show Collection_#{n} "
611 item_name = found_items[i].text.split[1]
612 if !items.include? item_name
613 unexpected_items << item_name
615 verify_items.delete item_name
619 assert_operator( previous.downcase, :<=, item_name.downcase) if previous
624 assert_equal true, unexpected_items.empty?, "Found unexpected #{item_list_parameter.humanize} #{unexpected_items.inspect}"
625 assert_equal nbr_items, item_count, "Found different number of #{item_list_parameter.humanize}"
626 assert_equal true, verify_items.empty?, "Did not find all the #{item_list_parameter.humanize}"
631 ['project_with_10_collections', 10],
632 ['project_with_201_collections', 201], # two pages of data
633 ].each do |project_name, nbr_items|
634 test "scroll collections tab for #{project_name} with #{nbr_items} objects" do
635 item_list_parameter = "Data_collections"
636 scroll_setup project_name,
639 scroll_items_check nbr_items,
642 'tr[data-kind="arvados#collection"]'
647 ['project_with_10_collections', 10],
648 ['project_with_201_collections', 201], # two pages of data
649 ].each do |project_name, nbr_items|
650 test "scroll collections tab for #{project_name} with #{nbr_items} objects with ascending sort (case insensitive)" do
651 item_list_parameter = "Data_collections"
652 scroll_setup project_name,
657 scroll_items_check nbr_items,
660 'tr[data-kind="arvados#collection"]',
666 ['project_with_10_pipelines', 10, 0],
667 ['project_with_2_pipelines_and_60_jobs', 2, 60],
668 ['project_with_25_pipelines', 25, 0],
669 ].each do |project_name, num_pipelines, num_jobs|
670 test "scroll pipeline instances tab for #{project_name} with #{num_pipelines} pipelines and #{num_jobs} jobs" do
671 item_list_parameter = "Jobs_and_pipelines"
672 scroll_setup project_name,
673 num_pipelines + num_jobs,
675 # check the general scrolling and the pipelines
676 scroll_items_check num_pipelines,
679 'tr[data-kind="arvados#pipelineInstance"]'
680 # Check job count separately
681 jobs_found = page.all('tr[data-kind="arvados#job"]')
682 found_job_count = jobs_found.count
683 assert_equal num_jobs, found_job_count, 'Did not find expected number of jobs'
687 # Move button accessibility
690 ['active', true], # project owner
691 ['project_viewer', false],
692 ].each do |user, can_move|
693 test "#{user} can move subproject under another user's Home #{can_move}" do
694 project = api_fixture('groups')['aproject']
695 collection = api_fixture('collections')['collection_to_move_around_in_aproject']
697 # verify the project move button
698 visit page_with_token user, "/projects/#{project['uuid']}"
700 assert page.has_link? 'Move project...'
702 assert page.has_no_link? 'Move project...'
707 test "error while loading tab" do
708 original_arvados_v1_base = Rails.configuration.arvados_v1_base
710 visit page_with_token 'active', '/projects/' + api_fixture('groups')['aproject']['uuid']
712 # Point to a bad api server url to generate error
713 Rails.configuration.arvados_v1_base = "https://[100::f]:1/"
714 click_link 'Other objects'
715 within '#Other_objects' do
717 assert_selector('a', text: 'Reload tab')
719 # Now point back to the orig api server and reload tab
720 Rails.configuration.arvados_v1_base = original_arvados_v1_base
721 click_link 'Reload tab'
722 assert_no_selector('a', text: 'Reload tab')
723 assert_selector('button', text: 'Selection')
724 within '.selection-action-container' do
725 assert_selector 'tr[data-kind="arvados#trait"]'
730 test "add new project using projects dropdown" do
731 # verify that selection options are disabled on the project until an item is selected
732 visit page_with_token 'active', '/'
735 find("#projects-menu").click
736 click_link 'Add a new project'
737 assert_text 'New project'
738 assert_text 'No description provided'
740 # Add one more new project
741 find("#projects-menu").click
742 click_link 'Add a new project'
743 match = /New project \(\d\)/.match page.text
744 assert match, 'Expected project name not found'
745 assert_text 'No description provided'
748 test "first tab loads data when visiting other tab directly" do
749 # As of 2014-12-19, the first tab of project#show uses infinite scrolling.
750 # Make sure that it loads data even if we visit another tab directly.
751 project = api_fixture("groups", "aproject")
752 visit(page_with_token("active_trustedclient",
753 "/projects/#{project['uuid']}#Advanced"))
754 assert_text("API response")
755 find("#page-wrapper .nav-tabs :first-child a").click
756 assert_text("bytes Collection")