3338: Tests that the fixture collection count for a project matches what is displayed...
[arvados.git] / apps / workbench / test / integration / projects_test.rb
1 require 'integration_helper'
2 require 'selenium-webdriver'
3 require 'headless'
4
5 class ProjectsTest < ActionDispatch::IntegrationTest
6   setup do
7     Capybara.current_driver = Capybara.javascript_driver
8   end
9
10   test 'Check collection count for A Project in the tab pane titles' do
11     project_uuid = api_fixture('groups')['aproject']['uuid']
12     collection_fixture_count = api_fixture('collections').select{|k,v| v['owner_uuid'] == project_uuid}.count
13     visit page_with_token 'active', '/projects/' + project_uuid
14     assert_selector '#Data_collections-tab span', text: "(#{collection_fixture_count})"
15   end
16
17   test 'Find a project and edit its description' do
18     visit page_with_token 'active', '/'
19     find('.arv-project-list a,button', text: 'A Project').
20       click
21     within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
22       find('span', text: api_fixture('groups')['aproject']['name']).click
23       within('.arv-description-as-subtitle') do
24         find('.fa-pencil').click
25         find('.editable-input textarea').set('I just edited this.')
26         find('.editable-submit').click
27       end
28       wait_for_ajax
29     end
30     visit current_path
31     assert(find?('.container-fluid', text: 'I just edited this.'),
32            "Description update did not survive page refresh")
33   end
34
35   test 'Find a project and edit description to textile description' do
36     visit page_with_token 'active', '/'
37     find('.arv-project-list a,button', text: 'A Project').
38       click
39     within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
40       find('span', text: api_fixture('groups')['aproject']['name']).click
41       within('.arv-description-as-subtitle') do
42         find('.fa-pencil').click
43         find('.editable-input textarea').set('<p>*Textile description for A project* - "take me home":/ </p><p>And a new paragraph in description.</p>')
44         find('.editable-submit').click
45       end
46       wait_for_ajax
47     end
48
49     # visit project page
50     visit current_path
51     assert(has_no_text?('.container-fluid', text: '*Textile description for A project*'),
52            "Description is not rendered properly")
53     assert(find?('.container-fluid', text: 'Textile description for A project'),
54            "Description update did not survive page refresh")
55     assert(find?('.container-fluid', text: 'And a new paragraph in description'),
56            "Description did not contain the expected new paragraph")
57     assert(page.has_link?("take me home"), "link not found in description")
58
59     click_link 'take me home'
60
61     # now in dashboard
62     assert(page.has_text?('My projects'), 'My projects - not found on dashboard')
63     assert(page.has_text?('Projects shared with me'), 'Projects shared with me - not found on dashboard')
64     assert(page.has_text?('Textile description for A project'), "Project description not found")
65     assert(page.has_no_text?('*Textile description for A project*'), "Project description is not rendered properly in dashboard")
66     assert(page.has_no_text?('And a new paragraph in description'), "Project description is not truncated after first paragraph")
67   end
68
69   test 'Find a project and edit description to html description' do
70     visit page_with_token 'active', '/'
71     find('.arv-project-list a,button', text: 'A Project').
72       click
73     within('.container-fluid', text: api_fixture('groups')['aproject']['name']) do
74       find('span', text: api_fixture('groups')['aproject']['name']).click
75       within('.arv-description-as-subtitle') do
76         find('.fa-pencil').click
77         find('.editable-input textarea').set('<br>Textile description for A project</br> - <a href="/">take me home</a>')
78         find('.editable-submit').click
79       end
80       wait_for_ajax
81     end
82     visit current_path
83     assert(find?('.container-fluid', text: 'Textile description for A project'),
84            "Description update did not survive page refresh")
85     assert(!find?('.container-fluid', text: '<br>Textile description for A project</br>'),
86            "Textile description is displayed with uninterpreted formatting characters")
87     assert(page.has_link?("take me home"),"link not found in description")
88     click_link 'take me home'
89     assert page.has_text?('My projects')
90     assert page.has_text?('Projects shared with me')
91   end
92
93   test 'Find a project and edit description to textile description with link to object' do
94     visit page_with_token 'active', '/'
95     find('.arv-project-list a,button', text: 'A Project').
96       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
103       end
104       wait_for_ajax
105     end
106     visit current_path
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')
114   end
115
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
132       end
133       wait_for_ajax
134       assert_selector '.editable', text: 'Now I have a new name.'
135     end
136     visit current_path
137     click_link 'Other objects'
138     within '.selection-action-container' do
139       find '.editable', text: 'Now I have a new name.'
140       page.assert_no_selector '.editable', text: 'Now I have a name.'
141     end
142   end
143
144   test 'Create a project and move it into a different project' do
145     visit page_with_token 'active', '/projects'
146     find('.btn', text: "Add new project").click
147
148     # within('.editable', text: 'New project') do
149     within('h2') do
150       find('.fa-pencil').click
151       find('.editable-input input').set('Project 1234')
152       find('.glyphicon-ok').click
153     end
154     wait_for_ajax
155
156     visit '/projects'
157     find('.btn', text: "Add new project").click
158     within('h2') do
159       find('.fa-pencil').click
160       find('.editable-input input').set('Project 5678')
161       find('.glyphicon-ok').click
162     end
163     wait_for_ajax
164
165     click_link 'Move project...'
166     find('.selectable', text: 'Project 1234').click
167     find('.modal-footer a,button', text: 'Move').click
168     wait_for_ajax
169
170     # Wait for the page to refresh and show the new parent in Sharing panel
171     click_link 'Sharing'
172     assert(page.has_link?("Project 1234"),
173            "Project 5678 should now be inside project 1234")
174   end
175
176   def show_project_using(auth_key, proj_key='aproject')
177     project_uuid = api_fixture('groups')[proj_key]['uuid']
178     visit(page_with_token(auth_key, "/projects/#{project_uuid}"))
179     assert(page.has_text?("A Project"), "not on expected project page")
180   end
181
182   def share_rows
183     find('#project_sharing').all('tr')
184   end
185
186   def add_share_and_check(share_type, name)
187     assert(page.has_no_text?(name), "project is already shared with #{name}")
188     start_share_count = share_rows.size
189     click_on("Share with #{share_type}")
190     within(".modal-container") do
191       # Order is important here: we should find something that appears in the
192       # modal before we make any assertions about what's not in the modal.
193       # Otherwise, the not-included assertions might falsely pass because
194       # the modal hasn't loaded yet.
195       find(".selectable", text: name).click
196       assert(has_no_selector?(".modal-dialog-preview-pane"),
197              "preview pane available in sharing dialog")
198       assert_raises(Capybara::ElementNotFound,
199                     "Projects pulldown available from sharing dialog") do
200         click_on "All projects"
201       end
202       click_on "Add"
203     end
204     using_wait_time(Capybara.default_wait_time * 3) do
205       assert(page.has_link?(name),
206              "new share was not added to sharing table")
207       assert_equal(start_share_count + 1, share_rows.size,
208                    "new share did not add row to sharing table")
209     end
210   end
211
212   def modify_share_and_check(name)
213     start_rows = share_rows
214     link_row = start_rows.select { |row| row.has_text?(name) }
215     assert_equal(1, link_row.size, "row with new permission not found")
216     within(link_row.first) do
217       click_on("Read")
218       select("Write", from: "share_change_level")
219       click_on("editable-submit")
220       assert(has_link?("Write"),
221              "failed to change access level on new share")
222       click_on "Revoke"
223     end
224     using_wait_time(Capybara.default_wait_time * 3) do
225       assert(page.has_no_text?(name),
226              "new share row still exists after being revoked")
227       assert_equal(start_rows.size - 1, share_rows.size,
228                    "revoking share did not remove row from sharing table")
229     end
230   end
231
232   test "project viewer can't see project sharing tab" do
233     show_project_using("project_viewer")
234     assert(page.has_no_link?("Sharing"),
235            "read-only project user sees sharing tab")
236   end
237
238   test "project owner can manage sharing for another user" do
239     add_user = api_fixture('users')['future_project_user']
240     new_name = ["first_name", "last_name"].map { |k| add_user[k] }.join(" ")
241
242     show_project_using("active")
243     click_on "Sharing"
244     add_share_and_check("users", new_name)
245     modify_share_and_check(new_name)
246   end
247
248   test "project owner can manage sharing for another group" do
249     new_name = api_fixture('groups')['future_project_viewing_group']['name']
250
251     show_project_using("active")
252     click_on "Sharing"
253     add_share_and_check("groups", new_name)
254     modify_share_and_check(new_name)
255   end
256
257   test "'share with group' listing does not offer projects" do
258     show_project_using("active")
259     click_on "Sharing"
260     click_on "Share with groups"
261     good_uuid = api_fixture("groups")["private"]["uuid"]
262     assert(page.has_selector?(".selectable[data-object-uuid=\"#{good_uuid}\"]"),
263            "'share with groups' listing missing owned user group")
264     bad_uuid = api_fixture("groups")["asubproject"]["uuid"]
265     assert(page.has_no_selector?(".selectable[data-object-uuid=\"#{bad_uuid}\"]"),
266            "'share with groups' listing includes project")
267   end
268
269   [
270     'Move',
271     'Remove',
272     'Copy',
273   ].each do |action|
274     test "selection #{action} for project" do
275       src = api_fixture('groups')['aproject']
276       dest = api_fixture('groups')['asubproject']
277       my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
278
279       perform_selection_action src, dest, my_collection, action
280
281       case action
282       when 'Copy'
283         assert page.has_text?(my_collection['name']), 'Collection not found in src project after copy'
284         visit page_with_token 'active', '/'
285         find('.arv-project-list a,button', text: dest['name']).click
286         assert page.has_text?(my_collection['name']), 'Collection not found in dest project after copy'
287
288         # now remove it from destination project to restore to original state
289         perform_selection_action dest, nil, my_collection, 'Remove'
290       when 'Move'
291         assert page.has_no_text?(my_collection['name']), 'Collection still found in src project after move'
292         visit page_with_token 'active', '/'
293         find('.arv-project-list a,button', text: dest['name']).click
294         assert page.has_text?(my_collection['name']), 'Collection not found in dest project after move'
295
296         # move it back to src project to restore to original state
297         perform_selection_action dest, src, my_collection, action
298       when 'Remove'
299         assert page.has_no_text?(my_collection['name']), 'Collection still found in src project after remove'
300         visit page_with_token 'active', '/'
301         find('.arv-project-list a,button', text: 'Home').click
302         assert page.has_text?(my_collection['name']), 'Collection not found in home project after remove'
303       end
304     end
305   end
306
307   def perform_selection_action src, dest, item, action
308     visit page_with_token 'active', '/'
309     find('.arv-project-list a,button', text: src['name']).click
310     assert page.has_text?(item['name']), 'Collection not found in src project'
311
312     within('tr', text: item['name']) do
313       find('input[type=checkbox]').click
314     end
315
316     click_button 'Selection...'
317
318     within('.selection-action-container') do
319       assert page.has_text?("Compare selected"), "Compare selected link text not found"
320       assert page.has_link?("Copy selected"), "Copy selected link not found"
321       assert page.has_link?("Move selected"), "Move selected link not found"
322       assert page.has_link?("Remove selected"), "Remove selected link not found"
323
324       click_link "#{action} selected"
325     end
326
327     # select the destination project if a Copy or Move action is being performed
328     if action == 'Copy' || action == 'Move'
329       within(".modal-container") do
330         find('.selectable', text: dest['name']).click
331         find('.modal-footer a,button', text: action).click
332         wait_for_ajax
333       end
334     end
335   end
336
337   # Test copy action state. It should not be available when a subproject is selected.
338   test "copy action is disabled when a subproject is selected" do
339     my_project = api_fixture('groups')['aproject']
340     my_collection = api_fixture('collections')['collection_to_move_around_in_aproject']
341     my_subproject = api_fixture('groups')['asubproject']
342
343     # verify that selection options are disabled on the project until an item is selected
344     visit page_with_token 'active', '/'
345     find('.arv-project-list a,button', text: my_project['name']).click
346
347     click_button 'Selection...'
348     within('.selection-action-container') do
349       page.assert_selector 'li.disabled', text: 'Compare selected'
350       page.assert_selector 'li.disabled', text: 'Copy selected'
351       page.assert_selector 'li.disabled', text: 'Move selected'
352       page.assert_selector 'li.disabled', text: 'Remove selected'
353     end
354
355     # select collection and verify links are enabled
356     visit page_with_token 'active', '/'
357     find('.arv-project-list a,button', text: my_project['name']).click
358     assert page.has_text?(my_collection['name']), 'Collection not found in project'
359
360     within('tr', text: my_collection['name']) do
361       find('input[type=checkbox]').click
362     end
363
364     click_button 'Selection...'
365     within('.selection-action-container') do
366       page.assert_selector 'li.disabled', text: 'Compare selected'
367       page.assert_no_selector 'li.disabled', text: 'Copy selected'
368       page.assert_selector 'li', text: 'Copy selected'
369       page.assert_no_selector 'li.disabled', text: 'Move selected'
370       page.assert_selector 'li', text: 'Move selected'
371       page.assert_no_selector 'li.disabled', text: 'Remove selected'
372       page.assert_selector 'li', text: 'Remove selected'
373     end
374
375     # select subproject and verify that copy action is disabled
376     visit page_with_token 'active', '/'
377     find('.arv-project-list a,button', text: my_project['name']).click
378
379     click_link 'Subprojects'
380     assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
381
382     within('tr', text: my_subproject['name']) do
383       find('input[type=checkbox]').click
384     end
385
386     click_button 'Selection...'
387     within('.selection-action-container') do
388       page.assert_selector 'li.disabled', text: 'Compare selected'
389       page.assert_selector 'li.disabled', text: 'Copy selected'
390       page.assert_no_selector 'li.disabled', text: 'Move selected'
391       page.assert_selector 'li', text: 'Move selected'
392       page.assert_no_selector 'li.disabled', text: 'Remove selected'
393       page.assert_selector 'li', text: 'Remove selected'
394     end
395
396     # select subproject and a collection and verify that copy action is still disabled
397     visit page_with_token 'active', '/'
398     find('.arv-project-list a,button', text: my_project['name']).click
399
400     click_link 'Subprojects'
401     assert page.has_text?(my_subproject['name']), 'Subproject not found in project'
402
403     within('tr', text: my_subproject['name']) do
404       find('input[type=checkbox]').click
405     end
406
407     click_link 'Data collections'
408     assert page.has_text?(my_collection['name']), 'Collection not found in project'
409
410     within('tr', text: my_collection['name']) do
411       find('input[type=checkbox]').click
412     end
413
414     click_button 'Selection...'
415     within('.selection-action-container') do
416       page.assert_selector 'li.disabled', text: 'Compare selected'
417       page.assert_selector 'li.disabled', text: 'Copy selected'
418       page.assert_no_selector 'li.disabled', text: 'Move selected'
419       page.assert_selector 'li', text: 'Move selected'
420       page.assert_no_selector 'li.disabled', text: 'Remove selected'
421       page.assert_selector 'li', text: 'Remove selected'
422     end
423   end
424
425 end