Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-08-30 18:49:22 +0300
committerPhil Hughes <me@iamphill.com>2017-08-30 18:49:22 +0300
commit4d2d744ae9a2d4c3bb0f00805c27704b79e00d72 (patch)
tree839b1c3ab4c09c80f7d643fe69dae8a83c4e4eb4 /spec
parent25a3b7fab905d09f6f064108f457a4e20c8915ff (diff)
parentf7c8434c7100c3c87eb2a75cd5a128e520d8c110 (diff)
Merge branch 'master' into enable-new-navigaton-by-default
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb38
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb8
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb4
-rw-r--r--spec/controllers/snippets_controller_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_author_spec.rb12
-rw-r--r--spec/features/issues/filtered_search/dropdown_emoji_spec.rb182
-rw-r--r--spec/features/issues/filtered_search/dropdown_hint_spec.rb288
-rw-r--r--spec/features/issues/filtered_search/dropdown_label_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/search_bar_spec.rb2
-rw-r--r--spec/features/projects/commits/rss_spec.rb (renamed from spec/features/projects/commit/rss_spec.rb)0
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb44
-rw-r--r--spec/features/projects/user_interacts_with_stars_spec.rb38
-rw-r--r--spec/finders/issues_finder_spec.rb35
-rw-r--r--spec/javascripts/droplab/drop_down_spec.js15
-rw-r--r--spec/javascripts/helpers/vue_mount_component_helper.js4
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js11
-rw-r--r--spec/javascripts/pipelines/navigation_tabs_spec.js127
-rw-r--r--spec/javascripts/vue_shared/components/identicon_spec.js (renamed from spec/javascripts/groups/group_identicon_spec.js)14
-rw-r--r--spec/lib/gitlab/sql/pattern_spec.rb55
-rw-r--r--spec/models/concerns/awardable_spec.rb22
-rw-r--r--spec/models/concerns/editable_spec.rb6
-rw-r--r--spec/models/repository_spec.rb58
-rw-r--r--spec/models/user_spec.rb17
-rw-r--r--spec/requests/api/award_emoji_spec.rb16
-rw-r--r--spec/requests/api/boards_spec.rb4
-rw-r--r--spec/requests/api/branches_spec.rb4
-rw-r--r--spec/requests/api/broadcast_messages_spec.rb4
-rw-r--r--spec/requests/api/deploy_keys_spec.rb4
-rw-r--r--spec/requests/api/environments_spec.rb4
-rw-r--r--spec/requests/api/group_variables_spec.rb4
-rw-r--r--spec/requests/api/groups_spec.rb5
-rw-r--r--spec/requests/api/issues_spec.rb8
-rw-r--r--spec/requests/api/labels_spec.rb5
-rw-r--r--spec/requests/api/members_spec.rb4
-rw-r--r--spec/requests/api/merge_requests_spec.rb4
-rw-r--r--spec/requests/api/notes_spec.rb12
-rw-r--r--spec/requests/api/pipeline_schedules_spec.rb7
-rw-r--r--spec/requests/api/project_hooks_spec.rb4
-rw-r--r--spec/requests/api/project_snippets_spec.rb11
-rw-r--r--spec/requests/api/projects_spec.rb71
-rw-r--r--spec/requests/api/protected_branches_spec.rb4
-rw-r--r--spec/requests/api/runner_spec.rb5
-rw-r--r--spec/requests/api/runners_spec.rb12
-rw-r--r--spec/requests/api/snippets_spec.rb8
-rw-r--r--spec/requests/api/system_hooks_spec.rb4
-rw-r--r--spec/requests/api/tags_spec.rb6
-rw-r--r--spec/requests/api/triggers_spec.rb4
-rw-r--r--spec/requests/api/users_spec.rb24
-rw-r--r--spec/requests/api/v3/issues_spec.rb4
-rw-r--r--spec/requests/api/v3/project_snippets_spec.rb4
-rw-r--r--spec/requests/api/v3/snippets_spec.rb2
-rw-r--r--spec/services/git_push_service_spec.rb4
-rw-r--r--spec/services/issues/create_service_spec.rb4
-rw-r--r--spec/services/spam_service_spec.rb6
-rw-r--r--spec/support/filtered_search_helpers.rb10
-rw-r--r--spec/support/shared_examples/requests/api/status_shared_examples.rb25
58 files changed, 1085 insertions, 214 deletions
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index 2fbab1e4040..572b567cddf 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -339,4 +339,42 @@ describe AutocompleteController do
end
end
end
+
+ context 'GET award_emojis' do
+ let(:user2) { create(:user) }
+ let!(:award_emoji1) { create_list(:award_emoji, 2, user: user, name: 'thumbsup') }
+ let!(:award_emoji2) { create_list(:award_emoji, 1, user: user, name: 'thumbsdown') }
+ let!(:award_emoji3) { create_list(:award_emoji, 3, user: user, name: 'star') }
+ let!(:award_emoji4) { create_list(:award_emoji, 1, user: user, name: 'tea') }
+
+ context 'unauthorized user' do
+ it 'returns empty json' do
+ get :award_emojis
+
+ expect(json_response).to be_empty
+ end
+ end
+
+ context 'sign in as user without award emoji' do
+ it 'returns empty json' do
+ sign_in(user2)
+ get :award_emojis
+
+ expect(json_response).to be_empty
+ end
+ end
+
+ context 'sign in as user with award emoji' do
+ it 'returns json sorted by name count' do
+ sign_in(user)
+ get :award_emojis
+
+ expect(json_response.count).to eq 4
+ expect(json_response[0]).to match('name' => 'star')
+ expect(json_response[1]).to match('name' => 'thumbsup')
+ expect(json_response[2]).to match('name' => 'tea')
+ expect(json_response[3]).to match('name' => 'thumbsdown')
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index b571b11dcac..da8f9e8376e 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -268,7 +268,7 @@ describe Projects::IssuesController do
context 'when an issue is not identified as spam' do
before do
allow_any_instance_of(described_class).to receive(:verify_recaptcha).and_return(false)
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(false)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(false)
end
it 'normally updates the issue' do
@@ -278,7 +278,7 @@ describe Projects::IssuesController do
context 'when an issue is identified as spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when captcha is not verified' do
@@ -672,7 +672,7 @@ describe Projects::IssuesController do
context 'when an issue is not identified as spam' do
before do
allow_any_instance_of(described_class).to receive(:verify_recaptcha).and_return(false)
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(false)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(false)
end
it 'does not create an issue' do
@@ -682,7 +682,7 @@ describe Projects::IssuesController do
context 'when an issue is identified as spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when captcha is not verified' do
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index cc444f31797..3a1550aa730 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -98,7 +98,7 @@ describe Projects::SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -176,7 +176,7 @@ describe Projects::SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 7c5d059760f..be273acb69b 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -217,7 +217,7 @@ describe SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -289,7 +289,7 @@ describe SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index 2cc027aac9e..1c4649d0ba9 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -204,6 +204,12 @@ describe 'Dropdown assignee', :js do
expect(page).to have_css(js_dropdown_assignee, visible: true)
end
+
+ it 'opens assignee dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star assignee:')
+
+ expect(page).to have_css(js_dropdown_assignee, visible: true)
+ end
end
describe 'caching requests' do
diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb
index 975dc035f2d..3cec59050ab 100644
--- a/spec/features/issues/filtered_search/dropdown_author_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb
@@ -6,7 +6,7 @@ describe 'Dropdown author', js: true do
let!(:project) { create(:project) }
let!(:user) { create(:user, name: 'administrator', username: 'root') }
let!(:user_john) { create(:user, name: 'John', username: 'th0mas') }
- let!(:user_jacob) { create(:user, name: 'Jacob', username: 'otter32') }
+ let!(:user_jacob) { create(:user, name: 'Jacob', username: 'ooter32') }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_author) { '#js-dropdown-author' }
@@ -82,31 +82,31 @@ describe 'Dropdown author', js: true do
end
it 'filters by name' do
- send_keys_to_filtered_search('ja')
+ send_keys_to_filtered_search('jac')
expect(dropdown_author_size).to eq(1)
end
it 'filters by case insensitive name' do
- send_keys_to_filtered_search('Ja')
+ send_keys_to_filtered_search('Jac')
expect(dropdown_author_size).to eq(1)
end
it 'filters by username with symbol' do
- send_keys_to_filtered_search('@ot')
+ send_keys_to_filtered_search('@oot')
expect(dropdown_author_size).to eq(2)
end
it 'filters by username without symbol' do
- send_keys_to_filtered_search('ot')
+ send_keys_to_filtered_search('oot')
expect(dropdown_author_size).to eq(2)
end
it 'filters by case insensitive username without symbol' do
- send_keys_to_filtered_search('OT')
+ send_keys_to_filtered_search('OOT')
expect(dropdown_author_size).to eq(2)
end
diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
new file mode 100644
index 00000000000..44741bcc92d
--- /dev/null
+++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
@@ -0,0 +1,182 @@
+require 'rails_helper'
+
+describe 'Dropdown emoji', js: true do
+ include FilteredSearchHelpers
+
+ let!(:project) { create(:project, :public) }
+ let!(:user) { create(:user, name: 'administrator', username: 'root') }
+ let!(:issue) { create(:issue, project: project) }
+ let!(:award_emoji_star) { create(:award_emoji, name: 'star', user: user, awardable: issue) }
+ let(:filtered_search) { find('.filtered-search') }
+ let(:js_dropdown_emoji) { '#js-dropdown-my-reaction' }
+
+ def send_keys_to_filtered_search(input)
+ input.split("").each do |i|
+ filtered_search.send_keys(i)
+ end
+
+ sleep 0.5
+ wait_for_requests
+ end
+
+ def dropdown_emoji_size
+ page.all('#js-dropdown-my-reaction .filter-dropdown .filter-dropdown-item').size
+ end
+
+ def click_emoji(text)
+ find('#js-dropdown-my-reaction .filter-dropdown .filter-dropdown-item', text: text).click
+ end
+
+ before do
+ project.team << [user, :master]
+ create_list(:award_emoji, 2, user: user, name: 'thumbsup')
+ create_list(:award_emoji, 1, user: user, name: 'thumbsdown')
+ create_list(:award_emoji, 3, user: user, name: 'star')
+ create_list(:award_emoji, 1, user: user, name: 'tea')
+ end
+
+ context 'when user not logged in' do
+ before do
+ visit project_issues_path(project)
+ end
+
+ describe 'behavior' do
+ it 'does not open when the search bar has my-reaction:' do
+ filtered_search.set('my-reaction:')
+
+ expect(page).not_to have_css(js_dropdown_emoji)
+ end
+ end
+ end
+
+ context 'when user loggged in' do
+ before do
+ sign_in(user)
+
+ visit project_issues_path(project)
+ end
+
+ describe 'behavior' do
+ it 'opens when the search bar has my-reaction:' do
+ filtered_search.set('my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'closes when the search bar is unfocused' do
+ find('body').click()
+
+ expect(page).to have_css(js_dropdown_emoji, visible: false)
+ end
+
+ it 'should show loading indicator when opened' do
+ filtered_search.set('my-reaction:')
+
+ expect(page).to have_css('#js-dropdown-my-reaction .filter-dropdown-loading', visible: true)
+ end
+
+ it 'should hide loading indicator when loaded' do
+ send_keys_to_filtered_search('my-reaction:')
+
+ expect(page).not_to have_css('#js-dropdown-my-reaction .filter-dropdown-loading')
+ end
+
+ it 'should load all the emojis when opened' do
+ send_keys_to_filtered_search('my-reaction:')
+
+ expect(dropdown_emoji_size).to eq(4)
+ end
+
+ it 'shows the most populated emoji at top of dropdown' do
+ send_keys_to_filtered_search('my-reaction:')
+
+ expect(first('#js-dropdown-my-reaction li')).to have_content(award_emoji_star.name)
+ end
+ end
+
+ describe 'filtering' do
+ before do
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+ end
+
+ it 'filters by name' do
+ send_keys_to_filtered_search('up')
+
+ expect(dropdown_emoji_size).to eq(1)
+ end
+
+ it 'filters by case insensitive name' do
+ send_keys_to_filtered_search('Up')
+
+ expect(dropdown_emoji_size).to eq(1)
+ end
+ end
+
+ describe 'selecting from dropdown' do
+ before do
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+ end
+
+ it 'fills in the my-reaction name' do
+ click_emoji('thumbsup')
+
+ wait_for_requests
+
+ expect(page).to have_css(js_dropdown_emoji, visible: false)
+ expect_tokens([emoji_token('thumbsup')])
+ expect_filtered_search_input_empty
+ end
+ end
+
+ describe 'input has existing content' do
+ it 'opens my-reaction dropdown with existing search term' do
+ filtered_search.set('searchTerm my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing assignee' do
+ filtered_search.set('assignee:@user my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing label' do
+ filtered_search.set('label:~bug my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing milestone' do
+ filtered_search.set('milestone:%v1.0 my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+ end
+
+ describe 'caching requests' do
+ it 'caches requests after the first load' do
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+ initial_size = dropdown_emoji_size
+
+ expect(initial_size).to be > 0
+
+ create_list(:award_emoji, 1, user: user, name: 'smile')
+ find('.filtered-search-box .clear-search').click
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+
+ expect(dropdown_emoji_size).to eq(initial_size)
+ end
+ end
+ end
+end
diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
index 04d6dea4b8c..0183495a1db 100644
--- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe 'Dropdown hint', :js do
include FilteredSearchHelpers
- let!(:project) { create(:project) }
+ let!(:project) { create(:project, :public) }
let!(:user) { create(:user) }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_hint) { '#js-dropdown-hint' }
@@ -14,165 +14,209 @@ describe 'Dropdown hint', :js do
before do
project.team << [user, :master]
- sign_in(user)
create(:issue, project: project)
-
- visit project_issues_path(project)
end
- describe 'behavior' do
+ context 'when user not logged in' do
before do
- expect(page).to have_css(js_dropdown_hint, visible: false)
- filtered_search.click
+ visit project_issues_path(project)
end
- it 'opens when the search bar is first focused' do
- expect(page).to have_css(js_dropdown_hint, visible: true)
- end
-
- it 'closes when the search bar is unfocused' do
- find('body').click
-
+ it 'does not exist my-reaction dropdown item' do
expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).not_to have_content('my-reaction')
end
end
- describe 'filtering' do
- it 'does not filter `Press Enter or click to search`' do
- filtered_search.set('randomtext')
-
- hint_dropdown = find(js_dropdown_hint)
+ context 'when user logged in' do
+ before do
+ sign_in(user)
- expect(hint_dropdown).to have_content('Press Enter or click to search')
- expect(hint_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 0)
+ visit project_issues_path(project)
end
- it 'filters with text' do
- filtered_search.set('a')
+ describe 'behavior' do
+ before do
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ filtered_search.click
+ end
- expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 3)
- end
- end
+ it 'opens when the search bar is first focused' do
+ expect(page).to have_css(js_dropdown_hint, visible: true)
+ end
- describe 'selecting from dropdown with no input' do
- before do
- filtered_search.click
- end
+ it 'closes when the search bar is unfocused' do
+ find('body').click
- it 'opens the author dropdown when you click on author' do
- click_hint('author')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'author' }])
- expect_filtered_search_input_empty
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ end
end
- it 'opens the assignee dropdown when you click on assignee' do
- click_hint('assignee')
+ describe 'filtering' do
+ it 'does not filter `Press Enter or click to search`' do
+ filtered_search.set('randomtext')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'assignee' }])
- expect_filtered_search_input_empty
- end
+ hint_dropdown = find(js_dropdown_hint)
- it 'opens the milestone dropdown when you click on milestone' do
- click_hint('milestone')
+ expect(hint_dropdown).to have_content('Press Enter or click to search')
+ expect(hint_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 0)
+ end
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'milestone' }])
- expect_filtered_search_input_empty
- end
+ it 'filters with text' do
+ filtered_search.set('a')
- it 'opens the label dropdown when you click on label' do
- click_hint('label')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'label' }])
- expect_filtered_search_input_empty
+ expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4)
+ end
end
- end
-
- describe 'selecting from dropdown with some input' do
- it 'opens the author dropdown when you click on author' do
- filtered_search.set('auth')
- click_hint('author')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'author' }])
- expect_filtered_search_input_empty
- end
+ describe 'selecting from dropdown with no input' do
+ before do
+ filtered_search.click
+ end
- it 'opens the assignee dropdown when you click on assignee' do
- filtered_search.set('assign')
- click_hint('assignee')
+ it 'opens the author dropdown when you click on author' do
+ click_hint('author')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'assignee' }])
- expect_filtered_search_input_empty
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-author', visible: true)
+ expect_tokens([{ name: 'author' }])
+ expect_filtered_search_input_empty
+ end
- it 'opens the milestone dropdown when you click on milestone' do
- filtered_search.set('mile')
- click_hint('milestone')
+ it 'opens the assignee dropdown when you click on assignee' do
+ click_hint('assignee')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'milestone' }])
- expect_filtered_search_input_empty
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-assignee', visible: true)
+ expect_tokens([{ name: 'assignee' }])
+ expect_filtered_search_input_empty
+ end
- it 'opens the label dropdown when you click on label' do
- filtered_search.set('lab')
- click_hint('label')
+ it 'opens the milestone dropdown when you click on milestone' do
+ click_hint('milestone')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'label' }])
- expect_filtered_search_input_empty
- end
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-milestone', visible: true)
+ expect_tokens([{ name: 'milestone' }])
+ expect_filtered_search_input_empty
+ end
- describe 'reselecting from dropdown' do
- it 'reuses existing author text' do
- filtered_search.send_keys('author:')
- filtered_search.send_keys(:backspace)
- click_hint('author')
+ it 'opens the label dropdown when you click on label' do
+ click_hint('label')
- expect_tokens([{ name: 'author' }])
- expect_filtered_search_input_empty
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-label', visible: true)
+ expect_tokens([{ name: 'label' }])
+ expect_filtered_search_input_empty
+ end
- it 'reuses existing assignee text' do
- filtered_search.send_keys('assignee:')
- filtered_search.send_keys(:backspace)
- click_hint('assignee')
+ it 'opens the emoji dropdown when you click on my-reaction' do
+ click_hint('my-reaction')
- expect_tokens([{ name: 'assignee' }])
- expect_filtered_search_input_empty
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
+ expect_tokens([{ name: 'my-reaction' }])
+ expect_filtered_search_input_empty
+ end
end
- it 'reuses existing milestone text' do
- filtered_search.send_keys('milestone:')
- filtered_search.send_keys(:backspace)
- click_hint('milestone')
-
- expect_tokens([{ name: 'milestone' }])
- expect_filtered_search_input_empty
- end
+ describe 'selecting from dropdown with some input' do
+ it 'opens the author dropdown when you click on author' do
+ filtered_search.set('auth')
+ click_hint('author')
- it 'reuses existing label text' do
- filtered_search.send_keys('label:')
- filtered_search.send_keys(:backspace)
- click_hint('label')
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-author', visible: true)
+ expect_tokens([{ name: 'author' }])
+ expect_filtered_search_input_empty
+ end
- expect_tokens([{ name: 'label' }])
- expect_filtered_search_input_empty
+ it 'opens the assignee dropdown when you click on assignee' do
+ filtered_search.set('assign')
+ click_hint('assignee')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-assignee', visible: true)
+ expect_tokens([{ name: 'assignee' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'opens the milestone dropdown when you click on milestone' do
+ filtered_search.set('mile')
+ click_hint('milestone')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-milestone', visible: true)
+ expect_tokens([{ name: 'milestone' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'opens the label dropdown when you click on label' do
+ filtered_search.set('lab')
+ click_hint('label')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-label', visible: true)
+ expect_tokens([{ name: 'label' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'opens the emoji dropdown when you click on my-reaction' do
+ filtered_search.set('my')
+ click_hint('my-reaction')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
+ expect_tokens([{ name: 'my-reaction' }])
+ expect_filtered_search_input_empty
+ end
+ end
+
+ describe 'reselecting from dropdown' do
+ it 'reuses existing author text' do
+ filtered_search.send_keys('author:')
+ filtered_search.send_keys(:backspace)
+ click_hint('author')
+
+ expect_tokens([{ name: 'author' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing assignee text' do
+ filtered_search.send_keys('assignee:')
+ filtered_search.send_keys(:backspace)
+ click_hint('assignee')
+
+ expect_tokens([{ name: 'assignee' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing milestone text' do
+ filtered_search.send_keys('milestone:')
+ filtered_search.send_keys(:backspace)
+ click_hint('milestone')
+
+ expect_tokens([{ name: 'milestone' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing label text' do
+ filtered_search.send_keys('label:')
+ filtered_search.send_keys(:backspace)
+ click_hint('label')
+
+ expect_tokens([{ name: 'label' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing emoji text' do
+ filtered_search.send_keys('my-reaction:')
+ filtered_search.send_keys(:backspace)
+ click_hint('my-reaction')
+
+ expect_tokens([{ name: 'my-reaction' }])
+ expect_filtered_search_input_empty
+ end
end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index e84b07ec2ef..c46803112a9 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -270,6 +270,12 @@ describe 'Dropdown label', js: true do
expect(page).to have_css(js_dropdown_label)
end
+
+ it 'opens label dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star label:')
+
+ expect(page).to have_css(js_dropdown_label)
+ end
end
describe 'caching requests' do
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index 5f99921ae2e..f6c2e952bea 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -242,6 +242,12 @@ describe 'Dropdown milestone', :js do
expect(page).to have_css(js_dropdown_milestone, visible: true)
end
+
+ it 'opens milestone dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star milestone:')
+
+ expect(page).to have_css(js_dropdown_milestone, visible: true)
+ end
end
describe 'caching requests' do
diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb
index a432d031337..d4dd570fb37 100644
--- a/spec/features/issues/filtered_search/search_bar_spec.rb
+++ b/spec/features/issues/filtered_search/search_bar_spec.rb
@@ -100,7 +100,7 @@ describe 'Search bar', js: true do
find('.filtered-search-box .clear-search').click
filtered_search.click
- expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4)
+ expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5)
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
end
end
diff --git a/spec/features/projects/commit/rss_spec.rb b/spec/features/projects/commits/rss_spec.rb
index db958346f06..db958346f06 100644
--- a/spec/features/projects/commit/rss_spec.rb
+++ b/spec/features/projects/commits/rss_spec.rb
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
new file mode 100644
index 00000000000..41f3c15a94c
--- /dev/null
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe 'User broweses commits' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context 'primary email' do
+ it 'finds a commit by a primary email' do
+ user = create(:user, email: 'dmitriy.zaporozhets@gmail.com')
+
+ visit(project_commit_path(project, RepoHelpers.sample_commit.id))
+
+ check_author_link(RepoHelpers.sample_commit.author_email, user)
+ end
+ end
+
+ context 'secondary email' do
+ it 'finds a commit by a secondary email' do
+ user =
+ create(:user) do |user|
+ create(:email, { user: user, email: 'dmitriy.zaporozhets@gmail.com' })
+ end
+
+ visit(project_commit_path(project, RepoHelpers.sample_commit.parent_id))
+
+ check_author_link(RepoHelpers.sample_commit.author_email, user)
+ end
+ end
+end
+
+private
+
+def check_author_link(email, author)
+ author_link = find('.commit-author-link')
+
+ expect(author_link['href']).to eq(user_path(author))
+ expect(author_link['title']).to eq(email)
+ expect(find('.commit-author-name').text).to eq(author.name)
+end
diff --git a/spec/features/projects/user_interacts_with_stars_spec.rb b/spec/features/projects/user_interacts_with_stars_spec.rb
new file mode 100644
index 00000000000..0ac3f8181fa
--- /dev/null
+++ b/spec/features/projects/user_interacts_with_stars_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe 'User interacts with project stars' do
+ let(:project) { create(:project, :public, :repository) }
+
+ context 'when user is signed in', js: true do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ visit(project_path(project))
+ end
+
+ it 'toggles the star' do
+ find('.star-btn').click
+
+ expect(page).to have_css('.star-count', text: 1)
+
+ find('.star-btn').click
+
+ expect(page).to have_css('.star-count', text: 0)
+ end
+ end
+
+ context 'when user is not signed in' do
+ before do
+ visit(project_path(project))
+ end
+
+ it 'does not allow to star a project' do
+ expect(page).not_to have_content('.toggle-star')
+
+ find('.star-btn').click
+
+ expect(current_path).to eq(new_user_session_path)
+ end
+ end
+end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 8769a52863c..0e80df94e18 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -10,6 +10,9 @@ describe IssuesFinder do
set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago) }
set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab') }
set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 1.week.from_now) }
+ set(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue1) }
+ set(:award_emoji2) { create(:award_emoji, name: 'thumbsup', user: user2, awardable: issue2) }
+ set(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) }
describe '#execute' do
set(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') }
@@ -26,6 +29,10 @@ describe IssuesFinder do
issue1
issue2
issue3
+
+ award_emoji1
+ award_emoji2
+ award_emoji3
end
context 'scope: all' do
@@ -250,6 +257,34 @@ describe IssuesFinder do
end
end
+ context 'filtering by reaction name' do
+ context 'user searches by "thumbsup" reaction' do
+ let(:params) { { my_reaction_emoji: 'thumbsup' } }
+
+ it 'returns issues that the user thumbsup to' do
+ expect(issues).to contain_exactly(issue1)
+ end
+ end
+
+ context 'user2 searches by "thumbsup" reaction' do
+ let(:search_user) { user2 }
+
+ let(:params) { { my_reaction_emoji: 'thumbsup' } }
+
+ it 'returns issues that the user2 thumbsup to' do
+ expect(issues).to contain_exactly(issue2)
+ end
+ end
+
+ context 'user searches by "thumbsdown" reaction' do
+ let(:params) { { my_reaction_emoji: 'thumbsdown' } }
+
+ it 'returns issues that the user thumbsdown to' do
+ expect(issues).to contain_exactly(issue3)
+ end
+ end
+ end
+
context 'when the user is unauthorized' do
let(:search_user) { nil }
diff --git a/spec/javascripts/droplab/drop_down_spec.js b/spec/javascripts/droplab/drop_down_spec.js
index 2bbcebeeac0..1ef494a00b8 100644
--- a/spec/javascripts/droplab/drop_down_spec.js
+++ b/spec/javascripts/droplab/drop_down_spec.js
@@ -351,14 +351,17 @@ describe('DropDown', function () {
describe('render', function () {
beforeEach(function () {
- this.list = { querySelector: () => {} };
+ this.list = { querySelector: () => {}, dispatchEvent: () => {} };
this.dropdown = { renderChildren: () => {}, list: this.list };
this.renderableList = {};
this.data = [0, 1];
+ this.customEvent = {};
spyOn(this.dropdown, 'renderChildren').and.callFake(data => data);
spyOn(this.list, 'querySelector').and.returnValue(this.renderableList);
+ spyOn(this.list, 'dispatchEvent');
spyOn(this.data, 'map').and.callThrough();
+ spyOn(window, 'CustomEvent').and.returnValue(this.customEvent);
DropDown.prototype.render.call(this.dropdown, this.data);
});
@@ -375,6 +378,14 @@ describe('DropDown', function () {
expect(this.renderableList.innerHTML).toBe('01');
});
+ it('should call render.dl', function () {
+ expect(window.CustomEvent).toHaveBeenCalledWith('render.dl', jasmine.any(Object));
+ });
+
+ it('should call dispatchEvent with the customEvent', function () {
+ expect(this.list.dispatchEvent).toHaveBeenCalledWith(this.customEvent);
+ });
+
describe('if no data argument is passed', function () {
beforeEach(function () {
this.data.map.calls.reset();
@@ -394,7 +405,7 @@ describe('DropDown', function () {
describe('if no dynamic list is present', function () {
beforeEach(function () {
- this.list = { querySelector: () => {} };
+ this.list = { querySelector: () => {}, dispatchEvent: () => {} };
this.dropdown = { renderChildren: () => {}, list: this.list };
this.data = [0, 1];
diff --git a/spec/javascripts/helpers/vue_mount_component_helper.js b/spec/javascripts/helpers/vue_mount_component_helper.js
new file mode 100644
index 00000000000..d7a2e86771c
--- /dev/null
+++ b/spec/javascripts/helpers/vue_mount_component_helper.js
@@ -0,0 +1,4 @@
+export default (Component, props = {}) => new Component({
+ propsData: props,
+}).$mount();
+
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index dc40244c20e..8830a2d29e5 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -295,6 +295,17 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
});
+ it('triggers scroll event when diff already loaded', function () {
+ spyOn(document, 'dispatchEvent');
+
+ this.class.diffsLoaded = true;
+ this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
+
+ expect(
+ document.dispatchEvent,
+ ).toHaveBeenCalledWith(new CustomEvent('scroll'));
+ });
+
describe('with inline diff', () => {
let noteId;
let noteLineNumId;
diff --git a/spec/javascripts/pipelines/navigation_tabs_spec.js b/spec/javascripts/pipelines/navigation_tabs_spec.js
new file mode 100644
index 00000000000..53a88e6322f
--- /dev/null
+++ b/spec/javascripts/pipelines/navigation_tabs_spec.js
@@ -0,0 +1,127 @@
+import Vue from 'vue';
+import navigationTabs from '~/pipelines/components/navigation_tabs.vue';
+import mountComponent from '../helpers/vue_mount_component_helper';
+
+describe('navigation tabs pipeline component', () => {
+ let vm;
+ let Component;
+ let data;
+
+ beforeEach(() => {
+ data = {
+ scope: 'all',
+ count: {
+ all: 16,
+ running: 1,
+ pending: 10,
+ finished: 0,
+ },
+ paths: {
+ allPath: '/gitlab-org/gitlab-ce/pipelines',
+ pendingPath: '/gitlab-org/gitlab-ce/pipelines?scope=pending',
+ finishedPath: '/gitlab-org/gitlab-ce/pipelines?scope=finished',
+ runningPath: '/gitlab-org/gitlab-ce/pipelines?scope=running',
+ branchesPath: '/gitlab-org/gitlab-ce/pipelines?scope=branches',
+ tagsPath: '/gitlab-org/gitlab-ce/pipelines?scope=tags',
+ },
+ };
+
+ Component = Vue.extend(navigationTabs);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render tabs with correct paths', () => {
+ vm = mountComponent(Component, data);
+
+ // All
+ const allTab = vm.$el.querySelector('.js-pipelines-tab-all a');
+ expect(allTab.textContent.trim()).toContain('All');
+ expect(allTab.getAttribute('href')).toEqual(data.paths.allPath);
+
+ // Pending
+ const pendingTab = vm.$el.querySelector('.js-pipelines-tab-pending a');
+ expect(pendingTab.textContent.trim()).toContain('Pending');
+ expect(pendingTab.getAttribute('href')).toEqual(data.paths.pendingPath);
+
+ // Running
+ const runningTab = vm.$el.querySelector('.js-pipelines-tab-running a');
+ expect(runningTab.textContent.trim()).toContain('Running');
+ expect(runningTab.getAttribute('href')).toEqual(data.paths.runningPath);
+
+ // Finished
+ const finishedTab = vm.$el.querySelector('.js-pipelines-tab-finished a');
+ expect(finishedTab.textContent.trim()).toContain('Finished');
+ expect(finishedTab.getAttribute('href')).toEqual(data.paths.finishedPath);
+
+ // Branches
+ const branchesTab = vm.$el.querySelector('.js-pipelines-tab-branches a');
+ expect(branchesTab.textContent.trim()).toContain('Branches');
+
+ // Tags
+ const tagsTab = vm.$el.querySelector('.js-pipelines-tab-tags a');
+ expect(tagsTab.textContent.trim()).toContain('Tags');
+ });
+
+ describe('scope', () => {
+ it('should render scope provided as active tab', () => {
+ vm = mountComponent(Component, data);
+ expect(vm.$el.querySelector('.js-pipelines-tab-all').className).toContain('active');
+ });
+ });
+
+ describe('badges', () => {
+ it('should render provided number', () => {
+ vm = mountComponent(Component, data);
+ // All
+ expect(
+ vm.$el.querySelector('.js-totalbuilds-count').textContent.trim(),
+ ).toContain(data.count.all);
+
+ // Pending
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-pending .badge').textContent.trim(),
+ ).toContain(data.count.pending);
+
+ // Running
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-running .badge').textContent.trim(),
+ ).toContain(data.count.running);
+
+ // Finished
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-finished .badge').textContent.trim(),
+ ).toContain(data.count.finished);
+ });
+
+ it('should not render badge when number is undefined', () => {
+ vm = mountComponent(Component, {
+ scope: 'all',
+ paths: {},
+ count: {},
+ });
+
+ // All
+ expect(
+ vm.$el.querySelector('.js-totalbuilds-count'),
+ ).toEqual(null);
+
+ // Pending
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-pending .badge'),
+ ).toEqual(null);
+
+ // Running
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-running .badge'),
+ ).toEqual(null);
+
+ // Finished
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-finished .badge'),
+ ).toEqual(null);
+ });
+ });
+});
diff --git a/spec/javascripts/groups/group_identicon_spec.js b/spec/javascripts/vue_shared/components/identicon_spec.js
index 66772327503..4f194e5a64e 100644
--- a/spec/javascripts/groups/group_identicon_spec.js
+++ b/spec/javascripts/vue_shared/components/identicon_spec.js
@@ -1,22 +1,18 @@
import Vue from 'vue';
-import groupIdenticonComponent from '~/groups/components/group_identicon.vue';
-import GroupsStore from '~/groups/stores/groups_store';
-import { group1 } from './mock_data';
+import identiconComponent from '~/vue_shared/components/identicon.vue';
const createComponent = () => {
- const Component = Vue.extend(groupIdenticonComponent);
- const store = new GroupsStore();
- const group = store.decorateGroup(group1);
+ const Component = Vue.extend(identiconComponent);
return new Component({
propsData: {
- entityId: group.id,
- entityName: group.name,
+ entityId: 1,
+ entityName: 'entity-name',
},
}).$mount();
};
-describe('GroupIdenticonComponent', () => {
+describe('IdenticonComponent', () => {
let vm;
beforeEach(() => {
diff --git a/spec/lib/gitlab/sql/pattern_spec.rb b/spec/lib/gitlab/sql/pattern_spec.rb
new file mode 100644
index 00000000000..9d7b2136dab
--- /dev/null
+++ b/spec/lib/gitlab/sql/pattern_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe Gitlab::SQL::Pattern do
+ describe '.to_pattern' do
+ subject(:to_pattern) { User.to_pattern(query) }
+
+ context 'when a query is shorter than 3 chars' do
+ let(:query) { '12' }
+
+ it 'returns exact matching pattern' do
+ expect(to_pattern).to eq('12')
+ end
+ end
+
+ context 'when a query with a escape character is shorter than 3 chars' do
+ let(:query) { '_2' }
+
+ it 'returns sanitized exact matching pattern' do
+ expect(to_pattern).to eq('\_2')
+ end
+ end
+
+ context 'when a query is equal to 3 chars' do
+ let(:query) { '123' }
+
+ it 'returns partial matching pattern' do
+ expect(to_pattern).to eq('%123%')
+ end
+ end
+
+ context 'when a query with a escape character is equal to 3 chars' do
+ let(:query) { '_23' }
+
+ it 'returns partial matching pattern' do
+ expect(to_pattern).to eq('%\_23%')
+ end
+ end
+
+ context 'when a query is longer than 3 chars' do
+ let(:query) { '1234' }
+
+ it 'returns partial matching pattern' do
+ expect(to_pattern).to eq('%1234%')
+ end
+ end
+
+ context 'when a query with a escape character is longer than 3 chars' do
+ let(:query) { '_234' }
+
+ it 'returns sanitized partial matching pattern' do
+ expect(to_pattern).to eq('%\_234%')
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb
index 63ad3a3630b..34f923d3f0c 100644
--- a/spec/models/concerns/awardable_spec.rb
+++ b/spec/models/concerns/awardable_spec.rb
@@ -12,17 +12,25 @@ describe Awardable do
describe "ClassMethods" do
let!(:issue2) { create(:issue) }
+ let!(:award_emoji2) { create(:award_emoji, awardable: issue2) }
- before do
- create(:award_emoji, awardable: issue2)
- end
+ describe "orders" do
+ it "orders on upvotes" do
+ expect(Issue.order_upvotes_desc.to_a).to eq [issue2, issue]
+ end
- it "orders on upvotes" do
- expect(Issue.order_upvotes_desc.to_a).to eq [issue2, issue]
+ it "orders on downvotes" do
+ expect(Issue.order_downvotes_desc.to_a).to eq [issue, issue2]
+ end
end
- it "orders on downvotes" do
- expect(Issue.order_downvotes_desc.to_a).to eq [issue, issue2]
+ describe ".awarded" do
+ it "filters by user and emoji name" do
+ expect(Issue.awarded(award_emoji.user, "thumbsup")).to be_empty
+ expect(Issue.awarded(award_emoji.user, "thumbsdown")).to eq [issue]
+ expect(Issue.awarded(award_emoji2.user, "thumbsup")).to eq [issue2]
+ expect(Issue.awarded(award_emoji2.user, "thumbsdown")).to be_empty
+ end
end
end
diff --git a/spec/models/concerns/editable_spec.rb b/spec/models/concerns/editable_spec.rb
index cd73af3b480..49a9a8ebcbc 100644
--- a/spec/models/concerns/editable_spec.rb
+++ b/spec/models/concerns/editable_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
describe Editable do
- describe '#is_edited?' do
+ describe '#edited?' do
let(:issue) { create(:issue, last_edited_at: nil) }
let(:edited_issue) { create(:issue, created_at: 3.days.ago, last_edited_at: 2.days.ago) }
- it { expect(issue.is_edited?).to eq(false) }
- it { expect(edited_issue.is_edited?).to eq(true) }
+ it { expect(issue.edited?).to eq(false) }
+ it { expect(edited_issue.edited?).to eq(true) }
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 462e92b8b62..34e1a955309 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -923,13 +923,16 @@ describe Repository, models: true do
describe '#update_branch_with_hooks' do
let(:old_rev) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } # git rev-parse feature
let(:new_rev) { 'a74ae73c1ccde9b974a70e82b901588071dc142a' } # commit whose parent is old_rev
+ let(:updating_ref) { 'refs/heads/feature' }
+ let(:target_project) { project }
+ let(:target_repository) { target_project.repository }
context 'when pre hooks were successful' do
before do
service = Gitlab::Git::HooksService.new
expect(Gitlab::Git::HooksService).to receive(:new).and_return(service)
expect(service).to receive(:execute)
- .with(committer, repository, old_rev, new_rev, 'refs/heads/feature')
+ .with(committer, target_repository, old_rev, new_rev, updating_ref)
.and_yield(service).and_return(true)
end
@@ -960,6 +963,37 @@ describe Repository, models: true do
expect(repository.find_branch('feature').dereferenced_target.id).to eq(new_rev)
end
end
+
+ context 'when target project does not have the commit' do
+ let(:target_project) { create(:project, :empty_repo) }
+ let(:old_rev) { Gitlab::Git::BLANK_SHA }
+ let(:new_rev) { project.commit('feature').sha }
+ let(:updating_ref) { 'refs/heads/master' }
+
+ it 'fetch_ref and create the branch' do
+ expect(target_project.repository).to receive(:fetch_ref)
+ .and_call_original
+
+ GitOperationService.new(committer, target_repository)
+ .with_branch(
+ 'master',
+ start_project: project,
+ start_branch_name: 'feature') { new_rev }
+
+ expect(target_repository.branch_names).to contain_exactly('master')
+ end
+ end
+
+ context 'when target project already has the commit' do
+ let(:target_project) { create(:project, :repository) }
+
+ it 'does not fetch_ref and just pass the commit' do
+ expect(target_repository).not_to receive(:fetch_ref)
+
+ GitOperationService.new(committer, target_repository)
+ .with_branch('feature', start_project: project) { new_rev }
+ end
+ end
end
context 'when temporary ref failed to be created from other project' do
@@ -2036,23 +2070,23 @@ describe Repository, models: true do
end
end
- describe '#is_ancestor?' do
+ describe '#ancestor?' do
let(:commit) { repository.commit }
let(:ancestor) { commit.parents.first }
context 'with Gitaly enabled' do
it 'it is an ancestor' do
- expect(repository.is_ancestor?(ancestor.id, commit.id)).to eq(true)
+ expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
end
it 'it is not an ancestor' do
- expect(repository.is_ancestor?(commit.id, ancestor.id)).to eq(false)
+ expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
end
it 'returns false on nil-values' do
- expect(repository.is_ancestor?(nil, commit.id)).to eq(false)
- expect(repository.is_ancestor?(ancestor.id, nil)).to eq(false)
- expect(repository.is_ancestor?(nil, nil)).to eq(false)
+ expect(repository.ancestor?(nil, commit.id)).to eq(false)
+ expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
+ expect(repository.ancestor?(nil, nil)).to eq(false)
end
end
@@ -2063,17 +2097,17 @@ describe Repository, models: true do
end
it 'it is an ancestor' do
- expect(repository.is_ancestor?(ancestor.id, commit.id)).to eq(true)
+ expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
end
it 'it is not an ancestor' do
- expect(repository.is_ancestor?(commit.id, ancestor.id)).to eq(false)
+ expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
end
it 'returns false on nil-values' do
- expect(repository.is_ancestor?(nil, commit.id)).to eq(false)
- expect(repository.is_ancestor?(ancestor.id, nil)).to eq(false)
- expect(repository.is_ancestor?(nil, nil)).to eq(false)
+ expect(repository.ancestor?(nil, commit.id)).to eq(false)
+ expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
+ expect(repository.ancestor?(nil, nil)).to eq(false)
end
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 8e04eea56a7..b70ab5581ac 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -789,6 +789,7 @@ describe User do
describe '.search' do
let!(:user) { create(:user, name: 'user', username: 'usern', email: 'email@gmail.com') }
let!(:user2) { create(:user, name: 'user name', username: 'username', email: 'someemail@gmail.com') }
+ let!(:user3) { create(:user, name: 'us', username: 'se', email: 'foo@gmail.com') }
describe 'name matching' do
it 'returns users with a matching name with exact match first' do
@@ -802,6 +803,14 @@ describe User do
it 'returns users with a matching name regardless of the casing' do
expect(described_class.search(user2.name.upcase)).to eq([user2])
end
+
+ it 'returns users with a exact matching name shorter than 3 chars' do
+ expect(described_class.search(user3.name)).to eq([user3])
+ end
+
+ it 'returns users with a exact matching name shorter than 3 chars regardless of the casing' do
+ expect(described_class.search(user3.name.upcase)).to eq([user3])
+ end
end
describe 'email matching' do
@@ -830,6 +839,14 @@ describe User do
it 'returns users with a matching username regardless of the casing' do
expect(described_class.search(user2.username.upcase)).to eq([user2])
end
+
+ it 'returns users with a exact matching username shorter than 3 chars' do
+ expect(described_class.search(user3.username)).to eq([user3])
+ end
+
+ it 'returns users with a exact matching username shorter than 3 chars regardless of the casing' do
+ expect(described_class.search(user3.username.upcase)).to eq([user3])
+ end
end
end
diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb
index 1dd9f3f6ddc..593068b8cd7 100644
--- a/spec/requests/api/award_emoji_spec.rb
+++ b/spec/requests/api/award_emoji_spec.rb
@@ -253,6 +253,10 @@ describe API::AwardEmoji do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}/award_emoji/#{award_emoji.id}", user) }
+ end
end
context 'when the awardable is a Merge Request' do
@@ -269,6 +273,10 @@ describe API::AwardEmoji do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/award_emoji/#{downvote.id}", user) }
+ end
end
context 'when the awardable is a Snippet' do
@@ -282,6 +290,10 @@ describe API::AwardEmoji do
expect(response).to have_http_status(204)
end.to change { snippet.award_emoji.count }.from(1).to(0)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user) }
+ end
end
end
@@ -295,5 +307,9 @@ describe API::AwardEmoji do
expect(response).to have_http_status(204)
end.to change { note.award_emoji.count }.from(1).to(0)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}/notes/#{note.id}/award_emoji/#{rocket.id}", user) }
+ end
end
end
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index 43b381c2219..f698d5dddb3 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -195,6 +195,10 @@ describe API::Boards do
expect(response).to have_http_status(204)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("#{base_url}/#{dev_list.id}", owner) }
+ end
end
end
end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 5a2e1b2cf2d..b1e011de604 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -499,6 +499,10 @@ describe API::Branches do
expect(response).to have_gitlab_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/repository/branches/#{branch_name}", user) }
+ end
end
describe 'DELETE /projects/:id/repository/merged_branches' do
diff --git a/spec/requests/api/broadcast_messages_spec.rb b/spec/requests/api/broadcast_messages_spec.rb
index 67989689799..b043a333d33 100644
--- a/spec/requests/api/broadcast_messages_spec.rb
+++ b/spec/requests/api/broadcast_messages_spec.rb
@@ -171,6 +171,10 @@ describe API::BroadcastMessages do
expect(response).to have_http_status(403)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/broadcast_messages/#{message.id}", admin) }
+ end
+
it 'deletes the broadcast message for admins' do
expect do
delete api("/broadcast_messages/#{message.id}", admin)
diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb
index e497ec333a2..684877c33c0 100644
--- a/spec/requests/api/deploy_keys_spec.rb
+++ b/spec/requests/api/deploy_keys_spec.rb
@@ -190,6 +190,10 @@ describe API::DeployKeys do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/deploy_keys/#{deploy_key.id}", admin) }
+ end
end
describe 'POST /projects/:id/deploy_keys/:key_id/enable' do
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index 87716c6fe3a..2361809e0e1 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -138,6 +138,10 @@ describe API::Environments do
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found')
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/environments/#{environment.id}", user) }
+ end
end
context 'a non member' do
diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb
index 2179790d098..93b9cf85c1d 100644
--- a/spec/requests/api/group_variables_spec.rb
+++ b/spec/requests/api/group_variables_spec.rb
@@ -200,6 +200,10 @@ describe API::GroupVariables do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/groups/#{group.id}/variables/#{variable.key}", user) }
+ end
end
context 'authorized user with invalid permissions' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index a7557c7fb22..77c43f92456 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -444,6 +444,7 @@ describe API::Groups do
expect(json_response["name"]).to eq(group[:name])
expect(json_response["path"]).to eq(group[:path])
expect(json_response["request_access_enabled"]).to eq(group[:request_access_enabled])
+ expect(json_response["visibility"]).to eq(Gitlab::VisibilityLevel.string_level(Gitlab::CurrentSettings.current_application_settings.default_group_visibility))
end
it "creates a nested group", :nested_groups do
@@ -488,6 +489,10 @@ describe API::Groups do
expect(response).to have_http_status(204)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/groups/#{group1.id}", user1) }
+ end
+
it "does not remove a group if not an owner" do
user4 = create(:user)
group1.add_master(user4)
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 7d120e4a234..9a0c62467d3 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -984,7 +984,7 @@ describe API::Issues, :mailer do
describe 'POST /projects/:id/issues with spam filtering' do
before do
allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
end
let(:params) do
@@ -1114,7 +1114,7 @@ describe API::Issues, :mailer do
it "does not create a new project issue" do
allow_any_instance_of(SpamService).to receive_messages(check_for_spam?: true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
put api("/projects/#{project.id}/issues/#{issue.iid}", user), params
@@ -1304,6 +1304,10 @@ describe API::Issues, :mailer do
expect(response).to have_http_status(204)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}", owner) }
+ end
end
context 'when issue does not exist' do
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 5a4257d1009..b231fdea2a3 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -189,6 +189,11 @@ describe API::Labels do
delete api("/projects/#{project.id}/labels", user)
expect(response).to have_http_status(400)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/labels", user) }
+ let(:params) { { name: 'label1' } }
+ end
end
describe 'PUT /projects/:id/labels' do
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 06aca698c91..d3bae8d2888 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -284,6 +284,10 @@ describe API::Members do
expect(response).to have_http_status(204)
end.to change { source.members.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master) }
+ end
end
it 'returns 404 if member does not exist' do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 0db645863fb..9027090aabd 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -698,6 +698,10 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user) }
+ end
end
end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 75e5062a99c..f5882c0c74a 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -390,6 +390,10 @@ describe API::Notes do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}/notes/#{issue_note.id}", user) }
+ end
end
context 'when noteable is a Snippet' do
@@ -410,6 +414,10 @@ describe API::Notes do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/snippets/#{snippet.id}/notes/#{snippet_note.id}", user) }
+ end
end
context 'when noteable is a Merge Request' do
@@ -430,6 +438,10 @@ describe API::Notes do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/notes/#{merge_request_note.id}", user) }
+ end
end
end
end
diff --git a/spec/requests/api/pipeline_schedules_spec.rb b/spec/requests/api/pipeline_schedules_spec.rb
index 1fc0ec528b9..b6a5a7ffbb5 100644
--- a/spec/requests/api/pipeline_schedules_spec.rb
+++ b/spec/requests/api/pipeline_schedules_spec.rb
@@ -267,8 +267,7 @@ describe API::PipelineSchedules do
delete api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", master)
end.to change { project.pipeline_schedules.count }.by(-1)
- expect(response).to have_http_status(:accepted)
- expect(response).to match_response_schema('pipeline_schedule')
+ expect(response).to have_http_status(204)
end
it 'responds with 404 Not Found if requesting non-existing pipeline_schedule' do
@@ -276,6 +275,10 @@ describe API::PipelineSchedules do
expect(response).to have_http_status(:not_found)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", master) }
+ end
end
context 'authenticated user with invalid permissions' do
diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb
index 2829c243af3..ac3bab09c4c 100644
--- a/spec/requests/api/project_hooks_spec.rb
+++ b/spec/requests/api/project_hooks_spec.rb
@@ -212,5 +212,9 @@ describe API::ProjectHooks, 'ProjectHooks' do
expect(response).to have_http_status(404)
expect(WebHook.exists?(hook.id)).to be_truthy
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/hooks/#{hook.id}", user) }
+ end
end
end
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index 2b541f5719e..db34149eb73 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -117,7 +117,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -179,7 +179,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -228,9 +228,6 @@ describe API::ProjectSnippets do
let(:snippet) { create(:project_snippet, author: admin) }
it 'deletes snippet' do
- admin = create(:admin)
- snippet = create(:project_snippet, author: admin)
-
delete api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin)
expect(response).to have_http_status(204)
@@ -242,6 +239,10 @@ describe API::ProjectSnippets do
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Snippet Not Found')
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin) }
+ end
end
describe 'GET /projects/:project_id/snippets/:id/raw' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index a89a58ff713..4490e50702b 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1029,6 +1029,10 @@ describe API::Projects do
delete api("/projects/#{project.id}/snippets/1234", user)
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/snippets/#{snippet.id}", user) }
+ end
end
describe 'GET /projects/:id/snippets/:snippet_id/raw' do
@@ -1104,23 +1108,31 @@ describe API::Projects do
project_fork_target.group.add_developer user2
end
- it 'is forbidden to non-owner users' do
- delete api("/projects/#{project_fork_target.id}/fork", user2)
- expect(response).to have_http_status(403)
- end
+ context 'for a forked project' do
+ before do
+ post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
+ project_fork_target.reload
+ expect(project_fork_target.forked_from_project).not_to be_nil
+ expect(project_fork_target.forked?).to be_truthy
+ end
- it 'makes forked project unforked' do
- post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project).not_to be_nil
- expect(project_fork_target.forked?).to be_truthy
+ it 'makes forked project unforked' do
+ delete api("/projects/#{project_fork_target.id}/fork", admin)
- delete api("/projects/#{project_fork_target.id}/fork", admin)
+ expect(response).to have_http_status(204)
+ project_fork_target.reload
+ expect(project_fork_target.forked_from_project).to be_nil
+ expect(project_fork_target.forked?).not_to be_truthy
+ end
- expect(response).to have_http_status(204)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project).to be_nil
- expect(project_fork_target.forked?).not_to be_truthy
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project_fork_target.id}/fork", admin) }
+ end
+ end
+
+ it 'is forbidden to non-owner users' do
+ delete api("/projects/#{project_fork_target.id}/fork", user2)
+ expect(response).to have_http_status(403)
end
it 'is idempotent if not forked' do
@@ -1188,14 +1200,23 @@ describe API::Projects do
end
describe 'DELETE /projects/:id/share/:group_id' do
- it 'returns 204 when deleting a group share' do
- group = create(:group, :public)
- create(:project_group_link, group: group, project: project)
+ context 'for a valid group' do
+ let(:group) { create(:group, :public) }
+
+ before do
+ create(:project_group_link, group: group, project: project)
+ end
+
+ it 'returns 204 when deleting a group share' do
+ delete api("/projects/#{project.id}/share/#{group.id}", user)
- delete api("/projects/#{project.id}/share/#{group.id}", user)
+ expect(response).to have_http_status(204)
+ expect(project.project_group_links).to be_empty
+ end
- expect(response).to have_http_status(204)
- expect(project.project_group_links).to be_empty
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/share/#{group.id}", user) }
+ end
end
it 'returns a 400 when group id is not an integer' do
@@ -1519,6 +1540,11 @@ describe API::Projects do
expect(json_response['message']).to eql('202 Accepted')
end
+ it_behaves_like '412 response' do
+ let(:success_status) { 202 }
+ let(:request) { api("/projects/#{project.id}", user) }
+ end
+
it 'does not remove a project if not an owner' do
user3 = create(:user)
project.team << [user3, :developer]
@@ -1549,6 +1575,11 @@ describe API::Projects do
delete api('/projects/1328', admin)
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:success_status) { 202 }
+ let(:request) { api("/projects/#{project.id}", admin) }
+ end
end
end
diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb
index 1aa8a95780e..07d7f96bd70 100644
--- a/spec/requests/api/protected_branches_spec.rb
+++ b/spec/requests/api/protected_branches_spec.rb
@@ -213,6 +213,10 @@ describe API::ProtectedBranches do
expect(response).to have_gitlab_http_status(204)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/protected_branches/#{branch_name}", user) }
+ end
+
it "returns 404 if branch does not exist" do
delete api("/projects/#{project.id}/protected_branches/barfoo", user)
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index e9ee3dd679d..993164aa8fe 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -149,6 +149,11 @@ describe API::Runner do
expect(response).to have_http_status 204
expect(Ci::Runner.count).to eq(0)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api('/runners') }
+ let(:params) { { token: runner.token } }
+ end
end
end
diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb
index c8ff25f70fa..244895a417e 100644
--- a/spec/requests/api/runners_spec.rb
+++ b/spec/requests/api/runners_spec.rb
@@ -279,6 +279,10 @@ describe API::Runners do
expect(response).to have_http_status(204)
end.to change { Ci::Runner.shared.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/runners/#{shared_runner.id}", admin) }
+ end
end
context 'when runner is not shared' do
@@ -332,6 +336,10 @@ describe API::Runners do
expect(response).to have_http_status(204)
end.to change { Ci::Runner.specific.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/runners/#{specific_runner.id}", user) }
+ end
end
end
@@ -463,6 +471,10 @@ describe API::Runners do
expect(response).to have_http_status(204)
end.to change { project.runners.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/runners/#{two_projects_runner.id}", user) }
+ end
end
context 'when runner have one associated projects' do
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index d09b8bc42f1..d3905f698bd 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -137,7 +137,7 @@ describe API::Snippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -209,7 +209,7 @@ describe API::Snippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -270,6 +270,10 @@ describe API::Snippets do
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Snippet Not Found')
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/snippets/#{public_snippet.id}", user) }
+ end
end
describe "GET /snippets/:id/user_agent_detail" do
diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb
index f65b475fe44..216d278ad21 100644
--- a/spec/requests/api/system_hooks_spec.rb
+++ b/spec/requests/api/system_hooks_spec.rb
@@ -102,5 +102,9 @@ describe API::SystemHooks do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/hooks/#{hook.id}", admin) }
+ end
end
end
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index 9884c1ec206..0bf7863bdc8 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -278,12 +278,16 @@ describe API::Tags do
expect(response).to have_gitlab_http_status(204)
end
+ it_behaves_like '412 response' do
+ let(:request) { api(route, current_user) }
+ end
+
context 'when tag does not exist' do
let(:tag_name) { 'unknown' }
it_behaves_like '404 response' do
let(:request) { delete api(route, current_user) }
- let(:message) { 'No such tag' }
+ let(:message) { '404 Tag Not Found' }
end
end
diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb
index 402d1040436..922b99a6cba 100644
--- a/spec/requests/api/triggers_spec.rb
+++ b/spec/requests/api/triggers_spec.rb
@@ -309,6 +309,10 @@ describe API::Triggers do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/triggers/#{trigger.id}", user) }
+ end
end
context 'authenticated user with invalid permissions' do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 49739a1601a..5fef4437997 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -733,6 +733,10 @@ describe API::Users do
end.to change { user.keys.count }.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}/keys/#{key.id}", admin) }
+ end
+
it 'returns 404 error if user not found' do
user.keys << key
user.save
@@ -838,6 +842,10 @@ describe API::Users do
end.to change { user.emails.count }.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}/emails/#{email.id}", admin) }
+ end
+
it 'returns 404 error if user not found' do
user.emails << email
user.save
@@ -876,6 +884,10 @@ describe API::Users do
expect { Namespace.find(namespace.id) }.to raise_error ActiveRecord::RecordNotFound
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}", admin) }
+ end
+
it "does not delete for unauthenticated user" do
Sidekiq::Testing.inline! { delete api("/users/#{user.id}") }
expect(response).to have_http_status(401)
@@ -1116,6 +1128,10 @@ describe API::Users do
end.to change { user.keys.count}.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/user/keys/#{key.id}", user) }
+ end
+
it "returns 404 if key ID not found" do
delete api("/user/keys/42", user)
@@ -1239,6 +1255,10 @@ describe API::Users do
end.to change { user.emails.count}.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/user/emails/#{email.id}", user) }
+ end
+
it "returns 404 if email ID not found" do
delete api("/user/emails/42", user)
@@ -1551,6 +1571,10 @@ describe API::Users do
expect(json_response['message']).to eq('403 Forbidden')
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin) }
+ end
+
it 'revokes a impersonation token' do
delete api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb
index 9eb538c4b09..9a0e6647ebf 100644
--- a/spec/requests/api/v3/issues_spec.rb
+++ b/spec/requests/api/v3/issues_spec.rb
@@ -884,7 +884,7 @@ describe API::V3::Issues, :mailer do
describe 'POST /projects/:id/issues with spam filtering' do
before do
allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
end
let(:params) do
@@ -1016,7 +1016,7 @@ describe API::V3::Issues, :mailer do
it "does not create a new project issue" do
allow_any_instance_of(SpamService).to receive_messages(check_for_spam?: true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), params
diff --git a/spec/requests/api/v3/project_snippets_spec.rb b/spec/requests/api/v3/project_snippets_spec.rb
index 3963924a066..7e88489082a 100644
--- a/spec/requests/api/v3/project_snippets_spec.rb
+++ b/spec/requests/api/v3/project_snippets_spec.rb
@@ -80,7 +80,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -140,7 +140,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/requests/api/v3/snippets_spec.rb b/spec/requests/api/v3/snippets_spec.rb
index 9ead3cad8bb..79860725634 100644
--- a/spec/requests/api/v3/snippets_spec.rb
+++ b/spec/requests/api/v3/snippets_spec.rb
@@ -107,7 +107,7 @@ describe API::V3::Snippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index e3c1bdce300..cc3d4e7da49 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -617,7 +617,7 @@ describe GitPushService, services: true do
context 'on the default branch' do
before do
- allow(service).to receive(:is_default_branch?).and_return(true)
+ allow(service).to receive(:default_branch?).and_return(true)
end
it 'flushes the caches of any special files that have been changed' do
@@ -638,7 +638,7 @@ describe GitPushService, services: true do
context 'on a non-default branch' do
before do
- allow(service).to receive(:is_default_branch?).and_return(false)
+ allow(service).to receive(:default_branch?).and_return(false)
end
it 'does not flush any conditional caches' do
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 78b11cd7991..cc3d648c340 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -370,7 +370,7 @@ describe Issues::CreateService do
context 'when recaptcha was not verified' do
context 'when akismet detects spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
it 'marks an issue as a spam ' do
@@ -392,7 +392,7 @@ describe Issues::CreateService do
context 'when akismet does not detect spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(false)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(false)
end
it 'does not mark an issue as a spam ' do
diff --git a/spec/services/spam_service_spec.rb b/spec/services/spam_service_spec.rb
index a14dfa3f01f..61312d55b84 100644
--- a/spec/services/spam_service_spec.rb
+++ b/spec/services/spam_service_spec.rb
@@ -23,7 +23,7 @@ describe SpamService do
before do
issue.closed_at = Time.zone.now
- allow(AkismetService).to receive(:new).and_return(double(is_spam?: true))
+ allow(AkismetService).to receive(:new).and_return(double(spam?: true))
end
it 'returns false' do
@@ -43,7 +43,7 @@ describe SpamService do
context 'when indicated as spam by akismet' do
before do
- allow(AkismetService).to receive(:new).and_return(double(is_spam?: true))
+ allow(AkismetService).to receive(:new).and_return(double(spam?: true))
end
it 'doesnt check as spam when request is missing' do
@@ -71,7 +71,7 @@ describe SpamService do
context 'when not indicated as spam by akismet' do
before do
- allow(AkismetService).to receive(:new).and_return(double(is_spam?: false))
+ allow(AkismetService).to receive(:new).and_return(double(spam?: false))
end
it 'returns false' do
diff --git a/spec/support/filtered_search_helpers.rb b/spec/support/filtered_search_helpers.rb
index 99b8b6b7ea4..05021ea9054 100644
--- a/spec/support/filtered_search_helpers.rb
+++ b/spec/support/filtered_search_helpers.rb
@@ -58,11 +58,17 @@ module FilteredSearchHelpers
page.all(:css, '.tokens-container li .selectable').each_with_index do |el, index|
token_name = tokens[index][:name]
token_value = tokens[index][:value]
+ token_emoji = tokens[index][:emoji_name]
expect(el.find('.name')).to have_content(token_name)
if token_value
expect(el.find('.value')).to have_content(token_value)
end
+ # gl-emoji content is blank when the emoji unicode is not supported
+ if token_emoji
+ selector = %(gl-emoji[data-name="#{token_emoji}"])
+ expect(el.find('.value')).to have_css(selector)
+ end
end
end
end
@@ -89,6 +95,10 @@ module FilteredSearchHelpers
create_token('Label', label_name, symbol)
end
+ def emoji_token(emoji_name = nil)
+ { name: 'My-Reaction', emoji_name: emoji_name }
+ end
+
def default_placeholder
'Search or filter results...'
end
diff --git a/spec/support/shared_examples/requests/api/status_shared_examples.rb b/spec/support/shared_examples/requests/api/status_shared_examples.rb
index 226277411d6..7d7f66adeab 100644
--- a/spec/support/shared_examples/requests/api/status_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/status_shared_examples.rb
@@ -40,3 +40,28 @@ shared_examples_for '404 response' do
end
end
end
+
+shared_examples_for '412 response' do
+ let(:params) { nil }
+ let(:success_status) { 204 }
+
+ context 'for a modified ressource' do
+ before do
+ delete request, params, { 'HTTP_IF_UNMODIFIED_SINCE' => '1990-01-12T00:00:48-0600' }
+ end
+
+ it 'returns 412' do
+ expect(response).to have_gitlab_http_status(412)
+ end
+ end
+
+ context 'for an unmodified ressource' do
+ before do
+ delete request, params, { 'HTTP_IF_UNMODIFIED_SINCE' => Time.now }
+ end
+
+ it 'returns accepted' do
+ expect(response).to have_gitlab_http_status(success_status)
+ end
+ end
+end