Commit e247a7c9eb52d31e99394364cb325f7cb401786e

Authored by Dmitriy Zaporozhets
2 parents 898e2acd cb9cf077

Merge pull request #5377 from tsigo/autocomplete_refactor

Refactor search_autocomplete_source
app/helpers/application_helper.rb
... ... @@ -98,51 +98,6 @@ module ApplicationHelper
98 98 grouped_options_for_select(options, @ref || @project.default_branch)
99 99 end
100 100  
101   - def search_autocomplete_source
102   - return unless current_user
103   -
104   - projects = current_user.authorized_projects.map { |p| { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } }
105   - groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
106   -
107   - default_nav = [
108   - { label: "My Profile settings", url: profile_path },
109   - { label: "My SSH Keys", url: profile_keys_path },
110   - { label: "My Dashboard", url: root_path },
111   - { label: "Admin Section", url: admin_root_path },
112   - ]
113   -
114   - help_nav = [
115   - { label: "help: API Help", url: help_api_path },
116   - { label: "help: Markdown Help", url: help_markdown_path },
117   - { label: "help: Permissions Help", url: help_permissions_path },
118   - { label: "help: Public Access Help", url: help_public_access_path },
119   - { label: "help: Rake Tasks Help", url: help_raketasks_path },
120   - { label: "help: SSH Keys Help", url: help_ssh_path },
121   - { label: "help: System Hooks Help", url: help_system_hooks_path },
122   - { label: "help: Web Hooks Help", url: help_web_hooks_path },
123   - { label: "help: Workflow Help", url: help_workflow_path },
124   - ]
125   -
126   - project_nav = []
127   - if @project && @project.repository.exists? && @project.repository.root_ref
128   - project_nav = [
129   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Files", url: project_tree_path(@project, @ref || @project.repository.root_ref) },
130   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Commits", url: project_commits_path(@project, @ref || @project.repository.root_ref) },
131   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Network", url: project_network_path(@project, @ref || @project.repository.root_ref) },
132   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Graph", url: project_graph_path(@project, @ref || @project.repository.root_ref) },
133   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Issues", url: project_issues_path(@project) },
134   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Merge Requests", url: project_merge_requests_path(@project) },
135   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Milestones", url: project_milestones_path(@project) },
136   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Snippets", url: project_snippets_path(@project) },
137   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Team", url: project_team_index_path(@project) },
138   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Wall", url: project_wall_path(@project) },
139   - { label: "#{simple_sanitize(@project.name_with_namespace)} - Wiki", url: project_wikis_path(@project) },
140   - ]
141   - end
142   -
143   - [groups, projects, default_nav, project_nav, help_nav].flatten.to_json
144   - end
145   -
146 101 def emoji_autocomplete_source
147 102 # should be an array of strings
148 103 # so to_s can be called, because it is sufficient and to_json is too slow
... ... @@ -192,7 +147,7 @@ module ApplicationHelper
192 147 alt: "Sign in with #{provider.to_s.titleize}")
193 148 end
194 149  
195   - def simple_sanitize str
  150 + def simple_sanitize(str)
196 151 sanitize(str, tags: %w(a span))
197 152 end
198 153  
... ...
app/helpers/search_helper.rb 0 → 100644
... ... @@ -0,0 +1,78 @@
  1 +module SearchHelper
  2 + def search_autocomplete_source
  3 + return unless current_user
  4 +
  5 + [
  6 + groups_autocomplete,
  7 + projects_autocomplete,
  8 + default_autocomplete,
  9 + project_autocomplete,
  10 + help_autocomplete
  11 + ].flatten.to_json
  12 + end
  13 +
  14 + private
  15 +
  16 + # Autocomplete results for various settings pages
  17 + def default_autocomplete
  18 + [
  19 + { label: "My Profile settings", url: profile_path },
  20 + { label: "My SSH Keys", url: profile_keys_path },
  21 + { label: "My Dashboard", url: root_path },
  22 + { label: "Admin Section", url: admin_root_path },
  23 + ]
  24 + end
  25 +
  26 + # Autocomplete results for internal help pages
  27 + def help_autocomplete
  28 + [
  29 + { label: "help: API Help", url: help_api_path },
  30 + { label: "help: Markdown Help", url: help_markdown_path },
  31 + { label: "help: Permissions Help", url: help_permissions_path },
  32 + { label: "help: Public Access Help", url: help_public_access_path },
  33 + { label: "help: Rake Tasks Help", url: help_raketasks_path },
  34 + { label: "help: SSH Keys Help", url: help_ssh_path },
  35 + { label: "help: System Hooks Help", url: help_system_hooks_path },
  36 + { label: "help: Web Hooks Help", url: help_web_hooks_path },
  37 + { label: "help: Workflow Help", url: help_workflow_path },
  38 + ]
  39 + end
  40 +
  41 + # Autocomplete results for the current project, if it's defined
  42 + def project_autocomplete
  43 + if @project && @project.repository.exists? && @project.repository.root_ref
  44 + prefix = simple_sanitize(@project.name_with_namespace)
  45 + ref = @ref || @project.repository.root_ref
  46 +
  47 + [
  48 + { label: "#{prefix} - Files", url: project_tree_path(@project, ref) },
  49 + { label: "#{prefix} - Commits", url: project_commits_path(@project, ref) },
  50 + { label: "#{prefix} - Network", url: project_network_path(@project, ref) },
  51 + { label: "#{prefix} - Graph", url: project_graph_path(@project, ref) },
  52 + { label: "#{prefix} - Issues", url: project_issues_path(@project) },
  53 + { label: "#{prefix} - Merge Requests", url: project_merge_requests_path(@project) },
  54 + { label: "#{prefix} - Milestones", url: project_milestones_path(@project) },
  55 + { label: "#{prefix} - Snippets", url: project_snippets_path(@project) },
  56 + { label: "#{prefix} - Team", url: project_team_index_path(@project) },
  57 + { label: "#{prefix} - Wall", url: project_wall_path(@project) },
  58 + { label: "#{prefix} - Wiki", url: project_wikis_path(@project) },
  59 + ]
  60 + else
  61 + []
  62 + end
  63 + end
  64 +
  65 + # Autocomplete results for the current user's groups
  66 + def groups_autocomplete
  67 + current_user.authorized_groups.map do |group|
  68 + { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) }
  69 + end
  70 + end
  71 +
  72 + # Autocomplete results for the current user's projects
  73 + def projects_autocomplete
  74 + current_user.authorized_projects.map do |p|
  75 + { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
  76 + end
  77 + end
  78 +end
... ...
spec/helpers/application_helper_spec.rb
... ... @@ -123,4 +123,21 @@ describe ApplicationHelper do
123 123 end
124 124 end
125 125  
  126 + describe "simple_sanitize" do
  127 + let(:a_tag) { '<a href="#">Foo</a>' }
  128 +
  129 + it "allows the a tag" do
  130 + simple_sanitize(a_tag).should == a_tag
  131 + end
  132 +
  133 + it "allows the span tag" do
  134 + input = '<span class="foo">Bar</span>'
  135 + simple_sanitize(input).should == input
  136 + end
  137 +
  138 + it "disallows other tags" do
  139 + input = "<strike><b>#{a_tag}</b></strike>"
  140 + simple_sanitize(input).should == a_tag
  141 + end
  142 + end
126 143 end
... ...
spec/helpers/search_helper_spec.rb 0 → 100644
... ... @@ -0,0 +1,64 @@
  1 +require 'spec_helper'
  2 +
  3 +describe SearchHelper do
  4 + # Override simple_sanitize for our testing purposes
  5 + def simple_sanitize(str)
  6 + str
  7 + end
  8 +
  9 + describe 'search_autocomplete_source' do
  10 + context "with no current user" do
  11 + before { stub!(:current_user).and_return(nil) }
  12 +
  13 + it "it returns nil" do
  14 + search_autocomplete_source.should be_nil
  15 + end
  16 + end
  17 +
  18 + context "with a user" do
  19 + let(:user) { create(:user) }
  20 + let(:result) { JSON.parse(search_autocomplete_source) }
  21 +
  22 + before do
  23 + stub!(:current_user).and_return(user)
  24 + end
  25 +
  26 + it "includes Help sections" do
  27 + result.select { |h| h['label'] =~ /^help:/ }.length.should == 9
  28 + end
  29 +
  30 + it "includes default sections" do
  31 + result.count { |h| h['label'] =~ /^(My|Admin)\s/ }.should == 4
  32 + end
  33 +
  34 + it "includes the user's groups" do
  35 + create(:group).add_owner(user)
  36 + result.count { |h| h['label'] =~ /^group:/ }.should == 1
  37 + end
  38 +
  39 + it "includes the user's projects" do
  40 + create(:project, namespace: create(:namespace, owner: user))
  41 + result.count { |h| h['label'] =~ /^project:/ }.should == 1
  42 + end
  43 +
  44 + context "with a current project" do
  45 + before { @project = create(:project_with_code) }
  46 +
  47 + it "includes project-specific sections" do
  48 + result.count { |h| h['label'] =~ /^#{@project.name_with_namespace} - / }.should == 11
  49 + end
  50 +
  51 + it "uses @ref in urls if defined" do
  52 + @ref = "foo_bar"
  53 + result.count { |h| h['url'] == project_tree_path(@project, @ref) }.should == 1
  54 + end
  55 + end
  56 +
  57 + context "with no current project" do
  58 + it "does not include project-specific sections" do
  59 + result.count { |h| h['label'] =~ /Files$/ }.should == 0
  60 + end
  61 + end
  62 + end
  63 + end
  64 +end
... ...