Merge branch '11345-nodemanager-retry-after' refs #11345
[arvados.git] / apps / workbench / test / integration / projects_test.rb
1 require 'integration_helper'
2 require 'helpers/share_object_helper'
3 require_relative 'integration_test_utils'
4
5 class ProjectsTest < ActionDispatch::IntegrationTest
6   include ShareObjectHelper
7
8   setup do
9     need_javascript
10   end
11
12   test 'Check collection count for A Project in the tab pane titles' do
13     project_uuid = api_fixture('groups')['aproject']['uuid']
14     visit page_with_token 'active', '/projects/' + project_uuid
15     click_link 'Data collections'
16     wait_for_ajax
17     collection_count = page.all("[data-pk*='collection']").count
18     assert_selector '#Data_collections-tab span', text: "(#{collection_count})"
19   end
20
21   test 'Find a project and edit its description' do
22     visit page_with_token 'active', '/'
23     find("#projects-menu").click
24     find(".dropdown-menu a", text: "A Project").click
25     within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
26       find('span', text: api_fixture('groups')['aproject']['name']).click
27       within('.arv-description-as-subtitle') do
28         find('.fa-pencil').click
29         find('.editable-input textarea').set('I just edited this.')
30         find('.editable-submit').click
31       end
32       wait_for_ajax
33     end
34     visit current_path
35     assert(find?('.container-fluid', text: 'I just edited this.'),
36            "Description update did not survive page refresh")
37   end
38
39   test 'Create a project and move it into a different project' do
40     visit page_with_token 'active', '/projects'
41     find("#projects-menu").click
42     within('.dropdown-menu') do
43       first('li', text: 'Home').click
44     end
45     wait_for_ajax
46     find('.btn', text: "Add a subproject").click
47
48     within('h2') do
49       find('.fa-pencil').click
50       find('.editable-input input').set('Project 1234')
51       find('.glyphicon-ok').click
52     end
53     wait_for_ajax
54
55     visit '/projects'
56     find("#projects-menu").click
57     within('.dropdown-menu') do
58       first('li', text: 'Home').click
59     end
60     wait_for_ajax
61     find('.btn', text: "Add a subproject").click
62     within('h2') do
63       find('.fa-pencil').click
64       find('.editable-input input').set('Project 5678')
65       find('.glyphicon-ok').click
66     end
67     wait_for_ajax
68
69     click_link 'Move project...'
70     find('.selectable', text: 'Project 1234').click
71     find('.modal-footer a,button', text: 'Move').click
72     wait_for_ajax
73
74     # Wait for the page to refresh and show the new parent in Sharing panel
75     click_link 'Sharing'
76     assert(page.has_link?("Project 1234"),
77            "Project 5678 should now be inside project 1234")
78   end
79
80   def open_groups_sharing(project_name="aproject", token_name="active")
81     project = api_fixture("groups", project_name)
82     visit(page_with_token(token_name, "/projects/#{project['uuid']}"))
83     click_on "Sharing"
84     click_on "Share with groups"
85   end
86
87   def group_name(group_key)
88     api_fixture("groups", group_key, "name")
89   end
90
91   test "projects not publicly sharable when anonymous browsing disabled" do
92     Rails.configuration.anonymous_user_token = false
93     open_groups_sharing
94     # Check for a group we do expect first, to make sure the modal's loaded.
95     assert_selector(".modal-container .selectable",
96                     text: group_name("all_users"))
97     assert_no_selector(".modal-container .selectable",
98                        text: group_name("anonymous_group"))
99   end
100
101   test "projects publicly sharable when anonymous browsing enabled" do
102     Rails.configuration.anonymous_user_token = "testonlytoken"
103     open_groups_sharing
104     assert_selector(".modal-container .selectable",
105                     text: group_name("anonymous_group"))
106   end
107
108   test "project owner can manage sharing for another user" do
109     add_user = api_fixture('users')['future_project_user']
110     new_name = ["first_name", "last_name"].map { |k| add_user[k] }.join(" ")
111
112     show_object_using('active', 'groups', 'aproject', 'A Project')
113     click_on "Sharing"
114     add_share_and_check("users", new_name, add_user)
115     modify_share_and_check(new_name)
116   end
117
118   test "project owner can manage sharing for another group" do
119     new_name = api_fixture('groups')['future_project_viewing_group']['name']
120
121     show_object_using('active', 'groups', 'aproject', 'A Project')
122     click_on "Sharing"
123     add_share_and_check("groups", new_name)
124     modify_share_and_check(new_name)
125   end
126
127   test "'share with group' listing does not offer projects" do
128     show_object_using('active', 'groups', 'aproject', 'A Project')
129     click_on "Sharing"
130     click_on "Share with groups"
131     good_uuid = api_fixture("groups")["private"]["uuid"]
132     assert(page.has_selector?(".selectable[data-object-uuid=\"#{good_uuid}\"]"),
133            "'share with groups' listing missing owned user group")
134     bad_uuid = api_fixture("groups")["asubproject"]["uuid"]
135     assert(page.has_no_selector?(".selectable[data-object-uuid=\"#{bad_uuid}\"]"),
136            "'share with groups' listing includes project")
137   end
138
139   [
140     ['Move',api_fixture('collections')['collection_to_move_around_in_aproject'],
141       api_fixture('groups')['aproject'],api_fixture('groups')['asubproject']],
142     ['Remove',api_fixture('collections')['collection_to_move_around_in_aproject'],
143       api_fixture('groups')['aproject']],
144     ['Copy',api_fixture('collections')['collection_to_move_around_in_aproject'],
145       api_fixture('groups')['aproject'],api_fixture('groups')['asubproject']],
146     ['Remove',api_fixture('collections')['collection_in_aproject_with_same_name_as_in_home_project'],
147       api_fixture('groups')['aproject'],nil,true],
148   ].each do |action, my_collection, src, dest=nil, expect_name_change=nil|
149     test "selection #{action} -> #{expect_name_change.inspect} for project" do
150       perform_selection_action src, dest, my_collection, action
151
152       case action
153       when 'Copy'
154         assert page.has_text?(my_collection['name']), 'Collection not found in src project after copy'
155         visit page_with_token 'active', '/'
156         find("#projects-menu").click
157         find(".dropdown-menu a", text: dest['name']).click
158         click_link 'Data collections'
159         assert page.has_text?(my_collection['name']), 'Collection not found in dest project after copy'
160
161       when 'Move'
162         assert page.has_no_text?(my_collection['name']), 'Collection still found in src project after move'
163         visit page_with_token 'active', '/'
164         find("#projects-menu").click
165         find(".dropdown-menu a", text: dest['name']).click
166         click_link 'Data collections'
167         assert page.has_text?(my_collection['name']), 'Collection not found in dest project after move'
168
169       when 'Remove'
170         assert page.has_no_text?(my_collection['name']), 'Collection still found in src project after remove'
171       end
172     end
173   end
174
175   def perform_selection_action src, dest, item, action
176     visit page_with_token 'active', '/'
177     find("#projects-menu").click
178     find(".dropdown-menu a", text: src['name']).click
179     click_link 'Data collections'
180     assert page.has_text?(item['name']), 'Collection not found in src project'
181
182     within('tr', text: item['name']) do
183       find('input[type=checkbox]').click
184     end
185
186     click_button 'Selection'
187
188     within('.selection-action-container') do
189       assert page.has_text?("Compare selected"), "Compare selected link text not found"
190       assert page.has_link?("Copy selected"), "Copy selected link not found"
191       assert page.has_link?("Move selected"), "Move selected link not found"
192       assert page.has_link?("Remove selected"), "Remove selected link not found"
193
194       click_link "#{action} selected"
195     end
196
197     # select the destination project if a Copy or Move action is being performed
198     if action == 'Copy' || action == 'Move'
199       within(".modal-container") do
200         find('.selectable', text: dest['name']).click
201         find('.modal-footer a,button', text: action).click
202         wait_for_ajax
203       end
204     end
205   end
206
207   # Test copy action state. It should not be available when a subproject is selected.
208   test "copy action is disabled when a subproject is selected" do
209     my_project = api_fixture('groups')['aproject']
210     my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
211     my_subproject = api_fixture('groups')['asubproject']
212
213     # verify that selection options are disabled on the project until an item is selected
214     visit page_with_token 'active', '/'
215     find("#projects-menu").click
216     find(".dropdown-menu a", text: my_project['name']).click
217
218     click_link 'Data collections'
219     click_button 'Selection'
220     within('.selection-action-container') do
221       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
222       assert_selector 'li.disabled', text: 'Compare selected'
223       assert_selector 'li.disabled', text: 'Copy selected'
224       assert_selector 'li.disabled', text: 'Move selected'
225       assert_selector 'li.disabled', text: 'Remove selected'
226     end
227
228     # select collection and verify links are enabled
229     visit page_with_token 'active', '/'
230     find("#projects-menu").click
231     find(".dropdown-menu a", text: my_project['name']).click
232     click_link 'Data collections'
233     assert page.has_text?(my_collection['name']), 'Collection not found in project'
234
235     within('tr', text: my_collection['name']) do
236       find('input[type=checkbox]').click
237     end
238
239     click_button 'Selection'
240     within('.selection-action-container') do
241       assert_no_selector 'li.disabled', text: 'Create new collection with selected collections'
242       assert_selector 'li', text: 'Create new collection with selected collections'
243       assert_selector 'li.disabled', text: 'Compare selected'
244       assert_no_selector 'li.disabled', text: 'Copy selected'
245       assert_selector 'li', text: 'Copy selected'
246       assert_no_selector 'li.disabled', text: 'Move selected'
247       assert_selector 'li', text: 'Move selected'
248       assert_no_selector 'li.disabled', text: 'Remove selected'
249       assert_selector 'li', text: 'Remove selected'
250     end
251
252     # select subproject and verify that copy action is disabled
253     visit page_with_token 'active', '/'
254     find("#projects-menu").click
255     find(".dropdown-menu a", text: my_project['name']).click
256
257     click_link 'Subprojects'
258     assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
259
260     within('tr', text: my_subproject['name']) do
261       find('input[type=checkbox]').click
262     end
263
264     click_button 'Selection'
265     within('.selection-action-container') do
266       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
267       assert_selector 'li.disabled', text: 'Compare selected'
268       assert_selector 'li.disabled', text: 'Copy selected'
269       assert_no_selector 'li.disabled', text: 'Move selected'
270       assert_selector 'li', text: 'Move selected'
271       assert_no_selector 'li.disabled', text: 'Remove selected'
272       assert_selector 'li', text: 'Remove selected'
273     end
274
275     # select subproject and a collection and verify that copy action is still disabled
276     visit page_with_token 'active', '/'
277     find("#projects-menu").click
278     find(".dropdown-menu a", text: my_project['name']).click
279
280     click_link 'Subprojects'
281     assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
282
283     within('tr', text: my_subproject['name']) do
284       find('input[type=checkbox]').click
285     end
286
287     click_link 'Data collections'
288     assert page.has_text?(my_collection['name']), 'Collection not found in project'
289
290     within('tr', text: my_collection['name']) do
291       find('input[type=checkbox]').click
292     end
293
294     click_link 'Subprojects'
295     click_button 'Selection'
296     within('.selection-action-container') do
297       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
298       assert_selector 'li.disabled', text: 'Compare selected'
299       assert_selector 'li.disabled', text: 'Copy selected'
300       assert_no_selector 'li.disabled', text: 'Move selected'
301       assert_selector 'li', text: 'Move selected'
302       assert_no_selector 'li.disabled', text: 'Remove selected'
303       assert_selector 'li', text: 'Remove selected'
304     end
305   end
306
307   # When project tabs are switched, only options applicable to the current tab's selections are enabled.
308   test "verify selection options when tabs are switched" do
309     my_project = api_fixture('groups')['aproject']
310     my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
311     my_subproject = api_fixture('groups')['asubproject']
312
313     # select subproject and a collection and verify that copy action is still disabled
314     visit page_with_token 'active', '/'
315     find("#projects-menu").click
316     find(".dropdown-menu a", text: my_project['name']).click
317
318     # Select a sub-project
319     click_link 'Subprojects'
320     assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
321
322     within('tr', text: my_subproject['name']) do
323       find('input[type=checkbox]').click
324     end
325
326     # Select a collection
327     click_link 'Data collections'
328     assert page.has_text?(my_collection['name']), 'Collection not found in project'
329
330     within('tr', text: my_collection['name']) do
331       find('input[type=checkbox]').click
332     end
333
334     # Go back to Subprojects tab
335     click_link 'Subprojects'
336     click_button 'Selection'
337     within('.selection-action-container') do
338       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
339       assert_selector 'li.disabled', text: 'Compare selected'
340       assert_selector 'li.disabled', text: 'Copy selected'
341       assert_no_selector 'li.disabled', text: 'Move selected'
342       assert_selector 'li', text: 'Move selected'
343       assert_no_selector 'li.disabled', text: 'Remove selected'
344       assert_selector 'li', text: 'Remove selected'
345     end
346
347     # Close the dropdown by clicking outside it.
348     find('.dropdown-toggle', text: 'Selection').find(:xpath, '..').click
349
350     # Go back to Data collections tab
351     find('.nav-tabs a', text: 'Data collections').click
352     click_button 'Selection'
353     within('.selection-action-container') do
354       assert_no_selector 'li.disabled', text: 'Create new collection with selected collections'
355       assert_selector 'li', text: 'Create new collection with selected collections'
356       assert_selector 'li.disabled', text: 'Compare selected'
357       assert_no_selector 'li.disabled', text: 'Copy selected'
358       assert_selector 'li', text: 'Copy selected'
359       assert_no_selector 'li.disabled', text: 'Move selected'
360       assert_selector 'li', text: 'Move selected'
361       assert_no_selector 'li.disabled', text: 'Remove selected'
362       assert_selector 'li', text: 'Remove selected'
363     end
364   end
365
366   # "Move selected" and "Remove selected" options should not be
367   # available when current user cannot write to the project
368   test "move selected and remove selected actions not available when current user cannot write to project" do
369     my_project = api_fixture('groups')['anonymously_accessible_project']
370     visit page_with_token 'active', "/projects/#{my_project['uuid']}"
371
372     click_link 'Data collections'
373     click_button 'Selection'
374     within('.selection-action-container') do
375       assert_selector 'li', text: 'Create new collection with selected collections'
376       assert_selector 'li', text: 'Compare selected'
377       assert_selector 'li', text: 'Copy selected'
378       assert_no_selector 'li', text: 'Move selected'
379       assert_no_selector 'li', text: 'Remove selected'
380     end
381   end
382
383   [
384     ['active', true],
385     ['project_viewer', false],
386   ].each do |user, expect_collection_in_aproject|
387     test "combine selected collections into new collection #{user} #{expect_collection_in_aproject}" do
388       my_project = api_fixture('groups')['aproject']
389       my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
390
391       visit page_with_token user, "/projects/#{my_project['uuid']}"
392       click_link 'Data collections'
393       assert page.has_text?(my_collection['name']), 'Collection not found in project'
394
395       within('tr', text: my_collection['name']) do
396         find('input[type=checkbox]').click
397       end
398
399       click_button 'Selection'
400       within('.selection-action-container') do
401         click_link 'Create new collection with selected collections'
402       end
403
404       # now in the new collection page
405       if expect_collection_in_aproject
406         assert page.has_text?("Created new collection in the project #{my_project['name']}"),
407                               'Not found flash message that new collection is created in aproject'
408       else
409         assert page.has_text?("Created new collection in your Home project"),
410                               'Not found flash message that new collection is created in Home project'
411       end
412     end
413   end
414
415   def scroll_setup(project_name,
416                    total_nbr_items,
417                    item_list_parameter,
418                    sorted = false,
419                    sort_parameters = nil)
420     project_uuid = api_fixture('groups')[project_name]['uuid']
421     visit page_with_token 'user1_with_load', '/projects/' + project_uuid
422
423     assert(page.has_text?("#{item_list_parameter.humanize} (#{total_nbr_items})"), "Number of #{item_list_parameter.humanize} did not match the input amount")
424
425     click_link item_list_parameter.humanize
426     wait_for_ajax
427
428     if sorted
429       find("th[data-sort-order='#{sort_parameters.gsub(/\s/,'')}']").click
430       wait_for_ajax
431     end
432   end
433
434   def scroll_items_check(nbr_items,
435                          fixture_prefix,
436                          item_list_parameter,
437                          item_selector,
438                          sorted = false)
439     items = []
440     for i in 1..nbr_items
441       items << "#{fixture_prefix}#{i}"
442     end
443
444     verify_items = items.dup
445     unexpected_items = []
446     item_count = 0
447     within(".arv-project-#{item_list_parameter}") do
448       page.execute_script "window.scrollBy(0,999000)"
449       begin
450         wait_for_ajax
451       rescue
452       end
453
454       # Visit all rows. If not all expected items are found, retry
455       found_items = page.all(item_selector)
456       item_count = found_items.count
457
458       previous = nil
459       (0..item_count-1).each do |i|
460         # Found row text using the fixture string e.g. "Show Collection_#{n} "
461         item_name = found_items[i].text.split[1]
462         if !items.include? item_name
463           unexpected_items << item_name
464         else
465           verify_items.delete item_name
466         end
467         if sorted
468           # check sort order
469           assert_operator( previous.downcase, :<=, item_name.downcase) if previous
470           previous = item_name
471         end
472       end
473
474       assert_equal true, unexpected_items.empty?, "Found unexpected #{item_list_parameter.humanize} #{unexpected_items.inspect}"
475       assert_equal nbr_items, item_count, "Found different number of #{item_list_parameter.humanize}"
476       assert_equal true, verify_items.empty?, "Did not find all the #{item_list_parameter.humanize}"
477     end
478   end
479
480   [
481     ['project_with_10_collections', 10],
482     ['project_with_201_collections', 201], # two pages of data
483   ].each do |project_name, nbr_items|
484     test "scroll collections tab for #{project_name} with #{nbr_items} objects" do
485       item_list_parameter = "Data_collections"
486       scroll_setup project_name,
487                    nbr_items,
488                    item_list_parameter
489       scroll_items_check nbr_items,
490                          "Collection_",
491                          item_list_parameter,
492                          'tr[data-kind="arvados#collection"]'
493     end
494   end
495
496   [
497     ['project_with_10_collections', 10],
498     ['project_with_201_collections', 201], # two pages of data
499   ].each do |project_name, nbr_items|
500     test "scroll collections tab for #{project_name} with #{nbr_items} objects with ascending sort (case insensitive)" do
501       item_list_parameter = "Data_collections"
502       scroll_setup project_name,
503                    nbr_items,
504                    item_list_parameter,
505                    true,
506                    "collections.name"
507       scroll_items_check nbr_items,
508                          "Collection_",
509                          item_list_parameter,
510                          'tr[data-kind="arvados#collection"]',
511                          true
512     end
513   end
514
515   [
516     ['project_with_10_pipelines', 10, 0],
517     ['project_with_2_pipelines_and_60_crs', 2, 60],
518     ['project_with_25_pipelines', 25, 0],
519   ].each do |project_name, num_pipelines, num_crs|
520     test "scroll pipeline instances tab for #{project_name} with #{num_pipelines} pipelines and #{num_crs} container requests" do
521       item_list_parameter = "Pipelines_and_processes"
522       scroll_setup project_name,
523                    num_pipelines + num_crs,
524                    item_list_parameter
525       # check the general scrolling and the pipelines
526       scroll_items_check num_pipelines,
527                          "pipeline_",
528                          item_list_parameter,
529                          'tr[data-kind="arvados#pipelineInstance"]'
530       # Check container request count separately
531       crs_found = page.all('tr[data-kind="arvados#containerRequest"]')
532       found_cr_count = crs_found.count
533       assert_equal num_crs, found_cr_count, 'Did not find expected number of container requests'
534     end
535   end
536
537   test "error while loading tab" do
538     original_arvados_v1_base = Rails.configuration.arvados_v1_base
539
540     visit page_with_token 'active', '/projects/' + api_fixture('groups')['aproject']['uuid']
541
542     # Point to a bad api server url to generate error
543     Rails.configuration.arvados_v1_base = "https://[::1]:1/"
544     click_link 'Other objects'
545     within '#Other_objects' do
546       # Error
547       assert_selector('a', text: 'Reload tab')
548
549       # Now point back to the orig api server and reload tab
550       Rails.configuration.arvados_v1_base = original_arvados_v1_base
551       click_link 'Reload tab'
552       assert_no_selector('a', text: 'Reload tab')
553       assert_selector('button', text: 'Selection')
554       within '.selection-action-container' do
555         assert_selector 'tr[data-kind="arvados#trait"]'
556       end
557     end
558   end
559
560   test "add new project using projects dropdown" do
561     visit page_with_token 'active', '/'
562
563     # Add a new project
564     find("#projects-menu").click
565     click_link 'Add a new project'
566     assert_text 'New project'
567     assert_text 'No description provided'
568   end
569
570   test "first tab loads data when visiting other tab directly" do
571     # As of 2014-12-19, the first tab of project#show uses infinite scrolling.
572     # Make sure that it loads data even if we visit another tab directly.
573     need_selenium 'to land on specified tab using {url}#Advanced'
574     user = api_fixture("users", "active")
575     visit(page_with_token("active_trustedclient",
576                           "/projects/#{user['uuid']}#Advanced"))
577     assert_text("API response")
578     find("#page-wrapper .nav-tabs :first-child a").click
579     assert_text("Collection modified at")
580   end
581
582   # "Select all" and "Unselect all" options
583   test "select all and unselect all actions" do
584     need_selenium 'to check and uncheck checkboxes'
585
586     visit page_with_token 'active', '/projects/' + api_fixture('groups')['aproject']['uuid']
587
588     # Go to "Data collections" tab and click on "Select all"
589     click_link 'Data collections'
590     wait_for_ajax
591
592     # Initially, all selection options for this tab should be disabled
593     click_button 'Selection'
594     within('.selection-action-container') do
595       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
596       assert_selector 'li.disabled', text: 'Copy selected'
597     end
598
599     # Select all
600     click_button 'Select all'
601
602     assert_checkboxes_state('input[type=checkbox]', true, '"select all" should check all checkboxes')
603
604     # Now the selection options should be enabled
605     click_button 'Selection'
606     within('.selection-action-container') do
607       assert_selector 'li', text: 'Create new collection with selected collections'
608       assert_no_selector 'li.disabled', text: 'Copy selected'
609       assert_selector 'li', text: 'Create new collection with selected collections'
610       assert_no_selector 'li.disabled', text: 'Copy selected'
611     end
612
613     # Go to Pipelines and processes tab and assert none selected
614     click_link 'Pipelines and processes'
615     wait_for_ajax
616
617     # Since this is the first visit to this tab, all selection options should be disabled
618     click_button 'Selection'
619     within('.selection-action-container') do
620       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
621       assert_selector 'li.disabled', text: 'Copy selected'
622     end
623
624     assert_checkboxes_state('input[type=checkbox]', false, '"select all" should check all checkboxes')
625
626     # Select all
627     click_button 'Select all'
628     assert_checkboxes_state('input[type=checkbox]', true, '"select all" should check all checkboxes')
629
630     # Applicable selection options should be enabled
631     click_button 'Selection'
632     within('.selection-action-container') do
633       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
634       assert_selector 'li', text: 'Copy selected'
635       assert_no_selector 'li.disabled', text: 'Copy selected'
636     end
637
638     # Unselect all
639     click_button 'Unselect all'
640     assert_checkboxes_state('input[type=checkbox]', false, '"select all" should check all checkboxes')
641
642     # All selection options should be disabled again
643     click_button 'Selection'
644     within('.selection-action-container') do
645       assert_selector 'li.disabled', text: 'Create new collection with selected collections'
646       assert_selector 'li.disabled', text: 'Copy selected'
647     end
648
649     # Go back to Data collections tab and verify all are still selected
650     click_link 'Data collections'
651     wait_for_ajax
652
653     # Selection options should be enabled based on the fact that all collections are still selected in this tab
654     click_button 'Selection'
655     within('.selection-action-container') do
656       assert_selector 'li', text: 'Create new collection with selected collections'
657       assert_no_selector 'li.disabled', text: 'Copy selected'
658       assert_selector 'li', text: 'Create new collection with selected collections'
659       assert_no_selector 'li.disabled', text: 'Copy selected'
660     end
661
662     assert_checkboxes_state('input[type=checkbox]', true, '"select all" should check all checkboxes')
663
664     # Unselect all
665     find('button#unselect-all').click
666     assert_checkboxes_state('input[type=checkbox]', false, '"unselect all" should clear all checkboxes')
667
668     # Now all selection options should be disabled because none of the collections are checked
669     click_button 'Selection'
670     within('.selection-action-container') do
671       assert_selector 'li.disabled', text: 'Copy selected'
672       assert_selector 'li.disabled', text: 'Copy selected'
673     end
674
675     # Verify checking just one checkbox still works as expected
676     within('tr', text: api_fixture('collections')['collection_to_move_around_in_aproject']['name']) do
677       find('input[type=checkbox]').click
678     end
679
680     click_button 'Selection'
681     within('.selection-action-container') do
682       assert_selector 'li', text: 'Create new collection with selected collections'
683       assert_no_selector 'li.disabled', text: 'Copy selected'
684       assert_selector 'li', text: 'Create new collection with selected collections'
685       assert_no_selector 'li.disabled', text: 'Copy selected'
686     end
687   end
688
689   test "test search all projects menu item in projects menu" do
690      need_selenium
691      visit page_with_token('active')
692      find('#projects-menu').click
693      within('.dropdown-menu') do
694        assert_selector 'a', text: 'Search all projects'
695        find('a', text: 'Search all projects').click
696      end
697      within('.modal-content') do
698         assert page.has_text?('All projects'), 'No text - All projects'
699         assert page.has_text?('Search'), 'No text - Search'
700         assert page.has_text?('Cancel'), 'No text - Cancel'
701         fill_in "Search", with: 'Unrestricted public data'
702         wait_for_ajax
703         assert_selector 'div', text: 'Unrestricted public data'
704         find(:xpath, '//*[@id="choose-scroll"]/div[2]/div').click
705         click_button 'Show'
706      end
707      assert page.has_text?('Unrestricted public data'), 'No text - Unrestricted public data'
708      assert page.has_text?('An anonymously accessible project'), 'No text - An anonymously accessible project'
709   end
710
711   test "test star and unstar project" do
712     visit page_with_token 'active', "/projects/#{api_fixture('groups')['anonymously_accessible_project']['uuid']}"
713
714     # add to favorites
715     find('.fa-star-o').click
716     wait_for_ajax
717
718     find("#projects-menu").click
719     within('.dropdown-menu') do
720       assert_selector 'li', text: 'Unrestricted public data'
721     end
722
723     # remove from favotires
724     find('.fa-star').click
725     wait_for_ajax
726
727     find("#projects-menu").click
728     within('.dropdown-menu') do
729       assert_no_selector 'li', text: 'Unrestricted public data'
730     end
731   end
732
733   [
734     ['Two Part Pipeline Template', 'part-one', 'Provide a value for the following'],
735     ['Workflow with input specifications', 'this workflow has inputs specified', 'Provide a value for the following'],
736   ].each do |template_name, preview_txt, process_txt|
737     test "run a process using template #{template_name} in a project" do
738       project = api_fixture('groups')['aproject']
739       visit page_with_token 'active', '/projects/' + project['uuid']
740
741       find('.btn', text: 'Run a process').click
742
743       # in the chooser, verify preview and click Next button
744       within('.modal-dialog') do
745         find('.selectable', text: template_name).click
746         assert_text preview_txt
747         find('.btn', text: 'Next: choose inputs').click
748       end
749
750       # in the process page now
751       assert_text process_txt
752       assert_text project['name']
753     end
754   end
755 end