summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects_controller.rb52
-rw-r--r--app/controllers/search_controller.rb2
-rw-r--r--app/models/repository.rb4
-rw-r--r--app/views/search/results/_commit.html.haml2
-rw-r--r--app/views/shared/issuable/_form.html.haml2
-rw-r--r--changelogs/unreleased/24255-search-fix.yml4
-rw-r--r--changelogs/unreleased/faster_project_search.yml4
-rw-r--r--changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml4
-rw-r--r--lib/constraints/constrainer_helper.rb15
-rw-r--r--lib/constraints/group_url_constrainer.rb16
-rw-r--r--lib/constraints/namespace_url_constrainer.rb24
-rw-r--r--lib/constraints/user_url_constrainer.rb16
-rw-r--r--lib/gitlab/project_search_results.rb30
-rw-r--r--spec/features/global_search_spec.rb28
-rw-r--r--spec/features/issues/new_branch_button_spec.rb7
-rw-r--r--spec/features/search_spec.rb26
-rw-r--r--spec/javascripts/boards/boards_store_spec.js.es6215
-rw-r--r--spec/javascripts/boards/list_spec.js.es65
-rw-r--r--spec/javascripts/boards/mock_data.js.es64
-rw-r--r--spec/lib/constraints/constrainer_helper_spec.rb20
-rw-r--r--spec/lib/constraints/group_url_constrainer_spec.rb17
-rw-r--r--spec/lib/constraints/namespace_url_constrainer_spec.rb35
-rw-r--r--spec/lib/constraints/user_url_constrainer_spec.rb12
-rw-r--r--spec/models/repository_spec.rb13
-rw-r--r--spec/routing/routing_spec.rb4
-rw-r--r--spec/spec_helper.rb1
-rw-r--r--spec/support/search_helpers.rb5
27 files changed, 342 insertions, 225 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 28820adcc46..a8a18b4fa16 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -325,26 +325,44 @@ class ProjectsController < Projects::ApplicationController
end
def project_params
- project_feature_attributes =
- {
- project_feature_attributes:
- [
- :issues_access_level, :builds_access_level,
- :wiki_access_level, :merge_requests_access_level,
- :snippets_access_level, :repository_access_level
- ]
- }
+ params.require(:project)
+ .permit(project_params_ce)
+ end
- params.require(:project).permit(
- :name, :path, :description, :issues_tracker, :tag_list, :runners_token,
+ def project_params_ce
+ [
+ :avatar,
+ :build_allow_git_fetch,
+ :build_coverage_regex,
+ :build_timeout_in_minutes,
:container_registry_enabled,
- :issues_tracker_id, :default_branch,
- :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
- :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
- :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled,
+ :default_branch,
+ :description,
+ :import_url,
+ :issues_tracker,
+ :issues_tracker_id,
+ :last_activity_at,
+ :lfs_enabled,
+ :name,
+ :namespace_id,
:only_allow_merge_if_all_discussions_are_resolved,
- :lfs_enabled, project_feature_attributes
- )
+ :only_allow_merge_if_build_succeeds,
+ :path,
+ :public_builds,
+ :request_access_enabled,
+ :runners_token,
+ :tag_list,
+ :visibility_level,
+
+ project_feature_attributes: %i[
+ builds_access_level
+ issues_access_level
+ merge_requests_access_level
+ repository_access_level
+ snippets_access_level
+ wiki_access_level
+ ]
+ ]
end
def repo_exists?
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index d01e0dedf52..b666aa01d6b 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -16,7 +16,7 @@ class SearchController < ApplicationController
@group = nil unless can?(current_user, :read_group, @group)
end
- return if params[:search].nil? || params[:search].blank?
+ return if params[:search].blank?
@search_term = params[:search]
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 30be7262438..7d06ce1e85b 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1064,6 +1064,10 @@ class Repository
end
def search_files(query, ref)
+ unless exists? && has_visible_content? && query.present?
+ return []
+ end
+
offset = 2
args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref})
Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
diff --git a/app/views/search/results/_commit.html.haml b/app/views/search/results/_commit.html.haml
index 5b2d83d6b92..f34eaf89027 100644
--- a/app/views/search/results/_commit.html.haml
+++ b/app/views/search/results/_commit.html.haml
@@ -1 +1 @@
-= render 'projects/commits/commit', project: @project, commit: commit
+= render 'projects/commits/commit', project: @project, commit: commit, ref: nil
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 8d976952781..3176af9c19b 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -129,7 +129,7 @@
.col-sm-10.col-sm-offset-2
.checkbox
= label_tag 'merge_request[force_remove_source_branch]' do
- = hidden_field_tag 'merge_request[force_remove_source_branch]', '0'
+ = hidden_field_tag 'merge_request[force_remove_source_branch]', '0', id: nil
= check_box_tag 'merge_request[force_remove_source_branch]', '1', @merge_request.force_remove_source_branch?
Remove source branch when merge request is accepted.
diff --git a/changelogs/unreleased/24255-search-fix.yml b/changelogs/unreleased/24255-search-fix.yml
new file mode 100644
index 00000000000..c0afade9bc8
--- /dev/null
+++ b/changelogs/unreleased/24255-search-fix.yml
@@ -0,0 +1,4 @@
+---
+title: Fix broken commits search
+merge_request:
+author:
diff --git a/changelogs/unreleased/faster_project_search.yml b/changelogs/unreleased/faster_project_search.yml
new file mode 100644
index 00000000000..e29a9f34ed4
--- /dev/null
+++ b/changelogs/unreleased/faster_project_search.yml
@@ -0,0 +1,4 @@
+---
+title: Faster search inside Project
+merge_request:
+author:
diff --git a/changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml b/changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml
new file mode 100644
index 00000000000..8b41063151b
--- /dev/null
+++ b/changelogs/unreleased/fix-uncheckable-label-for-force_remove_source_branch.yml
@@ -0,0 +1,4 @@
+---
+title: Clicking "force remove source branch" label now toggles the checkbox again
+merge_request:
+author:
diff --git a/lib/constraints/constrainer_helper.rb b/lib/constraints/constrainer_helper.rb
new file mode 100644
index 00000000000..ab07a6793d9
--- /dev/null
+++ b/lib/constraints/constrainer_helper.rb
@@ -0,0 +1,15 @@
+module ConstrainerHelper
+ def extract_resource_path(path)
+ id = path.dup
+ id.sub!(/\A#{relative_url_root}/, '') if relative_url_root
+ id.sub(/\A\/+/, '').sub(/\/+\z/, '').sub(/.atom\z/, '')
+ end
+
+ private
+
+ def relative_url_root
+ if defined?(Gitlab::Application.config.relative_url_root)
+ Gitlab::Application.config.relative_url_root
+ end
+ end
+end
diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb
index ca39b1961ae..2af6e1a11c8 100644
--- a/lib/constraints/group_url_constrainer.rb
+++ b/lib/constraints/group_url_constrainer.rb
@@ -1,7 +1,15 @@
-require 'constraints/namespace_url_constrainer'
+require_relative 'constrainer_helper'
-class GroupUrlConstrainer < NamespaceUrlConstrainer
- def find_resource(id)
- Group.find_by_path(id)
+class GroupUrlConstrainer
+ include ConstrainerHelper
+
+ def matches?(request)
+ id = extract_resource_path(request.path)
+
+ if id =~ Gitlab::Regex.namespace_regex
+ Group.find_by(path: id).present?
+ else
+ false
+ end
end
end
diff --git a/lib/constraints/namespace_url_constrainer.rb b/lib/constraints/namespace_url_constrainer.rb
deleted file mode 100644
index 91b70143f11..00000000000
--- a/lib/constraints/namespace_url_constrainer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-class NamespaceUrlConstrainer
- def matches?(request)
- id = request.path
- id = id.sub(/\A#{relative_url_root}/, '') if relative_url_root
- id = id.sub(/\A\/+/, '').split('/').first
- id = id.sub(/.atom\z/, '') if id
-
- if id =~ Gitlab::Regex.namespace_regex
- find_resource(id)
- end
- end
-
- def find_resource(id)
- Namespace.find_by_path(id)
- end
-
- private
-
- def relative_url_root
- if defined?(Gitlab::Application.config.relative_url_root)
- Gitlab::Application.config.relative_url_root
- end
- end
-end
diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb
index 504a0f5d93e..4d722ad5af2 100644
--- a/lib/constraints/user_url_constrainer.rb
+++ b/lib/constraints/user_url_constrainer.rb
@@ -1,7 +1,15 @@
-require 'constraints/namespace_url_constrainer'
+require_relative 'constrainer_helper'
-class UserUrlConstrainer < NamespaceUrlConstrainer
- def find_resource(id)
- User.find_by('lower(username) = ?', id.downcase)
+class UserUrlConstrainer
+ include ConstrainerHelper
+
+ def matches?(request)
+ id = extract_resource_path(request.path)
+
+ if id =~ Gitlab::Regex.namespace_regex
+ User.find_by('lower(username) = ?', id.downcase).present?
+ else
+ false
+ end
end
end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 24733435a5a..b8326a64b22 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -5,11 +5,7 @@ module Gitlab
def initialize(current_user, project, query, repository_ref = nil)
@current_user = current_user
@project = project
- @repository_ref = if repository_ref.present?
- repository_ref
- else
- nil
- end
+ @repository_ref = repository_ref.presence
@query = query
end
@@ -47,33 +43,31 @@ module Gitlab
private
def blobs
- if project.empty_repo? || query.blank?
- []
- else
- project.repository.search_files(query, repository_ref)
- end
+ @blobs ||= project.repository.search_files(query, repository_ref)
end
def wiki_blobs
- if project.wiki_enabled? && query.present?
- project_wiki = ProjectWiki.new(project)
+ @wiki_blobs ||= begin
+ if project.wiki_enabled? && query.present?
+ project_wiki = ProjectWiki.new(project)
- unless project_wiki.empty?
- project_wiki.search_files(query)
+ unless project_wiki.empty?
+ project_wiki.search_files(query)
+ else
+ []
+ end
else
[]
end
- else
- []
end
end
def notes
- project.notes.user.search(query, as_user: @current_user).order('updated_at DESC')
+ @notes ||= project.notes.user.search(query, as_user: @current_user).order('updated_at DESC')
end
def commits
- project.repository.find_commits_by_message(query)
+ @commits ||= project.repository.find_commits_by_message(query)
end
def project_ids_relation
diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb
new file mode 100644
index 00000000000..f6409e00f22
--- /dev/null
+++ b/spec/features/global_search_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+feature 'Global search', feature: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ before do
+ project.team << [user, :master]
+ login_with(user)
+ end
+
+ describe 'I search through the issues and I see pagination' do
+ before do
+ allow_any_instance_of(Gitlab::SearchResults).to receive(:per_page).and_return(1)
+ create_list(:issue, 2, project: project, title: 'initial')
+ end
+
+ it "has a pagination" do
+ visit dashboard_projects_path
+
+ fill_in "search", with: "initial"
+ click_button "Go"
+
+ select_filter("Issues")
+ expect(page).to have_selector('.gl-pagination .page', count: 2)
+ end
+ end
+end
diff --git a/spec/features/issues/new_branch_button_spec.rb b/spec/features/issues/new_branch_button_spec.rb
index fb0c4704285..755f4eb1b0b 100644
--- a/spec/features/issues/new_branch_button_spec.rb
+++ b/spec/features/issues/new_branch_button_spec.rb
@@ -18,8 +18,8 @@ feature 'Start new branch from an issue', feature: true do
end
context "when there is a referenced merge request" do
- let(:note) do
- create(:note, :on_issue, :system, project: project,
+ let!(:note) do
+ create(:note, :on_issue, :system, project: project, noteable: issue,
note: "Mentioned in !#{referenced_mr.iid}")
end
let(:referenced_mr) do
@@ -28,12 +28,13 @@ feature 'Start new branch from an issue', feature: true do
end
before do
- issue.notes << note
+ referenced_mr.cache_merge_request_closes_issues!(user)
visit namespace_project_issue_path(project.namespace, project, issue)
end
it "hides the new branch button", js: true do
+ expect(page).to have_css('#new-branch .unavailable')
expect(page).not_to have_css('#new-branch .available')
expect(page).to have_content /1 Related Merge Request/
end
diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb
index 1806200c82c..caecd027aaa 100644
--- a/spec/features/search_spec.rb
+++ b/spec/features/search_spec.rb
@@ -100,6 +100,32 @@ describe "Search", feature: true do
expect(page).to have_link(snippet.title)
end
+
+ it 'finds a commit' do
+ visit namespace_project_path(project.namespace, project)
+
+ page.within '.search' do
+ fill_in 'search', with: 'add'
+ click_button 'Go'
+ end
+
+ click_link "Commits"
+
+ expect(page).to have_selector('.commit-row-description')
+ end
+
+ it 'finds a code' do
+ visit namespace_project_path(project.namespace, project)
+
+ page.within '.search' do
+ fill_in 'search', with: 'def'
+ click_button 'Go'
+ end
+
+ click_link "Code"
+
+ expect(page).to have_selector('.file-content .code')
+ end
end
describe 'Right header search field', feature: true do
diff --git a/spec/javascripts/boards/boards_store_spec.js.es6 b/spec/javascripts/boards/boards_store_spec.js.es6
index 6208c2386b0..b84dfc8197b 100644
--- a/spec/javascripts/boards/boards_store_spec.js.es6
+++ b/spec/javascripts/boards/boards_store_spec.js.es6
@@ -13,8 +13,9 @@
//= require boards/stores/boards_store
//= require ./mock_data
-(() => {
+describe('Store', () => {
beforeEach(() => {
+ Vue.http.interceptors.push(boardsMockInterceptor);
gl.boardService = new BoardService('/test/issue-boards/board', '1');
gl.issueBoards.BoardsStore.create();
@@ -24,145 +25,147 @@
});
});
- describe('Store', () => {
- it('starts with a blank state', () => {
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0);
- });
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
+ });
- describe('lists', () => {
- it('creates new list without persisting to DB', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
+ it('starts with a blank state', () => {
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0);
+ });
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
- });
+ describe('lists', () => {
+ it('creates new list without persisting to DB', () => {
+ gl.issueBoards.BoardsStore.addList(listObj);
- it('finds list by ID', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
- const list = gl.issueBoards.BoardsStore.findList('id', 1);
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ });
- expect(list.id).toBe(1);
- });
+ it('finds list by ID', () => {
+ gl.issueBoards.BoardsStore.addList(listObj);
+ const list = gl.issueBoards.BoardsStore.findList('id', 1);
- it('finds list by type', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
- const list = gl.issueBoards.BoardsStore.findList('type', 'label');
+ expect(list.id).toBe(1);
+ });
- expect(list).toBeDefined();
- });
+ it('finds list by type', () => {
+ gl.issueBoards.BoardsStore.addList(listObj);
+ const list = gl.issueBoards.BoardsStore.findList('type', 'label');
- it('finds list limited by type', () => {
- gl.issueBoards.BoardsStore.addList({
- id: 1,
- position: 0,
- title: 'Test',
- list_type: 'backlog'
- });
- const list = gl.issueBoards.BoardsStore.findList('id', 1, 'backlog');
+ expect(list).toBeDefined();
+ });
- expect(list).toBeDefined();
+ it('finds list limited by type', () => {
+ gl.issueBoards.BoardsStore.addList({
+ id: 1,
+ position: 0,
+ title: 'Test',
+ list_type: 'backlog'
});
+ const list = gl.issueBoards.BoardsStore.findList('id', 1, 'backlog');
- it('gets issue when new list added', (done) => {
- gl.issueBoards.BoardsStore.addList(listObj);
- const list = gl.issueBoards.BoardsStore.findList('id', 1);
+ expect(list).toBeDefined();
+ });
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ it('gets issue when new list added', (done) => {
+ gl.issueBoards.BoardsStore.addList(listObj);
+ const list = gl.issueBoards.BoardsStore.findList('id', 1);
- setTimeout(() => {
- expect(list.issues.length).toBe(1);
- expect(list.issues[0].id).toBe(1);
- done();
- }, 0);
- });
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
- it('persists new list', (done) => {
- gl.issueBoards.BoardsStore.new({
- title: 'Test',
- type: 'label',
- label: {
- id: 1,
- title: 'Testing',
- color: 'red',
- description: 'testing;'
- }
- });
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
-
- setTimeout(() => {
- const list = gl.issueBoards.BoardsStore.findList('id', 1);
- expect(list).toBeDefined();
- expect(list.id).toBe(1);
- expect(list.position).toBe(0);
- done();
- }, 0);
- });
+ setTimeout(() => {
+ expect(list.issues.length).toBe(1);
+ expect(list.issues[0].id).toBe(1);
+ done();
+ }, 0);
+ });
- it('check for blank state adding', () => {
- expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true);
+ it('persists new list', (done) => {
+ gl.issueBoards.BoardsStore.new({
+ title: 'Test',
+ type: 'label',
+ label: {
+ id: 1,
+ title: 'Testing',
+ color: 'red',
+ description: 'testing;'
+ }
});
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
- it('check for blank state not adding', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
- expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(false);
- });
+ setTimeout(() => {
+ const list = gl.issueBoards.BoardsStore.findList('id', 1);
+ expect(list).toBeDefined();
+ expect(list.id).toBe(1);
+ expect(list.position).toBe(0);
+ done();
+ }, 0);
+ });
- it('check for blank state adding when backlog & done list exist', () => {
- gl.issueBoards.BoardsStore.addList({
- list_type: 'backlog'
- });
- gl.issueBoards.BoardsStore.addList({
- list_type: 'done'
- });
+ it('check for blank state adding', () => {
+ expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true);
+ });
+
+ it('check for blank state not adding', () => {
+ gl.issueBoards.BoardsStore.addList(listObj);
+ expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(false);
+ });
- expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true);
+ it('check for blank state adding when backlog & done list exist', () => {
+ gl.issueBoards.BoardsStore.addList({
+ list_type: 'backlog'
});
+ gl.issueBoards.BoardsStore.addList({
+ list_type: 'done'
+ });
+
+ expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true);
+ });
- it('adds the blank state', () => {
- gl.issueBoards.BoardsStore.addBlankState();
+ it('adds the blank state', () => {
+ gl.issueBoards.BoardsStore.addBlankState();
- const list = gl.issueBoards.BoardsStore.findList('type', 'blank', 'blank');
- expect(list).toBeDefined();
- });
+ const list = gl.issueBoards.BoardsStore.findList('type', 'blank', 'blank');
+ expect(list).toBeDefined();
+ });
- it('removes list from state', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
+ it('removes list from state', () => {
+ gl.issueBoards.BoardsStore.addList(listObj);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
- gl.issueBoards.BoardsStore.removeList(1, 'label');
+ gl.issueBoards.BoardsStore.removeList(1, 'label');
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0);
- });
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0);
+ });
- it('moves the position of lists', () => {
- const listOne = gl.issueBoards.BoardsStore.addList(listObj),
- listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
+ it('moves the position of lists', () => {
+ const listOne = gl.issueBoards.BoardsStore.addList(listObj),
+ listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
- gl.issueBoards.BoardsStore.moveList(listOne, ['2', '1']);
+ gl.issueBoards.BoardsStore.moveList(listOne, ['2', '1']);
- expect(listOne.position).toBe(1);
- });
+ expect(listOne.position).toBe(1);
+ });
- it('moves an issue from one list to another', (done) => {
- const listOne = gl.issueBoards.BoardsStore.addList(listObj),
- listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
+ it('moves an issue from one list to another', (done) => {
+ const listOne = gl.issueBoards.BoardsStore.addList(listObj),
+ listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
+ expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
- setTimeout(() => {
- expect(listOne.issues.length).toBe(1);
- expect(listTwo.issues.length).toBe(1);
+ setTimeout(() => {
+ expect(listOne.issues.length).toBe(1);
+ expect(listTwo.issues.length).toBe(1);
- gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1));
+ gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1));
- expect(listOne.issues.length).toBe(0);
- expect(listTwo.issues.length).toBe(1);
+ expect(listOne.issues.length).toBe(0);
+ expect(listTwo.issues.length).toBe(1);
- done();
- }, 0);
- });
+ done();
+ }, 0);
});
});
-})();
+});
diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js.es6
index 1a0427fdd90..dfbcbe3a7c1 100644
--- a/spec/javascripts/boards/list_spec.js.es6
+++ b/spec/javascripts/boards/list_spec.js.es6
@@ -17,12 +17,17 @@ describe('List model', () => {
let list;
beforeEach(() => {
+ Vue.http.interceptors.push(boardsMockInterceptor);
gl.boardService = new BoardService('/test/issue-boards/board', '1');
gl.issueBoards.BoardsStore.create();
list = new List(listObj);
});
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
+ });
+
it('gets issues when created', (done) => {
setTimeout(() => {
expect(list.issues.length).toBe(1);
diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js.es6
index 80d05e8a1a3..fcb3d8f17d8 100644
--- a/spec/javascripts/boards/mock_data.js.es6
+++ b/spec/javascripts/boards/mock_data.js.es6
@@ -48,10 +48,10 @@ const BoardsMockData = {
}
};
-Vue.http.interceptors.push((request, next) => {
+const boardsMockInterceptor = (request, next) => {
const body = BoardsMockData[request.method][request.url];
next(request.respondWith(JSON.stringify(body), {
status: 200
}));
-});
+};
diff --git a/spec/lib/constraints/constrainer_helper_spec.rb b/spec/lib/constraints/constrainer_helper_spec.rb
new file mode 100644
index 00000000000..27c8d72aefc
--- /dev/null
+++ b/spec/lib/constraints/constrainer_helper_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe ConstrainerHelper, lib: true do
+ include ConstrainerHelper
+
+ describe '#extract_resource_path' do
+ it { expect(extract_resource_path('/gitlab/')).to eq('gitlab') }
+ it { expect(extract_resource_path('///gitlab//')).to eq('gitlab') }
+ it { expect(extract_resource_path('/gitlab.atom')).to eq('gitlab') }
+
+ context 'relative url' do
+ before do
+ allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' }
+ end
+
+ it { expect(extract_resource_path('/gitlab/foo')).to eq('foo') }
+ it { expect(extract_resource_path('/foo/bar')).to eq('foo/bar') }
+ end
+ end
+end
diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb
index f0b75a664f2..42299b17c2b 100644
--- a/spec/lib/constraints/group_url_constrainer_spec.rb
+++ b/spec/lib/constraints/group_url_constrainer_spec.rb
@@ -1,10 +1,19 @@
require 'spec_helper'
describe GroupUrlConstrainer, lib: true do
- let!(:username) { create(:group, path: 'gitlab-org') }
+ let!(:group) { create(:group, path: 'gitlab') }
- describe '#find_resource' do
- it { expect(!!subject.find_resource('gitlab-org')).to be_truthy }
- it { expect(!!subject.find_resource('gitlab-com')).to be_falsey }
+ describe '#matches?' do
+ context 'root group' do
+ it { expect(subject.matches?(request '/gitlab')).to be_truthy }
+ it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy }
+ it { expect(subject.matches?(request '/gitlab/edit')).to be_falsey }
+ it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey }
+ it { expect(subject.matches?(request '/.gitlab')).to be_falsey }
+ end
+ end
+
+ def request(path)
+ double(:request, path: path)
end
end
diff --git a/spec/lib/constraints/namespace_url_constrainer_spec.rb b/spec/lib/constraints/namespace_url_constrainer_spec.rb
deleted file mode 100644
index 7814711fe27..00000000000
--- a/spec/lib/constraints/namespace_url_constrainer_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-require 'spec_helper'
-
-describe NamespaceUrlConstrainer, lib: true do
- let!(:group) { create(:group, path: 'gitlab') }
-
- describe '#matches?' do
- context 'existing namespace' do
- it { expect(subject.matches?(request '/gitlab')).to be_truthy }
- it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy }
- it { expect(subject.matches?(request '/gitlab/')).to be_truthy }
- it { expect(subject.matches?(request '//gitlab/')).to be_truthy }
- end
-
- context 'non-existing namespace' do
- it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey }
- it { expect(subject.matches?(request '/gitlab.ce')).to be_falsey }
- it { expect(subject.matches?(request '/g/gitlab')).to be_falsey }
- it { expect(subject.matches?(request '/.gitlab')).to be_falsey }
- end
-
- context 'relative url' do
- before do
- allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' }
- end
-
- it { expect(subject.matches?(request '/gitlab/gitlab')).to be_truthy }
- it { expect(subject.matches?(request '/gitlab/gitlab-ce')).to be_falsey }
- it { expect(subject.matches?(request '/gitlab/')).to be_falsey }
- end
- end
-
- def request(path)
- OpenStruct.new(path: path)
- end
-end
diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb
index 4b26692672f..b3f8530c609 100644
--- a/spec/lib/constraints/user_url_constrainer_spec.rb
+++ b/spec/lib/constraints/user_url_constrainer_spec.rb
@@ -3,8 +3,14 @@ require 'spec_helper'
describe UserUrlConstrainer, lib: true do
let!(:username) { create(:user, username: 'dz') }
- describe '#find_resource' do
- it { expect(!!subject.find_resource('dz')).to be_truthy }
- it { expect(!!subject.find_resource('john')).to be_falsey }
+ describe '#matches?' do
+ it { expect(subject.matches?(request '/dz')).to be_truthy }
+ it { expect(subject.matches?(request '/dz.atom')).to be_truthy }
+ it { expect(subject.matches?(request '/dz/projects')).to be_falsey }
+ it { expect(subject.matches?(request '/gitlab')).to be_falsey }
+ end
+
+ def request(path)
+ double(:request, path: path)
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 04b7d19d414..12989d4db53 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -362,6 +362,19 @@ describe Repository, models: true do
expect(results.first).not_to start_with('fatal:')
end
+ it 'properly handles when query is not present' do
+ results = repository.search_files('', 'master')
+
+ expect(results).to match_array([])
+ end
+
+ it 'properly handles query when repo is empty' do
+ repository = create(:empty_project).repository
+ results = repository.search_files('test', 'master')
+
+ expect(results).to match_array([])
+ end
+
describe 'result' do
subject { results.first }
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index c18a2d55e43..61dca5d5a62 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -266,13 +266,13 @@ describe "Groups", "routing" do
end
it "also display group#show on the short path" do
- allow(Group).to receive(:find_by_path).and_return(true)
+ allow(Group).to receive(:find_by).and_return(true)
expect(get('/1')).to route_to('groups#show', id: '1')
end
it "also display group#show with dot in the path" do
- allow(Group).to receive(:find_by_path).and_return(true)
+ allow(Group).to receive(:find_by).and_return(true)
expect(get('/group.with.dot')).to route_to('groups#show', id: 'group.with.dot')
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index b2ca856f89f..73cf4c9a24c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -29,6 +29,7 @@ RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Warden::Test::Helpers, type: :request
config.include LoginHelpers, type: :feature
+ config.include SearchHelpers, type: :feature
config.include StubConfiguration
config.include EmailHelpers
config.include TestEnv
diff --git a/spec/support/search_helpers.rb b/spec/support/search_helpers.rb
new file mode 100644
index 00000000000..abbbb636d66
--- /dev/null
+++ b/spec/support/search_helpers.rb
@@ -0,0 +1,5 @@
+module SearchHelpers
+ def select_filter(name)
+ find(:xpath, "//ul[contains(@class, 'search-filter')]//a[contains(.,'#{name}')]").click
+ end
+end