PageRenderTime 60ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/spec/lib/gitlab/project_search_results_spec.rb

https://gitlab.com/dandunckelman/gitlab-ce
Ruby | 371 lines | 278 code | 87 blank | 6 comment | 1 complexity | 48cbea1b2fd82fd80dbfd0149dd6ec3f MD5 | raw file
  1. require 'spec_helper'
  2. describe Gitlab::ProjectSearchResults do
  3. let(:user) { create(:user) }
  4. let(:project) { create(:empty_project) }
  5. let(:query) { 'hello world' }
  6. describe 'initialize with empty ref' do
  7. let(:results) { described_class.new(user, project, query, '') }
  8. it { expect(results.project).to eq(project) }
  9. it { expect(results.query).to eq('hello world') }
  10. end
  11. describe 'initialize with ref' do
  12. let(:ref) { 'refs/heads/test' }
  13. let(:results) { described_class.new(user, project, query, ref) }
  14. it { expect(results.project).to eq(project) }
  15. it { expect(results.repository_ref).to eq(ref) }
  16. it { expect(results.query).to eq('hello world') }
  17. end
  18. describe 'blob search' do
  19. let(:project) { create(:project, :public, :repository) }
  20. subject(:results) { described_class.new(user, project, 'files').objects('blobs') }
  21. context 'when repository is disabled' do
  22. let(:project) { create(:project, :public, :repository, :repository_disabled) }
  23. it 'hides blobs from members' do
  24. project.add_reporter(user)
  25. is_expected.to be_empty
  26. end
  27. it 'hides blobs from non-members' do
  28. is_expected.to be_empty
  29. end
  30. end
  31. context 'when repository is internal' do
  32. let(:project) { create(:project, :public, :repository, :repository_private) }
  33. it 'finds blobs for members' do
  34. project.add_reporter(user)
  35. is_expected.not_to be_empty
  36. end
  37. it 'hides blobs from non-members' do
  38. is_expected.to be_empty
  39. end
  40. end
  41. it 'finds by name' do
  42. expect(results.map(&:first)).to include('files/images/wm.svg')
  43. end
  44. it 'finds by content' do
  45. blob = results.select { |result| result.first == "CHANGELOG" }.flatten.last
  46. expect(blob.filename).to eq("CHANGELOG")
  47. end
  48. describe 'parsing results' do
  49. let(:results) { project.repository.search_files_by_content('feature', 'master') }
  50. let(:search_result) { results.first }
  51. subject { described_class.parse_search_result(search_result) }
  52. it "returns a valid FoundBlob" do
  53. is_expected.to be_an Gitlab::SearchResults::FoundBlob
  54. expect(subject.id).to be_nil
  55. expect(subject.path).to eq('CHANGELOG')
  56. expect(subject.filename).to eq('CHANGELOG')
  57. expect(subject.basename).to eq('CHANGELOG')
  58. expect(subject.ref).to eq('master')
  59. expect(subject.startline).to eq(188)
  60. expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n")
  61. end
  62. context "when filename has extension" do
  63. let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" }
  64. it { expect(subject.path).to eq('CONTRIBUTE.md') }
  65. it { expect(subject.filename).to eq('CONTRIBUTE.md') }
  66. it { expect(subject.basename).to eq('CONTRIBUTE') }
  67. end
  68. context "when file under directory" do
  69. let(:search_result) { "master:a/b/c.md:5:a b c\n" }
  70. it { expect(subject.path).to eq('a/b/c.md') }
  71. it { expect(subject.filename).to eq('a/b/c.md') }
  72. it { expect(subject.basename).to eq('a/b/c') }
  73. end
  74. end
  75. end
  76. describe 'wiki search' do
  77. let(:project) { create(:project, :public) }
  78. let(:wiki) { build(:project_wiki, project: project) }
  79. let!(:wiki_page) { wiki.create_page('Title', 'Content') }
  80. subject(:results) { described_class.new(user, project, 'Content').objects('wiki_blobs') }
  81. context 'when wiki is disabled' do
  82. let(:project) { create(:project, :public, :wiki_disabled) }
  83. it 'hides wiki blobs from members' do
  84. project.add_reporter(user)
  85. is_expected.to be_empty
  86. end
  87. it 'hides wiki blobs from non-members' do
  88. is_expected.to be_empty
  89. end
  90. end
  91. context 'when wiki is internal' do
  92. let(:project) { create(:project, :public, :wiki_private) }
  93. it 'finds wiki blobs for guest' do
  94. project.add_guest(user)
  95. is_expected.not_to be_empty
  96. end
  97. it 'hides wiki blobs from non-members' do
  98. is_expected.to be_empty
  99. end
  100. end
  101. it 'finds by content' do
  102. expect(results).to include("master:Title.md:1:Content\n")
  103. end
  104. end
  105. it 'does not list issues on private projects' do
  106. issue = create(:issue, project: project)
  107. results = described_class.new(user, project, issue.title)
  108. expect(results.objects('issues')).not_to include issue
  109. end
  110. describe 'confidential issues' do
  111. let(:query) { 'issue' }
  112. let(:author) { create(:user) }
  113. let(:assignee) { create(:user) }
  114. let(:non_member) { create(:user) }
  115. let(:member) { create(:user) }
  116. let(:admin) { create(:admin) }
  117. let(:project) { create(:empty_project, :internal) }
  118. let!(:issue) { create(:issue, project: project, title: 'Issue 1') }
  119. let!(:security_issue_1) { create(:issue, :confidential, project: project, title: 'Security issue 1', author: author) }
  120. let!(:security_issue_2) { create(:issue, :confidential, title: 'Security issue 2', project: project, assignees: [assignee]) }
  121. it 'does not list project confidential issues for non project members' do
  122. results = described_class.new(non_member, project, query)
  123. issues = results.objects('issues')
  124. expect(issues).to include issue
  125. expect(issues).not_to include security_issue_1
  126. expect(issues).not_to include security_issue_2
  127. expect(results.issues_count).to eq 1
  128. end
  129. it 'does not list project confidential issues for project members with guest role' do
  130. project.team << [member, :guest]
  131. results = described_class.new(member, project, query)
  132. issues = results.objects('issues')
  133. expect(issues).to include issue
  134. expect(issues).not_to include security_issue_1
  135. expect(issues).not_to include security_issue_2
  136. expect(results.issues_count).to eq 1
  137. end
  138. it 'lists project confidential issues for author' do
  139. results = described_class.new(author, project, query)
  140. issues = results.objects('issues')
  141. expect(issues).to include issue
  142. expect(issues).to include security_issue_1
  143. expect(issues).not_to include security_issue_2
  144. expect(results.issues_count).to eq 2
  145. end
  146. it 'lists project confidential issues for assignee' do
  147. results = described_class.new(assignee, project, query)
  148. issues = results.objects('issues')
  149. expect(issues).to include issue
  150. expect(issues).not_to include security_issue_1
  151. expect(issues).to include security_issue_2
  152. expect(results.issues_count).to eq 2
  153. end
  154. it 'lists project confidential issues for project members' do
  155. project.team << [member, :developer]
  156. results = described_class.new(member, project, query)
  157. issues = results.objects('issues')
  158. expect(issues).to include issue
  159. expect(issues).to include security_issue_1
  160. expect(issues).to include security_issue_2
  161. expect(results.issues_count).to eq 3
  162. end
  163. it 'lists all project issues for admin' do
  164. results = described_class.new(admin, project, query)
  165. issues = results.objects('issues')
  166. expect(issues).to include issue
  167. expect(issues).to include security_issue_1
  168. expect(issues).to include security_issue_2
  169. expect(results.issues_count).to eq 3
  170. end
  171. end
  172. describe 'notes search' do
  173. it 'lists notes' do
  174. project = create(:empty_project, :public)
  175. note = create(:note, project: project)
  176. results = described_class.new(user, project, note.note)
  177. expect(results.objects('notes')).to include note
  178. end
  179. it "doesn't list issue notes when access is restricted" do
  180. project = create(:empty_project, :public, :issues_private)
  181. note = create(:note_on_issue, project: project)
  182. results = described_class.new(user, project, note.note)
  183. expect(results.objects('notes')).not_to include note
  184. end
  185. it "doesn't list merge_request notes when access is restricted" do
  186. project = create(:empty_project, :public, :merge_requests_private)
  187. note = create(:note_on_merge_request, project: project)
  188. results = described_class.new(user, project, note.note)
  189. expect(results.objects('notes')).not_to include note
  190. end
  191. end
  192. # Examples for commit access level test
  193. #
  194. # params:
  195. # * search_phrase
  196. # * commit
  197. #
  198. shared_examples 'access restricted commits' do
  199. context 'when project is internal' do
  200. let(:project) { create(:project, :internal, :repository) }
  201. it 'does not search if user is not authenticated' do
  202. commits = described_class.new(nil, project, search_phrase).objects('commits')
  203. expect(commits).to be_empty
  204. end
  205. it 'searches if user is authenticated' do
  206. commits = described_class.new(user, project, search_phrase).objects('commits')
  207. expect(commits).to contain_exactly commit
  208. end
  209. end
  210. context 'when project is private' do
  211. let!(:creator) { create(:user, username: 'private-project-author') }
  212. let!(:private_project) { create(:project, :private, :repository, creator: creator, namespace: creator.namespace) }
  213. let(:team_master) do
  214. user = create(:user, username: 'private-project-master')
  215. private_project.team << [user, :master]
  216. user
  217. end
  218. let(:team_reporter) do
  219. user = create(:user, username: 'private-project-reporter')
  220. private_project.team << [user, :reporter]
  221. user
  222. end
  223. it 'does not show commit to stranger' do
  224. commits = described_class.new(nil, private_project, search_phrase).objects('commits')
  225. expect(commits).to be_empty
  226. end
  227. context 'team access' do
  228. it 'shows commit to creator' do
  229. commits = described_class.new(creator, private_project, search_phrase).objects('commits')
  230. expect(commits).to contain_exactly commit
  231. end
  232. it 'shows commit to master' do
  233. commits = described_class.new(team_master, private_project, search_phrase).objects('commits')
  234. expect(commits).to contain_exactly commit
  235. end
  236. it 'shows commit to reporter' do
  237. commits = described_class.new(team_reporter, private_project, search_phrase).objects('commits')
  238. expect(commits).to contain_exactly commit
  239. end
  240. end
  241. end
  242. end
  243. describe 'commit search' do
  244. context 'by commit message' do
  245. let(:project) { create(:project, :public, :repository) }
  246. let(:commit) { project.repository.commit('59e29889be61e6e0e5e223bfa9ac2721d31605b8') }
  247. let(:message) { 'Sorry, I did a mistake' }
  248. it 'finds commit by message' do
  249. commits = described_class.new(user, project, message).objects('commits')
  250. expect(commits).to contain_exactly commit
  251. end
  252. it 'handles when no commit match' do
  253. commits = described_class.new(user, project, 'not really an existing description').objects('commits')
  254. expect(commits).to be_empty
  255. end
  256. it_behaves_like 'access restricted commits' do
  257. let(:search_phrase) { message }
  258. let(:commit) { project.repository.commit('59e29889be61e6e0e5e223bfa9ac2721d31605b8') }
  259. end
  260. end
  261. context 'by commit hash' do
  262. let(:project) { create(:project, :public, :repository) }
  263. let(:commit) { project.repository.commit('0b4bc9a') }
  264. commit_hashes = { short: '0b4bc9a', full: '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
  265. commit_hashes.each do |type, commit_hash|
  266. it "shows commit by #{type} hash id" do
  267. commits = described_class.new(user, project, commit_hash).objects('commits')
  268. expect(commits).to contain_exactly commit
  269. end
  270. end
  271. it 'handles not existing commit hash correctly' do
  272. commits = described_class.new(user, project, 'deadbeef').objects('commits')
  273. expect(commits).to be_empty
  274. end
  275. it_behaves_like 'access restricted commits' do
  276. let(:search_phrase) { '0b4bc9a49' }
  277. let(:commit) { project.repository.commit('0b4bc9a') }
  278. end
  279. end
  280. end
  281. end