summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/application_controller_spec.rb71
-rw-r--r--spec/factories/personal_access_tokens.rb9
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb94
-rw-r--r--spec/features/projects/files/project_owner_creates_license_file_spec.rb14
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb12
-rw-r--r--spec/features/projects/labels/update_prioritization_spec.rb1
-rw-r--r--spec/finders/notes_finder_spec.rb7
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb6
-rw-r--r--spec/javascripts/merge_request_spec.js.coffee2
-rw-r--r--spec/lib/banzai/filter/abstract_link_filter_spec.rb52
-rw-r--r--spec/lib/banzai/filter/external_link_filter_spec.rb34
-rw-r--r--spec/lib/banzai/filter/issue_reference_filter_spec.rb9
-rw-r--r--spec/lib/ci/gitlab_ci_yaml_processor_spec.rb115
-rw-r--r--spec/lib/gitlab/reference_extractor_spec.rb3
-rw-r--r--spec/mailers/previews/devise_mailer_preview.rb23
-rw-r--r--spec/models/ci/pipeline_spec.rb13
-rw-r--r--spec/models/jira_issue_spec.rb30
-rw-r--r--spec/models/personal_access_token_spec.rb15
-rw-r--r--spec/models/project_services/jira_service_spec.rb6
-rw-r--r--spec/models/project_spec.rb18
-rw-r--r--spec/requests/api/api_helpers_spec.rb76
-rw-r--r--spec/services/ci/create_builds_service_spec.rb6
-rw-r--r--spec/services/create_commit_builds_service_spec.rb23
-rw-r--r--spec/services/git_push_service_spec.rb3
-rw-r--r--spec/services/system_note_service_spec.rb2
-rw-r--r--spec/workers/expire_build_artifacts_worker_spec.rb12
26 files changed, 557 insertions, 99 deletions
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 186239d3096..ff5b3916273 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -30,4 +30,75 @@ describe ApplicationController do
controller.send(:check_password_expiration)
end
end
+
+ describe "#authenticate_user_from_token!" do
+ describe "authenticating a user from a private token" do
+ controller(ApplicationController) do
+ def index
+ render text: "authenticated"
+ end
+ end
+
+ let(:user) { create(:user) }
+
+ context "when the 'private_token' param is populated with the private token" do
+ it "logs the user in" do
+ get :index, private_token: user.private_token
+ expect(response.status).to eq(200)
+ expect(response.body).to eq("authenticated")
+ end
+ end
+
+
+ context "when the 'PRIVATE-TOKEN' header is populated with the private token" do
+ it "logs the user in" do
+ @request.headers['PRIVATE-TOKEN'] = user.private_token
+ get :index
+ expect(response.status).to eq(200)
+ expect(response.body).to eq("authenticated")
+ end
+ end
+
+ it "doesn't log the user in otherwise" do
+ @request.headers['PRIVATE-TOKEN'] = "token"
+ get :index, private_token: "token", authenticity_token: "token"
+ expect(response.status).not_to eq(200)
+ expect(response.body).not_to eq("authenticated")
+ end
+ end
+
+ describe "authenticating a user from a personal access token" do
+ controller(ApplicationController) do
+ def index
+ render text: 'authenticated'
+ end
+ end
+
+ let(:user) { create(:user) }
+ let(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ context "when the 'personal_access_token' param is populated with the personal access token" do
+ it "logs the user in" do
+ get :index, private_token: personal_access_token.token
+ expect(response.status).to eq(200)
+ expect(response.body).to eq('authenticated')
+ end
+ end
+
+ context "when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do
+ it "logs the user in" do
+ @request.headers["PRIVATE-TOKEN"] = personal_access_token.token
+ get :index
+ expect(response.status).to eq(200)
+ expect(response.body).to eq('authenticated')
+ end
+ end
+
+ it "doesn't log the user in otherwise" do
+ get :index, private_token: "token"
+ expect(response.status).not_to eq(200)
+ expect(response.body).not_to eq('authenticated')
+ end
+ end
+ end
end
diff --git a/spec/factories/personal_access_tokens.rb b/spec/factories/personal_access_tokens.rb
new file mode 100644
index 00000000000..da4c72bcb5b
--- /dev/null
+++ b/spec/factories/personal_access_tokens.rb
@@ -0,0 +1,9 @@
+FactoryGirl.define do
+ factory :personal_access_token do
+ user
+ token { SecureRandom.hex(50) }
+ name { FFaker::Product.brand }
+ revoked false
+ expires_at { 5.days.from_now }
+ end
+end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
new file mode 100644
index 00000000000..a85930c7543
--- /dev/null
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -0,0 +1,94 @@
+require 'spec_helper'
+
+describe 'Profile > Personal Access Tokens', feature: true, js: true do
+ let(:user) { create(:user) }
+
+ def active_personal_access_tokens
+ find(".table.active-personal-access-tokens")
+ end
+
+ def inactive_personal_access_tokens
+ find(".table.inactive-personal-access-tokens")
+ end
+
+ def created_personal_access_token
+ find("#created-personal-access-token").value
+ end
+
+ def disallow_personal_access_token_saves!
+ allow_any_instance_of(PersonalAccessToken).to receive(:save).and_return(false)
+ errors = ActiveModel::Errors.new(PersonalAccessToken.new).tap { |e| e.add(:name, "cannot be nil") }
+ allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors)
+ end
+
+ before do
+ login_as(user)
+ end
+
+ describe "token creation" do
+ it "allows creation of a token" do
+ visit profile_personal_access_tokens_path
+ fill_in "Name", with: FFaker::Product.brand
+
+ expect {click_on "Create Personal Access Token"}.to change { PersonalAccessToken.count }.by(1)
+ expect(created_personal_access_token).to eq(PersonalAccessToken.last.token)
+ expect(active_personal_access_tokens).to have_text(PersonalAccessToken.last.name)
+ expect(active_personal_access_tokens).to have_text("Never")
+ end
+
+ it "allows creation of a token with an expiry date" do
+ visit profile_personal_access_tokens_path
+ fill_in "Name", with: FFaker::Product.brand
+
+ # Set date to 1st of next month
+ find_field("Expires at").trigger('focus')
+ find("a[title='Next']").click
+ click_on "1"
+
+ expect {click_on "Create Personal Access Token"}.to change { PersonalAccessToken.count }.by(1)
+ expect(created_personal_access_token).to eq(PersonalAccessToken.last.token)
+ expect(active_personal_access_tokens).to have_text(PersonalAccessToken.last.name)
+ expect(active_personal_access_tokens).to have_text(Date.today.next_month.at_beginning_of_month.to_s(:medium))
+ end
+
+ context "when creation fails" do
+ it "displays an error message" do
+ disallow_personal_access_token_saves!
+ visit profile_personal_access_tokens_path
+ fill_in "Name", with: FFaker::Product.brand
+
+ expect { click_on "Create Personal Access Token" }.not_to change { PersonalAccessToken.count }
+ expect(page).to have_content("Name cannot be nil")
+ end
+ end
+ end
+
+ describe "inactive tokens" do
+ let!(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ it "allows revocation of an active token" do
+ visit profile_personal_access_tokens_path
+ click_on "Revoke"
+
+ expect(inactive_personal_access_tokens).to have_text(personal_access_token.name)
+ end
+
+ it "moves expired tokens to the 'inactive' section" do
+ personal_access_token.update(expires_at: 5.days.ago)
+ visit profile_personal_access_tokens_path
+
+ expect(inactive_personal_access_tokens).to have_text(personal_access_token.name)
+ end
+
+ context "when revocation fails" do
+ it "displays an error message" do
+ disallow_personal_access_token_saves!
+ visit profile_personal_access_tokens_path
+
+ expect { click_on "Revoke" }.not_to change { PersonalAccessToken.inactive.count }
+ expect(active_personal_access_tokens).to have_text(personal_access_token.name)
+ expect(page).to have_content("Could not revoke")
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
index ecc818eb1e1..e1e105e6bbe 100644
--- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb
+++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
feature 'project owner creates a license file', feature: true, js: true do
- include Select2Helper
+ include WaitForAjax
let(:project_master) { create(:user) }
let(:project) { create(:project) }
@@ -21,7 +21,7 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(page).to have_selector('.license-selector')
- select2('mit', from: '#license_type')
+ select_template('MIT License')
file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)')
@@ -44,7 +44,7 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(find('#file_name').value).to eq('LICENSE')
expect(page).to have_selector('.license-selector')
- select2('mit', from: '#license_type')
+ select_template('MIT License')
file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)')
@@ -58,4 +58,12 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(page).to have_content('The MIT License (MIT)')
expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
end
+
+ def select_template(template)
+ page.within('.js-license-selector-wrap') do
+ click_button 'Choose a License template'
+ click_link template
+ wait_for_ajax
+ end
+ end
end
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 34eda29c285..67aac25e427 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
feature 'project owner sees a link to create a license file in empty project', feature: true, js: true do
- include Select2Helper
+ include WaitForAjax
let(:project_master) { create(:user) }
let(:project) { create(:empty_project) }
@@ -20,7 +20,7 @@ feature 'project owner sees a link to create a license file in empty project', f
expect(find('#file_name').value).to eq('LICENSE')
expect(page).to have_selector('.license-selector')
- select2('mit', from: '#license_type')
+ select_template('MIT License')
file_content = find('.file-content')
expect(file_content).to have_content('The MIT License (MIT)')
@@ -36,4 +36,12 @@ feature 'project owner sees a link to create a license file in empty project', f
expect(page).to have_content('The MIT License (MIT)')
expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
end
+
+ def select_template(template)
+ page.within('.js-license-selector-wrap') do
+ click_button 'Choose a License template'
+ click_link template
+ wait_for_ajax
+ end
+ end
end
diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb
index 8550d279d09..6a39c302f55 100644
--- a/spec/features/projects/labels/update_prioritization_spec.rb
+++ b/spec/features/projects/labels/update_prioritization_spec.rb
@@ -77,6 +77,7 @@ feature 'Prioritize labels', feature: true do
end
visit current_url
+ wait_for_ajax
page.within('.prioritized-labels') do
expect(first('li')).to have_content('wontfix')
diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb
index 639b28d49ee..1bd354815e4 100644
--- a/spec/finders/notes_finder_spec.rb
+++ b/spec/finders/notes_finder_spec.rb
@@ -49,6 +49,13 @@ describe NotesFinder do
user = create(:user)
expect { NotesFinder.new.execute(project, user, params) }.to raise_error(ActiveRecord::RecordNotFound)
end
+
+ it 'raises an error for project members with guest role' do
+ user = create(:user)
+ project.team << [user, :guest]
+
+ expect { NotesFinder.new.execute(project, user, params) }.to raise_error(ActiveRecord::RecordNotFound)
+ end
end
end
end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index a3336c87173..903224589dd 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -33,9 +33,9 @@ describe MergeRequestsHelper do
let(:project) { create(:project) }
let(:issues) do
[
- JiraIssue.new('JIRA-123', project),
- JiraIssue.new('JIRA-456', project),
- JiraIssue.new('FOOBAR-7890', project)
+ ExternalIssue.new('JIRA-123', project),
+ ExternalIssue.new('JIRA-456', project),
+ ExternalIssue.new('FOOBAR-7890', project)
]
end
diff --git a/spec/javascripts/merge_request_spec.js.coffee b/spec/javascripts/merge_request_spec.js.coffee
index 22ebc7039d1..3cb67d51c85 100644
--- a/spec/javascripts/merge_request_spec.js.coffee
+++ b/spec/javascripts/merge_request_spec.js.coffee
@@ -6,7 +6,7 @@ describe 'MergeRequest', ->
beforeEach ->
fixture.load('merge_requests_show.html')
- @merge = new MergeRequest({})
+ @merge = new MergeRequest()
it 'modifies the Markdown field', ->
spyOn(jQuery, 'ajax').and.stub()
diff --git a/spec/lib/banzai/filter/abstract_link_filter_spec.rb b/spec/lib/banzai/filter/abstract_link_filter_spec.rb
new file mode 100644
index 00000000000..0c55d8e19da
--- /dev/null
+++ b/spec/lib/banzai/filter/abstract_link_filter_spec.rb
@@ -0,0 +1,52 @@
+require 'spec_helper'
+
+describe Banzai::Filter::AbstractReferenceFilter do
+ let(:project) { create(:empty_project) }
+
+ describe '#references_per_project' do
+ it 'returns a Hash containing references grouped per project paths' do
+ doc = Nokogiri::HTML.fragment("#1 #{project.to_reference}#2")
+ filter = described_class.new(doc, project: project)
+
+ expect(filter).to receive(:object_class).twice.and_return(Issue)
+ expect(filter).to receive(:object_sym).twice.and_return(:issue)
+
+ refs = filter.references_per_project
+
+ expect(refs).to be_an_instance_of(Hash)
+ expect(refs[project.to_reference]).to eq(Set.new(%w[1 2]))
+ end
+ end
+
+ describe '#projects_per_reference' do
+ it 'returns a Hash containing projects grouped per project paths' do
+ doc = Nokogiri::HTML.fragment('')
+ filter = described_class.new(doc, project: project)
+
+ expect(filter).to receive(:references_per_project).
+ and_return({ project.path_with_namespace => Set.new(%w[1]) })
+
+ expect(filter.projects_per_reference).
+ to eq({ project.path_with_namespace => project })
+ end
+ end
+
+ describe '#find_projects_for_paths' do
+ it 'returns a list of Projects for a list of paths' do
+ doc = Nokogiri::HTML.fragment('')
+ filter = described_class.new(doc, project: project)
+
+ expect(filter.find_projects_for_paths([project.path_with_namespace])).
+ to eq([project])
+ end
+ end
+
+ describe '#current_project_path' do
+ it 'returns the path of the current project' do
+ doc = Nokogiri::HTML.fragment('')
+ filter = described_class.new(doc, project: project)
+
+ expect(filter.current_project_path).to eq(project.path_with_namespace)
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb
index f4c5c621bd0..695a5bc6fd4 100644
--- a/spec/lib/banzai/filter/external_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_link_filter_spec.rb
@@ -19,19 +19,31 @@ describe Banzai::Filter::ExternalLinkFilter, lib: true do
expect(filter(act).to_html).to eq exp
end
- it 'adds rel="nofollow" to external links' do
- act = %q(<a href="https://google.com/">Google</a>)
- doc = filter(act)
-
- expect(doc.at_css('a')).to have_attribute('rel')
- expect(doc.at_css('a')['rel']).to include 'nofollow'
+ context 'for root links on document' do
+ let(:doc) { filter %q(<a href="https://google.com/">Google</a>) }
+
+ it 'adds rel="nofollow" to external links' do
+ expect(doc.at_css('a')).to have_attribute('rel')
+ expect(doc.at_css('a')['rel']).to include 'nofollow'
+ end
+
+ it 'adds rel="noreferrer" to external links' do
+ expect(doc.at_css('a')).to have_attribute('rel')
+ expect(doc.at_css('a')['rel']).to include 'noreferrer'
+ end
end
- it 'adds rel="noreferrer" to external links' do
- act = %q(<a href="https://google.com/">Google</a>)
- doc = filter(act)
+ context 'for nested links on document' do
+ let(:doc) { filter %q(<p><a href="https://google.com/">Google</a></p>) }
+
+ it 'adds rel="nofollow" to external links' do
+ expect(doc.at_css('a')).to have_attribute('rel')
+ expect(doc.at_css('a')['rel']).to include 'nofollow'
+ end
- expect(doc.at_css('a')).to have_attribute('rel')
- expect(doc.at_css('a')['rel']).to include 'noreferrer'
+ it 'adds rel="noreferrer" to external links' do
+ expect(doc.at_css('a')).to have_attribute('rel')
+ expect(doc.at_css('a')['rel']).to include 'noreferrer'
+ end
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 8e6a264970d..25f0bc2092f 100644
--- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
@@ -25,7 +25,9 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do
let(:reference) { issue.to_reference }
it 'ignores valid references when using non-default tracker' do
- expect(project).to receive(:get_issue).with(issue.iid).and_return(nil)
+ expect_any_instance_of(described_class).to receive(:find_object).
+ with(project, issue.iid).
+ and_return(nil)
exp = act = "Issue #{reference}"
expect(reference_filter(act).to_html).to eq exp
@@ -107,8 +109,9 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do
let(:reference) { issue.to_reference(project) }
it 'ignores valid references when cross-reference project uses external tracker' do
- expect_any_instance_of(Project).to receive(:get_issue).
- with(issue.iid).and_return(nil)
+ expect_any_instance_of(described_class).to receive(:find_object).
+ with(project2, issue.iid).
+ and_return(nil)
exp = act = "Issue #{reference}"
expect(reference_filter(act).to_html).to eq exp
diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
index 143e2e6d238..d562d8b25ea 100644
--- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
+++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
@@ -157,6 +157,35 @@ module Ci
expect(config_processor.builds_for_stage_and_ref("test", "deploy").size).to eq(1)
expect(config_processor.builds_for_stage_and_ref("deploy", "master").size).to eq(1)
end
+
+ context 'for invalid value' do
+ let(:config) { { rspec: { script: "rspec", type: "test", only: only } } }
+ let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
+
+ shared_examples 'raises an error' do
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'rspec job: only parameter should be an array of strings or regexps')
+ end
+ end
+
+ context 'when it is integer' do
+ let(:only) { 1 }
+
+ it_behaves_like 'raises an error'
+ end
+
+ context 'when it is an array of integers' do
+ let(:only) { [1, 1] }
+
+ it_behaves_like 'raises an error'
+ end
+
+ context 'when it is invalid regex' do
+ let(:only) { ["/*invalid/"] }
+
+ it_behaves_like 'raises an error'
+ end
+ end
end
describe :except do
@@ -284,16 +313,44 @@ module Ci
expect(config_processor.builds_for_stage_and_ref("test", "test").size).to eq(0)
expect(config_processor.builds_for_stage_and_ref("deploy", "master").size).to eq(0)
end
- end
+ context 'for invalid value' do
+ let(:config) { { rspec: { script: "rspec", except: except } } }
+ let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
+
+ shared_examples 'raises an error' do
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'rspec job: except parameter should be an array of strings or regexps')
+ end
+ end
+
+ context 'when it is integer' do
+ let(:except) { 1 }
+
+ it_behaves_like 'raises an error'
+ end
+
+ context 'when it is an array of integers' do
+ let(:except) { [1, 1] }
+
+ it_behaves_like 'raises an error'
+ end
+
+ context 'when it is invalid regex' do
+ let(:except) { ["/*invalid/"] }
+
+ it_behaves_like 'raises an error'
+ end
+ end
+ end
end
-
+
describe "Scripts handling" do
let(:config_data) { YAML.dump(config) }
let(:config_processor) { GitlabCiYamlProcessor.new(config_data, path) }
-
+
subject { config_processor.builds_for_stage_and_ref("test", "master").first }
-
+
describe "before_script" do
context "in global context" do
let(:config) do
@@ -302,12 +359,12 @@ module Ci
test: { script: ["script"] }
}
end
-
+
it "return commands with scripts concencaced" do
expect(subject[:commands]).to eq("global script\nscript")
end
end
-
+
context "overwritten in local context" do
let(:config) do
{
@@ -465,19 +522,41 @@ module Ci
end
context 'when syntax is incorrect' do
- it 'raises error' do
- variables = [:KEY1, 'value1', :KEY2, 'value2']
-
- config = YAML.dump(
- { before_script: ['pwd'],
- rspec: {
- variables: variables,
- script: 'rspec' }
- })
+ context 'when variables defined but invalid' do
+ it 'raises error' do
+ variables = [:KEY1, 'value1', :KEY2, 'value2']
+
+ config = YAML.dump(
+ { before_script: ['pwd'],
+ rspec: {
+ variables: variables,
+ script: 'rspec' }
+ })
+
+ expect { GitlabCiYamlProcessor.new(config, path) }
+ .to raise_error(GitlabCiYamlProcessor::ValidationError,
+ /job: variables should be a map/)
+ end
+ end
- expect { GitlabCiYamlProcessor.new(config, path) }
- .to raise_error(GitlabCiYamlProcessor::ValidationError,
- /job: variables should be a map/)
+ context 'when variables key defined but value not specified' do
+ it 'returns empty array' do
+ config = YAML.dump(
+ { before_script: ['pwd'],
+ rspec: {
+ variables: nil,
+ script: 'rspec' }
+ })
+
+ config_processor = GitlabCiYamlProcessor.new(config, path)
+
+ ##
+ # TODO, in next version of CI configuration processor this
+ # should be invalid configuration, see #18775 and #15060
+ #
+ expect(config_processor.job_variables(:rspec))
+ .to be_an_instance_of(Array).and be_empty
+ end
end
end
end
diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb
index 7c617723e6d..7b4ccc83915 100644
--- a/spec/lib/gitlab/reference_extractor_spec.rb
+++ b/spec/lib/gitlab/reference_extractor_spec.rb
@@ -105,7 +105,8 @@ describe Gitlab::ReferenceExtractor, lib: true do
it 'returns JIRA issues for a JIRA-integrated project' do
subject.analyze('JIRA-123 and FOOBAR-4567')
- expect(subject.issues).to eq [JiraIssue.new('JIRA-123', project), JiraIssue.new('FOOBAR-4567', project)]
+ expect(subject.issues).to eq [ExternalIssue.new('JIRA-123', project),
+ ExternalIssue.new('FOOBAR-4567', project)]
end
end
diff --git a/spec/mailers/previews/devise_mailer_preview.rb b/spec/mailers/previews/devise_mailer_preview.rb
index dc3062a4332..d6588efc486 100644
--- a/spec/mailers/previews/devise_mailer_preview.rb
+++ b/spec/mailers/previews/devise_mailer_preview.rb
@@ -1,11 +1,30 @@
class DeviseMailerPreview < ActionMailer::Preview
def confirmation_instructions_for_signup
- user = User.new(name: 'Jane Doe', email: 'signup@example.com')
- DeviseMailer.confirmation_instructions(user, 'faketoken', {})
+ DeviseMailer.confirmation_instructions(unsaved_user, 'faketoken', {})
end
def confirmation_instructions_for_new_email
user = User.last
+ user.unconfirmed_email = 'unconfirmed@example.com'
+
DeviseMailer.confirmation_instructions(user, 'faketoken', {})
end
+
+ def reset_password_instructions
+ DeviseMailer.reset_password_instructions(unsaved_user, 'faketoken', {})
+ end
+
+ def unlock_instructions
+ DeviseMailer.unlock_instructions(unsaved_user, 'faketoken', {})
+ end
+
+ def password_change
+ DeviseMailer.password_change(unsaved_user, {})
+ end
+
+ private
+
+ def unsaved_user
+ User.new(name: 'Jane Doe', email: 'jdoe@example.com')
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 0d769ed7324..34507cf5083 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -258,6 +258,19 @@ describe Ci::Pipeline, models: true do
end
end
end
+
+ context 'when no builds created' do
+ let(:pipeline) { build(:ci_pipeline) }
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(before_script: ['ls']))
+ end
+
+ it 'returns false' do
+ expect(pipeline.create_builds(nil)).to be_falsey
+ expect(pipeline).not_to be_persisted
+ end
+ end
end
describe "#finished_at" do
diff --git a/spec/models/jira_issue_spec.rb b/spec/models/jira_issue_spec.rb
deleted file mode 100644
index 1634265b439..00000000000
--- a/spec/models/jira_issue_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'spec_helper'
-
-describe JiraIssue do
- let(:project) { create(:project) }
- subject { JiraIssue.new('JIRA-123', project) }
-
- describe 'id' do
- subject { super().id }
- it { is_expected.to eq('JIRA-123') }
- end
-
- describe 'iid' do
- subject { super().iid }
- it { is_expected.to eq('JIRA-123') }
- end
-
- describe 'to_s' do
- subject { super().to_s }
- it { is_expected.to eq('JIRA-123') }
- end
-
- describe :== do
- specify { expect(subject).to eq(JiraIssue.new('JIRA-123', project)) }
- specify { expect(subject).not_to eq(JiraIssue.new('JIRA-124', project)) }
-
- it 'only compares with JiraIssues' do
- expect(subject).not_to eq('JIRA-123')
- end
- end
-end
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
new file mode 100644
index 00000000000..46eb71cef14
--- /dev/null
+++ b/spec/models/personal_access_token_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe PersonalAccessToken, models: true do
+ describe ".generate" do
+ it "generates a random token" do
+ personal_access_token = PersonalAccessToken.generate({})
+ expect(personal_access_token.token).to be_present
+ end
+
+ it "doesn't save the record" do
+ personal_access_token = PersonalAccessToken.generate({})
+ expect(personal_access_token).not_to be_persisted
+ end
+ end
+end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 5309cfb99ff..c9517324541 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -76,7 +76,8 @@ describe JiraService, models: true do
end
it "should call JIRA API" do
- @jira_service.execute(merge_request, JiraIssue.new("JIRA-123", project))
+ @jira_service.execute(merge_request,
+ ExternalIssue.new("JIRA-123", project))
expect(WebMock).to have_requested(:post, @comment_url).with(
body: /Issue solved with/
).once
@@ -84,7 +85,8 @@ describe JiraService, models: true do
it "calls the api with jira_issue_transition_id" do
@jira_service.jira_issue_transition_id = 'this-is-a-custom-id'
- @jira_service.execute(merge_request, JiraIssue.new("JIRA-123", project))
+ @jira_service.execute(merge_request,
+ ExternalIssue.new("JIRA-123", project))
expect(WebMock).to have_requested(:post, @api_url).with(
body: /this-is-a-custom-id/
).once
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index fedab1f913b..53c8408633c 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -220,7 +220,7 @@ describe Project, models: true do
end
end
- describe :find_with_namespace do
+ describe '.find_with_namespace' do
context 'with namespace' do
before do
@group = create :group, name: 'gitlab'
@@ -231,6 +231,22 @@ describe Project, models: true do
it { expect(Project.find_with_namespace('GitLab/GitlabHQ')).to eq(@project) }
it { expect(Project.find_with_namespace('gitlab-ci')).to be_nil }
end
+
+ context 'when multiple projects using a similar name exist' do
+ let(:group) { create(:group, name: 'gitlab') }
+
+ let!(:project1) do
+ create(:empty_project, name: 'gitlab1', path: 'gitlab', namespace: group)
+ end
+
+ let!(:project2) do
+ create(:empty_project, name: 'gitlab2', path: 'GITLAB', namespace: group)
+ end
+
+ it 'returns the row where the path matches literally' do
+ expect(Project.find_with_namespace('gitlab/GITLAB')).to eq(project2)
+ end
+ end
end
describe :to_param do
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
index 0c19094ec54..f22db61e744 100644
--- a/spec/requests/api/api_helpers_spec.rb
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -1,8 +1,10 @@
require 'spec_helper'
-describe API, api: true do
+describe API::Helpers, api: true do
+
include API::Helpers
include ApiHelpers
+
let(:user) { create(:user) }
let(:admin) { create(:admin) }
let(:key) { create(:key, user: user) }
@@ -39,24 +41,64 @@ describe API, api: true do
end
describe ".current_user" do
- it "should return nil for an invalid token" do
- env[API::Helpers::PRIVATE_TOKEN_HEADER] = 'invalid token'
- allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false }
- expect(current_user).to be_nil
- end
-
- it "should return nil for a user without access" do
- env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token
- allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
- expect(current_user).to be_nil
+ describe "when authenticating using a user's private token" do
+ it "should return nil for an invalid token" do
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = 'invalid token'
+ allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false }
+ expect(current_user).to be_nil
+ end
+
+ it "should return nil for a user without access" do
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token
+ allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
+ expect(current_user).to be_nil
+ end
+
+ it "should leave user as is when sudo not specified" do
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token
+ expect(current_user).to eq(user)
+ clear_env
+ params[API::Helpers::PRIVATE_TOKEN_PARAM] = user.private_token
+ expect(current_user).to eq(user)
+ end
end
- it "should leave user as is when sudo not specified" do
- env[API::Helpers::PRIVATE_TOKEN_HEADER] = user.private_token
- expect(current_user).to eq(user)
- clear_env
- params[API::Helpers::PRIVATE_TOKEN_PARAM] = user.private_token
- expect(current_user).to eq(user)
+ describe "when authenticating using a user's personal access tokens" do
+ let(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ it "should return nil for an invalid token" do
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = 'invalid token'
+ allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false }
+ expect(current_user).to be_nil
+ end
+
+ it "should return nil for a user without access" do
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = personal_access_token.token
+ allow(Gitlab::UserAccess).to receive(:allowed?).and_return(false)
+ expect(current_user).to be_nil
+ end
+
+ it "should leave user as is when sudo not specified" do
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = personal_access_token.token
+ expect(current_user).to eq(user)
+ clear_env
+ params[API::Helpers::PRIVATE_TOKEN_PARAM] = personal_access_token.token
+ expect(current_user).to eq(user)
+ end
+
+ it 'does not allow revoked tokens' do
+ personal_access_token.revoke!
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = personal_access_token.token
+ allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false }
+ expect(current_user).to be_nil
+ end
+
+ it 'does not allow expired tokens' do
+ personal_access_token.update_attributes!(expires_at: 1.day.ago)
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = personal_access_token.token
+ allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false }
+ expect(current_user).to be_nil
+ end
end
it "should change current user to sudo when admin" do
diff --git a/spec/services/ci/create_builds_service_spec.rb b/spec/services/ci/create_builds_service_spec.rb
index 984b78487d4..8b0becd83d3 100644
--- a/spec/services/ci/create_builds_service_spec.rb
+++ b/spec/services/ci/create_builds_service_spec.rb
@@ -9,7 +9,7 @@ describe Ci::CreateBuildsService, services: true do
#
subject do
- described_class.new(pipeline).execute('test', nil, user, status)
+ described_class.new(pipeline).execute('test', user, status, nil)
end
context 'next builds available' do
@@ -17,6 +17,10 @@ describe Ci::CreateBuildsService, services: true do
it { is_expected.to be_an_instance_of Array }
it { is_expected.to all(be_an_instance_of Ci::Build) }
+
+ it 'does not persist created builds' do
+ expect(subject.first).not_to be_persisted
+ end
end
context 'builds skipped' do
diff --git a/spec/services/create_commit_builds_service_spec.rb b/spec/services/create_commit_builds_service_spec.rb
index a5b4d9f05de..deab242f45a 100644
--- a/spec/services/create_commit_builds_service_spec.rb
+++ b/spec/services/create_commit_builds_service_spec.rb
@@ -39,7 +39,7 @@ describe CreateCommitBuildsService, services: true do
end
it "creates commit if there is no appropriate job but deploy job has right ref setting" do
- config = YAML.dump({ deploy: { deploy: "ls", only: ["0_1"] } })
+ config = YAML.dump({ deploy: { script: "ls", only: ["0_1"] } })
stub_ci_pipeline_yaml_file(config)
result = service.execute(project, user,
@@ -81,7 +81,7 @@ describe CreateCommitBuildsService, services: true do
expect(pipeline.yaml_errors).not_to be_nil
end
- describe :ci_skip? do
+ context 'when commit contains a [ci skip] directive' do
let(:message) { "some message[ci skip]" }
before do
@@ -171,5 +171,24 @@ describe CreateCommitBuildsService, services: true do
expect(pipeline.status).to eq("failed")
expect(pipeline.builds.any?).to be false
end
+
+ context 'when there are no jobs for this pipeline' do
+ before do
+ config = YAML.dump({ test: { script: 'ls', only: ['feature'] } })
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ it 'does not create a new pipeline' do
+ result = service.execute(project, user,
+ ref: 'refs/heads/master',
+ before: '00000000',
+ after: '31das312',
+ commits: [{ message: 'some msg' }])
+
+ expect(result).to be_falsey
+ expect(Ci::Build.all).to be_empty
+ expect(Ci::Pipeline.count).to eq(0)
+ end
+ end
end
end
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 18692f1279a..f99ad046f0d 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -312,7 +312,8 @@ describe GitPushService, services: true do
end
it "doesn't close issues when external issue tracker is in use" do
- allow(project).to receive(:default_issues_tracker?).and_return(false)
+ allow_any_instance_of(Project).to receive(:default_issues_tracker?).
+ and_return(false)
# The push still shouldn't create cross-reference notes.
expect do
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 09f0ee3871d..85dd30bf48c 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -529,7 +529,7 @@ describe SystemNoteService, services: true do
let(:author) { create(:user) }
let(:issue) { create(:issue, project: project) }
let(:mergereq) { create(:merge_request, :simple, target_project: project, source_project: project) }
- let(:jira_issue) { JiraIssue.new("JIRA-1", project)}
+ let(:jira_issue) { ExternalIssue.new("JIRA-1", project)}
let(:jira_tracker) { project.create_jira_service if project.jira_service.nil? }
let(:commit) { project.commit }
diff --git a/spec/workers/expire_build_artifacts_worker_spec.rb b/spec/workers/expire_build_artifacts_worker_spec.rb
index e3827cae9a6..7d6668920c0 100644
--- a/spec/workers/expire_build_artifacts_worker_spec.rb
+++ b/spec/workers/expire_build_artifacts_worker_spec.rb
@@ -20,6 +20,10 @@ describe ExpireBuildArtifactsWorker do
it 'does remove files' do
expect(build.reload.artifacts_file.exists?).to be_falsey
end
+
+ it 'does nullify artifacts_file column' do
+ expect(build.reload.artifacts_file_identifier).to be_nil
+ end
end
context 'with not yet expired artifacts' do
@@ -32,6 +36,10 @@ describe ExpireBuildArtifactsWorker do
it 'does not remove files' do
expect(build.reload.artifacts_file.exists?).to be_truthy
end
+
+ it 'does not nullify artifacts_file column' do
+ expect(build.reload.artifacts_file_identifier).not_to be_nil
+ end
end
context 'without expire date' do
@@ -44,6 +52,10 @@ describe ExpireBuildArtifactsWorker do
it 'does not remove files' do
expect(build.reload.artifacts_file.exists?).to be_truthy
end
+
+ it 'does not nullify artifacts_file column' do
+ expect(build.reload.artifacts_file_identifier).not_to be_nil
+ end
end
context 'for expired artifacts' do