diff options
author | Phil Hughes <me@iamphill.com> | 2017-08-30 18:49:22 +0300 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2017-08-30 18:49:22 +0300 |
commit | 4d2d744ae9a2d4c3bb0f00805c27704b79e00d72 (patch) | |
tree | 839b1c3ab4c09c80f7d643fe69dae8a83c4e4eb4 /spec | |
parent | 25a3b7fab905d09f6f064108f457a4e20c8915ff (diff) | |
parent | f7c8434c7100c3c87eb2a75cd5a128e520d8c110 (diff) |
Merge branch 'master' into enable-new-navigaton-by-default
Diffstat (limited to 'spec')
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 |