From ab529cddac543c2052f7347d22e87f9a6ed04182 Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Thu, 13 Apr 2017 16:20:04 +0100
Subject: [PATCH] Refactor group search out of global search

---
 app/services/search/global_service.rb       | 11 +++---
 app/services/search/group_service.rb        | 18 ++++++++++
 app/services/search_service.rb              |  2 ++
 spec/services/search/global_service_spec.rb | 21 -----------
 spec/services/search/group_service_spec.rb  | 40 +++++++++++++++++++++
 5 files changed, 64 insertions(+), 28 deletions(-)
 create mode 100644 app/services/search/group_service.rb
 create mode 100644 spec/services/search/group_service_spec.rb

diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index 8409b592b72f..ff188102b621 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -7,16 +7,13 @@ def initialize(user, params)
     end
 
     def execute
-      group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
-      projects = ProjectsFinder.new(current_user: current_user).execute
-
-      if group
-        projects = projects.inside_path(group.full_path)
-      end
-
       Gitlab::SearchResults.new(current_user, projects, params[:search])
     end
 
+    def projects
+      @projects ||= ProjectsFinder.new(current_user: current_user).execute
+    end
+
     def scope
       @scope ||= begin
         allowed_scopes = %w[issues merge_requests milestones]
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
new file mode 100644
index 000000000000..29478e3251f3
--- /dev/null
+++ b/app/services/search/group_service.rb
@@ -0,0 +1,18 @@
+module Search
+  class GroupService < Search::GlobalService
+    attr_accessor :group
+
+    def initialize(user, group, params)
+      super(user, params)
+
+      @group = group
+    end
+
+    def projects
+      return Project.none unless group
+      return @projects if defined? @projects
+
+      @projects = super.inside_path(group.full_path)
+    end
+  end
+end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 8d46a8dab3e0..22736c717254 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -54,6 +54,8 @@ def search_service
         Search::ProjectService.new(project, current_user, params)
       elsif show_snippets?
         Search::SnippetService.new(current_user, params)
+      elsif group
+        Search::GroupService.new(current_user, group, params)
       else
         Search::GlobalService.new(current_user, params)
       end
diff --git a/spec/services/search/global_service_spec.rb b/spec/services/search/global_service_spec.rb
index 2531607acad7..cbf4f56213da 100644
--- a/spec/services/search/global_service_spec.rb
+++ b/spec/services/search/global_service_spec.rb
@@ -40,27 +40,6 @@
 
         expect(results.objects('projects')).to match_array [found_project]
       end
-
-      context 'nested group' do
-        let!(:nested_group) { create(:group, :nested) }
-        let!(:project) { create(:empty_project, namespace: nested_group) }
-
-        before do
-          project.add_master(user)
-        end
-
-        it 'returns result from nested group' do
-          results = Search::GlobalService.new(user, search: project.path).execute
-
-          expect(results.objects('projects')).to match_array [project]
-        end
-
-        it 'returns result from descendants when search inside group' do
-          results = Search::GlobalService.new(user, search: project.path, group_id: nested_group.parent).execute
-
-          expect(results.objects('projects')).to match_array [project]
-        end
-      end
     end
   end
 end
diff --git a/spec/services/search/group_service_spec.rb b/spec/services/search/group_service_spec.rb
new file mode 100644
index 000000000000..38f264f6e7b9
--- /dev/null
+++ b/spec/services/search/group_service_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe Search::GroupService, services: true do
+  shared_examples_for 'group search' do
+    context 'finding projects by name' do
+      let(:user) { create(:user) }
+      let(:term) { "Project Name" }
+      let(:nested_group) { create(:group, :nested) }
+
+      # These projects shouldn't be found
+      let!(:outside_project) { create(:empty_project, :public, name: "Outside #{term}") }
+      let!(:private_project) { create(:empty_project, :private, namespace: nested_group, name: "Private #{term}" )}
+      let!(:other_project)   { create(:empty_project, :public, namespace: nested_group, name: term.reverse) }
+
+      # These projects should be found
+      let!(:project1) { create(:empty_project, :internal, namespace: nested_group, name: "Inner #{term} 1") }
+      let!(:project2) { create(:empty_project, :internal, namespace: nested_group, name: "Inner #{term} 2") }
+      let!(:project3) { create(:empty_project, :internal, namespace: nested_group.parent, name: "Outer #{term}") }
+
+      let(:results) { Search::GroupService.new(user, search_group, search: term).execute }
+      subject { results.objects('projects') }
+
+      context 'in parent group' do
+        let(:search_group) { nested_group.parent }
+
+        it { is_expected.to match_array([project1, project2, project3]) }
+      end
+
+      context 'in subgroup' do
+        let(:search_group) { nested_group }
+
+        it { is_expected.to match_array([project1, project2]) }
+      end
+    end
+  end
+
+  describe 'basic search' do
+    include_examples 'group search'
+  end
+end
-- 
GitLab