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