From b92e7103fcced2d62000ed382848219016484f7b Mon Sep 17 00:00:00 2001
From: Bob Van Landuyt <bob@vanlanduyt.co>
Date: Tue, 26 Sep 2017 14:12:12 +0200
Subject: [PATCH] Fix nesting bug when rendering children of a shared subgroup

---
 app/finders/group_descendants_finder.rb    |  2 +-
 app/serializers/group_child_serializer.rb  |  2 +-
 spec/controllers/groups_controller_spec.rb | 26 ++++++++++++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb
index 07178a026e8..4ed9c0ea39a 100644
--- a/app/finders/group_descendants_finder.rb
+++ b/app/finders/group_descendants_finder.rb
@@ -64,7 +64,7 @@ class GroupDescendantsFinder
       subgroups_with_counts = ancestors_for_project_search.with_route.select(group_selects) | subgroups_with_counts
     end
 
-    @children = subgroups_with_counts + projects.preload(:route)
+    @children = subgroups_with_counts + projects.with_route
   end
 
   def direct_child_groups
diff --git a/app/serializers/group_child_serializer.rb b/app/serializers/group_child_serializer.rb
index ba81f99fff4..6fa269ee5c0 100644
--- a/app/serializers/group_child_serializer.rb
+++ b/app/serializers/group_child_serializer.rb
@@ -41,7 +41,7 @@ class GroupChildSerializer < BaseSerializer
           .merge(children: Array.wrap(serializer.represent_hierarchy(children, opts)))
       end
     elsif hierarchy.is_a?(Array)
-      hierarchy.map { |child| serializer.represent_hierarchy(child, opts) }
+      hierarchy.map { |child| serializer.represent_hierarchy(child, opts) }.flatten
     else
       serializer.represent(hierarchy, opts)
     end
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 84207144036..ff76eaee25f 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -293,6 +293,32 @@ describe GroupsController do
           expect(matched_group_json['id']).to eq(matched_group.id)
         end
 
+        it 'merges the trees correctly' do
+          shared_subgroup = create(:group, :public, parent: group, path: 'hardware')
+          matched_project_1 = create(:project, :public, namespace: shared_subgroup, name: 'mobile-soc')
+
+          l2_subgroup = create(:group, :public, parent: shared_subgroup, path: 'broadcom')
+          l3_subgroup = create(:group, :public,  parent: l2_subgroup, path: 'wifi-group')
+          matched_project_2 = create(:project, :public, namespace: l3_subgroup, name: 'mobile')
+
+          get :children, id: group.to_param, filter: 'mobile', format: :json
+
+          shared_group_json = json_response.first
+          expect(shared_group_json['id']).to eq(shared_subgroup.id)
+
+          matched_project_1_json = shared_group_json['children'].detect { |child| child['type'] == 'project' }
+          expect(matched_project_1_json['id']).to eq(matched_project_1.id)
+
+          l2_subgroup_json = shared_group_json['children'].detect { |child| child['type'] == 'group' }
+          expect(l2_subgroup_json['id']).to eq(l2_subgroup.id)
+
+          l3_subgroup_json = l2_subgroup_json['children'].first
+          expect(l3_subgroup_json['id']).to eq(l3_subgroup.id)
+
+          matched_project_2_json = l3_subgroup_json['children'].first
+          expect(matched_project_2_json['id']).to eq(matched_project_2.id)
+        end
+
         it 'includes pagination headers' do
           2.times { |i| create(:group, :public, parent: public_subgroup, name: "filterme#{i}") }
 
-- 
2.30.9