diff options
Diffstat (limited to 'spec')
35 files changed, 1106 insertions, 467 deletions
diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb index 294fae95752..0b8ff006d22 100644 --- a/spec/config/mail_room_spec.rb +++ b/spec/config/mail_room_spec.rb @@ -8,7 +8,7 @@ describe 'mail_room.yml' do context 'when incoming email is disabled' do before do - ENV['MAIL_ROOM_GITLAB_CONFIG_FILE'] = Rails.root.join('spec/fixtures/mail_room_disabled.yml').to_s + ENV['MAIL_ROOM_GITLAB_CONFIG_FILE'] = Rails.root.join('spec/fixtures/config/mail_room_disabled.yml').to_s Gitlab::MailRoom.reset_config! end @@ -26,7 +26,7 @@ describe 'mail_room.yml' do let(:gitlab_redis) { Gitlab::Redis.new(Rails.env) } before do - ENV['MAIL_ROOM_GITLAB_CONFIG_FILE'] = Rails.root.join('spec/fixtures/mail_room_enabled.yml').to_s + ENV['MAIL_ROOM_GITLAB_CONFIG_FILE'] = Rails.root.join('spec/fixtures/config/mail_room_enabled.yml').to_s Gitlab::MailRoom.reset_config! end diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb index 0a3ac9f9512..7072bd5e87c 100644 --- a/spec/controllers/dashboard/todos_controller_spec.rb +++ b/spec/controllers/dashboard/todos_controller_spec.rb @@ -46,7 +46,7 @@ describe Dashboard::TodosController do expect(todo.reload).to be_pending expect(response).to have_http_status(200) - expect(json_response).to eq({ "count" => 1, "done_count" => 0 }) + expect(json_response).to eq({ "count" => "1", "done_count" => "0" }) end end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index e576bf9ef79..7871b6a9e10 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -152,6 +152,113 @@ describe Projects::IssuesController do end end + context 'Akismet is enabled' do + let(:project) { create(:project_empty_repo, :public) } + + before do + stub_application_setting(recaptcha_enabled: true) + allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true) + end + + 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) + end + + it 'normally updates the issue' do + expect { update_issue(title: 'Foo') }.to change { issue.reload.title }.to('Foo') + end + end + + context 'when an issue is identified as spam' do + before { allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) } + + context 'when captcha is not verified' do + def update_spam_issue + update_issue(title: 'Spam Title', description: 'Spam lives here') + end + + before { allow_any_instance_of(described_class).to receive(:verify_recaptcha).and_return(false) } + + it 'rejects an issue recognized as a spam' do + expect { update_spam_issue }.not_to change{ issue.reload.title } + end + + it 'rejects an issue recognized as a spam when recaptcha disabled' do + stub_application_setting(recaptcha_enabled: false) + + expect { update_spam_issue }.not_to change{ issue.reload.title } + end + + it 'creates a spam log' do + update_spam_issue + + spam_logs = SpamLog.all + + expect(spam_logs.count).to eq(1) + expect(spam_logs.first.title).to eq('Spam Title') + expect(spam_logs.first.recaptcha_verified).to be_falsey + end + + it 'renders verify template' do + update_spam_issue + + expect(response).to render_template(:verify) + end + end + + context 'when captcha is verified' do + let(:spammy_title) { 'Whatever' } + let!(:spam_logs) { create_list(:spam_log, 2, user: user, title: spammy_title) } + + def update_verified_issue + update_issue({ title: spammy_title }, + { spam_log_id: spam_logs.last.id, + recaptcha_verification: true }) + end + + before do + allow_any_instance_of(described_class).to receive(:verify_recaptcha) + .and_return(true) + end + + it 'redirect to issue page' do + update_verified_issue + + expect(response). + to redirect_to(namespace_project_issue_path(project.namespace, project, issue)) + end + + it 'accepts an issue after recaptcha is verified' do + expect{ update_verified_issue }.to change{ issue.reload.title }.to(spammy_title) + end + + it 'marks spam log as recaptcha_verified' do + expect { update_verified_issue }.to change { SpamLog.last.recaptcha_verified }.from(false).to(true) + end + + it 'does not mark spam log as recaptcha_verified when it does not belong to current_user' do + spam_log = create(:spam_log) + + expect { update_issue(spam_log_id: spam_log.id, recaptcha_verification: true) }. + not_to change { SpamLog.last.recaptcha_verified } + end + end + end + end + + def update_issue(issue_params = {}, additional_params = {}) + params = { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: issue.iid, + issue: issue_params + }.merge(additional_params) + + put :update, params + end + def move_issue put :update, namespace_id: project.namespace.to_param, @@ -384,7 +491,7 @@ describe Projects::IssuesController do allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true) end - context 'when an issue is not identified as a spam' 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) @@ -395,7 +502,7 @@ describe Projects::IssuesController do end end - context 'when an issue is identified as a spam' do + context 'when an issue is identified as spam' do before { allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) } 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 77ee10a1e15..8bab094a79e 100644 --- a/spec/controllers/projects/snippets_controller_spec.rb +++ b/spec/controllers/projects/snippets_controller_spec.rb @@ -70,7 +70,7 @@ describe Projects::SnippetsController do end describe 'POST #create' do - def create_snippet(project, snippet_params = {}) + def create_snippet(project, snippet_params = {}, additional_params = {}) sign_in(user) project.add_developer(user) @@ -79,7 +79,7 @@ describe Projects::SnippetsController do namespace_id: project.namespace.to_param, project_id: project.to_param, project_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params) - } + }.merge(additional_params) end context 'when the snippet is spam' do @@ -87,35 +87,179 @@ describe Projects::SnippetsController do allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) end - context 'when the project is private' do - let(:private_project) { create(:project_empty_repo, :private) } + context 'when the snippet is private' do + it 'creates the snippet' do + expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. + to change { Snippet.count }.by(1) + end + end + + context 'when the snippet is public' do + it 'rejects the shippet' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + not_to change { Snippet.count } + expect(response).to render_template(:new) + end + + it 'creates a spam log' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + + it 'renders :new with recaptcha disabled' do + stub_application_setting(recaptcha_enabled: false) + + create_snippet(project, visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:new) + end - context 'when the snippet is public' do - it 'creates the snippet' do - expect { create_snippet(private_project, visibility_level: Snippet::PUBLIC) }. - to change { Snippet.count }.by(1) + context 'recaptcha enabled' do + before do + stub_application_setting(recaptcha_enabled: true) end + + it 'renders :verify with recaptcha enabled' do + create_snippet(project, visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:verify) + end + + it 'renders snippet page when recaptcha verified' do + spammy_title = 'Whatever' + + spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title) + create_snippet(project, + { visibility_level: Snippet::PUBLIC }, + { spam_log_id: spam_logs.last.id, + recaptcha_verification: true }) + + expect(response).to redirect_to(Snippet.last) + end + end + end + end + end + + describe 'PUT #update' do + let(:project) { create :project, :public } + let(:snippet) { create :project_snippet, author: user, project: project, visibility_level: visibility_level } + + def update_snippet(snippet_params = {}, additional_params = {}) + sign_in(user) + + project.add_developer(user) + + put :update, { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: snippet.id, + project_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params) + }.merge(additional_params) + + snippet.reload + end + + context 'when the snippet is spam' do + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the snippet is private' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'updates the snippet' do + expect { update_snippet(title: 'Foo') }. + to change { snippet.reload.title }.to('Foo') end end - context 'when the project is public' do - context 'when the snippet is private' do - it 'creates the snippet' do - expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. - to change { Snippet.count }.by(1) + context 'when the snippet is public' do + let(:visibility_level) { Snippet::PUBLIC } + + it 'rejects the shippet' do + expect { update_snippet(title: 'Foo') }. + not_to change { snippet.reload.title } + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo') }. + to change { SpamLog.count }.by(1) + end + + it 'renders :edit with recaptcha disabled' do + stub_application_setting(recaptcha_enabled: false) + + update_snippet(title: 'Foo') + + expect(response).to render_template(:edit) + end + + context 'recaptcha enabled' do + before do + stub_application_setting(recaptcha_enabled: true) + end + + it 'renders :verify with recaptcha enabled' do + update_snippet(title: 'Foo') + + expect(response).to render_template(:verify) + end + + it 'renders snippet page when recaptcha verified' do + spammy_title = 'Whatever' + + spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title) + snippet = update_snippet({ title: spammy_title }, + { spam_log_id: spam_logs.last.id, + recaptcha_verification: true }) + + expect(response).to redirect_to(snippet) end end + end + + context 'when the private snippet is made public' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'rejects the shippet' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + not_to change { snippet.reload.title } + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + + it 'renders :edit with recaptcha disabled' do + stub_application_setting(recaptcha_enabled: false) - context 'when the snippet is public' do - it 'rejects the shippet' do - expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. - not_to change { Snippet.count } - expect(response).to render_template(:new) + update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:edit) + end + + context 'recaptcha enabled' do + before do + stub_application_setting(recaptcha_enabled: true) + end + + it 'renders :verify with recaptcha enabled' do + update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:verify) end - it 'creates a spam log' do - expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. - to change { SpamLog.count }.by(1) + it 'renders snippet page when recaptcha verified' do + spammy_title = 'Whatever' + + spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title) + snippet = update_snippet({ title: spammy_title, visibility_level: Snippet::PUBLIC }, + { spam_log_id: spam_logs.last.id, + recaptcha_verification: true }) + + expect(response).to redirect_to(snippet) end end end diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index f90c0d76ceb..5de3b9890ef 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -139,12 +139,14 @@ describe SnippetsController do end describe 'POST #create' do - def create_snippet(snippet_params = {}) + def create_snippet(snippet_params = {}, additional_params = {}) sign_in(user) post :create, { personal_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params) - } + }.merge(additional_params) + + Snippet.last end context 'when the snippet is spam' do @@ -163,13 +165,164 @@ describe SnippetsController do it 'rejects the shippet' do expect { create_snippet(visibility_level: Snippet::PUBLIC) }. not_to change { Snippet.count } - expect(response).to render_template(:new) end it 'creates a spam log' do expect { create_snippet(visibility_level: Snippet::PUBLIC) }. to change { SpamLog.count }.by(1) end + + it 'renders :new with recaptcha disabled' do + stub_application_setting(recaptcha_enabled: false) + + create_snippet(visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:new) + end + + context 'recaptcha enabled' do + before do + stub_application_setting(recaptcha_enabled: true) + end + + it 'renders :verify with recaptcha enabled' do + create_snippet(visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:verify) + end + + it 'renders snippet page when recaptcha verified' do + spammy_title = 'Whatever' + + spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title) + snippet = create_snippet({ title: spammy_title }, + { spam_log_id: spam_logs.last.id, + recaptcha_verification: true }) + + expect(response).to redirect_to(snippet_path(snippet)) + end + end + end + end + end + + describe 'PUT #update' do + let(:project) { create :project } + let(:snippet) { create :personal_snippet, author: user, project: project, visibility_level: visibility_level } + + def update_snippet(snippet_params = {}, additional_params = {}) + sign_in(user) + + put :update, { + id: snippet.id, + personal_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params) + }.merge(additional_params) + + snippet.reload + end + + context 'when the snippet is spam' do + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the snippet is private' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'updates the snippet' do + expect { update_snippet(title: 'Foo') }. + to change { snippet.reload.title }.to('Foo') + end + end + + context 'when a private snippet is made public' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'rejects the snippet' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + not_to change { snippet.reload.title } + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + + it 'renders :edit with recaptcha disabled' do + stub_application_setting(recaptcha_enabled: false) + + update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:edit) + end + + context 'recaptcha enabled' do + before do + stub_application_setting(recaptcha_enabled: true) + end + + it 'renders :verify with recaptcha enabled' do + update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) + + expect(response).to render_template(:verify) + end + + it 'renders snippet page when recaptcha verified' do + spammy_title = 'Whatever' + + spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title) + snippet = update_snippet({ title: spammy_title, visibility_level: Snippet::PUBLIC }, + { spam_log_id: spam_logs.last.id, + recaptcha_verification: true }) + + expect(response).to redirect_to(snippet) + end + end + end + + context 'when the snippet is public' do + let(:visibility_level) { Snippet::PUBLIC } + + it 'rejects the shippet' do + expect { update_snippet(title: 'Foo') }. + not_to change { snippet.reload.title } + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo') }. + to change { SpamLog.count }.by(1) + end + + it 'renders :edit with recaptcha disabled' do + stub_application_setting(recaptcha_enabled: false) + + update_snippet(title: 'Foo') + + expect(response).to render_template(:edit) + end + + context 'recaptcha enabled' do + before do + stub_application_setting(recaptcha_enabled: true) + end + + it 'renders :verify with recaptcha enabled' do + update_snippet(title: 'Foo') + + expect(response).to render_template(:verify) + end + + it 'renders snippet page when recaptcha verified' do + spammy_title = 'Whatever' + + spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title) + snippet = update_snippet({ title: spammy_title }, + { spam_log_id: spam_logs.last.id, + recaptcha_verification: true }) + + expect(response).to redirect_to(snippet_path(snippet)) + end + end end end end diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 8f561c8f90b..324ede798fe 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -153,7 +153,7 @@ describe 'Commits' do expect(page).to have_content pipeline.git_author_name expect(page).to have_link('Download artifacts') expect(page).not_to have_link('Cancel running') - expect(page).not_to have_link('Retry failed') + expect(page).not_to have_link('Retry') end end @@ -172,7 +172,7 @@ describe 'Commits' do expect(page).to have_content pipeline.git_author_name expect(page).not_to have_link('Download artifacts') expect(page).not_to have_link('Cancel running') - expect(page).not_to have_link('Retry failed') + expect(page).not_to have_link('Retry') 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 c6a88e1b7b0..ab3b868fd3a 100644 --- a/spec/features/issues/filtered_search/dropdown_label_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe 'Dropdown label', js: true, feature: true do + include FilteredSearchHelpers + let(:project) { create(:empty_project) } let(:user) { create(:user) } let(:filtered_search) { find('.filtered-search') } @@ -17,12 +19,6 @@ describe 'Dropdown label', js: true, feature: true do let!(:long_label) { create(:label, project: project, title: 'this is a very long title this is a very long title this is a very long title this is a very long title this is a very long title') } end - def init_label_search - filtered_search.set('label:') - # This ensures the dropdown is shown - expect(find(js_dropdown_label)).not_to have_css('.filter-dropdown-loading') - end - def search_for_label(label) init_label_search filtered_search.send_keys(label) diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index 64f448a83b7..0420e64d42c 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -1,6 +1,7 @@ require 'rails_helper' describe 'Filter issues', js: true, feature: true do + include FilteredSearchHelpers include WaitForAjax let!(:group) { create(:group) } @@ -17,19 +18,6 @@ describe 'Filter issues', js: true, feature: true do let!(:multiple_words_label) { create(:label, project: project, title: "Two words") } let!(:closed_issue) { create(:issue, title: 'bug that is closed', project: project, state: :closed) } - let(:filtered_search) { find('.filtered-search') } - - def input_filtered_search(search_term, submit: true) - filtered_search.set(search_term) - - if submit - filtered_search.send_keys(:enter) - end - end - - def expect_filtered_search_input(input) - expect(find('.filtered-search').value).to eq(input) - end def expect_no_issues_list page.within '.issues-list' do diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 1eb981942ea..7b9d4534ada 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -7,9 +7,9 @@ feature 'Issue Sidebar', feature: true do let(:project) { create(:project, :public) } let(:issue) { create(:issue, project: project) } let!(:user) { create(:user)} + let!(:label) { create(:label, project: project, title: 'bug') } before do - create(:label, project: project, title: 'bug') login_as(user) end @@ -50,16 +50,6 @@ feature 'Issue Sidebar', feature: true do visit_issue(project, issue) end - describe 'when clicking on edit labels', js: true do - it 'shows dropdown option to create a new label' do - find('.block.labels .edit-link').click - - page.within('.block.labels') do - expect(page).to have_content 'Create new' - end - end - end - context 'sidebar', js: true do it 'changes size when the screen size is smaller' do sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed' @@ -77,36 +67,53 @@ feature 'Issue Sidebar', feature: true do end end - context 'creating a new label', js: true do - it 'shows option to crate a new label is present' do + context 'editing issue labels', js: true do + before do page.within('.block.labels') do find('.edit-link').click + end + end + it 'shows option to create a new label' do + page.within('.block.labels') do expect(page).to have_content 'Create new' end end - it 'shows dropdown switches to "create label" section' do - page.within('.block.labels') do - find('.edit-link').click - click_link 'Create new' + context 'creating a new label', js: true do + before do + page.within('.block.labels') do + click_link 'Create new' + end + end - expect(page).to have_content 'Create new label' + it 'shows dropdown switches to "create label" section' do + page.within('.block.labels') do + expect(page).to have_content 'Create new label' + end end - end - it 'adds new label' do - page.within('.block.labels') do - find('.edit-link').click - sleep 1 - click_link 'Create new' + it 'adds new label' do + page.within('.block.labels') do + fill_in 'new_label_name', with: 'wontfix' + page.find(".suggest-colors a", match: :first).click + click_button 'Create' + + page.within('.dropdown-page-one') do + expect(page).to have_content 'wontfix' + end + end + end - fill_in 'new_label_name', with: 'wontfix' - page.find(".suggest-colors a", match: :first).click - click_button 'Create' + it 'shows error message if label title is taken' do + page.within('.block.labels') do + fill_in 'new_label_name', with: label.title + page.find('.suggest-colors a', match: :first).click + click_button 'Create' - page.within('.dropdown-page-one') do - expect(page).to have_content 'wontfix' + page.within('.dropdown-page-two') do + expect(page).to have_content 'Title has already been taken' + end end end end diff --git a/spec/features/merge_requests/filter_by_labels_spec.rb b/spec/features/merge_requests/filter_by_labels_spec.rb index 4c60329865c..55f3c1863ff 100644 --- a/spec/features/merge_requests/filter_by_labels_spec.rb +++ b/spec/features/merge_requests/filter_by_labels_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' feature 'Issue filtering by Labels', feature: true, js: true do + include FilteredSearchHelpers + include MergeRequestHelpers include WaitForAjax let(:project) { create(:project, :public) } @@ -32,123 +34,77 @@ feature 'Issue filtering by Labels', feature: true, js: true do context 'filter by label bug' do before do - select_labels('bug') + input_filtered_search('label:~bug') end it 'apply the filter' do expect(page).to have_content "Bugfix1" expect(page).to have_content "Bugfix2" expect(page).not_to have_content "Feature1" - expect(find('.filtered-labels')).to have_content "bug" - expect(find('.filtered-labels')).not_to have_content "feature" - expect(find('.filtered-labels')).not_to have_content "enhancement" - - find('.js-label-filter-remove').click - wait_for_ajax - expect(find('.filtered-labels', visible: false)).to have_no_content "bug" end end context 'filter by label feature' do before do - select_labels('feature') + input_filtered_search('label:~feature') end it 'applies the filter' do expect(page).to have_content "Feature1" expect(page).not_to have_content "Bugfix2" expect(page).not_to have_content "Bugfix1" - expect(find('.filtered-labels')).to have_content "feature" - expect(find('.filtered-labels')).not_to have_content "bug" - expect(find('.filtered-labels')).not_to have_content "enhancement" end end context 'filter by label enhancement' do before do - select_labels('enhancement') + input_filtered_search('label:~enhancement') end it 'applies the filter' do expect(page).to have_content "Bugfix2" expect(page).not_to have_content "Feature1" expect(page).not_to have_content "Bugfix1" - expect(find('.filtered-labels')).to have_content "enhancement" - expect(find('.filtered-labels')).not_to have_content "bug" - expect(find('.filtered-labels')).not_to have_content "feature" end end context 'filter by label enhancement and bug in issues list' do before do - select_labels('bug', 'enhancement') + input_filtered_search('label:~bug label:~enhancement') end it 'applies the filters' do expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_content "Bugfix2" expect(page).not_to have_content "Feature1" - expect(find('.filtered-labels')).to have_content "bug" - expect(find('.filtered-labels')).to have_content "enhancement" - expect(find('.filtered-labels')).not_to have_content "feature" - - find('.js-label-filter-remove', match: :first).click - wait_for_ajax - - expect(page).to have_content "Bugfix2" - expect(page).not_to have_content "Feature1" - expect(page).not_to have_content "Bugfix1" - expect(find('.filtered-labels')).not_to have_content "bug" - expect(find('.filtered-labels')).to have_content "enhancement" - expect(find('.filtered-labels')).not_to have_content "feature" end end - context 'remove filtered labels' do + context 'clear button' do before do - page.within '.labels-filter' do - click_button 'Label' - wait_for_ajax - click_link 'bug' - find('.dropdown-menu-close').click - end - - page.within '.filtered-labels' do - expect(page).to have_content 'bug' - end + input_filtered_search('label:~bug') end it 'allows user to remove filtered labels' do - first('.js-label-filter-remove').click - wait_for_ajax + first('.clear-search').click + filtered_search.send_keys(:enter) - expect(find('.filtered-labels', visible: false)).not_to have_content 'bug' - expect(find('.labels-filter')).not_to have_content 'bug' + expect(page).to have_issuable_counts(open: 3, closed: 0, all: 3) + expect(page).to have_content "Bugfix2" + expect(page).to have_content "Feature1" + expect(page).to have_content "Bugfix1" end end - context 'dropdown filtering' do + context 'filter dropdown' do it 'filters by label name' do - page.within '.labels-filter' do - click_button 'Label' - wait_for_ajax - find('.dropdown-input input').set 'bug' - - page.within '.dropdown-content' do - expect(page).not_to have_content 'enhancement' - expect(page).to have_content 'bug' - end - end - end - end + init_label_search + filtered_search.send_keys('~bug') - def select_labels(*labels) - page.find('.js-label-select').click - wait_for_ajax - labels.each do |label| - execute_script("$('.dropdown-menu-labels li:contains(\"#{label}\") a').click()") + page.within '.filter-dropdown' do + expect(page).not_to have_content 'enhancement' + expect(page).to have_content 'bug' + end end - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax end end diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb index f6e9230c8da..5608cda28f8 100644 --- a/spec/features/merge_requests/filter_by_milestone_spec.rb +++ b/spec/features/merge_requests/filter_by_milestone_spec.rb @@ -1,10 +1,18 @@ require 'rails_helper' feature 'Merge Request filtering by Milestone', feature: true do + include FilteredSearchHelpers + include MergeRequestHelpers + let(:project) { create(:project, :public) } let!(:user) { create(:user)} let(:milestone) { create(:milestone, project: project) } + def filter_by_milestone(title) + find(".js-milestone-select").click + find(".milestone-filter a", text: title).click + end + before do project.team << [user, :master] login_as(user) @@ -15,42 +23,42 @@ feature 'Merge Request filtering by Milestone', feature: true do create(:merge_request, :simple, source_project: project, milestone: milestone) visit_merge_requests(project) - filter_by_milestone(Milestone::None.title) + input_filtered_search('milestone:none') expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_css('.merge-request', count: 1) end context 'filters by upcoming milestone', js: true do - it 'does not show issues with no expiry' do + it 'does not show merge requests with no expiry' do create(:merge_request, :with_diffs, source_project: project) create(:merge_request, :simple, source_project: project, milestone: milestone) visit_merge_requests(project) - filter_by_milestone(Milestone::Upcoming.title) + input_filtered_search('milestone:upcoming') expect(page).to have_css('.merge-request', count: 0) end - it 'shows issues in future' do + it 'shows merge requests in future' do milestone = create(:milestone, project: project, due_date: Date.tomorrow) create(:merge_request, :with_diffs, source_project: project) create(:merge_request, :simple, source_project: project, milestone: milestone) visit_merge_requests(project) - filter_by_milestone(Milestone::Upcoming.title) + input_filtered_search('milestone:upcoming') expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_css('.merge-request', count: 1) end - it 'does not show issues in past' do + it 'does not show merge requests in past' do milestone = create(:milestone, project: project, due_date: Date.yesterday) create(:merge_request, :with_diffs, source_project: project) create(:merge_request, :simple, source_project: project, milestone: milestone) visit_merge_requests(project) - filter_by_milestone(Milestone::Upcoming.title) + input_filtered_search('milestone:upcoming') expect(page).to have_css('.merge-request', count: 0) end @@ -61,7 +69,7 @@ feature 'Merge Request filtering by Milestone', feature: true do create(:merge_request, :simple, source_project: project) visit_merge_requests(project) - filter_by_milestone(milestone.title) + input_filtered_search("milestone:%'#{milestone.title}'") expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_css('.merge-request', count: 1) @@ -77,19 +85,10 @@ feature 'Merge Request filtering by Milestone', feature: true do create(:merge_request, :simple, source_project: project) visit_merge_requests(project) - filter_by_milestone(milestone.title) + input_filtered_search("milestone:%\"#{milestone.title}\"") expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_css('.merge-request', count: 1) end end - - def visit_merge_requests(project) - visit namespace_project_merge_requests_path(project.namespace, project) - end - - def filter_by_milestone(title) - find(".js-milestone-select").click - find(".milestone-filter a", text: title).click - end end diff --git a/spec/features/merge_requests/filter_merge_requests_spec.rb b/spec/features/merge_requests/filter_merge_requests_spec.rb index 4642b5a530d..6579a88d4ab 100644 --- a/spec/features/merge_requests/filter_merge_requests_spec.rb +++ b/spec/features/merge_requests/filter_merge_requests_spec.rb @@ -1,11 +1,13 @@ require 'rails_helper' describe 'Filter merge requests', feature: true do + include FilteredSearchHelpers + include MergeRequestHelpers include WaitForAjax let!(:project) { create(:project) } let!(:group) { create(:group) } - let!(:user) { create(:user)} + let!(:user) { create(:user) } let!(:milestone) { create(:milestone, project: project) } let!(:label) { create(:label, project: project) } let!(:wontfix) { create(:label, project: project, title: "Won't fix") } @@ -15,183 +17,134 @@ describe 'Filter merge requests', feature: true do group.add_developer(user) login_as(user) create(:merge_request, source_project: project, target_project: project) + + visit namespace_project_merge_requests_path(project.namespace, project) end describe 'for assignee from mr#index' do - before do - visit namespace_project_merge_requests_path(project.namespace, project) + let(:search_query) { "assignee:@#{user.username}" } - find('.js-assignee-search').click - - find('.dropdown-menu-user-link', text: user.username).click + before do + input_filtered_search(search_query) - wait_for_ajax + expect_mr_list_count(0) end context 'assignee', js: true do it 'updates to current user' do - expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) + expect_filtered_search_input(search_query) end it 'does not change when closed link is clicked' do find('.issues-state-filters a', text: "Closed").click - expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) + expect_filtered_search_input(search_query) end it 'does not change when all link is clicked' do find('.issues-state-filters a', text: "All").click - expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) + expect_filtered_search_input(search_query) end end end describe 'for milestone from mr#index' do - before do - visit namespace_project_merge_requests_path(project.namespace, project) - - find('.js-milestone-select').click + let(:search_query) { "milestone:%#{milestone.title}" } - find('.milestone-filter .dropdown-content a', text: milestone.title).click + before do + input_filtered_search(search_query) - wait_for_ajax + expect_mr_list_count(0) end context 'milestone', js: true do it 'updates to current milestone' do - expect(find('.js-milestone-select .dropdown-toggle-text')).to have_content(milestone.title) + expect_filtered_search_input(search_query) end it 'does not change when closed link is clicked' do find('.issues-state-filters a', text: "Closed").click - expect(find('.js-milestone-select .dropdown-toggle-text')).to have_content(milestone.title) + expect_filtered_search_input(search_query) end it 'does not change when all link is clicked' do find('.issues-state-filters a', text: "All").click - expect(find('.js-milestone-select .dropdown-toggle-text')).to have_content(milestone.title) + expect_filtered_search_input(search_query) end end end describe 'for label from mr#index', js: true do - before do - visit namespace_project_merge_requests_path(project.namespace, project) - find('.js-label-select').click - wait_for_ajax - end - - it 'filters by any label' do - find('.dropdown-menu-labels a', text: 'Any Label').click - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax - - expect(find('.labels-filter')).to have_content 'Label' - end - it 'filters by no label' do - find('.dropdown-menu-labels a', text: 'No Label').click - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + input_filtered_search('label:none') - page.within '.labels-filter' do - expect(page).to have_content 'Labels' - end - expect(find('.js-label-select .dropdown-toggle-text')).to have_content('Labels') + expect_mr_list_count(1) + expect_filtered_search_input('label:none') end it 'filters by a label' do - find('.dropdown-menu-labels a', text: label.title).click - page.within '.labels-filter' do - expect(page).to have_content label.title - end - expect(find('.js-label-select .dropdown-toggle-text')).to have_content(label.title) + input_filtered_search("label:~#{label.title}") + + expect_mr_list_count(0) + expect_filtered_search_input("label:~#{label.title}") end it "filters by `won't fix` and another label" do - page.within '.labels-filter' do - click_link wontfix.title - expect(page).to have_content wontfix.title - click_link label.title - end + input_filtered_search("label:~\"#{wontfix.title}\" label:~#{label.title}") - expect(find('.js-label-select .dropdown-toggle-text')).to have_content("#{wontfix.title} +1 more") + expect_mr_list_count(0) + expect_filtered_search_input("label:~\"#{wontfix.title}\" label:~#{label.title}") end it "filters by `won't fix` label followed by another label after page load" do - page.within '.labels-filter' do - click_link wontfix.title - expect(page).to have_content wontfix.title - end - - find('body').click - - expect(find('.filtered-labels')).to have_content(wontfix.title) - - find('.js-label-select').click - wait_for_ajax - find('.dropdown-menu-labels a', text: label.title).click - - find('body').click + input_filtered_search("label:~\"#{wontfix.title}\"") - expect(find('.filtered-labels')).to have_content(wontfix.title) - expect(find('.filtered-labels')).to have_content(label.title) + expect_mr_list_count(0) + expect_filtered_search_input("label:~\"#{wontfix.title}\"") - find('.js-label-select').click - wait_for_ajax + input_filtered_search_keys(" label:~#{label.title}") - expect(find('.dropdown-menu-labels li', text: wontfix.title)).to have_css('.is-active') - expect(find('.dropdown-menu-labels li', text: label.title)).to have_css('.is-active') - end + expect_filtered_search_input("label:~\"#{wontfix.title}\" label:~#{label.title}") - it "selects and unselects `won't fix`" do - find('.dropdown-menu-labels a', text: wontfix.title).click - find('.dropdown-menu-labels a', text: wontfix.title).click - # Close label dropdown to load - find('body').click - expect(page).not_to have_css('.filtered-labels') + expect_mr_list_count(0) + expect_filtered_search_input("label:~\"#{wontfix.title}\" label:~#{label.title}") end end describe 'for assignee and label from issues#index' do - before do - visit namespace_project_merge_requests_path(project.namespace, project) - - find('.js-assignee-search').click + let(:search_query) { "assignee:@#{user.username} label:~#{label.title}" } - find('.dropdown-menu-user-link', text: user.username).click + before do + input_filtered_search("assignee:@#{user.username}") - expect(page).not_to have_selector('.mr-list .merge-request') + expect_mr_list_count(1) + expect_filtered_search_input("assignee:@#{user.username}") - find('.js-label-select').click + input_filtered_search_keys(" label:~#{label.title}") - find('.dropdown-menu-labels .dropdown-content a', text: label.title).click - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click + expect_mr_list_count(1) - wait_for_ajax + find("#state-opened[href=\"#{URI.parse(current_url).path}?assignee_username=#{user.username}&label_name%5B%5D=#{label.title}&scope=all&state=opened\"]") end context 'assignee and label', js: true do it 'updates to current assignee and label' do - expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) - expect(find('.js-label-select .dropdown-toggle-text')).to have_content(label.title) + expect_filtered_search_input(search_query) end it 'does not change when closed link is clicked' do find('.issues-state-filters a', text: "Closed").click - expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) - expect(find('.js-label-select .dropdown-toggle-text')).to have_content(label.title) + expect_filtered_search_input(search_query) end it 'does not change when all link is clicked' do find('.issues-state-filters a', text: "All").click - expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) - expect(find('.js-label-select .dropdown-toggle-text')).to have_content(label.title) + expect_filtered_search_input(search_query) end end end @@ -203,11 +156,11 @@ describe 'Filter merge requests', feature: true do bug_label = create(:label, project: project, title: 'bug') milestone = create(:milestone, title: "8", project: project) - mr = create(:merge_request, - title: "Bug 2", - source_project: project, - target_project: project, - source_branch: "bug2", + mr = create(:merge_request, + title: "Bug 2", + source_project: project, + target_project: project, + source_branch: "bug2", milestone: milestone, author: user, assignee: user) @@ -218,15 +171,13 @@ describe 'Filter merge requests', feature: true do context 'only text', js: true do it 'filters merge requests by searched text' do - fill_in 'issuable_search', with: 'Bug' + input_filtered_search('bug') - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 2) - end + expect_mr_list_count(2) end it 'does not show any merge requests' do - fill_in 'issuable_search', with: 'testing' + input_filtered_search('testing') page.within '.mr-list' do expect(page).not_to have_selector('.merge-request') @@ -234,82 +185,49 @@ describe 'Filter merge requests', feature: true do end end - context 'text and dropdown options', js: true do + context 'filters and searches', js: true do it 'filters by text and label' do - fill_in 'issuable_search', with: 'Bug' + input_filtered_search('Bug') - expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 2) - end + expect_mr_list_count(2) + expect_filtered_search_input('Bug') - click_button 'Label' - page.within '.labels-filter' do - click_link 'bug' - end - find('.dropdown-menu-close-icon').click + input_filtered_search_keys(' label:~bug') - expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 1) - end + expect_mr_list_count(1) end it 'filters by text and milestone' do - fill_in 'issuable_search', with: 'Bug' + input_filtered_search('Bug') - expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 2) - end + expect_mr_list_count(2) + expect_filtered_search_input('Bug') - click_button 'Milestone' - page.within '.milestone-filter' do - click_link '8' - end + input_filtered_search_keys(' milestone:%8') - expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 1) - end + expect_mr_list_count(1) end it 'filters by text and assignee' do - fill_in 'issuable_search', with: 'Bug' + input_filtered_search('Bug') - expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 2) - end + expect_mr_list_count(2) + expect_filtered_search_input('Bug') - click_button 'Assignee' - page.within '.dropdown-menu-assignee' do - click_link user.name - end + input_filtered_search_keys(" assignee:@#{user.username}") - expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 1) - end + expect_mr_list_count(1) end it 'filters by text and author' do - fill_in 'issuable_search', with: 'Bug' + input_filtered_search('Bug') - expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 2) - end + expect_mr_list_count(2) + expect_filtered_search_input('Bug') - click_button 'Author' - page.within '.dropdown-menu-author' do - click_link user.name - end + input_filtered_search_keys(" author:@#{user.username}") - expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 1) - end + expect_mr_list_count(1) end end end @@ -328,18 +246,9 @@ describe 'Filter merge requests', feature: true do end it 'is able to filter and sort merge requests' do - click_button 'Label' - wait_for_ajax - page.within '.labels-filter' do - click_link 'bug' - end - find('.dropdown-menu-close-icon').click - wait_for_ajax + input_filtered_search('label:~bug') - expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) - page.within '.mr-list' do - expect(page).to have_selector('.merge-request', count: 2) - end + expect_mr_list_count(2) click_button 'Last created' page.within '.dropdown-menu-sort' do @@ -352,4 +261,38 @@ describe 'Filter merge requests', feature: true do end end end + + describe 'filter by assignee id', js: true do + it 'filter by current user' do + visit namespace_project_merge_requests_path(project.namespace, project, assignee_id: user.id) + + expect_filtered_search_input("assignee:@#{user.username}") + end + + it 'filter by new user' do + new_user = create(:user) + project.add_developer(new_user) + + visit namespace_project_merge_requests_path(project.namespace, project, assignee_id: new_user.id) + + expect_filtered_search_input("assignee:@#{new_user.username}") + end + end + + describe 'filter by author id', js: true do + it 'filter by current user' do + visit namespace_project_merge_requests_path(project.namespace, project, author_id: user.id) + + expect_filtered_search_input("author:@#{user.username}") + end + + it 'filter by new user' do + new_user = create(:user) + project.add_developer(new_user) + + visit namespace_project_merge_requests_path(project.namespace, project, author_id: new_user.id) + + expect_filtered_search_input("author:@#{new_user.username}") + end + end end diff --git a/spec/features/merge_requests/reset_filters_spec.rb b/spec/features/merge_requests/reset_filters_spec.rb index 3a7ece7e1d6..58f11499e3f 100644 --- a/spec/features/merge_requests/reset_filters_spec.rb +++ b/spec/features/merge_requests/reset_filters_spec.rb @@ -1,17 +1,20 @@ require 'rails_helper' feature 'Issues filter reset button', feature: true, js: true do + include FilteredSearchHelpers + include MergeRequestHelpers include WaitForAjax include IssueHelpers - let!(:project) { create(:project, :public) } - let!(:user) { create(:user)} - let!(:milestone) { create(:milestone, project: project) } - let!(:bug) { create(:label, project: project, name: 'bug')} + let!(:project) { create(:project, :public) } + let!(:user) { create(:user) } + let!(:milestone) { create(:milestone, project: project) } + let!(:bug) { create(:label, project: project, name: 'bug')} let!(:mr1) { create(:merge_request, title: "Feature", source_project: project, target_project: project, source_branch: "Feature", milestone: milestone, author: user, assignee: user) } let!(:mr2) { create(:merge_request, title: "Bugfix1", source_project: project, target_project: project, source_branch: "Bugfix1") } - let(:merge_request_css) { '.merge-request' } + let(:merge_request_css) { '.merge-request' } + let(:clear_search_css) { '.filtered-search-input-container .clear-search' } before do mr2.labels << bug @@ -50,7 +53,7 @@ feature 'Issues filter reset button', feature: true, js: true do context 'when author filter has been applied' do it 'resets the author filter' do - visit_merge_requests(project, author_id: user.id) + visit_merge_requests(project, author_username: user.username) expect(page).to have_css(merge_request_css, count: 1) reset_filters @@ -60,7 +63,7 @@ feature 'Issues filter reset button', feature: true, js: true do context 'when assignee filter has been applied' do it 'resets the assignee filter' do - visit_merge_requests(project, assignee_id: user.id) + visit_merge_requests(project, assignee_username: user.username) expect(page).to have_css(merge_request_css, count: 1) reset_filters @@ -70,7 +73,7 @@ feature 'Issues filter reset button', feature: true, js: true do context 'when all filters have been applied' do it 'resets all filters' do - visit_merge_requests(project, assignee_id: user.id, author_id: user.id, milestone_title: milestone.title, label_name: bug.name, search: 'Bug') + visit_merge_requests(project, assignee_username: user.username, author_username: user.username, milestone_title: milestone.title, label_name: bug.name, search: 'Bug') expect(page).to have_css(merge_request_css, count: 0) reset_filters @@ -82,15 +85,7 @@ feature 'Issues filter reset button', feature: true, js: true do it 'the reset link should not be visible' do visit_merge_requests(project) expect(page).to have_css(merge_request_css, count: 2) - expect(page).not_to have_css '.reset_filters' + expect(page).not_to have_css(clear_search_css) end end - - def visit_merge_requests(project, opts = {}) - visit namespace_project_merge_requests_path project.namespace, project, opts - end - - def reset_filters - find('.reset-filters').click - end end diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index b56e562b2b6..45185f2dd1f 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -19,6 +19,51 @@ feature "New project", feature: true do end end + context "Namespace selector" do + context "with user namespace" do + before do + visit new_project_path + end + + it "selects the user namespace" do + namespace = find("#project_namespace_id") + + expect(namespace.text).to eq user.username + end + end + + context "with group namespace" do + let(:group) { create(:group, :private, owner: user) } + + before do + group.add_owner(user) + visit new_project_path(namespace_id: group.id) + end + + it "selects the group namespace" do + namespace = find("#project_namespace_id option[selected]") + + expect(namespace.text).to eq group.name + end + + context "on validation error" do + before do + fill_in('project_path', with: 'private-group-project') + choose('Internal') + click_button('Create project') + + expect(page).to have_css '.project-edit-errors .alert.alert-danger' + end + + it "selects the group namespace" do + namespace = find("#project_namespace_id option[selected]") + + expect(namespace.text).to eq group.name + end + end + end + end + context 'Import project options' do before do visit new_project_path diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 0b5ccc8c515..9f06e52ab55 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -54,7 +54,7 @@ describe 'Pipeline', :feature, :js do expect(page).to have_content('Build') expect(page).to have_content('Test') expect(page).to have_content('Deploy') - expect(page).to have_content('Retry failed') + expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end @@ -164,9 +164,9 @@ describe 'Pipeline', :feature, :js do it { expect(page).not_to have_content('retried') } context 'when retrying' do - before { click_on 'Retry failed' } + before { find('.js-retry-button').trigger('click') } - it { expect(page).not_to have_content('Retry failed') } + it { expect(page).not_to have_content('Retry') } end end @@ -198,7 +198,7 @@ describe 'Pipeline', :feature, :js do expect(page).to have_content(build_failed.id) expect(page).to have_content(build_running.id) expect(page).to have_content(build_external.id) - expect(page).to have_content('Retry failed') + expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') expect(page).to have_link('Play') end @@ -226,9 +226,9 @@ describe 'Pipeline', :feature, :js do it { expect(page).not_to have_content('retried') } context 'when retrying' do - before { click_on 'Retry failed' } + before { find('.js-retry-button').trigger('click') } - it { expect(page).not_to have_content('Retry failed') } + it { expect(page).not_to have_content('Retry') } it { expect(page).to have_selector('.retried') } end end diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index 0fe5a897565..7da05defa81 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -186,7 +186,7 @@ describe "Search", feature: true do sleep 2 expect(page).to have_selector('.merge-requests-holder') - expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) + expect(find('.filtered-search').value).to eq("assignee:@#{user.username}") end it 'takes user to her MR page when MR authored is clicked' do @@ -194,7 +194,7 @@ describe "Search", feature: true do sleep 2 expect(page).to have_selector('.merge-requests-holder') - expect(find('.js-author-search .dropdown-toggle-text')).to have_content(user.name) + expect(find('.filtered-search').value).to eq("author:@#{user.username}") end end diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb index fb19dac1d6a..3495091a0d5 100644 --- a/spec/features/todos/todos_spec.rb +++ b/spec/features/todos/todos_spec.rb @@ -171,6 +171,29 @@ describe 'Dashboard Todos', feature: true do end end + context 'User have large number of todos' do + before do + create_list(:todo, 101, :mentioned, user: user, project: project, target: issue, author: author) + + login_as(user) + visit dashboard_todos_path + end + + it 'shows 99+ for count >= 100 in notification' do + expect(page).to have_selector('.todos-pending-count', text: '99+') + end + + it 'shows exact number in To do tab' do + expect(page).to have_selector('.todos-pending .badge', text: '101') + end + + it 'shows exact number for count < 100' do + 3.times { first('.js-done-todo').click } + + expect(page).to have_selector('.todos-pending-count', text: '98') + end + end + context 'User has a Build Failed todo' do let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: author) } diff --git a/spec/fixtures/mail_room_disabled.yml b/spec/fixtures/config/mail_room_disabled.yml index 97f8cff051f..97f8cff051f 100644 --- a/spec/fixtures/mail_room_disabled.yml +++ b/spec/fixtures/config/mail_room_disabled.yml diff --git a/spec/fixtures/mail_room_enabled.yml b/spec/fixtures/config/mail_room_enabled.yml index 9c94649244d..9c94649244d 100644 --- a/spec/fixtures/mail_room_enabled.yml +++ b/spec/fixtures/config/mail_room_enabled.yml diff --git a/spec/javascripts/header_spec.js b/spec/javascripts/header_spec.js index 576b6cfefdc..46a27b8c98f 100644 --- a/spec/javascripts/header_spec.js +++ b/spec/javascripts/header_spec.js @@ -45,8 +45,8 @@ require('~/lib/utils/text_utility'); expect(isTodosCountHidden()).toEqual(false); }); - it('should add delimiter to todos-pending-count', function() { - expect($(todosPendingCount).text()).toEqual('1,000'); + it('should show 99+ for todos-pending-count', function() { + expect($(todosPendingCount).text()).toEqual('99+'); }); }); }); diff --git a/spec/javascripts/lib/utils/text_utility_spec.js.es6 b/spec/javascripts/lib/utils/text_utility_spec.js.es6 index 86ade66ec29..06b69b8ac17 100644 --- a/spec/javascripts/lib/utils/text_utility_spec.js.es6 +++ b/spec/javascripts/lib/utils/text_utility_spec.js.es6 @@ -35,5 +35,16 @@ require('~/lib/utils/text_utility'); expect(gl.text.pluralize('test', 1)).toBe('test'); }); }); + + describe('gl.text.highCountTrim', () => { + it('returns 99+ for count >= 100', () => { + expect(gl.text.highCountTrim(105)).toBe('99+'); + expect(gl.text.highCountTrim(100)).toBe('99+'); + }); + + it('returns exact number for count < 100', () => { + expect(gl.text.highCountTrim(45)).toBe(45); + }); + }); }); })(); diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index cb8754581c0..aaf058bd755 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -89,8 +89,8 @@ require('vendor/fuzzaldrin-plus'); var a1, a2, a3, a4, issuesAssignedToMeLink, issuesIHaveCreatedLink, mrsAssignedToMeLink, mrsIHaveCreatedLink; issuesAssignedToMeLink = issuesPath + "/?assignee_username=" + userName; issuesIHaveCreatedLink = issuesPath + "/?author_username=" + userName; - mrsAssignedToMeLink = mrsPath + "/?assignee_id=" + userId; - mrsIHaveCreatedLink = mrsPath + "/?author_id=" + userId; + mrsAssignedToMeLink = mrsPath + "/?assignee_username=" + userName; + mrsIHaveCreatedLink = mrsPath + "/?author_username=" + userName; a1 = "a[href='" + issuesAssignedToMeLink + "']"; a2 = "a[href='" + issuesIHaveCreatedLink + "']"; a3 = "a[href='" + mrsAssignedToMeLink + "']"; diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index e94ca4fcfd2..e007044868c 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -101,6 +101,16 @@ describe Gitlab::Database::MigrationHelpers, lib: true do end end + describe '#concurrent_foreign_key_name' do + it 'returns the name for a foreign key' do + name = model.concurrent_foreign_key_name(:this_is_a_very_long_table_name, + :with_a_very_long_column_name) + + expect(name).to be_an_instance_of(String) + expect(name.length).to eq(13) + end + end + describe '#disable_statement_timeout' do context 'using PostgreSQL' do it 'disables statement timeouts' do diff --git a/spec/models/concerns/spammable_spec.rb b/spec/models/concerns/spammable_spec.rb index b6e5c95d18a..fd3b8307571 100644 --- a/spec/models/concerns/spammable_spec.rb +++ b/spec/models/concerns/spammable_spec.rb @@ -23,6 +23,7 @@ describe Issue, 'Spammable' do describe '#check_for_spam?' do it 'returns true for public project' do issue.project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) + expect(issue.check_for_spam?).to eq(true) end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 774a8a1946f..56ca4c04e7d 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -1028,6 +1028,33 @@ describe API::Issues, api: true do end end + describe 'PUT /projects/:id/issues/:issue_id with spam filtering' do + let(:params) do + { + title: 'updated title', + description: 'content here', + labels: 'label, label2' + } + end + + 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) + + put api("/projects/#{project.id}/issues/#{issue.id}", user), params + + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) + + spam_logs = SpamLog.all + expect(spam_logs.count).to eq(1) + expect(spam_logs[0].title).to eq('updated title') + expect(spam_logs[0].description).to eq('content here') + expect(spam_logs[0].user).to eq(user) + expect(spam_logs[0].noteable_type).to eq('Issue') + end + end + describe 'PUT /projects/:id/issues/:issue_id to update labels' do let!(:label) { create(:label, title: 'dummy', project: project) } let!(:label_link) { create(:label_link, label: label, target: issue) } diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index f56876bcf54..da9df56401b 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -78,43 +78,33 @@ describe API::ProjectSnippets, api: true do allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) end - context 'when the project is private' do - let(:private_project) { create(:project_empty_repo, :private) } - - context 'when the snippet is public' do - it 'creates the snippet' do - expect { create_snippet(private_project, visibility_level: Snippet::PUBLIC) }. - to change { Snippet.count }.by(1) - end + context 'when the snippet is private' do + it 'creates the snippet' do + expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. + to change { Snippet.count }.by(1) end end - context 'when the project is public' do - context 'when the snippet is private' do - it 'creates the snippet' do - expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. - to change { Snippet.count }.by(1) - end + context 'when the snippet is public' do + it 'rejects the shippet' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + not_to change { Snippet.count } + + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) end - context 'when the snippet is public' do - it 'rejects the shippet' do - expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. - not_to change { Snippet.count } - expect(response).to have_http_status(400) - end - - it 'creates a spam log' do - expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. - to change { SpamLog.count }.by(1) - end + it 'creates a spam log' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) end end end end describe 'PUT /projects/:project_id/snippets/:id/' do - let(:snippet) { create(:project_snippet, author: admin) } + let(:visibility_level) { Snippet::PUBLIC } + let(:snippet) { create(:project_snippet, author: admin, visibility_level: visibility_level) } it 'updates snippet' do new_content = 'New content' @@ -138,6 +128,56 @@ describe API::ProjectSnippets, api: true do expect(response).to have_http_status(400) end + + context 'when the snippet is spam' do + def update_snippet(snippet_params = {}) + put api("/projects/#{snippet.project.id}/snippets/#{snippet.id}", admin), snippet_params + end + + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the snippet is private' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'creates the snippet' do + expect { update_snippet(title: 'Foo') }. + to change { snippet.reload.title }.to('Foo') + end + end + + context 'when the snippet is public' do + let(:visibility_level) { Snippet::PUBLIC } + + it 'rejects the snippet' do + expect { update_snippet(title: 'Foo') }. + not_to change { snippet.reload.title } + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo') }. + to change { SpamLog.count }.by(1) + end + end + + context 'when the private snippet is made public' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'rejects the snippet' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + not_to change { snippet.reload.title } + + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + end + end end describe 'DELETE /projects/:project_id/snippets/:id/' do diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb index 1ef92930b3c..41def7cd1d4 100644 --- a/spec/requests/api/snippets_spec.rb +++ b/spec/requests/api/snippets_spec.rb @@ -129,7 +129,9 @@ describe API::Snippets, api: true do it 'rejects the shippet' do expect { create_snippet(visibility_level: Snippet::PUBLIC) }. not_to change { Snippet.count } + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) end it 'creates a spam log' do @@ -141,16 +143,20 @@ describe API::Snippets, api: true do end describe 'PUT /snippets/:id' do + let(:visibility_level) { Snippet::PUBLIC } let(:other_user) { create(:user) } - let(:public_snippet) { create(:personal_snippet, :public, author: user) } + let(:snippet) do + create(:personal_snippet, author: user, visibility_level: visibility_level) + end + it 'updates snippet' do new_content = 'New content' - put api("/snippets/#{public_snippet.id}", user), content: new_content + put api("/snippets/#{snippet.id}", user), content: new_content expect(response).to have_http_status(200) - public_snippet.reload - expect(public_snippet.content).to eq(new_content) + snippet.reload + expect(snippet.content).to eq(new_content) end it 'returns 404 for invalid snippet id' do @@ -161,7 +167,7 @@ describe API::Snippets, api: true do end it "returns 404 for another user's snippet" do - put api("/snippets/#{public_snippet.id}", other_user), title: 'fubar' + put api("/snippets/#{snippet.id}", other_user), title: 'fubar' expect(response).to have_http_status(404) expect(json_response['message']).to eq('404 Snippet Not Found') @@ -172,6 +178,56 @@ describe API::Snippets, api: true do expect(response).to have_http_status(400) end + + context 'when the snippet is spam' do + def update_snippet(snippet_params = {}) + put api("/snippets/#{snippet.id}", user), snippet_params + end + + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the snippet is private' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'updates the snippet' do + expect { update_snippet(title: 'Foo') }. + to change { snippet.reload.title }.to('Foo') + end + end + + context 'when the snippet is public' do + let(:visibility_level) { Snippet::PUBLIC } + + it 'rejects the shippet' do + expect { update_snippet(title: 'Foo') }. + not_to change { snippet.reload.title } + + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo') }. + to change { SpamLog.count }.by(1) + end + end + + context 'when a private snippet is made public' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'rejects the snippet' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + not_to change { snippet.reload.title } + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + end + end end describe 'DELETE /snippets/:id' do diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb index 33a127de98a..8e6732fe23e 100644 --- a/spec/requests/api/v3/issues_spec.rb +++ b/spec/requests/api/v3/issues_spec.rb @@ -986,6 +986,33 @@ describe API::V3::Issues, api: true do end end + describe 'PUT /projects/:id/issues/:issue_id with spam filtering' do + let(:params) do + { + title: 'updated title', + description: 'content here', + labels: 'label, label2' + } + end + + 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) + + put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), params + + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) + + spam_logs = SpamLog.all + expect(spam_logs.count).to eq(1) + expect(spam_logs[0].title).to eq('updated title') + expect(spam_logs[0].description).to eq('content here') + expect(spam_logs[0].user).to eq(user) + expect(spam_logs[0].noteable_type).to eq('Issue') + end + end + describe 'PUT /projects/:id/issues/:issue_id to update labels' do let!(:label) { create(:label, title: 'dummy', project: project) } let!(:label_link) { create(:label_link, label: label, target: issue) } diff --git a/spec/requests/api/v3/project_snippets_spec.rb b/spec/requests/api/v3/project_snippets_spec.rb index 3700477f0db..957a3bf97ef 100644 --- a/spec/requests/api/v3/project_snippets_spec.rb +++ b/spec/requests/api/v3/project_snippets_spec.rb @@ -85,43 +85,33 @@ describe API::ProjectSnippets, api: true do allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) end - context 'when the project is private' do - let(:private_project) { create(:project_empty_repo, :private) } - - context 'when the snippet is public' do - it 'creates the snippet' do - expect { create_snippet(private_project, visibility_level: Snippet::PUBLIC) }. - to change { Snippet.count }.by(1) - end + context 'when the snippet is private' do + it 'creates the snippet' do + expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. + to change { Snippet.count }.by(1) end end - context 'when the project is public' do - context 'when the snippet is private' do - it 'creates the snippet' do - expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. - to change { Snippet.count }.by(1) - end + context 'when the snippet is public' do + it 'rejects the shippet' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + not_to change { Snippet.count } + + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) end - context 'when the snippet is public' do - it 'rejects the shippet' do - expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. - not_to change { Snippet.count } - expect(response).to have_http_status(400) - end - - it 'creates a spam log' do - expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. - to change { SpamLog.count }.by(1) - end + it 'creates a spam log' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) end end end end describe 'PUT /projects/:project_id/snippets/:id/' do - let(:snippet) { create(:project_snippet, author: admin) } + let(:visibility_level) { Snippet::PUBLIC } + let(:snippet) { create(:project_snippet, author: admin, visibility_level: visibility_level) } it 'updates snippet' do new_content = 'New content' @@ -145,6 +135,56 @@ describe API::ProjectSnippets, api: true do expect(response).to have_http_status(400) end + + context 'when the snippet is spam' do + def update_snippet(snippet_params = {}) + put v3_api("/projects/#{snippet.project.id}/snippets/#{snippet.id}", admin), snippet_params + end + + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the snippet is private' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'creates the snippet' do + expect { update_snippet(title: 'Foo') }. + to change { snippet.reload.title }.to('Foo') + end + end + + context 'when the snippet is public' do + let(:visibility_level) { Snippet::PUBLIC } + + it 'rejects the snippet' do + expect { update_snippet(title: 'Foo') }. + not_to change { snippet.reload.title } + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo') }. + to change { SpamLog.count }.by(1) + end + end + + context 'when the private snippet is made public' do + let(:visibility_level) { Snippet::PRIVATE } + + it 'rejects the snippet' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + not_to change { snippet.reload.title } + + expect(response).to have_http_status(400) + expect(json_response['message']).to eq({ "error" => "Spam detected" }) + end + + it 'creates a spam log' do + expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + end + end end describe 'DELETE /projects/:project_id/snippets/:id/' do diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index e1feeed8a67..6045d00ff09 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -230,16 +230,6 @@ describe Issues::CreateService, services: true do expect { issue }.not_to change{SpamLog.last.recaptcha_verified} end end - - context 'when spam log title does not match the issue title' do - before do - opts[:title] = 'Another issue' - end - - it 'does not mark spam_log as recaptcha_verified' do - expect { issue }.not_to change{SpamLog.last.recaptcha_verified} - end - end end context 'when recaptcha was not verified' do diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb index dc945ca4868..0768f644036 100644 --- a/spec/services/merge_requests/build_service_spec.rb +++ b/spec/services/merge_requests/build_service_spec.rb @@ -44,15 +44,14 @@ describe MergeRequests::BuildService, services: true do end end - context 'missing target branch' do - let(:target_branch) { '' } + context 'when target branch is missing' do + let(:target_branch) { nil } + let(:commits) { Commit.decorate([commit_1], project) } - it 'forbids the merge request from being created' do + it 'creates compare object with target branch as default branch' do expect(merge_request.can_be_created).to eq(false) - end - - it 'adds an error message to the merge request' do - expect(merge_request.errors).to contain_exactly('You must select source and target branch') + expect(merge_request.compare).to be_present + expect(merge_request.target_branch).to eq(project.default_branch) end end diff --git a/spec/services/spam_service_spec.rb b/spec/services/spam_service_spec.rb index 271c17dd8c0..4ce3b95aa87 100644 --- a/spec/services/spam_service_spec.rb +++ b/spec/services/spam_service_spec.rb @@ -1,46 +1,61 @@ require 'spec_helper' describe SpamService, services: true do - describe '#check' do - let(:project) { create(:project, :public) } - let(:issue) { create(:issue, project: project) } - let(:request) { double(:request, env: {}) } + describe '#when_recaptcha_verified' do + def check_spam(issue, request, recaptcha_verified) + described_class.new(issue, request).when_recaptcha_verified(recaptcha_verified) do + 'yielded' + end + end + + it 'yields block when recaptcha was already verified' do + issue = build_stubbed(:issue) - def check_spam(issue, request) - described_class.new(issue, request).check + expect(check_spam(issue, nil, true)).to eql('yielded') end - context 'when indicated as spam by akismet' do - before { allow(AkismetService).to receive(:new).and_return(double(is_spam?: true)) } + context 'when recaptcha was not verified' do + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project) } + let(:request) { double(:request, env: {}) } - it 'returns false when request is missing' do - expect(check_spam(issue, nil)).to be_falsey - end + context 'when indicated as spam by akismet' do + before { allow(AkismetService).to receive(:new).and_return(double(is_spam?: true)) } - it 'returns false when issue is not public' do - issue = create(:issue, project: create(:project, :private)) + it 'doesnt check as spam when request is missing' do + check_spam(issue, nil, false) - expect(check_spam(issue, request)).to be_falsey - end + expect(issue.spam).to be_falsey + end - it 'returns true' do - expect(check_spam(issue, request)).to be_truthy - end + it 'checks as spam' do + check_spam(issue, request, false) - it 'creates a spam log' do - expect { check_spam(issue, request) }.to change { SpamLog.count }.from(0).to(1) - end - end + expect(issue.spam).to be_truthy + end - context 'when not indicated as spam by akismet' do - before { allow(AkismetService).to receive(:new).and_return(double(is_spam?: false)) } + it 'creates a spam log' do + expect { check_spam(issue, request, false) } + .to change { SpamLog.count }.from(0).to(1) + end - it 'returns false' do - expect(check_spam(issue, request)).to be_falsey + it 'doesnt yield block' do + expect(check_spam(issue, request, false)) + .to eql(SpamLog.last) + end end - it 'does not create a spam log' do - expect { check_spam(issue, request) }.not_to change { SpamLog.count } + context 'when not indicated as spam by akismet' do + before { allow(AkismetService).to receive(:new).and_return(double(is_spam?: false)) } + + it 'returns false' do + expect(check_spam(issue, request, false)).to be_falsey + end + + it 'does not create a spam log' do + expect { check_spam(issue, request, false) } + .not_to change { SpamLog.count } + end end end end diff --git a/spec/services/users/destroy_spec.rb b/spec/services/users/destroy_spec.rb index 46e58393218..c0bf27c698c 100644 --- a/spec/services/users/destroy_spec.rb +++ b/spec/services/users/destroy_spec.rb @@ -2,11 +2,11 @@ require 'spec_helper' describe Users::DestroyService, services: true do describe "Deletes a user and all their personal projects" do - let!(:user) { create(:user) } - let!(:current_user) { create(:user) } - let!(:namespace) { create(:namespace, owner: user) } - let!(:project) { create(:project, namespace: namespace) } - let(:service) { described_class.new(current_user) } + let!(:user) { create(:user) } + let!(:admin) { create(:admin) } + let!(:namespace) { create(:namespace, owner: user) } + let!(:project) { create(:project, namespace: namespace) } + let(:service) { described_class.new(admin) } context 'no options are given' do it 'deletes the user' do @@ -57,5 +57,26 @@ describe Users::DestroyService, services: true do expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) end end + + context "deletion permission checks" do + it 'does not delete the user when user is not an admin' do + other_user = create(:user) + + expect { described_class.new(other_user).execute(user) }.to raise_error(Gitlab::Access::AccessDeniedError) + expect(User.exists?(user.id)).to be(true) + end + + it 'allows admins to delete anyone' do + described_class.new(admin).execute(user) + + expect(User.exists?(user.id)).to be(false) + end + + it 'allows users to delete their own account' do + described_class.new(user).execute(user) + + expect(User.exists?(user.id)).to be(false) + end + end end end diff --git a/spec/support/filtered_search_helpers.rb b/spec/support/filtered_search_helpers.rb new file mode 100644 index 00000000000..58f6636e680 --- /dev/null +++ b/spec/support/filtered_search_helpers.rb @@ -0,0 +1,37 @@ +module FilteredSearchHelpers + def filtered_search + page.find('.filtered-search') + end + + def input_filtered_search(search_term, submit: true) + filtered_search.set(search_term) + + if submit + filtered_search.send_keys(:enter) + end + end + + def input_filtered_search_keys(search_term) + filtered_search.send_keys(search_term) + filtered_search.send_keys(:enter) + end + + def expect_filtered_search_input(input) + expect(find('.filtered-search').value).to eq(input) + end + + def clear_search_field + find('.filtered-search-input-container .clear-search').click + end + + def reset_filters + clear_search_field + filtered_search.send_keys(:enter) + end + + def init_label_search + filtered_search.set('label:') + # This ensures the dropdown is shown + expect(find('#js-dropdown-label')).not_to have_css('.filter-dropdown-loading') + end +end diff --git a/spec/support/merge_request_helpers.rb b/spec/support/merge_request_helpers.rb index d5801c8272f..326b85eabd0 100644 --- a/spec/support/merge_request_helpers.rb +++ b/spec/support/merge_request_helpers.rb @@ -10,4 +10,13 @@ module MergeRequestHelpers def last_merge_request page.all('ul.mr-list > li').last.text end + + def expect_mr_list_count(open_count, closed_count = 0) + all_count = open_count + closed_count + + expect(page).to have_issuable_counts(open: open_count, closed: closed_count, all: all_count) + page.within '.mr-list' do + expect(page).to have_selector('.merge-request', count: open_count) + end + end end |