Remove redundant test case.
[arvados.git] / services / api / test / functional / arvados / v1 / groups_controller_test.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 require 'test_helper'
6
7 class Arvados::V1::GroupsControllerTest < ActionController::TestCase
8
9   test "attempt to delete group without read or write access" do
10     authorize_with :active
11     post :destroy, id: groups(:empty_lonely_group).uuid
12     assert_response 404
13   end
14
15   test "attempt to delete group without write access" do
16     authorize_with :active
17     post :destroy, id: groups(:all_users).uuid
18     assert_response 403
19   end
20
21   test "get list of projects" do
22     authorize_with :active
23     get :index, filters: [['group_class', '=', 'project']], format: :json
24     assert_response :success
25     group_uuids = []
26     json_response['items'].each do |group|
27       assert_equal 'project', group['group_class']
28       group_uuids << group['uuid']
29     end
30     assert_includes group_uuids, groups(:aproject).uuid
31     assert_includes group_uuids, groups(:asubproject).uuid
32     assert_not_includes group_uuids, groups(:system_group).uuid
33     assert_not_includes group_uuids, groups(:private).uuid
34   end
35
36   test "get list of groups that are not projects" do
37     authorize_with :active
38     get :index, filters: [['group_class', '!=', 'project']], format: :json
39     assert_response :success
40     group_uuids = []
41     json_response['items'].each do |group|
42       assert_not_equal 'project', group['group_class']
43       group_uuids << group['uuid']
44     end
45     assert_not_includes group_uuids, groups(:aproject).uuid
46     assert_not_includes group_uuids, groups(:asubproject).uuid
47     assert_includes group_uuids, groups(:private).uuid
48     assert_includes group_uuids, groups(:group_with_no_class).uuid
49   end
50
51   test "get list of groups with bogus group_class" do
52     authorize_with :active
53     get :index, {
54       filters: [['group_class', '=', 'nogrouphasthislittleclass']],
55       format: :json,
56     }
57     assert_response :success
58     assert_equal [], json_response['items']
59     assert_equal 0, json_response['items_available']
60   end
61
62   def check_project_contents_response disabled_kinds=[]
63     assert_response :success
64     assert_operator 2, :<=, json_response['items_available']
65     assert_operator 2, :<=, json_response['items'].count
66     kinds = json_response['items'].collect { |i| i['kind'] }.uniq
67     expect_kinds = %w'arvados#group arvados#specimen arvados#pipelineTemplate arvados#job' - disabled_kinds
68     assert_equal expect_kinds, (expect_kinds & kinds)
69
70     json_response['items'].each do |i|
71       if i['kind'] == 'arvados#group'
72         assert(i['group_class'] == 'project',
73                "group#contents returned a non-project group")
74       end
75     end
76
77     disabled_kinds.each do |d|
78       assert_equal true, !kinds.include?(d)
79     end
80   end
81
82   test 'get group-owned objects' do
83     authorize_with :active
84     get :contents, {
85       id: groups(:aproject).uuid,
86       format: :json,
87     }
88     check_project_contents_response
89   end
90
91   test "user with project read permission can see project objects" do
92     authorize_with :project_viewer
93     get :contents, {
94       id: groups(:aproject).uuid,
95       format: :json,
96     }
97     check_project_contents_response
98   end
99
100   test "list objects across projects" do
101     authorize_with :project_viewer
102     get :contents, {
103       format: :json,
104       filters: [['uuid', 'is_a', 'arvados#specimen']]
105     }
106     assert_response :success
107     found_uuids = json_response['items'].collect { |i| i['uuid'] }
108     [[:in_aproject, true],
109      [:in_asubproject, true],
110      [:owned_by_private_group, false]].each do |specimen_fixture, should_find|
111       if should_find
112         assert_includes found_uuids, specimens(specimen_fixture).uuid, "did not find specimen fixture '#{specimen_fixture}'"
113       else
114         refute_includes found_uuids, specimens(specimen_fixture).uuid, "found specimen fixture '#{specimen_fixture}'"
115       end
116     end
117   end
118
119   test "list objects in home project" do
120     authorize_with :active
121     get :contents, {
122       format: :json,
123       limit: 200,
124       id: users(:active).uuid
125     }
126     assert_response :success
127     found_uuids = json_response['items'].collect { |i| i['uuid'] }
128     assert_includes found_uuids, specimens(:owned_by_active_user).uuid, "specimen did not appear in home project"
129     refute_includes found_uuids, specimens(:in_asubproject).uuid, "specimen appeared unexpectedly in home project"
130   end
131
132   test "user with project read permission can see project collections" do
133     authorize_with :project_viewer
134     get :contents, {
135       id: groups(:asubproject).uuid,
136       format: :json,
137     }
138     ids = json_response['items'].map { |item| item["uuid"] }
139     assert_includes ids, collections(:baz_file_in_asubproject).uuid
140   end
141
142   [
143     ['collections.name', 'asc', :<=, "name"],
144     ['collections.name', 'desc', :>=, "name"],
145     ['name', 'asc', :<=, "name"],
146     ['name', 'desc', :>=, "name"],
147     ['collections.created_at', 'asc', :<=, "created_at"],
148     ['collections.created_at', 'desc', :>=, "created_at"],
149     ['created_at', 'asc', :<=, "created_at"],
150     ['created_at', 'desc', :>=, "created_at"],
151   ].each do |column, order, operator, field|
152     test "user with project read permission can sort projects on #{column} #{order}" do
153       authorize_with :project_viewer
154       get :contents, {
155         id: groups(:asubproject).uuid,
156         format: :json,
157         filters: [['uuid', 'is_a', "arvados#collection"]],
158         order: "#{column} #{order}"
159       }
160       sorted_values = json_response['items'].collect { |item| item[field] }
161       if field == "name"
162         # Here we avoid assuming too much about the database
163         # collation. Both "alice"<"Bob" and "alice">"Bob" can be
164         # correct. Hopefully it _is_ safe to assume that if "a" comes
165         # before "b" in the ascii alphabet, "aX">"bY" is never true for
166         # any strings X and Y.
167         reliably_sortable_names = sorted_values.select do |name|
168           name[0] >= 'a' && name[0] <= 'z'
169         end.uniq do |name|
170           name[0]
171         end
172         # Preserve order of sorted_values. But do not use &=. If
173         # sorted_values has out-of-order duplicates, we want to preserve
174         # them here, so we can detect them and fail the test below.
175         sorted_values.select! do |name|
176           reliably_sortable_names.include? name
177         end
178       end
179       assert_sorted(operator, sorted_values)
180     end
181   end
182
183   def assert_sorted(operator, sorted_items)
184     actually_checked_anything = false
185     previous = nil
186     sorted_items.each do |entry|
187       if !previous.nil?
188         assert_operator(previous, operator, entry,
189                         "Entries sorted incorrectly.")
190         actually_checked_anything = true
191       end
192       previous = entry
193     end
194     assert actually_checked_anything, "Didn't even find two items to compare."
195   end
196
197   # Even though the project_viewer tests go through other controllers,
198   # I'm putting them here so they're easy to find alongside the other
199   # project tests.
200   def check_new_project_link_fails(link_attrs)
201     @controller = Arvados::V1::LinksController.new
202     post :create, link: {
203       link_class: "permission",
204       name: "can_read",
205       head_uuid: groups(:aproject).uuid,
206     }.merge(link_attrs)
207     assert_includes(403..422, response.status)
208   end
209
210   test "user with project read permission can't add users to it" do
211     authorize_with :project_viewer
212     check_new_project_link_fails(tail_uuid: users(:spectator).uuid)
213   end
214
215   test "user with project read permission can't add items to it" do
216     authorize_with :project_viewer
217     check_new_project_link_fails(tail_uuid: collections(:baz_file).uuid)
218   end
219
220   test "user with project read permission can't rename items in it" do
221     authorize_with :project_viewer
222     @controller = Arvados::V1::LinksController.new
223     post :update, {
224       id: jobs(:running).uuid,
225       name: "Denied test name",
226     }
227     assert_includes(403..404, response.status)
228   end
229
230   test "user with project read permission can't remove items from it" do
231     @controller = Arvados::V1::PipelineTemplatesController.new
232     authorize_with :project_viewer
233     post :update, {
234       id: pipeline_templates(:two_part).uuid,
235       pipeline_template: {
236         owner_uuid: users(:project_viewer).uuid,
237       }
238     }
239     assert_response 403
240   end
241
242   test "user with project read permission can't delete it" do
243     authorize_with :project_viewer
244     post :destroy, {id: groups(:aproject).uuid}
245     assert_response 403
246   end
247
248   test 'get group-owned objects with limit' do
249     authorize_with :active
250     get :contents, {
251       id: groups(:aproject).uuid,
252       limit: 1,
253       format: :json,
254     }
255     assert_response :success
256     assert_operator 1, :<, json_response['items_available']
257     assert_equal 1, json_response['items'].count
258   end
259
260   test 'get group-owned objects with limit and offset' do
261     authorize_with :active
262     get :contents, {
263       id: groups(:aproject).uuid,
264       limit: 1,
265       offset: 12345,
266       format: :json,
267     }
268     assert_response :success
269     assert_operator 1, :<, json_response['items_available']
270     assert_equal 0, json_response['items'].count
271   end
272
273   test 'get group-owned objects with additional filter matching nothing' do
274     authorize_with :active
275     get :contents, {
276       id: groups(:aproject).uuid,
277       filters: [['uuid', 'in', ['foo_not_a_uuid','bar_not_a_uuid']]],
278       format: :json,
279     }
280     assert_response :success
281     assert_equal [], json_response['items']
282     assert_equal 0, json_response['items_available']
283   end
284
285   %w(offset limit).each do |arg|
286     ['foo', '', '1234five', '0x10', '-8'].each do |val|
287       test "Raise error on bogus #{arg} parameter #{val.inspect}" do
288         authorize_with :active
289         get :contents, {
290           :id => groups(:aproject).uuid,
291           :format => :json,
292           arg => val,
293         }
294         assert_response 422
295       end
296     end
297   end
298
299   test "Collection contents don't include manifest_text" do
300     authorize_with :active
301     get :contents, {
302       id: groups(:aproject).uuid,
303       filters: [["uuid", "is_a", "arvados#collection"]],
304       format: :json,
305     }
306     assert_response :success
307     refute(json_response["items"].any? { |c| not c["portable_data_hash"] },
308            "response included an item without a portable data hash")
309     refute(json_response["items"].any? { |c| c.include?("manifest_text") },
310            "response included an item with a manifest text")
311   end
312
313   test 'get writable_by list for owned group' do
314     authorize_with :active
315     get :show, {
316       id: groups(:aproject).uuid,
317       format: :json
318     }
319     assert_response :success
320     assert_not_nil(json_response['writable_by'],
321                    "Should receive uuid list in 'writable_by' field")
322     assert_includes(json_response['writable_by'], users(:active).uuid,
323                     "owner should be included in writable_by list")
324   end
325
326   test 'no writable_by list for group with read-only access' do
327     authorize_with :rominiadmin
328     get :show, {
329       id: groups(:testusergroup_admins).uuid,
330       format: :json
331     }
332     assert_response :success
333     assert_equal([json_response['owner_uuid']],
334                  json_response['writable_by'],
335                  "Should only see owner_uuid in 'writable_by' field")
336   end
337
338   test 'get writable_by list by admin user' do
339     authorize_with :admin
340     get :show, {
341       id: groups(:testusergroup_admins).uuid,
342       format: :json
343     }
344     assert_response :success
345     assert_not_nil(json_response['writable_by'],
346                    "Should receive uuid list in 'writable_by' field")
347     assert_includes(json_response['writable_by'],
348                     users(:admin).uuid,
349                     "Current user should be included in 'writable_by' field")
350   end
351
352   test 'creating subproject with duplicate name fails' do
353     authorize_with :active
354     post :create, {
355       group: {
356         name: 'A Project',
357         owner_uuid: users(:active).uuid,
358         group_class: 'project',
359       },
360     }
361     assert_response 422
362     response_errors = json_response['errors']
363     assert_not_nil response_errors, 'Expected error in response'
364     assert(response_errors.first.include?('duplicate key'),
365            "Expected 'duplicate key' error in #{response_errors.first}")
366   end
367
368   test 'creating duplicate named subproject succeeds with ensure_unique_name' do
369     authorize_with :active
370     post :create, {
371       group: {
372         name: 'A Project',
373         owner_uuid: users(:active).uuid,
374         group_class: 'project',
375       },
376       ensure_unique_name: true
377     }
378     assert_response :success
379     new_project = json_response
380     assert_not_equal(new_project['uuid'],
381                      groups(:aproject).uuid,
382                      "create returned same uuid as existing project")
383     assert_match(/^A Project \(\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z\)$/,
384                  new_project['name'])
385   end
386
387   test "unsharing a project results in hiding it from previously shared user" do
388     # remove sharing link for project
389     @controller = Arvados::V1::LinksController.new
390     authorize_with :admin
391     post :destroy, id: links(:share_starred_project_with_project_viewer).uuid
392     assert_response :success
393
394     # verify that the user can no longer see the project
395     @test_counter = 0  # Reset executed action counter
396     @controller = Arvados::V1::GroupsController.new
397     authorize_with :project_viewer
398     get :index, filters: [['group_class', '=', 'project']], format: :json
399     assert_response :success
400     found_projects = {}
401     json_response['items'].each do |g|
402       found_projects[g['uuid']] = g
403     end
404     assert_equal false, found_projects.include?(groups(:starred_and_shared_active_user_project).uuid)
405
406     # share the project
407     @test_counter = 0
408     @controller = Arvados::V1::LinksController.new
409     authorize_with :system_user
410     post :create, link: {
411       link_class: "permission",
412       name: "can_read",
413       head_uuid: groups(:starred_and_shared_active_user_project).uuid,
414       tail_uuid: users(:project_viewer).uuid,
415     }
416
417     # verify that project_viewer user can now see shared project again
418     @test_counter = 0
419     @controller = Arvados::V1::GroupsController.new
420     authorize_with :project_viewer
421     get :index, filters: [['group_class', '=', 'project']], format: :json
422     assert_response :success
423     found_projects = {}
424     json_response['items'].each do |g|
425       found_projects[g['uuid']] = g
426     end
427     assert_equal true, found_projects.include?(groups(:starred_and_shared_active_user_project).uuid)
428   end
429
430   [
431     [['owner_uuid', '!=', 'zzzzz-tpzed-xurymjxw79nv3jz'], 200,
432         'zzzzz-d1hrv-subprojpipeline', 'zzzzz-d1hrv-1xfj6xkicf2muk2'],
433     [["pipeline_instances.state", "not in", ["Complete", "Failed"]], 200,
434         'zzzzz-d1hrv-1xfj6xkicf2muk2', 'zzzzz-d1hrv-i3e77t9z5y8j9cc'],
435     [['container_requests.requesting_container_uuid', '=', nil], 200,
436         'zzzzz-xvhdp-cr4queuedcontnr', 'zzzzz-xvhdp-cr4requestercn2'],
437     [['container_requests.no_such_column', '=', nil], 422],
438     [['container_requests.', '=', nil], 422],
439     [['.requesting_container_uuid', '=', nil], 422],
440     [['no_such_table.uuid', '!=', 'zzzzz-tpzed-xurymjxw79nv3jz'], 422],
441   ].each do |filter, expect_code, expect_uuid, not_expect_uuid|
442     test "get contents with '#{filter}' filter" do
443       authorize_with :active
444       get :contents, filters: [filter], format: :json
445       assert_response expect_code
446       if expect_code == 200
447         assert_not_empty json_response['items']
448         item_uuids = json_response['items'].collect {|item| item['uuid']}
449         assert_includes(item_uuids, expect_uuid)
450         assert_not_includes(item_uuids, not_expect_uuid)
451       end
452     end
453   end
454
455   test 'get contents with jobs and pipeline instances disabled' do
456     Rails.configuration.disable_api_methods = ['jobs.index', 'pipeline_instances.index']
457
458     authorize_with :active
459     get :contents, {
460       id: groups(:aproject).uuid,
461       format: :json,
462     }
463     check_project_contents_response %w'arvados#pipelineInstance arvados#job'
464   end
465
466   test 'get contents with low max_index_database_read' do
467     # Some result will certainly have at least 12 bytes in a
468     # restricted column
469     Rails.configuration.max_index_database_read = 12
470     authorize_with :active
471     get :contents, {
472           id: groups(:aproject).uuid,
473           format: :json,
474         }
475     assert_response :success
476     assert_not_empty(json_response['items'])
477     assert_operator(json_response['items'].count,
478                     :<, json_response['items_available'])
479   end
480
481   test 'get contents, recursive=true' do
482     authorize_with :active
483     params = {
484       id: groups(:aproject).uuid,
485       recursive: true,
486       format: :json,
487     }
488     get :contents, params
489     owners = json_response['items'].map do |item|
490       item['owner_uuid']
491     end
492     assert_includes(owners, groups(:aproject).uuid)
493     assert_includes(owners, groups(:asubproject).uuid)
494   end
495
496   [false, nil].each do |recursive|
497     test "get contents, recursive=#{recursive.inspect}" do
498       authorize_with :active
499       params = {
500         id: groups(:aproject).uuid,
501         format: :json,
502       }
503       params[:recursive] = false if recursive == false
504       get :contents, params
505       owners = json_response['items'].map do |item|
506         item['owner_uuid']
507       end
508       assert_includes(owners, groups(:aproject).uuid)
509       refute_includes(owners, groups(:asubproject).uuid)
510     end
511   end
512
513   test 'get home project contents, recursive=true' do
514     authorize_with :active
515     get :contents, {
516           id: users(:active).uuid,
517           recursive: true,
518           format: :json,
519         }
520     owners = json_response['items'].map do |item|
521       item['owner_uuid']
522     end
523     assert_includes(owners, users(:active).uuid)
524     assert_includes(owners, groups(:aproject).uuid)
525     assert_includes(owners, groups(:asubproject).uuid)
526   end
527
528   ### trashed project tests ###
529
530   [:active, :admin].each do |auth|
531     # project: to query,    to untrash,    is visible, parent contents listing success
532     [[:trashed_project,     [],                 false, true],
533      [:trashed_project,     [:trashed_project], true,  true],
534      [:trashed_subproject,  [],                 false, false],
535      [:trashed_subproject,  [:trashed_project], true,  true],
536      [:trashed_subproject3, [:trashed_project], false, true],
537      [:trashed_subproject3, [:trashed_subproject3], false, false],
538      [:trashed_subproject3, [:trashed_project, :trashed_subproject3], true, true],
539     ].each do |project, untrash, visible, success|
540
541       test "contents listing #{project} #{untrash} as #{auth}" do
542         authorize_with auth
543         untrash.each do |pr|
544           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
545         end
546         get :contents, {
547               id: groups(project).owner_uuid,
548               format: :json
549             }
550         if success
551           assert_response :success
552           item_uuids = json_response['items'].map do |item|
553             item['uuid']
554           end
555           if visible
556             assert_includes(item_uuids, groups(project).uuid)
557           else
558             assert_not_includes(item_uuids, groups(project).uuid)
559           end
560         else
561           assert_response 404
562         end
563       end
564
565       test "contents of #{project} #{untrash} as #{auth}" do
566         authorize_with auth
567         untrash.each do |pr|
568           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
569         end
570         get :contents, {
571               id: groups(project).uuid,
572               format: :json
573             }
574         if visible
575           assert_response :success
576         else
577           assert_response 404
578         end
579       end
580
581       test "index #{project} #{untrash} as #{auth}" do
582         authorize_with auth
583         untrash.each do |pr|
584           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
585         end
586         get :index, {
587               format: :json,
588             }
589         assert_response :success
590         item_uuids = json_response['items'].map do |item|
591           item['uuid']
592         end
593         if visible
594           assert_includes(item_uuids, groups(project).uuid)
595         else
596           assert_not_includes(item_uuids, groups(project).uuid)
597         end
598       end
599
600       test "show #{project} #{untrash} as #{auth}" do
601         authorize_with auth
602         untrash.each do |pr|
603           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
604         end
605         get :show, {
606               id: groups(project).uuid,
607               format: :json
608             }
609         if visible
610           assert_response :success
611         else
612           assert_response 404
613         end
614       end
615
616       test "show include_trash #{project} #{untrash} as #{auth}" do
617         authorize_with auth
618         untrash.each do |pr|
619           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
620         end
621         get :show, {
622               id: groups(project).uuid,
623               format: :json,
624               include_trash: true
625             }
626         assert_response :success
627       end
628
629       test "index include_trash #{project} #{untrash} as #{auth}" do
630         authorize_with auth
631         untrash.each do |pr|
632           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
633         end
634         get :index, {
635               format: :json,
636               include_trash: true
637             }
638         assert_response :success
639         item_uuids = json_response['items'].map do |item|
640           item['uuid']
641         end
642         assert_includes(item_uuids, groups(project).uuid)
643       end
644     end
645
646     test "delete project #{auth}" do
647       authorize_with auth
648       [:trashed_project].each do |pr|
649         Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
650       end
651       assert !Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
652       post :destroy, {
653             id: groups(:trashed_project).uuid,
654             format: :json,
655           }
656       assert_response :success
657       assert Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
658     end
659
660     test "untrash project #{auth}" do
661       authorize_with auth
662       assert Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
663       post :untrash, {
664             id: groups(:trashed_project).uuid,
665             format: :json,
666           }
667       assert_response :success
668       assert !Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
669     end
670
671     test "untrash project with name conflict #{auth}" do
672       authorize_with auth
673       [:trashed_project].each do |pr|
674         Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
675       end
676       gc = Group.create!({owner_uuid: "zzzzz-j7d0g-trashedproject1",
677                          name: "trashed subproject 3",
678                          group_class: "project"})
679       post :untrash, {
680             id: groups(:trashed_subproject3).uuid,
681             format: :json,
682             ensure_unique_name: true
683            }
684       assert_response :success
685       assert_match /^trashed subproject 3 \(\d{4}-\d\d-\d\d.*?Z\)$/, json_response['name']
686     end
687
688     test "move trashed subproject to new owner #{auth}" do
689       authorize_with auth
690       assert_nil Group.readable_by(users(auth)).where(uuid: groups(:trashed_subproject).uuid).first
691       put :update, {
692             id: groups(:trashed_subproject).uuid,
693             group: {
694               owner_uuid: users(:active).uuid
695             },
696             include_trash: true,
697             format: :json,
698           }
699       assert_response :success
700       assert_not_nil Group.readable_by(users(auth)).where(uuid: groups(:trashed_subproject).uuid).first
701     end
702   end
703
704   test 'get shared owned by another user' do
705     authorize_with :user_bar_in_sharing_group
706
707     act_as_system_user do
708       Link.create!(
709         tail_uuid: users(:user_bar_in_sharing_group).uuid,
710         link_class: 'permission',
711         name: 'can_read',
712         head_uuid: groups(:project_owned_by_foo).uuid)
713     end
714
715     get :shared, {:filters => [["group_class", "=", "project"]], :include => "owner_uuid"}
716
717     assert_equal 1, json_response['items'].length
718     assert_equal json_response['items'][0]["uuid"], groups(:project_owned_by_foo).uuid
719
720     assert_equal 1, json_response['included'].length
721     assert_equal json_response['included'][0]["uuid"], users(:user_foo_in_sharing_group).uuid
722   end
723
724   test 'get shared, owned by unreadable project' do
725     authorize_with :user_bar_in_sharing_group
726
727     act_as_system_user do
728       Group.find_by_uuid(groups(:project_owned_by_foo).uuid).update!(owner_uuid: groups(:aproject).uuid)
729       Link.create!(
730         tail_uuid: users(:user_bar_in_sharing_group).uuid,
731         link_class: 'permission',
732         name: 'can_read',
733         head_uuid: groups(:project_owned_by_foo).uuid)
734     end
735
736     get :shared, {:filters => [["group_class", "=", "project"]], :include => "owner_uuid"}
737
738     assert_equal 1, json_response['items'].length
739     assert_equal json_response['items'][0]["uuid"], groups(:project_owned_by_foo).uuid
740
741     assert_equal 0, json_response['included'].length
742   end
743
744   test 'get shared, owned by non-project' do
745     authorize_with :user_bar_in_sharing_group
746
747     act_as_system_user do
748       Group.find_by_uuid(groups(:project_owned_by_foo).uuid).update!(owner_uuid: groups(:group_for_sharing_tests).uuid)
749     end
750
751     get :shared, {:filters => [["group_class", "=", "project"]], :include => "owner_uuid"}
752
753     assert_equal 1, json_response['items'].length
754     assert_equal json_response['items'][0]["uuid"], groups(:project_owned_by_foo).uuid
755
756     assert_equal 1, json_response['included'].length
757     assert_equal json_response['included'][0]["uuid"], groups(:group_for_sharing_tests).uuid
758   end
759
760 end