diff options
author | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-06-10 10:49:07 +0200 |
---|---|---|
committer | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-06-10 10:49:07 +0200 |
commit | 51046dd22628cc54e92ca6da016c05762158e8ea (patch) | |
tree | a9352e9e0be4b74ee2622d85ee93a10e748fb225 /spec | |
parent | d7e125116124b9c08c27b4a02f4738619db1d2f5 (diff) | |
parent | cea3cf177c68bb1fa9326d4e88631b7737ae8a98 (diff) | |
download | gitlab-ce-51046dd22628cc54e92ca6da016c05762158e8ea.tar.gz |
Merge branch 'master' into refactor/ci-config-add-global-entry
* master: (147 commits)
Minor MR comment fixes.
Update CHANGELOG for 8.8.4 and 8.8.5
Properly quote table name in Rake task for MySQL and PostgreSQL compatibility
Checks based on whether data is loaded not undefined
Checks for undefined when inserting autocomplete into textarea
Ignore frequent emojis in search.
Fixed tests
CHANGELOG
Improved the UX of issue & milestone date picker
Change date format to be non zero padded in order to fix failing test
Update method name for better understanding
Add tests for dates on tooltips
Fix local timeago on user dashboard
Update CHANGELOG
Toggling a task in a description with mentions doesn't creates a Todo
Update CHANGELOG
Fixed failing label subscribe test
Tests update
Updated subscribe icon
Fixed failing tests
...
Diffstat (limited to 'spec')
32 files changed, 867 insertions, 341 deletions
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb index 81c03c9059b..07bf8d2d1c3 100644 --- a/spec/controllers/import/bitbucket_controller_spec.rb +++ b/spec/controllers/import/bitbucket_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::BitbucketController do include ImportSpecHelper diff --git a/spec/controllers/import/fogbugz_controller_spec.rb b/spec/controllers/import/fogbugz_controller_spec.rb index 27b11267d2a..5f0f6dea821 100644 --- a/spec/controllers/import/fogbugz_controller_spec.rb +++ b/spec/controllers/import/fogbugz_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::FogbugzController do include ImportSpecHelper diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb index bcc713dce2a..c55a3c28208 100644 --- a/spec/controllers/import/github_controller_spec.rb +++ b/spec/controllers/import/github_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GithubController do include ImportSpecHelper diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb index 198d006af76..e8cf6aa7767 100644 --- a/spec/controllers/import/gitlab_controller_spec.rb +++ b/spec/controllers/import/gitlab_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GitlabController do include ImportSpecHelper diff --git a/spec/controllers/import/gitorious_controller_spec.rb b/spec/controllers/import/gitorious_controller_spec.rb index 7cb1b85a46d..4ae2b78e11c 100644 --- a/spec/controllers/import/gitorious_controller_spec.rb +++ b/spec/controllers/import/gitorious_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GitoriousController do include ImportSpecHelper diff --git a/spec/controllers/import/google_code_controller_spec.rb b/spec/controllers/import/google_code_controller_spec.rb index 66088139a69..4241db6e771 100644 --- a/spec/controllers/import/google_code_controller_spec.rb +++ b/spec/controllers/import/google_code_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require_relative 'import_spec_helper' describe Import::GoogleCodeController do include ImportSpecHelper diff --git a/spec/controllers/oauth/applications_controller_spec.rb b/spec/controllers/oauth/applications_controller_spec.rb new file mode 100644 index 00000000000..af378304893 --- /dev/null +++ b/spec/controllers/oauth/applications_controller_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe Oauth::ApplicationsController do + let(:user) { create(:user) } + + context 'project members' do + before do + sign_in(user) + end + + describe 'GET #index' do + it 'shows list of applications' do + get :index + + expect(response.status).to eq(200) + end + + it 'redirects back to profile page if OAuth applications are disabled' do + settings = double(user_oauth_applications?: false) + allow_any_instance_of(Gitlab::CurrentSettings).to receive(:current_application_settings).and_return(settings) + + get :index + + expect(response.status).to eq(302) + expect(response).to redirect_to(profile_path) + end + end + end +end diff --git a/spec/factories/wiki_pages.rb b/spec/factories/wiki_pages.rb index 938ccf2306b..efa6cbe5bb1 100644 --- a/spec/factories/wiki_pages.rb +++ b/spec/factories/wiki_pages.rb @@ -2,7 +2,7 @@ require 'ostruct' FactoryGirl.define do factory :wiki_page do - page = OpenStruct.new(url_path: 'some-name') + page { OpenStruct.new(url_path: 'some-name') } association :wiki, factory: :project_wiki, strategy: :build initialize_with { new(wiki, page, true) } end diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb new file mode 100644 index 00000000000..365cb445df1 --- /dev/null +++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +feature 'Tooltips on .timeago dates', feature: true, js: true do + include WaitForAjax + + let(:user) { create(:user) } + let(:project) { create(:project, name: 'test', namespace: user.namespace) } + let(:created_date) { Date.yesterday.to_time } + let(:expected_format) { created_date.strftime('%b %-d, %Y %l:%M%P UTC') } + + context 'on the activity tab' do + before do + project.team << [user, :master] + + Event.create( project: project, author_id: user.id, action: Event::JOINED, + updated_at: created_date, created_at: created_date) + + login_as user + visit user_path(user) + wait_for_ajax() + + page.find('.js-timeago').hover + end + + it 'has the datetime formated correctly' do + expect(page).to have_selector('.local-timeago', text: expected_format) + end + end + + context 'on the snippets tab' do + before do + project.team << [user, :master] + create(:snippet, author: user, updated_at: created_date, created_at: created_date) + + login_as user + visit user_snippets_path(user) + wait_for_ajax() + + page.find('.js-timeago').hover + end + + it 'has the datetime formated correctly' do + expect(page).to have_selector('.local-timeago', text: expected_format) + end + end +end diff --git a/spec/features/issues/filter_by_labels_spec.rb b/spec/features/issues/filter_by_labels_spec.rb index 7f654684143..0ec8b6b180a 100644 --- a/spec/features/issues/filter_by_labels_spec.rb +++ b/spec/features/issues/filter_by_labels_spec.rb @@ -54,6 +54,11 @@ feature 'Issue filtering by Labels', feature: true do expect(find('.filtered-labels')).not_to have_content "feature" expect(find('.filtered-labels')).not_to have_content "enhancement" end + + it 'should remove label "bug"' do + first('.js-label-filter-remove').click + expect(find('.filtered-labels')).to have_no_content "bug" + end end context 'filter by label feature', js: true do @@ -135,6 +140,11 @@ feature 'Issue filtering by Labels', feature: true do it 'should not show label "bug" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "bug" end + + it 'should remove label "enhancement"' do + first('.js-label-filter-remove').click + expect(find('.filtered-labels')).to have_no_content "enhancement" + end end context 'filter by label enhancement and bug in issues list', js: true do @@ -164,4 +174,29 @@ feature 'Issue filtering by Labels', feature: true do expect(find('.filtered-labels')).not_to have_content "feature" end end + + context 'remove filtered labels', js: true do + before do + page.within '.labels-filter' do + click_button 'Label' + click_link 'bug' + find('.dropdown-menu-close').click + end + + page.within '.filtered-labels' do + expect(page).to have_content 'bug' + end + end + + it 'should allow user to remove filtered labels' do + page.within '.filtered-labels' do + first('.js-label-filter-remove').click + expect(page).not_to have_content 'bug' + end + + page.within '.labels-filter' do + expect(page).not_to have_content 'bug' + end + end + end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 460d7f82b36..f6fb6a72d22 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -75,12 +75,13 @@ describe 'Issues', feature: true do fill_in 'issue_title', with: 'bug 345' fill_in 'issue_description', with: 'bug description' + find('#issuable-due-date').click - page.within '.datepicker' do + page.within '.ui-datepicker' do click_link date.day end - expect(find('#issuable-due-date', visible: false).value).to eq date.to_s + expect(find('#issuable-due-date').value).to eq date.to_s click_button 'Submit issue' @@ -100,18 +101,19 @@ describe 'Issues', feature: true do it 'should save with due date' do date = Date.today.at_beginning_of_month - expect(find('#issuable-due-date', visible: false).value).to eq date.to_s + expect(find('#issuable-due-date').value).to eq date.to_s date = date.tomorrow fill_in 'issue_title', with: 'bug 345' fill_in 'issue_description', with: 'bug description' + find('#issuable-due-date').click - page.within '.datepicker' do + page.within '.ui-datepicker' do click_link date.day end - expect(find('#issuable-due-date', visible: false).value).to eq date.to_s + expect(find('#issuable-due-date').value).to eq date.to_s click_button 'Save changes' diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 1d892fe1a55..09ccc77c101 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -165,22 +165,32 @@ describe 'GitLab Markdown', feature: true do describe 'ExternalLinkFilter' do it 'adds nofollow to external link' do link = doc.at_css('a:contains("Google")') + expect(link.attr('rel')).to include('nofollow') end it 'adds noreferrer to external link' do link = doc.at_css('a:contains("Google")') + expect(link.attr('rel')).to include('noreferrer') end + it 'adds _blank to target attribute for external links' do + link = doc.at_css('a:contains("Google")') + + expect(link.attr('target')).to match('_blank') + end + it 'ignores internal link' do link = doc.at_css('a:contains("GitLab Root")') + expect(link.attr('rel')).not_to match 'nofollow' + expect(link.attr('target')).not_to match '_blank' end end end - before(:all) do + before do @feat = MarkdownFeature.new # `markdown` helper expects a `@project` variable @@ -188,7 +198,7 @@ describe 'GitLab Markdown', feature: true do end context 'default pipeline' do - before(:all) do + before do @html = markdown(@feat.raw_markdown) end @@ -231,13 +241,14 @@ describe 'GitLab Markdown', feature: true do context 'wiki pipeline' do before do @project_wiki = @feat.project_wiki + @project_wiki_page = @feat.project_wiki_page 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 }) + @html = markdown(@feat.raw_markdown, { pipeline: :wiki, project_wiki: @project_wiki, page_slug: @project_wiki_page.slug }) end it_behaves_like 'all pipelines' diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb index 34ce7c4f033..c75d28d9801 100644 --- a/spec/fixtures/markdown.md.erb +++ b/spec/fixtures/markdown.md.erb @@ -136,7 +136,7 @@ But it shouldn't autolink text inside certain tags: ### ExternalLinkFilter -External links get a `rel="nofollow"` attribute: +External links get a `rel="nofollow noreferrer"` and `target="_blank"` attributes: - [Google](https://google.com/) - [GitLab Root](<%= Gitlab.config.gitlab.url %>) diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 13de88e2f21..ade5c3b02d9 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -121,13 +121,14 @@ describe GitlabMarkdownHelper do before do @wiki = double('WikiPage') allow(@wiki).to receive(:content).and_return('wiki content') + allow(@wiki).to receive(:slug).and_return('nested/page') helper.instance_variable_set(:@project_wiki, @wiki) end it "should use Wiki pipeline for markdown files" do allow(@wiki).to receive(:format).and_return(:markdown) - expect(helper).to receive(:markdown).with('wiki content', pipeline: :wiki, project_wiki: @wiki) + expect(helper).to receive(:markdown).with('wiki content', pipeline: :wiki, project_wiki: @wiki, page_slug: "nested/page") helper.render_wiki_content(@wiki) end diff --git a/spec/javascripts/awards_handler_spec.js.coffee b/spec/javascripts/awards_handler_spec.js.coffee index 0bd6d696387..ba191199dc7 100644 --- a/spec/javascripts/awards_handler_spec.js.coffee +++ b/spec/javascripts/awards_handler_spec.js.coffee @@ -3,10 +3,11 @@ #= require jquery.cookie #= require ./fixtures/emoji_menu -awardsHandler = null -window.gl or= {} -gl.emojiAliases = -> return { '+1': 'thumbsup', '-1': 'thumbsdown' } -gl.awardMenuUrl = '/emojis' +awardsHandler = null +window.gl or= {} +window.gon or= {} +gl.emojiAliases = -> return { '+1': 'thumbsup', '-1': 'thumbsdown' } +gon.award_menu_url = '/emojis' lazyAssert = (done, assertFn) -> @@ -25,9 +26,7 @@ describe 'AwardsHandler', -> fixture.load 'awards_handler.html' awardsHandler = new AwardsHandler spyOn(awardsHandler, 'postEmoji').and.callFake (url, emoji, cb) => cb() - spyOn(jQuery, 'get').and.callFake (req, cb) -> - expect(req).toBe '/emojis' - cb window.emojiMenu + spyOn(jQuery, 'get').and.callFake (req, cb) -> cb window.emojiMenu describe '::showEmojiMenu', -> diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb deleted file mode 100644 index 185abbb2108..00000000000 --- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'spec_helper' - -describe Banzai::Filter::WikiLinkFilter, lib: true do - include FilterSpecHelper - - let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") } - let(:project) { build_stubbed(:empty_project, :public, name: "wiki_link_project", namespace: namespace) } - let(:user) { double } - let(:project_wiki) { ProjectWiki.new(project, user) } - - describe "links within the wiki (relative)" do - describe "hierarchical links to the current directory" do - it "doesn't rewrite non-file links" do - link = "<a href='./page'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('./page') - end - - it "doesn't rewrite file links" do - link = "<a href='./page.md'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('./page.md') - end - end - - describe "hierarchical links to the parent directory" do - it "doesn't rewrite non-file links" do - link = "<a href='../page'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('../page') - end - - it "doesn't rewrite file links" do - link = "<a href='../page.md'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('../page.md') - end - end - - describe "hierarchical links to a sub-directory" do - it "doesn't rewrite non-file links" do - link = "<a href='./subdirectory/page'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('./subdirectory/page') - end - - it "doesn't rewrite file links" do - link = "<a href='./subdirectory/page.md'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('./subdirectory/page.md') - end - end - - describe "non-hierarchical links" do - it 'rewrites non-file links to be at the scope of the wiki root' do - link = "<a href='page'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to match('/wiki_link_ns/wiki_link_project/wikis/page') - end - - it "doesn't rewrite file links" do - link = "<a href='page.md'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('page.md') - end - end - end - - describe "links outside the wiki (absolute)" do - it "doesn't rewrite links" do - link = "<a href='http://example.com/page'>Link to Page</a>" - filtered_link = filter(link, project_wiki: project_wiki).children[0] - - expect(filtered_link.attribute('href').value).to eq('http://example.com/page') - end - end -end diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb index 7aa1b4a3bf6..ea4ab2c852e 100644 --- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb @@ -50,4 +50,112 @@ describe Banzai::Pipeline::WikiPipeline do end end end + + describe "Links" do + let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") } + let(:project) { build_stubbed(:empty_project, :public, name: "wiki_link_project", namespace: namespace) } + let(:project_wiki) { ProjectWiki.new(project, double(:user)) } + let(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) } + + { "when GitLab is hosted at a root URL" => '/', + "when GitLab is hosted at a relative URL" => '/nested/relative/gitlab' }.each do |test_name, relative_url_root| + + context test_name do + before do + allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return(relative_url_root) + end + + describe "linking to pages within the wiki" do + context "when creating hierarchical links to the current directory" do + it "rewrites non-file links to be at the scope of the current directory" do + markdown = "[Page](./page)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page\"") + end + + it "rewrites file links to be at the scope of the current directory" do + markdown = "[Link to Page](./page.md)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"") + end + end + + context "when creating hierarchical links to the parent directory" do + it "rewrites non-file links to be at the scope of the parent directory" do + markdown = "[Link to Page](../page)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page\"") + end + + it "rewrites file links to be at the scope of the parent directory" do + markdown = "[Link to Page](../page.md)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page.md\"") + end + end + + context "when creating hierarchical links to a sub-directory" do + it "rewrites non-file links to be at the scope of the sub-directory" do + markdown = "[Link to Page](./subdirectory/page)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page\"") + end + + it "rewrites file links to be at the scope of the sub-directory" do + markdown = "[Link to Page](./subdirectory/page.md)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page.md\"") + end + end + + describe "when creating non-hierarchical links" do + it 'rewrites non-file links to be at the scope of the wiki root' do + markdown = "[Link to Page](page)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"") + end + + it "rewrites file links to be at the scope of the current directory" do + markdown = "[Link to Page](page.md)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"") + end + end + + describe "when creating root links" do + it 'rewrites non-file links to be at the scope of the wiki root' do + markdown = "[Link to Page](/page)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"") + end + + it 'rewrites file links to be at the scope of the wiki root' do + markdown = "[Link to Page](/page.md)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page.md\"") + end + end + end + + describe "linking to pages outside the wiki (absolute)" do + it "doesn't rewrite links" do + markdown = "[Link to Page](http://example.com/page)" + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include('href="http://example.com/page"') + end + end + end + end + end end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index aad291c03cd..a814ad2a4e7 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -1,9 +1,47 @@ require 'spec_helper' describe Gitlab::Auth, lib: true do - let(:gl_auth) { Gitlab::Auth.new } + let(:gl_auth) { described_class } - describe :find do + describe 'find' do + it 'recognizes CI' do + token = '123' + project = create(:empty_project) + project.update_attributes(runners_token: token, builds_enabled: true) + ip = 'ip' + + expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: 'gitlab-ci-token') + expect(gl_auth.find('gitlab-ci-token', token, project: project, ip: ip)).to eq(Gitlab::Auth::Result.new(nil, :ci)) + end + + it 'recognizes master passwords' do + user = create(:user, password: 'password') + ip = 'ip' + + expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: user.username) + expect(gl_auth.find(user.username, 'password', project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :gitlab_or_ldap)) + end + + it 'recognizes OAuth tokens' do + user = create(:user) + application = Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) + token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id) + ip = 'ip' + + expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: 'oauth2') + expect(gl_auth.find("oauth2", token.token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :oauth)) + end + + it 'returns double nil for invalid credentials' do + login = 'foo' + ip = 'ip' + + expect(gl_auth).to receive(:rate_limit!).with(ip, success: false, login: login) + expect(gl_auth.find(login, 'bar', project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new) + end + end + + describe 'find_in_gitlab_or_ldap' do let!(:user) do create(:user, username: username, @@ -14,25 +52,25 @@ describe Gitlab::Auth, lib: true do let(:password) { 'my-secret' } it "should find user by valid login/password" do - expect( gl_auth.find(username, password) ).to eql user + expect( gl_auth.find_in_gitlab_or_ldap(username, password) ).to eql user end it 'should find user by valid email/password with case-insensitive email' do - expect(gl_auth.find(user.email.upcase, password)).to eql user + expect(gl_auth.find_in_gitlab_or_ldap(user.email.upcase, password)).to eql user end it 'should find user by valid username/password with case-insensitive username' do - expect(gl_auth.find(username.upcase, password)).to eql user + expect(gl_auth.find_in_gitlab_or_ldap(username.upcase, password)).to eql user end it "should not find user with invalid password" do password = 'wrong' - expect( gl_auth.find(username, password) ).not_to eql user + expect( gl_auth.find_in_gitlab_or_ldap(username, password) ).not_to eql user end it "should not find user with invalid login" do user = 'wrong' - expect( gl_auth.find(username, password) ).not_to eql user + expect( gl_auth.find_in_gitlab_or_ldap(username, password) ).not_to eql user end context "with ldap enabled" do @@ -43,13 +81,13 @@ describe Gitlab::Auth, lib: true do it "tries to autheticate with db before ldap" do expect(Gitlab::LDAP::Authentication).not_to receive(:login) - gl_auth.find(username, password) + gl_auth.find_in_gitlab_or_ldap(username, password) end it "uses ldap as fallback to for authentication" do expect(Gitlab::LDAP::Authentication).to receive(:login) - gl_auth.find('ldap_user', 'password') + gl_auth.find_in_gitlab_or_ldap('ldap_user', 'password') end end end diff --git a/spec/lib/gitlab/backend/grack_auth_spec.rb b/spec/lib/gitlab/backend/grack_auth_spec.rb deleted file mode 100644 index cd26dca0998..00000000000 --- a/spec/lib/gitlab/backend/grack_auth_spec.rb +++ /dev/null @@ -1,209 +0,0 @@ -require "spec_helper" - -describe Grack::Auth, lib: true do - let(:user) { create(:user) } - let(:project) { create(:project) } - - let(:app) { lambda { |env| [200, {}, "Success!"] } } - let!(:auth) { Grack::Auth.new(app) } - let(:env) do - { - 'rack.input' => '', - 'REQUEST_METHOD' => 'GET', - 'QUERY_STRING' => 'service=git-upload-pack' - } - end - let(:status) { auth.call(env).first } - - describe "#call" do - context "when the project doesn't exist" do - before do - env["PATH_INFO"] = "doesnt/exist.git" - end - - context "when no authentication is provided" do - it "responds with status 401" do - expect(status).to eq(401) - end - end - - context "when username and password are provided" do - context "when authentication fails" do - before do - env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope") - end - - it "responds with status 401" do - expect(status).to eq(401) - end - end - - context "when authentication succeeds" do - before do - env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) - end - - it "responds with status 404" do - expect(status).to eq(404) - end - end - end - end - - context "when the Wiki for a project exists" do - before do - @wiki = ProjectWiki.new(project) - env["PATH_INFO"] = "#{@wiki.repository.path_with_namespace}.git/info/refs" - project.update_attribute(:visibility_level, Project::PUBLIC) - end - - it "responds with the right project" do - response = auth.call(env) - json_body = ActiveSupport::JSON.decode(response[2][0]) - - expect(response.first).to eq(200) - expect(json_body['RepoPath']).to include(@wiki.repository.path_with_namespace) - end - end - - context "when the project exists" do - before do - env["PATH_INFO"] = project.path_with_namespace + ".git" - end - - context "when the project is public" do - before do - project.update_attribute(:visibility_level, Project::PUBLIC) - end - - it "responds with status 200" do - expect(status).to eq(200) - end - end - - context "when the project is private" do - before do - project.update_attribute(:visibility_level, Project::PRIVATE) - end - - context "when no authentication is provided" do - it "responds with status 401" do - expect(status).to eq(401) - end - end - - context "when username and password are provided" do - context "when authentication fails" do - before do - env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope") - end - - it "responds with status 401" do - expect(status).to eq(401) - end - - context "when the user is IP banned" do - before do - expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true) - allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4') - end - - it "responds with status 401" do - expect(status).to eq(401) - end - end - end - - context "when authentication succeeds" do - before do - env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) - end - - context "when the user has access to the project" do - before do - project.team << [user, :master] - end - - context "when the user is blocked" do - before do - user.block - project.team << [user, :master] - end - - it "responds with status 404" do - expect(status).to eq(404) - end - end - - context "when the user isn't blocked" do - before do - expect(Rack::Attack::Allow2Ban).to receive(:reset) - end - - it "responds with status 200" do - expect(status).to eq(200) - end - end - - context "when blank password attempts follow a valid login" do - let(:options) { Gitlab.config.rack_attack.git_basic_auth } - let(:maxretry) { options[:maxretry] - 1 } - let(:ip) { '1.2.3.4' } - - before do - allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip) - Rack::Attack::Allow2Ban.reset(ip, options) - end - - after do - Rack::Attack::Allow2Ban.reset(ip, options) - end - - def attempt_login(include_password) - password = include_password ? user.password : "" - env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, password) - Grack::Auth.new(app) - auth.call(env).first - end - - it "repeated attempts followed by successful attempt" do - maxretry.times.each do - expect(attempt_login(false)).to eq(401) - end - - expect(attempt_login(true)).to eq(200) - expect(Rack::Attack::Allow2Ban.banned?(ip)).to be_falsey - - maxretry.times.each do - expect(attempt_login(false)).to eq(401) - end - end - end - end - - context "when the user doesn't have access to the project" do - it "responds with status 404" do - expect(status).to eq(404) - end - end - end - end - - context "when a gitlab ci token is provided" do - let(:token) { "123" } - let(:project) { FactoryGirl.create :empty_project } - - before do - project.update_attributes(runners_token: token, builds_enabled: true) - - env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials("gitlab-ci-token", token) - end - - it "responds with status 200" do - expect(status).to eq(200) - end - end - end - end - end -end diff --git a/spec/lib/gitlab/bitbucket_import/client_spec.rb b/spec/lib/gitlab/bitbucket_import/client_spec.rb index 7718689e6d4..760d66a1488 100644 --- a/spec/lib/gitlab/bitbucket_import/client_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/client_spec.rb @@ -1,12 +1,14 @@ require 'spec_helper' describe Gitlab::BitbucketImport::Client, lib: true do + include ImportSpecHelper + let(:token) { '123456' } let(:secret) { 'secret' } let(:client) { Gitlab::BitbucketImport::Client.new(token, secret) } before do - Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket") + stub_omniauth_provider('bitbucket') end it 'all OAuth client options are symbols' do diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb index 1a833f255a5..aa00f32becb 100644 --- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' describe Gitlab::BitbucketImport::Importer, lib: true do + include ImportSpecHelper + before do - Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket") + stub_omniauth_provider('bitbucket') end let(:statuses) do diff --git a/spec/lib/gitlab/gitlab_import/client_spec.rb b/spec/lib/gitlab/gitlab_import/client_spec.rb index e6831e7c383..cd8e805466a 100644 --- a/spec/lib/gitlab/gitlab_import/client_spec.rb +++ b/spec/lib/gitlab/gitlab_import/client_spec.rb @@ -1,11 +1,13 @@ require 'spec_helper' describe Gitlab::GitlabImport::Client, lib: true do + include ImportSpecHelper + let(:token) { '123456' } let(:client) { Gitlab::GitlabImport::Client.new(token) } before do - Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "gitlab") + stub_omniauth_provider('gitlab') end it 'all OAuth2 client options are symbols' do diff --git a/spec/lib/gitlab/saml/user_spec.rb b/spec/lib/gitlab/saml/user_spec.rb index c2a51d9249c..84c21ceefd9 100644 --- a/spec/lib/gitlab/saml/user_spec.rb +++ b/spec/lib/gitlab/saml/user_spec.rb @@ -145,6 +145,7 @@ describe Gitlab::Saml::User, lib: true do 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) + allow(Gitlab::LDAP::Person).to receive(:find_by_dn).and_return(ldap_user) end context 'and no account for the LDAP user' do @@ -177,6 +178,23 @@ describe Gitlab::Saml::User, lib: true do ]) end end + + context 'user has SAML user, and wants to add their LDAP identity' do + it 'adds the LDAP identity to the existing SAML user' do + create(:omniauth_user, email: 'john@mail.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'saml', username: 'john') + local_hash = OmniAuth::AuthHash.new(uid: 'uid=user1,ou=People,dc=example', provider: provider, info: info_hash) + local_saml_user = described_class.new(local_hash) + local_saml_user.save + local_gl_user = local_saml_user.gl_user + + expect(local_gl_user).to be_valid + expect(local_gl_user.identities.length).to eql 2 + identities_as_hash = local_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' }, + { provider: 'saml', extern_uid: 'uid=user1,ou=People,dc=example' } + ]) + end + end end end end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index dd03d64f750..efbcbf72f76 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -10,6 +10,16 @@ describe Issue, "Issuable" do it { is_expected.to belong_to(:assignee) } it { is_expected.to have_many(:notes).dependent(:destroy) } it { is_expected.to have_many(:todos).dependent(:destroy) } + + context 'Notes' do + let!(:note) { create(:note, noteable: issue, project: issue.project) } + let(:scoped_issue) { Issue.includes(notes: :author).find(issue.id) } + + it 'indicates if the notes have their authors loaded' do + expect(issue.notes).not_to be_authors_loaded + expect(scoped_issue.notes).to be_authors_loaded + end + end end describe 'Included modules' do @@ -245,6 +255,22 @@ describe Issue, "Issuable" do end end + describe '#user_notes_count' do + let(:project) { create(:project) } + let(:issue1) { create(:issue, project: project) } + let(:issue2) { create(:issue, project: project) } + + before do + create_list(:note, 3, noteable: issue1, project: project) + create_list(:note, 6, noteable: issue2, project: project) + end + + it 'counts the user notes' do + expect(issue1.user_notes_count).to be(3) + expect(issue2.user_notes_count).to be(6) + end + end + describe "votes" do let(:project) { issue.project } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6ea8bf9bbe1..73bee535fe3 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -68,7 +68,10 @@ describe User, models: true do describe 'email' do context 'when no signup domains listed' do - before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return([]) } + before do + allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return([]) + end + it 'accepts any email' do user = build(:user, email: "info@example.com") expect(user).to be_valid @@ -76,7 +79,10 @@ describe User, models: true do end context 'when a signup domain is listed and subdomains are allowed' do - before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com', '*.example.com']) } + before do + allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com', '*.example.com']) + end + it 'accepts info@example.com' do user = build(:user, email: "info@example.com") expect(user).to be_valid @@ -94,7 +100,9 @@ describe User, models: true do end context 'when a signup domain is listed and subdomains are not allowed' do - before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com']) } + before do + allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com']) + end it 'accepts info@example.com' do user = build(:user, email: "info@example.com") @@ -202,7 +210,10 @@ describe User, models: true do end describe '#confirm' do - before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) } + before do + allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) + end + let(:user) { create(:user, confirmed_at: nil, unconfirmed_email: 'test@gitlab.com') } it 'returns unconfirmed' do @@ -845,6 +856,75 @@ describe User, models: true do it { is_expected.to eq([private_project]) } end + describe '#ci_authorized_runners' do + let(:user) { create(:user) } + let(:runner) { create(:ci_runner) } + + before do + project.runners << runner + end + + context 'without any projects' do + let(:project) { create(:project) } + + it 'does not load' do + expect(user.ci_authorized_runners).to be_empty + end + end + + context 'with personal projects runners' do + let(:namespace) { create(:namespace, owner: user) } + let(:project) { create(:project, namespace: namespace) } + + it 'loads' do + expect(user.ci_authorized_runners).to contain_exactly(runner) + end + end + + shared_examples :member do + context 'when the user is a master' do + before do + add_user(Gitlab::Access::MASTER) + end + + it 'loads' do + expect(user.ci_authorized_runners).to contain_exactly(runner) + end + end + + context 'when the user is a developer' do + before do + add_user(Gitlab::Access::DEVELOPER) + end + + it 'does not load' do + expect(user.ci_authorized_runners).to be_empty + end + end + end + + context 'with groups projects runners' do + let(:group) { create(:group) } + let(:project) { create(:project, group: group) } + + def add_user(access) + group.add_user(user, access) + end + + it_behaves_like :member + end + + context 'with other projects runners' do + let(:project) { create(:project) } + + def add_user(access) + project.team << [user, access] + end + + it_behaves_like :member + end + end + describe '#viewable_starred_projects' do let(:user) { create(:user) } let(:public_project) { create(:empty_project, :public) } diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb new file mode 100644 index 00000000000..c44a4a7a1fc --- /dev/null +++ b/spec/requests/git_http_spec.rb @@ -0,0 +1,395 @@ +require "spec_helper" + +describe 'Git HTTP requests', lib: true do + let(:user) { create(:user) } + let(:project) { create(:project, path: 'project.git-project') } + + it "gives WWW-Authenticate hints" do + clone_get('doesnt/exist.git') + + expect(response.header['WWW-Authenticate']).to start_with('Basic ') + end + + context "when the project doesn't exist" do + context "when no authentication is provided" do + it "responds with status 401 (no project existence information leak)" do + download('doesnt/exist.git') do |response| + expect(response.status).to eq(401) + end + end + end + + context "when username and password are provided" do + context "when authentication fails" do + it "responds with status 401" do + download('doesnt/exist.git', user: user.username, password: "nope") do |response| + expect(response.status).to eq(401) + end + end + end + + context "when authentication succeeds" do + it "responds with status 404" do + download('/doesnt/exist.git', user: user.username, password: user.password) do |response| + expect(response.status).to eq(404) + end + end + end + end + end + + context "when the Wiki for a project exists" do + it "responds with the right project" do + wiki = ProjectWiki.new(project) + project.update_attribute(:visibility_level, Project::PUBLIC) + + download("/#{wiki.repository.path_with_namespace}.git") do |response| + json_body = ActiveSupport::JSON.decode(response.body) + + expect(response.status).to eq(200) + expect(json_body['RepoPath']).to include(wiki.repository.path_with_namespace) + end + end + end + + context "when the project exists" do + let(:path) { "#{project.path_with_namespace}.git" } + + context "when the project is public" do + before do + project.update_attribute(:visibility_level, Project::PUBLIC) + end + + it "downloads get status 200" do + download(path, {}) do |response| + expect(response.status).to eq(200) + end + end + + it "uploads get status 401" do + upload(path, {}) do |response| + expect(response.status).to eq(401) + end + end + + context "with correct credentials" do + let(:env) { { user: user.username, password: user.password } } + + it "uploads get status 200 (because Git hooks do the real check)" do + upload(path, env) do |response| + expect(response.status).to eq(200) + end + end + + context 'but git-receive-pack is disabled' do + it "responds with status 404" do + allow(Gitlab.config.gitlab_shell).to receive(:receive_pack).and_return(false) + + upload(path, env) do |response| + expect(response.status).to eq(404) + end + end + end + end + + context 'but git-upload-pack is disabled' do + it "responds with status 404" do + allow(Gitlab.config.gitlab_shell).to receive(:upload_pack).and_return(false) + + download(path, {}) do |response| + expect(response.status).to eq(404) + end + end + end + end + + context "when the project is private" do + before do + project.update_attribute(:visibility_level, Project::PRIVATE) + end + + context "when no authentication is provided" do + it "responds with status 401 to downloads" do + download(path, {}) do |response| + expect(response.status).to eq(401) + end + end + + it "responds with status 401 to uploads" do + upload(path, {}) do |response| + expect(response.status).to eq(401) + end + end + end + + context "when username and password are provided" do + let(:env) { { user: user.username, password: 'nope' } } + + context "when authentication fails" do + it "responds with status 401" do + download(path, env) do |response| + expect(response.status).to eq(401) + end + end + + context "when the user is IP banned" do + it "responds with status 401" do + expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true) + allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4') + + clone_get(path, env) + + expect(response.status).to eq(401) + end + end + end + + context "when authentication succeeds" do + let(:env) { { user: user.username, password: user.password } } + + context "when the user has access to the project" do + before do + project.team << [user, :master] + end + + context "when the user is blocked" do + it "responds with status 404" do + user.block + project.team << [user, :master] + + download(path, env) do |response| + expect(response.status).to eq(404) + end + end + end + + context "when the user isn't blocked" do + it "downloads get status 200" do + expect(Rack::Attack::Allow2Ban).to receive(:reset) + + clone_get(path, env) + + expect(response.status).to eq(200) + end + + it "uploads get status 200" do + upload(path, env) do |response| + expect(response.status).to eq(200) + end + end + end + + context "when an oauth token is provided" do + before do + application = Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) + @token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id) + end + + it "downloads get status 200" do + clone_get "#{project.path_with_namespace}.git", user: 'oauth2', password: @token.token + + expect(response.status).to eq(200) + end + + it "uploads get status 401 (no project existence information leak)" do + push_get "#{project.path_with_namespace}.git", user: 'oauth2', password: @token.token + + expect(response.status).to eq(401) + end + end + + context "when blank password attempts follow a valid login" do + def attempt_login(include_password) + password = include_password ? user.password : "" + clone_get path, user: user.username, password: password + response.status + end + + it "repeated attempts followed by successful attempt" do + options = Gitlab.config.rack_attack.git_basic_auth + maxretry = options[:maxretry] - 1 + ip = '1.2.3.4' + + allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip) + Rack::Attack::Allow2Ban.reset(ip, options) + + maxretry.times.each do + expect(attempt_login(false)).to eq(401) + end + + expect(attempt_login(true)).to eq(200) + expect(Rack::Attack::Allow2Ban.banned?(ip)).to be_falsey + + maxretry.times.each do + expect(attempt_login(false)).to eq(401) + end + + Rack::Attack::Allow2Ban.reset(ip, options) + end + end + end + + context "when the user doesn't have access to the project" do + it "downloads get status 404" do + download(path, user: user.username, password: user.password) do |response| + expect(response.status).to eq(404) + end + end + + it "uploads get status 200 (because Git hooks do the real check)" do + upload(path, user: user.username, password: user.password) do |response| + expect(response.status).to eq(200) + end + end + end + end + end + + context "when a gitlab ci token is provided" do + let(:token) { 123 } + let(:project) { FactoryGirl.create :empty_project } + + before do + project.update_attributes(runners_token: token, builds_enabled: true) + end + + it "downloads get status 200" do + clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: token + + expect(response.status).to eq(200) + end + + it "uploads get status 401 (no project existence information leak)" do + push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: token + + expect(response.status).to eq(401) + end + end + end + end + + context "when the project path doesn't end in .git" do + context "GET info/refs" do + let(:path) { "/#{project.path_with_namespace}/info/refs" } + + context "when no params are added" do + before { get path } + + it "redirects to the .git suffix version" do + expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs") + end + end + + context "when the upload-pack service is requested" do + let(:params) { { service: 'git-upload-pack' } } + before { get path, params } + + it "redirects to the .git suffix version" do + expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + end + end + + context "when the receive-pack service is requested" do + let(:params) { { service: 'git-receive-pack' } } + before { get path, params } + + it "redirects to the .git suffix version" do + expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + end + end + + context "when the params are anything else" do + let(:params) { { service: 'git-implode-pack' } } + before { get path, params } + + it "redirects to the sign-in page" do + expect(response).to redirect_to(new_user_session_path) + end + end + end + + context "POST git-upload-pack" do + it "fails to find a route" do + expect { clone_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + end + end + + context "POST git-receive-pack" do + it "failes to find a route" do + expect { push_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + end + end + end + + context "retrieving an info/refs file" do + before { project.update_attribute(:visibility_level, Project::PUBLIC) } + + context "when the file exists" do + before do + # Provide a dummy file in its place + allow_any_instance_of(Repository).to receive(:blob_at).and_call_original + allow_any_instance_of(Repository).to receive(:blob_at).with('5937ac0a7beb003549fc5fd26fc247adbce4a52e', 'info/refs') do + Gitlab::Git::Blob.find(project.repository, 'master', '.gitignore') + end + + get "/#{project.path_with_namespace}/blob/master/info/refs" + end + + it "returns the file" do + expect(response.status).to eq(200) + end + end + + context "when the file exists" do + before { get "/#{project.path_with_namespace}/blob/master/info/refs" } + + it "returns not found" do + expect(response.status).to eq(404) + end + end + end + + def clone_get(project, options={}) + get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password)) + end + + def clone_post(project, options={}) + post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password)) + end + + def push_get(project, options={}) + get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password)) + end + + def push_post(project, options={}) + post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password)) + end + + def download(project, user: nil, password: nil) + args = [project, { user: user, password: password }] + + clone_get(*args) + yield response + + clone_post(*args) + yield response + end + + def upload(project, user: nil, password: nil) + args = [project, { user: user, password: password }] + + push_get(*args) + yield response + + push_post(*args) + yield response + end + + def auth_env(user, password) + if user && password + { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password) } + else + {} + end + end +end diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index d006ff195cf..c995993a853 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -44,7 +44,7 @@ describe JwtController do let(:user) { create(:user) } let(:headers) { { authorization: credentials('user', 'password') } } - before { expect_any_instance_of(Gitlab::Auth).to receive(:find).with('user', 'password').and_return(user) } + before { expect(Gitlab::Auth).to receive(:find_in_gitlab_or_ldap).with('user', 'password').and_return(user) } subject! { get '/jwt/auth', parameters, headers } diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb index 9d90bfceb73..068c9a1219c 100644 --- a/spec/services/projects/import_service_spec.rb +++ b/spec/services/projects/import_service_spec.rb @@ -124,7 +124,7 @@ describe Projects::ImportService, services: true do } ) - Gitlab.config.omniauth.providers << provider + allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider]) end end end diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb index 6e7ecbd39ba..489c920f19f 100644 --- a/spec/services/todo_service_spec.rb +++ b/spec/services/todo_service_spec.rb @@ -18,7 +18,7 @@ describe TodoService, services: true do end describe 'Issues' do - let(:issue) { create(:issue, project: project, assignee: john_doe, author: author, description: mentions) } + let(:issue) { create(:issue, project: project, assignee: john_doe, author: author, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") } let(:unassigned_issue) { create(:issue, project: project, assignee: nil) } let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee, description: mentions) } @@ -101,6 +101,19 @@ describe TodoService, services: true do should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) should_not_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED) end + + it 'does not create todo when when tasks are marked as completed' do + issue.update(description: "- [x] Task 1\n- [X] Task 2 #{mentions}") + + service.update_issue(issue, author) + + should_not_create_todo(user: admin, target: issue, action: Todo::MENTIONED) + should_not_create_todo(user: assignee, target: issue, action: Todo::MENTIONED) + should_not_create_todo(user: author, target: issue, action: Todo::MENTIONED) + should_not_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED) + should_not_create_todo(user: member, target: issue, action: Todo::MENTIONED) + should_not_create_todo(user: non_member, target: issue, action: Todo::MENTIONED) + end end describe '#close_issue' do @@ -210,7 +223,7 @@ describe TodoService, services: true do end describe 'Merge Requests' do - let(:mr_assigned) { create(:merge_request, source_project: project, author: author, assignee: john_doe, description: mentions) } + let(:mr_assigned) { create(:merge_request, source_project: project, author: author, assignee: john_doe, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") } let(:mr_unassigned) { create(:merge_request, source_project: project, author: author, assignee: nil) } describe '#new_merge_request' do @@ -253,6 +266,19 @@ describe TodoService, services: true do expect { service.update_merge_request(mr_assigned, author) }.not_to change(member.todos, :count) end + + it 'does not create todo when when tasks are marked as completed' do + mr_assigned.update(description: "- [x] Task 1\n- [X] Task 2 #{mentions}") + + service.update_merge_request(mr_assigned, author) + + should_not_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: assignee, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED) + end end describe '#close_merge_request' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a20f4c05971..b43f38ef202 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -15,9 +15,11 @@ require 'rspec/rails' require 'shoulda/matchers' require 'sidekiq/testing/inline' require 'rspec/retry' -require 'knapsack' -Knapsack::Adapters::RSpecAdapter.bind +if ENV['CI'] + require 'knapsack' + Knapsack::Adapters::RSpecAdapter.bind +end # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. diff --git a/spec/controllers/import/import_spec_helper.rb b/spec/support/import_spec_helper.rb index 9d7648e25a7..6710962f082 100644 --- a/spec/controllers/import/import_spec_helper.rb +++ b/spec/support/import_spec_helper.rb @@ -28,6 +28,6 @@ module ImportSpecHelper app_id: 'asd123', app_secret: 'asd123' ) - Gitlab.config.omniauth.providers << provider + allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider]) end end diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb index 7fc6d6fcc5e..a79386b5db9 100644 --- a/spec/support/markdown_feature.rb +++ b/spec/support/markdown_feature.rb @@ -32,6 +32,10 @@ class MarkdownFeature @project_wiki ||= ProjectWiki.new(project, user) end + def project_wiki_page + @project_wiki_page ||= build(:wiki_page, wiki: project_wiki) + end + def issue @issue ||= create(:issue, project: project) end |