diff options
author | James Lopez <james@jameslopez.es> | 2016-04-07 14:15:48 +0200 |
---|---|---|
committer | James Lopez <james@jameslopez.es> | 2016-04-07 14:15:48 +0200 |
commit | e8b7e37c6de2c541510ff804730e3d9946857b9e (patch) | |
tree | 6553e5dd3424c52ae0261f24f6671f585b01bb54 /spec | |
parent | 05be0c306ea8663461ee73023f162aeaf77a4325 (diff) | |
parent | b30ebdaa1a704f4e81e91153b1b33a4c1c1a5c12 (diff) | |
download | gitlab-ce-e8b7e37c6de2c541510ff804730e3d9946857b9e.tar.gz |
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into fix/project-import_url
Diffstat (limited to 'spec')
26 files changed, 679 insertions, 129 deletions
diff --git a/spec/controllers/admin/projects_controller_spec.rb b/spec/controllers/admin/projects_controller_spec.rb new file mode 100644 index 00000000000..2ba0d489197 --- /dev/null +++ b/spec/controllers/admin/projects_controller_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe Admin::ProjectsController do + let!(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + + before do + sign_in(create(:admin)) + end + + describe 'GET /projects' do + render_views + + it 'retrieves the project for the given visibility level' do + get :index, visibility_levels: [Gitlab::VisibilityLevel::PUBLIC] + expect(response.body).to match(project.name) + end + + it 'does not retrieve the project' do + get :index, visibility_levels: [Gitlab::VisibilityLevel::INTERNAL] + expect(response.body).to_not match(project.name) + end + end +end diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 98ae424ed7c..8ad73472117 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -93,6 +93,20 @@ describe Projects::BranchesController do end end + describe "POST destroy with HTML format" do + render_views + + it 'returns 303' do + post :destroy, + format: :html, + id: 'foo/bar/baz', + namespace_id: project.namespace.to_param, + project_id: project.to_param + + expect(response.status).to eq(303) + end + end + describe "POST destroy" do render_views diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb new file mode 100644 index 00000000000..d47e4ab9a4f --- /dev/null +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -0,0 +1,49 @@ +require('spec_helper') + +describe Projects::ProjectMembersController do + let(:project) { create(:project) } + let(:another_project) { create(:project, :private) } + let(:user) { create(:user) } + let(:member) { create(:user) } + + before do + project.team << [user, :master] + another_project.team << [member, :guest] + sign_in(user) + end + + describe '#apply_import' do + shared_context 'import applied' do + before do + post(:apply_import, namespace_id: project.namespace.to_param, + project_id: project.to_param, + source_project_id: another_project.id) + end + end + + context 'when user can access source project members' do + before { another_project.team << [user, :guest] } + include_context 'import applied' + + it 'imports source project members' do + expect(project.team_members).to include member + expect(response).to set_flash.to 'Successfully imported' + expect(response).to redirect_to( + namespace_project_project_members_path(project.namespace, project) + ) + end + end + + context 'when user is not member of a source project' do + include_context 'import applied' + + it 'does not import team members' do + expect(project.team_members).to_not include member + end + + it 'responds with not found' do + expect(response.status).to eq 404 + end + end + end +end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 1893e946f5c..069cd917e5a 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -83,6 +83,28 @@ describe ProjectsController do end end + describe "#update" do + render_views + + let(:admin) { create(:admin) } + + it "sets the repository to the right path after a rename" do + new_path = 'renamed_path' + project_params = { path: new_path } + controller.instance_variable_set(:@project, project) + sign_in(admin) + + put :update, + namespace_id: project.namespace.to_param, + id: project.id, + project: project_params + + expect(project.repository.path).to include(new_path) + expect(assigns(:repository).path).to eq(project.repository.path) + expect(response.status).to eq(200) + end + end + describe "#destroy" do let(:admin) { create(:admin) } diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb new file mode 100644 index 00000000000..83cc8ec6d26 --- /dev/null +++ b/spec/controllers/sessions_controller_spec.rb @@ -0,0 +1,101 @@ +require 'spec_helper' + +describe SessionsController do + describe '#create' do + before do + @request.env['devise.mapping'] = Devise.mappings[:user] + end + + context 'when using standard authentications' do + context 'invalid password' do + it 'does not authenticate user' do + post(:create, user: { login: 'invalid', password: 'invalid' }) + + expect(response) + .to set_flash.now[:alert].to /Invalid login or password/ + end + end + + context 'when using valid password' do + let(:user) { create(:user) } + + it 'authenticates user correctly' do + post(:create, user: { login: user.username, password: user.password }) + + expect(response).to set_flash.to /Signed in successfully/ + expect(subject.current_user). to eq user + end + end + end + + context 'when using two-factor authentication' do + let(:user) { create(:user, :two_factor) } + + def authenticate_2fa(user_params) + post(:create, { user: user_params }, { otp_user_id: user.id }) + end + + ## + # See #14900 issue + # + context 'when authenticating with login and OTP of another user' do + context 'when another user has 2FA enabled' do + let(:another_user) { create(:user, :two_factor) } + + context 'when OTP is valid for another user' do + it 'does not authenticate' do + authenticate_2fa(login: another_user.username, + otp_attempt: another_user.current_otp) + + expect(subject.current_user).to_not eq another_user + end + end + + context 'when OTP is invalid for another user' do + it 'does not authenticate' do + authenticate_2fa(login: another_user.username, + otp_attempt: 'invalid') + + expect(subject.current_user).to_not eq another_user + end + end + + context 'when authenticating with OTP' do + context 'when OTP is valid' do + it 'authenticates correctly' do + authenticate_2fa(otp_attempt: user.current_otp) + + expect(subject.current_user).to eq user + end + end + + context 'when OTP is invalid' do + before { authenticate_2fa(otp_attempt: 'invalid') } + + it 'does not authenticate' do + expect(subject.current_user).to_not eq user + end + + it 'warns about invalid OTP code' do + expect(response).to set_flash.now[:alert] + .to /Invalid two-factor code/ + end + end + end + + context 'when another user does not have 2FA enabled' do + let(:another_user) { create(:user) } + + it 'does not leak that 2FA is disabled for another user' do + authenticate_2fa(login: another_user.username, + otp_attempt: 'invalid') + + expect(response).to set_flash.now[:alert] + .to /Invalid two-factor code/ + end + end + end + end + end + end +end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb new file mode 100644 index 00000000000..90822a8c123 --- /dev/null +++ b/spec/features/issues/filter_issues_spec.rb @@ -0,0 +1,119 @@ +require 'rails_helper' + +describe 'Filter issues', feature: true do + + let!(:project) { create(:project) } + let!(:user) { create(:user)} + let!(:milestone) { create(:milestone, project: project) } + let!(:label) { create(:label, project: project) } + + before do + project.team << [user, :master] + login_as(user) + end + + describe 'Filter issues for assignee from issues#index' do + + before do + visit namespace_project_issues_path(project.namespace, project) + + find('.js-assignee-search').click + + find('.dropdown-menu-user-link', text: user.username).click + + sleep 2 + end + + context 'assignee', js: true do + it 'should update to current user' do + expect(find('.js-assignee-search .dropdown-toggle-text')).to have_content(user.name) + end + + it 'should 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) + end + + + it 'should 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) + end + end + end + + describe 'Filter issues for milestone from issues#index' do + + before do + visit namespace_project_issues_path(project.namespace, project) + + find('.js-milestone-select').click + + find('.milestone-filter .dropdown-content a', text: milestone.title).click + + sleep 2 + end + + context 'milestone', js: true do + it 'should update to current milestone' do + expect(find('.js-milestone-select .dropdown-toggle-text')).to have_content(milestone.title) + end + + it 'should 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) + end + + + it 'should 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) + end + end + end + + describe 'Filter issues for assignee and label from issues#index' do + + before do + visit namespace_project_issues_path(project.namespace, project) + + find('.js-assignee-search').click + + find('.dropdown-menu-user-link', text: user.username).click + + sleep 2 + + find('.js-label-select').click + + find('.dropdown-menu-labels .dropdown-content a', text: label.title).click + + sleep 2 + end + + context 'assignee and label', js: true do + it 'should update 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) + end + + it 'should 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) + end + + + it 'should 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) + end + end + end +end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index db46657c36a..79000666ccc 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -22,7 +22,7 @@ describe 'Issues', feature: true do before do visit edit_namespace_project_issue_path(project.namespace, project, issue) - click_link "Edit" + click_button "Go full screen" end it 'should open new issue popup' do diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 12fd8d37210..3d0d0e59fd7 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -39,7 +39,7 @@ describe 'GitLab Markdown', feature: true do end def doc(html = @html) - Nokogiri::HTML::DocumentFragment.parse(html) + @doc ||= Nokogiri::HTML::DocumentFragment.parse(html) end # Shared behavior that all pipelines should exhibit @@ -230,6 +230,7 @@ describe 'GitLab Markdown', feature: true do file = Gollum::File.new(@project_wiki.wiki) expect(file).to receive(:path).and_return('images/example.jpg') expect(@project_wiki).to receive(:find_file).with('images/example.jpg').and_return(file) + allow(@project_wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' } @html = markdown(@feat.raw_markdown, { pipeline: :wiki, project_wiki: @project_wiki }) end diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index d9a8058efd9..70d0864783d 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -152,7 +152,7 @@ describe 'Comments', feature: true do it 'has .new_note css class' do page.within('.js-temp-notes-holder') do - expect(subject).to have_css('.new_note') + expect(subject).to have_css('.new-note') end end end @@ -225,6 +225,6 @@ describe 'Comments', feature: true do end def click_diff_line(data = line_code) - page.find(%Q{button[data-line-code="#{data}"]}, visible: false).click + execute_script("$('button[data-line-code=\"#{data}\"]').click()") end end diff --git a/spec/features/projects/badges/list_spec.rb b/spec/features/projects/badges/list_spec.rb new file mode 100644 index 00000000000..13c9b95b316 --- /dev/null +++ b/spec/features/projects/badges/list_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +feature 'list of badges' do + include Select2Helper + + background do + user = create(:user) + project = create(:project) + project.team << [user, :master] + login_as(user) + visit edit_namespace_project_path(project.namespace, project) + end + + scenario 'user displays list of badges' do + click_link 'Badges' + + expect(page).to have_content 'build status' + expect(page).to have_content 'Markdown' + expect(page).to have_content 'HTML' + expect(page).to have_css('.highlight', count: 2) + expect(page).to have_xpath("//img[@alt='build status']") + + page.within('.highlight', match: :first) do + expect(page).to have_content 'badges/master/build.svg' + end + end + + scenario 'user changes current ref on badges list page', js: true do + click_link 'Badges' + select2('improve/awesome', from: '#ref') + + expect(page).to have_content 'badges/improve/awesome/build.svg' + end +end diff --git a/spec/javascripts/fixtures/zen_mode.html.haml b/spec/javascripts/fixtures/zen_mode.html.haml index 1701652c61e..cb906a7feaa 100644 --- a/spec/javascripts/fixtures/zen_mode.html.haml +++ b/spec/javascripts/fixtures/zen_mode.html.haml @@ -1,4 +1,4 @@ -.zennable +.md-area .zen-backdrop %textarea#note_note.js-gfm-input.markdown-area %a.js-zen-enter(tabindex="-1" href="#") diff --git a/spec/javascripts/issue_spec.js.coffee b/spec/javascripts/issue_spec.js.coffee index 86ba9dd8e96..ea27f36e9b5 100644 --- a/spec/javascripts/issue_spec.js.coffee +++ b/spec/javascripts/issue_spec.js.coffee @@ -29,8 +29,8 @@ describe 'reopen/close issue', -> spyOn(jQuery, 'ajax').and.callFake (req) -> expect(req.type).toBe('PUT') expect(req.url).toBe('http://gitlab.com/issues/6/close') - req.success saved: true - + req.success id: 34 + $btnClose = $('a.btn-close') $btnReopen = $('a.btn-reopen') expect($btnReopen).toBeHidden() @@ -94,7 +94,7 @@ describe 'reopen/close issue', -> spyOn(jQuery, 'ajax').and.callFake (req) -> expect(req.type).toBe('PUT') expect(req.url).toBe('http://gitlab.com/issues/6/reopen') - req.success saved: true + req.success id: 34 $btnClose = $('a.btn-close') $btnReopen = $('a.btn-reopen') diff --git a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb index 5e23c5c319a..fe2ce092e6b 100644 --- a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb +++ b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb @@ -70,20 +70,22 @@ describe Banzai::Filter::GollumTagsFilter, lib: true do end context 'linking internal resources' do - it "the created link's text will be equal to the resource's text" do + it "the created link's text includes the resource's text and wiki base path" do tag = '[[wiki-slug]]' doc = filter("See #{tag}", project_wiki: project_wiki) + expected_path = ::File.join(project_wiki.wiki_base_path, 'wiki-slug') expect(doc.at_css('a').text).to eq 'wiki-slug' - expect(doc.at_css('a')['href']).to eq 'wiki-slug' + expect(doc.at_css('a')['href']).to eq expected_path end it "the created link's text will be link-text" do tag = '[[link-text|wiki-slug]]' doc = filter("See #{tag}", project_wiki: project_wiki) + expected_path = ::File.join(project_wiki.wiki_base_path, 'wiki-slug') expect(doc.at_css('a').text).to eq 'link-text' - expect(doc.at_css('a')['href']).to eq 'wiki-slug' + expect(doc.at_css('a')['href']).to eq expected_path end end diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb index 5a0d3d577a8..266ebef33d6 100644 --- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb @@ -95,6 +95,14 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do result = reference_pipeline_result("Fixed #{reference}") expect(result[:references][:issue]).to eq [issue] end + + it 'does not process links containing issue numbers followed by text' do + href = "#{reference}st" + doc = reference_filter("<a href='#{href}'></a>") + link = doc.css('a').first.attr('href') + + expect(link).to eq(href) + end end context 'cross-project reference' do diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb index 3e25406e498..7aa1b4a3bf6 100644 --- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb @@ -11,7 +11,7 @@ describe Banzai::Pipeline::WikiPipeline do Foo MD - result = described_class.call(markdown, project: spy, project_wiki: double) + result = described_class.call(markdown, project: spy, project_wiki: spy) aggregate_failures do expect(result[:output].text).not_to include '[[' @@ -29,7 +29,7 @@ describe Banzai::Pipeline::WikiPipeline do Foo MD - output = described_class.to_html(markdown, project: spy, project_wiki: double) + output = described_class.to_html(markdown, project: spy, project_wiki: spy) expect(output).to include('[[<em>toc</em>]]') end @@ -42,7 +42,7 @@ describe Banzai::Pipeline::WikiPipeline do Foo MD - output = described_class.to_html(markdown, project: spy, project_wiki: double) + output = described_class.to_html(markdown, project: spy, project_wiki: spy) aggregate_failures do expect(output).not_to include('<ul>') diff --git a/spec/lib/gitlab/badge/build_spec.rb b/spec/lib/gitlab/badge/build_spec.rb index b78c2b6224f..329792bb685 100644 --- a/spec/lib/gitlab/badge/build_spec.rb +++ b/spec/lib/gitlab/badge/build_spec.rb @@ -3,13 +3,44 @@ require 'spec_helper' describe Gitlab::Badge::Build do let(:project) { create(:project) } let(:sha) { project.commit.sha } - let(:badge) { described_class.new(project, 'master') } + let(:branch) { 'master' } + let(:badge) { described_class.new(project, branch) } describe '#type' do subject { badge.type } it { is_expected.to eq 'image/svg+xml' } end + describe '#to_html' do + let(:html) { Nokogiri::HTML.parse(badge.to_html) } + let(:a_href) { html.at('a') } + + it 'points to link' do + expect(a_href[:href]).to eq badge.link_url + end + + it 'contains clickable image' do + expect(a_href.children.first.name).to eq 'img' + end + end + + describe '#to_markdown' do + subject { badge.to_markdown } + + it { is_expected.to include badge.image_url } + it { is_expected.to include badge.link_url } + end + + describe '#image_url' do + subject { badge.image_url } + it { is_expected.to include "badges/#{branch}/build.svg" } + end + + describe '#link_url' do + subject { badge.link_url } + it { is_expected.to include "commits/#{branch}" } + end + context 'build exists' do let(:ci_commit) { create(:ci_commit, project: project, sha: sha) } let!(:build) { create(:ci_build, commit: ci_commit) } diff --git a/spec/lib/gitlab/ldap/access_spec.rb b/spec/lib/gitlab/ldap/access_spec.rb index 32a19bf344b..f5b66b8156f 100644 --- a/spec/lib/gitlab/ldap/access_spec.rb +++ b/spec/lib/gitlab/ldap/access_spec.rb @@ -33,7 +33,7 @@ describe Gitlab::LDAP::Access, lib: true do it { is_expected.to be_falsey } - it 'should block user in GitLab' do + it 'blocks user in GitLab' do access.allowed? expect(user).to be_blocked expect(user).to be_ldap_blocked @@ -78,6 +78,31 @@ describe Gitlab::LDAP::Access, lib: true do end it { is_expected.to be_truthy } + + context 'when user cannot be found' do + before do + allow(Gitlab::LDAP::Person).to receive(:find_by_dn).and_return(nil) + end + + it { is_expected.to be_falsey } + + it 'blocks user in GitLab' do + access.allowed? + expect(user).to be_blocked + expect(user).to be_ldap_blocked + end + end + + context 'when user was previously ldap_blocked' do + before do + user.ldap_block + end + + it 'unblocks the user if it exists' do + access.allowed? + expect(user).not_to be_blocked + end + end end end end diff --git a/spec/lib/gitlab/metrics_spec.rb b/spec/lib/gitlab/metrics_spec.rb index 0ec8a6dc5cb..8f63a5f2043 100644 --- a/spec/lib/gitlab/metrics_spec.rb +++ b/spec/lib/gitlab/metrics_spec.rb @@ -13,7 +13,7 @@ describe Gitlab::Metrics do end end - describe '#submit_metrics' do + describe '.submit_metrics' do it 'prepares and writes the metrics to InfluxDB' do connection = double(:connection) pool = double(:pool) @@ -26,7 +26,7 @@ describe Gitlab::Metrics do end end - describe '#prepare_metrics' do + describe '.prepare_metrics' do it 'returns a Hash with the keys as Symbols' do metrics = described_class. prepare_metrics([{ 'values' => {}, 'tags' => {} }]) @@ -51,7 +51,7 @@ describe Gitlab::Metrics do end end - describe '#escape_value' do + describe '.escape_value' do it 'escapes an equals sign' do expect(described_class.escape_value('foo=')).to eq('foo\\=') end @@ -60,4 +60,45 @@ describe Gitlab::Metrics do expect(described_class.escape_value(10)).to eq('10') end end + + describe '.measure' do + context 'without a transaction' do + it 'returns the return value of the block' do + val = Gitlab::Metrics.measure(:foo) { 10 } + + expect(val).to eq(10) + end + end + + context 'with a transaction' do + let(:transaction) { Gitlab::Metrics::Transaction.new } + + before do + allow(Gitlab::Metrics::Transaction).to receive(:current). + and_return(transaction) + end + + it 'adds a metric to the current transaction' do + expect(transaction).to receive(:add_metric). + with(:foo, { duration: a_kind_of(Numeric) }, { tag: 'value' }) + + Gitlab::Metrics.measure(:foo, {}, tag: 'value') { 10 } + end + + it 'supports adding of custom values' do + values = { duration: a_kind_of(Numeric), number: 10 } + + expect(transaction).to receive(:add_metric). + with(:foo, values, { tag: 'value' }) + + Gitlab::Metrics.measure(:foo, { number: 10 }, tag: 'value') { 10 } + end + + it 'returns the return value of the block' do + val = Gitlab::Metrics.measure(:foo) { 10 } + + expect(val).to eq(10) + end + end + end end diff --git a/spec/lib/gitlab/saml/user_spec.rb b/spec/lib/gitlab/saml/user_spec.rb index de7cd99d49d..c2a51d9249c 100644 --- a/spec/lib/gitlab/saml/user_spec.rb +++ b/spec/lib/gitlab/saml/user_spec.rb @@ -5,7 +5,7 @@ describe Gitlab::Saml::User, lib: true do let(:gl_user) { saml_user.gl_user } let(:uid) { 'my-uid' } let(:provider) { 'saml' } - let(:auth_hash) { OmniAuth::AuthHash.new(uid: uid, provider: provider, info: info_hash) } + let(:auth_hash) { OmniAuth::AuthHash.new(uid: uid, provider: provider, info: info_hash, extra: { raw_info: OneLogin::RubySaml::Attributes.new({ 'groups' => %w(Developers Freelancers Designers) }) }) } let(:info_hash) do { name: 'John', @@ -23,10 +23,20 @@ describe Gitlab::Saml::User, lib: true do allow(Gitlab::LDAP::Config).to receive_messages(messages) end + def stub_basic_saml_config + allow(Gitlab::Saml::Config).to receive_messages({ options: { name: 'saml', args: {} } }) + end + + def stub_saml_group_config(groups) + allow(Gitlab::Saml::Config).to receive_messages({ options: { name: 'saml', groups_attribute: 'groups', external_groups: groups, args: {} } }) + end + + before { stub_basic_saml_config } + describe 'account exists on server' do before { stub_omniauth_config({ allow_single_sign_on: ['saml'], auto_link_saml_user: true }) } + let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') } context 'and should bind with SAML' do - let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') } it 'adds the SAML identity to the existing user' do saml_user.save expect(gl_user).to be_valid @@ -36,6 +46,35 @@ describe Gitlab::Saml::User, lib: true do expect(identity.provider).to eql 'saml' end end + + context 'external groups' do + context 'are defined' do + it 'marks the user as external' do + stub_saml_group_config(%w(Freelancers)) + saml_user.save + expect(gl_user).to be_valid + expect(gl_user.external).to be_truthy + end + end + + before { stub_saml_group_config(%w(Interns)) } + context 'are defined but the user does not belong there' do + it 'does not mark the user as external' do + saml_user.save + expect(gl_user).to be_valid + expect(gl_user.external).to be_falsey + end + end + + context 'user was external, now should not be' do + it 'should make user internal' do + existing_user.update_attribute('external', true) + saml_user.save + expect(gl_user).to be_valid + expect(gl_user.external).to be_falsey + end + end + end end describe 'no account exists on server' do @@ -68,6 +107,26 @@ describe Gitlab::Saml::User, lib: true do end end + context 'external groups' do + context 'are defined' do + it 'marks the user as external' do + stub_saml_group_config(%w(Freelancers)) + saml_user.save + expect(gl_user).to be_valid + expect(gl_user.external).to be_truthy + end + end + + context 'are defined but the user does not belong there' do + it 'does not mark the user as external' do + stub_saml_group_config(%w(Interns)) + saml_user.save + expect(gl_user).to be_valid + expect(gl_user.external).to be_falsey + end + end + end + context 'with auto_link_ldap_user disabled (default)' do before { stub_omniauth_config({ auto_link_ldap_user: false, auto_link_saml_user: false, allow_single_sign_on: ['saml'] }) } include_examples 'to verify compliance with allow_single_sign_on' @@ -76,12 +135,6 @@ describe Gitlab::Saml::User, lib: true do context 'with auto_link_ldap_user enabled' do before { stub_omniauth_config({ auto_link_ldap_user: true, auto_link_saml_user: false }) } - context 'and no LDAP provider defined' do - before { stub_ldap_config(providers: []) } - - include_examples 'to verify compliance with allow_single_sign_on' - end - context 'and at least one LDAP provider is defined' do before { stub_ldap_config(providers: %w(ldapmain)) } @@ -89,19 +142,18 @@ describe Gitlab::Saml::User, lib: true do before do allow(ldap_user).to receive(:uid) { uid } allow(ldap_user).to receive(:username) { uid } - allow(ldap_user).to receive(:email) { ['johndoe@example.com','john2@example.com'] } + allow(ldap_user).to receive(:email) { %w(john@mail.com john2@example.com) } allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' } allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user) end context 'and no account for the LDAP user' do - it 'creates a user with dual LDAP and SAML identities' do saml_user.save expect(gl_user).to be_valid expect(gl_user.username).to eql uid - expect(gl_user.email).to eql 'johndoe@example.com' + expect(gl_user.email).to eql 'john@mail.com' expect(gl_user.identities.length).to eql 2 identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } } expect(identities_as_hash).to match_array([ { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' }, @@ -111,13 +163,13 @@ describe Gitlab::Saml::User, lib: true do end context 'and LDAP user has an account already' do - let!(:existing_user) { create(:omniauth_user, email: 'john@example.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') } - it "adds the omniauth identity to the LDAP account" do + let!(:existing_user) { create(:omniauth_user, email: 'john@mail.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') } + it 'adds the omniauth identity to the LDAP account' do saml_user.save expect(gl_user).to be_valid expect(gl_user.username).to eql 'john' - expect(gl_user.email).to eql 'john@example.com' + expect(gl_user.email).to eql 'john@mail.com' expect(gl_user.identities.length).to eql 2 identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } } expect(identities_as_hash).to match_array([ { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' }, @@ -126,19 +178,13 @@ describe Gitlab::Saml::User, lib: true do end end end - - context 'and no corresponding LDAP person' do - before { allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(nil) } - - include_examples 'to verify compliance with allow_single_sign_on' - end end end end describe 'blocking' do - before { stub_omniauth_config({ allow_saml_sign_up: true, auto_link_saml_user: true }) } + before { stub_omniauth_config({ allow_single_sign_on: ['saml'], auto_link_saml_user: true }) } context 'signup with SAML only' do context 'dont block on create' do @@ -162,64 +208,6 @@ describe Gitlab::Saml::User, lib: true do end end - context 'signup with linked omniauth and LDAP account' do - before do - stub_omniauth_config(auto_link_ldap_user: true) - allow(ldap_user).to receive(:uid) { uid } - allow(ldap_user).to receive(:username) { uid } - allow(ldap_user).to receive(:email) { ['johndoe@example.com','john2@example.com'] } - allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' } - allow(saml_user).to receive(:ldap_person).and_return(ldap_user) - end - - context "and no account for the LDAP user" do - context 'dont block on create (LDAP)' do - before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: false) } - - it do - saml_user.save - expect(gl_user).to be_valid - expect(gl_user).not_to be_blocked - end - end - - context 'block on create (LDAP)' do - before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: true) } - - it do - saml_user.save - expect(gl_user).to be_valid - expect(gl_user).to be_blocked - end - end - end - - context 'and LDAP user has an account already' do - let!(:existing_user) { create(:omniauth_user, email: 'john@example.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') } - - context 'dont block on create (LDAP)' do - before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: false) } - - it do - saml_user.save - expect(gl_user).to be_valid - expect(gl_user).not_to be_blocked - end - end - - context 'block on create (LDAP)' do - before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: true) } - - it do - saml_user.save - expect(gl_user).to be_valid - expect(gl_user).not_to be_blocked - end - end - end - end - - context 'sign-in' do before do saml_user.save @@ -245,26 +233,6 @@ describe Gitlab::Saml::User, lib: true do expect(gl_user).not_to be_blocked end end - - context 'dont block on create (LDAP)' do - before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: false) } - - it do - saml_user.save - expect(gl_user).to be_valid - expect(gl_user).not_to be_blocked - end - end - - context 'block on create (LDAP)' do - before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: true) } - - it do - saml_user.save - expect(gl_user).to be_valid - expect(gl_user).not_to be_blocked - end - end end end end diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 56a6dbf96f9..5a85cb501dd 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -141,10 +141,12 @@ shared_examples 'a new user email' do end shared_examples 'it should have Gmail Actions links' do + it { is_expected.to have_body_text '<script type="application/ld+json">' } it { is_expected.to have_body_text /ViewAction/ } end shared_examples 'it should not have Gmail Actions links' do + it { is_expected.to_not have_body_text '<script type="application/ld+json">' } it { is_expected.to_not have_body_text /ViewAction/ } end diff --git a/spec/models/project_services/builds_email_service_spec.rb b/spec/models/project_services/builds_email_service_spec.rb index 905379a64e3..2ccbff553f0 100644 --- a/spec/models/project_services/builds_email_service_spec.rb +++ b/spec/models/project_services/builds_email_service_spec.rb @@ -6,18 +6,38 @@ describe BuildsEmailService do let(:service) { BuildsEmailService.new } describe :execute do - it "sends email" do + it 'sends email' do service.recipients = 'test@gitlab.com' data[:build_status] = 'failed' expect(BuildEmailWorker).to receive(:perform_async) service.execute(data) end - it "does not sends email with failed build and allowed_failure on" do + it 'does not send email with succeeded build and notify_only_broken_builds on' do + expect(service).to receive(:notify_only_broken_builds).and_return(true) + data[:build_status] = 'success' + expect(BuildEmailWorker).not_to receive(:perform_async) + service.execute(data) + end + + it 'does not send email with failed build and build_allow_failure is true' do data[:build_status] = 'failed' data[:build_allow_failure] = true expect(BuildEmailWorker).not_to receive(:perform_async) service.execute(data) end + + it 'does not send email with unknown build status' do + data[:build_status] = 'foo' + expect(BuildEmailWorker).not_to receive(:perform_async) + service.execute(data) + end + + it 'does not send email when recipients list is empty' do + service.recipients = ' ,, ' + data[:build_status] = 'failed' + expect(BuildEmailWorker).not_to receive(:perform_async) + service.execute(data) + end end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index c5d5a1c2492..4e49c413f23 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -612,6 +612,20 @@ describe Repository, models: true do end end + describe '#before_import' do + it 'flushes the emptiness cachess' do + expect(repository).to receive(:expire_emptiness_caches) + + repository.before_import + end + + it 'flushes the exists cache' do + expect(repository).to receive(:expire_exists_cache) + + repository.before_import + end + end + describe '#after_import' do it 'flushes the emptiness cachess' do expect(repository).to receive(:expire_emptiness_caches) @@ -656,6 +670,19 @@ describe Repository, models: true do repository.after_create end + + it 'flushes the root ref cache' do + expect(repository).to receive(:expire_root_ref_cache) + + repository.after_create + end + + it 'flushes the emptiness caches' do + expect(repository).to receive(:expire_emptiness_caches) + + repository.after_create + end + end describe "#main_language" do diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index db0f6e3c0f5..d97bf6d38ff 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -4,6 +4,7 @@ describe API::API, api: true do include ApiHelpers let(:user) { create(:user) } let!(:project) { create(:project, namespace: user.namespace ) } + let!(:closed_milestone) { create(:closed_milestone, project: project) } let!(:milestone) { create(:milestone, project: project) } before { project.team << [user, :developer] } @@ -20,6 +21,24 @@ describe API::API, api: true do get api("/projects/#{project.id}/milestones") expect(response.status).to eq(401) end + + it 'returns an array of active milestones' do + get api("/projects/#{project.id}/milestones?state=active", user) + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(milestone.id) + end + + it 'returns an array of closed milestones' do + get api("/projects/#{project.id}/milestones?state=closed", user) + + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(closed_milestone.id) + end end describe 'GET /projects/:id/milestones/:milestone_id' do diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 8490a729e51..b40a5c1c818 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -159,18 +159,44 @@ describe GitPushService, services: true do end describe "Updates main language" do - context "before push" do it { expect(project.main_language).to eq(nil) } end context "after push" do - before do - @service = execute_service(project, user, @oldrev, @newrev, @ref) + def execute + execute_service(project, user, @oldrev, @newrev, ref) end - it { expect(@service.update_main_language).to eq(true) } - it { expect(project.main_language).to eq("Ruby") } + context "to master" do + let(:ref) { @ref } + + context 'when main_language is nil' do + it 'obtains the language from the repository' do + expect(project.repository).to receive(:main_language) + execute + end + + it 'sets the project main language' do + execute + expect(project.main_language).to eq("Ruby") + end + end + + context 'when main_language is already set' do + it 'does not check the repository' do + execute # do an initial run to simulate lang being preset + expect(project.repository).not_to receive(:main_language) + execute + end + end + end + + context "to other branch" do + let(:ref) { 'refs/heads/feature/branch' } + + it { expect(project.main_language).to eq(nil) } + end end end diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb index 04f474c736c..32bf3acf483 100644 --- a/spec/services/projects/import_service_spec.rb +++ b/spec/services/projects/import_service_spec.rb @@ -72,6 +72,23 @@ describe Projects::ImportService, services: true do expect(result[:status]).to eq :success end + it 'flushes various caches' do + expect_any_instance_of(Gitlab::Shell).to receive(:import_repository). + with(project.path_with_namespace, project.import_url). + and_return(true) + + expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute). + and_return(true) + + expect_any_instance_of(Repository).to receive(:expire_emptiness_caches). + and_call_original + + expect_any_instance_of(Repository).to receive(:expire_exists_cache). + and_call_original + + subject.execute + end + it 'fails if importer fails' do expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true) expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute).and_return(false) diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb index 1d52489e804..43cb6ef43f2 100644 --- a/spec/support/matchers/markdown_matchers.rb +++ b/spec/support/matchers/markdown_matchers.rb @@ -13,7 +13,7 @@ module MarkdownMatchers set_default_markdown_messages match do |actual| - link = actual.at_css('a:contains("Relative Link")') + link = actual.at_css('a:contains("Relative Link")') image = actual.at_css('img[alt="Relative Image"]') expect(link['href']).to end_with('master/doc/README.md') @@ -72,14 +72,15 @@ module MarkdownMatchers have_css("img[src$='#{src}']") end + prefix = '/namespace1/gitlabhq/wikis' set_default_markdown_messages match do |actual| - expect(actual).to have_link('linked-resource', href: 'linked-resource') - expect(actual).to have_link('link-text', href: 'linked-resource') + expect(actual).to have_link('linked-resource', href: "#{prefix}/linked-resource") + expect(actual).to have_link('link-text', href: "#{prefix}/linked-resource") expect(actual).to have_link('http://example.com', href: 'http://example.com') expect(actual).to have_link('link-text', href: 'http://example.com/pdfs/gollum.pdf') - expect(actual).to have_image('/gitlabhq/wikis/images/example.jpg') + expect(actual).to have_image("#{prefix}/images/example.jpg") expect(actual).to have_image('http://example.com/images/example.jpg') end end |