mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-28 14:06:05 +10:00
Fix merge error
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe TrendingProjectsFinder, benchmark: true do
|
||||
describe '#execute' do
|
||||
let(:finder) { described_class.new }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
# to_a is used to force actually running the query (instead of just building
|
||||
# it).
|
||||
benchmark_subject { finder.execute(user).non_archived.to_a }
|
||||
|
||||
it { is_expected.to iterate_per_second(500) }
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Markdown::ReferenceFilter, benchmark: true do
|
||||
let(:input) do
|
||||
html = <<-EOF
|
||||
<p>Hello @alice and @bob, how are you doing today?</p>
|
||||
<p>This is simple @dummy text to see how the @ReferenceFilter class performs
|
||||
when @processing HTML.</p>
|
||||
EOF
|
||||
|
||||
Nokogiri::HTML.fragment(html)
|
||||
end
|
||||
|
||||
let(:project) { create(:empty_project) }
|
||||
|
||||
let(:filter) { described_class.new(input, project: project) }
|
||||
|
||||
describe '#replace_text_nodes_matching' do
|
||||
let(:iterations) { 6000 }
|
||||
|
||||
describe 'with identical input and output HTML' do
|
||||
benchmark_subject do
|
||||
filter.replace_text_nodes_matching(User.reference_pattern) do |content|
|
||||
content
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
|
||||
describe 'with different input and output HTML' do
|
||||
benchmark_subject do
|
||||
filter.replace_text_nodes_matching(User.reference_pattern) do |content|
|
||||
'@eve'
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Milestone, benchmark: true do
|
||||
describe '#sort_issues' do
|
||||
let(:milestone) { create(:milestone) }
|
||||
|
||||
let(:issue1) { create(:issue, milestone: milestone) }
|
||||
let(:issue2) { create(:issue, milestone: milestone) }
|
||||
let(:issue3) { create(:issue, milestone: milestone) }
|
||||
|
||||
let(:issue_ids) { [issue3.id, issue2.id, issue1.id] }
|
||||
|
||||
benchmark_subject { milestone.sort_issues(issue_ids) }
|
||||
|
||||
it { is_expected.to iterate_per_second(500) }
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Project, benchmark: true do
|
||||
describe '.trending' do
|
||||
let(:group) { create(:group) }
|
||||
let(:project1) { create(:empty_project, :public, group: group) }
|
||||
let(:project2) { create(:empty_project, :public, group: group) }
|
||||
|
||||
let(:iterations) { 500 }
|
||||
|
||||
before do
|
||||
2.times do
|
||||
create(:note_on_commit, project: project1)
|
||||
end
|
||||
|
||||
create(:note_on_commit, project: project2)
|
||||
end
|
||||
|
||||
describe 'without an explicit start date' do
|
||||
benchmark_subject { described_class.trending.to_a }
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
|
||||
describe 'with an explicit start date' do
|
||||
let(:date) { 1.month.ago }
|
||||
|
||||
benchmark_subject { described_class.trending(date).to_a }
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.find_with_namespace' do
|
||||
let(:group) { create(:group, name: 'sisinmaru') }
|
||||
let(:project) { create(:project, name: 'maru', namespace: group) }
|
||||
|
||||
describe 'using a capitalized namespace' do
|
||||
benchmark_subject { described_class.find_with_namespace('sisinmaru/MARU') }
|
||||
|
||||
it { is_expected.to iterate_per_second(600) }
|
||||
end
|
||||
|
||||
describe 'using a lowercased namespace' do
|
||||
benchmark_subject { described_class.find_with_namespace('sisinmaru/maru') }
|
||||
|
||||
it { is_expected.to iterate_per_second(600) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe ProjectTeam, benchmark: true do
|
||||
describe '#max_member_access' do
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:empty_project, group: group) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
project.team << [user, :master]
|
||||
|
||||
5.times do
|
||||
project.team << [create(:user), :reporter]
|
||||
|
||||
project.group.add_user(create(:user), :reporter)
|
||||
end
|
||||
end
|
||||
|
||||
benchmark_subject { project.team.max_member_access(user.id) }
|
||||
|
||||
it { is_expected.to iterate_per_second(35000) }
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,42 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe User, benchmark: true do
|
||||
describe '.by_login' do
|
||||
before do
|
||||
%w{Alice Bob Eve}.each do |name|
|
||||
create(:user,
|
||||
email: "#{name}@gitlab.com",
|
||||
username: name,
|
||||
name: name)
|
||||
end
|
||||
end
|
||||
|
||||
# The iteration count is based on the query taking little over 1 ms when
|
||||
# using PostgreSQL.
|
||||
let(:iterations) { 900 }
|
||||
|
||||
describe 'using a capitalized username' do
|
||||
benchmark_subject { User.by_login('Alice') }
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
|
||||
describe 'using a lowercase username' do
|
||||
benchmark_subject { User.by_login('alice') }
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
|
||||
describe 'using a capitalized Email address' do
|
||||
benchmark_subject { User.by_login('Alice@gitlab.com') }
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
|
||||
describe 'using a lowercase Email address' do
|
||||
benchmark_subject { User.by_login('alice@gitlab.com') }
|
||||
|
||||
it { is_expected.to iterate_per_second(iterations) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,72 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe AbuseReportsController do
|
||||
let(:reporter) { create(:user) }
|
||||
let(:user) { create(:user) }
|
||||
let(:message) { "This user is a spammer" }
|
||||
|
||||
before do
|
||||
sign_in(reporter)
|
||||
end
|
||||
|
||||
describe "POST create" do
|
||||
context "with admin notification email set" do
|
||||
let(:admin_email) { "admin@example.com"}
|
||||
|
||||
before(:each) do
|
||||
stub_application_setting(admin_notification_email: admin_email)
|
||||
end
|
||||
|
||||
it "sends a notification email" do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
|
||||
email = ActionMailer::Base.deliveries.last
|
||||
|
||||
expect(email.to).to eq([admin_email])
|
||||
expect(email.subject).to include(user.username)
|
||||
expect(email.text_part.body).to include(message)
|
||||
end
|
||||
|
||||
it "saves the abuse report" do
|
||||
expect do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
end.to change { AbuseReport.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "without admin notification email set" do
|
||||
before(:each) do
|
||||
stub_application_setting(admin_notification_email: nil)
|
||||
end
|
||||
|
||||
it "does not send a notification email" do
|
||||
expect do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
end.not_to change { ActionMailer::Base.deliveries.count }
|
||||
end
|
||||
|
||||
it "saves the abuse report" do
|
||||
expect do
|
||||
post :create,
|
||||
abuse_report: {
|
||||
user_id: user.id,
|
||||
message: message
|
||||
}
|
||||
end.to change { AbuseReport.count }.by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -7,6 +7,21 @@ describe Admin::UsersController do
|
||||
sign_in(admin)
|
||||
end
|
||||
|
||||
describe 'POST login_as' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'logs admin as another user' do
|
||||
expect(warden.authenticate(scope: :user)).not_to eq(user)
|
||||
post :login_as, id: user.username
|
||||
expect(warden.authenticate(scope: :user)).to eq(user)
|
||||
end
|
||||
|
||||
it 'redirects user to homepage' do
|
||||
post :login_as, id: user.username
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #user with projects' do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, namespace: user.namespace) }
|
||||
@@ -22,6 +37,32 @@ describe Admin::UsersController do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT block/:id' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'blocks user' do
|
||||
put :block, id: user.username
|
||||
user.reload
|
||||
expect(user.blocked?).to be_truthy
|
||||
expect(flash[:notice]).to eq 'Successfully blocked'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT unblock/:id' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
user.block
|
||||
end
|
||||
|
||||
it 'unblocks user' do
|
||||
put :unblock, id: user.username
|
||||
user.reload
|
||||
expect(user.blocked?).to be_falsey
|
||||
expect(flash[:notice]).to eq 'Successfully unblocked'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT unlock/:id' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
require "spec_helper"
|
||||
|
||||
describe Ci::CommitsController do
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
end
|
||||
|
||||
describe "GET /status" do
|
||||
it "returns status of commit" do
|
||||
commit = FactoryGirl.create :ci_commit, project: @project
|
||||
get :status, id: commit.sha, ref_id: commit.ref, project_id: @project.id
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.code).to eq('200')
|
||||
JSON.parse(response.body)["status"] == "pending"
|
||||
end
|
||||
|
||||
it "returns not_found status" do
|
||||
commit = FactoryGirl.create :ci_commit, project: @project
|
||||
get :status, id: commit.sha, ref_id: "deploy", project_id: @project.id
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response.code).to eq('200')
|
||||
JSON.parse(response.body)["status"] == "not_found"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -41,7 +41,7 @@ describe Import::GithubController do
|
||||
|
||||
it "assigns variables" do
|
||||
@project = create(:project, import_type: 'github', creator_id: user.id)
|
||||
stub_client(repos: [@repo], orgs: [@org], org_repos: [@org_repo])
|
||||
stub_client(repos: [@repo, @org_repo], orgs: [@org], org_repos: [@org_repo])
|
||||
|
||||
get :status
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe InvitesController do
|
||||
let(:token) { '123456' }
|
||||
let(:user) { create(:user) }
|
||||
let(:member) { create(:project_member, invite_token: token, invite_email: 'test@abc.com', user: user) }
|
||||
|
||||
before do
|
||||
controller.instance_variable_set(:@member, member)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
describe 'GET #accept' do
|
||||
it 'accepts user' do
|
||||
get :accept, id: token
|
||||
member.reload
|
||||
|
||||
expect(response.status).to eq(302)
|
||||
expect(member.user).to eq(user)
|
||||
expect(flash[:notice]).to include 'You have been granted'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #decline' do
|
||||
it 'declines user' do
|
||||
get :decline, id: token
|
||||
expect{member.reload}.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(response.status).to eq(302)
|
||||
expect(flash[:notice]).to include 'You have declined the invitation to join'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -8,28 +8,34 @@ describe Projects::IssuesController do
|
||||
before do
|
||||
sign_in(user)
|
||||
project.team << [user, :developer]
|
||||
controller.instance_variable_set(:@project, project)
|
||||
end
|
||||
|
||||
describe "GET #index" do
|
||||
it "returns index" do
|
||||
get :index, namespace_id: project.namespace.id, project_id: project.id
|
||||
get :index, namespace_id: project.namespace.path, project_id: project.path
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
|
||||
it "return 301 if request path doesn't match project path" do
|
||||
get :index, namespace_id: project.namespace.path, project_id: project.path.upcase
|
||||
|
||||
expect(response).to redirect_to(namespace_project_issues_path(project.namespace, project))
|
||||
end
|
||||
|
||||
it "returns 404 when issues are disabled" do
|
||||
project.issues_enabled = false
|
||||
project.save
|
||||
|
||||
get :index, namespace_id: project.namespace.id, project_id: project.id
|
||||
get :index, namespace_id: project.namespace.path, project_id: project.path
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "returns 404 when external issue tracker is enabled" do
|
||||
controller.instance_variable_set(:@project, project)
|
||||
allow(project).to receive(:default_issues_tracker?).and_return(false)
|
||||
|
||||
get :index, namespace_id: project.namespace.id, project_id: project.id
|
||||
get :index, namespace_id: project.namespace.path, project_id: project.path
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
|
||||
@@ -33,33 +33,5 @@ describe Projects::RepositoriesController do
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service doesn't return a path" do
|
||||
|
||||
before do
|
||||
allow(service).to receive(:execute).and_return(nil)
|
||||
end
|
||||
|
||||
it "reloads the page" do
|
||||
get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip"
|
||||
|
||||
expect(response).to redirect_to(archive_namespace_project_repository_path(project.namespace, project, ref: "master", format: "zip"))
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service returns a path" do
|
||||
|
||||
let(:path) { Rails.root.join("spec/fixtures/dk.png").to_s }
|
||||
|
||||
before do
|
||||
allow(service).to receive(:execute).and_return(path)
|
||||
end
|
||||
|
||||
it "sends the file" do
|
||||
get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip"
|
||||
|
||||
expect(response.body).to eq(File.binread(path))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,26 +10,43 @@ describe Projects::ServicesController do
|
||||
project.team << [user, :master]
|
||||
controller.instance_variable_set(:@project, project)
|
||||
controller.instance_variable_set(:@service, service)
|
||||
request.env["HTTP_REFERER"] = "/"
|
||||
end
|
||||
|
||||
describe "#test" do
|
||||
context 'success' do
|
||||
it "should redirect and show success message" do
|
||||
expect(service).to receive(:test).and_return({ success: true, result: 'done' })
|
||||
get :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, format: :html
|
||||
expect(response.status).to redirect_to('/')
|
||||
expect(flash[:notice]).to eq('We sent a request to the provided URL')
|
||||
end
|
||||
shared_examples_for 'services controller' do |referrer|
|
||||
before do
|
||||
request.env["HTTP_REFERER"] = referrer
|
||||
end
|
||||
|
||||
context 'failure' do
|
||||
it "should redirect and show failure message" do
|
||||
expect(service).to receive(:test).and_return({ success: false, result: 'Bad test' })
|
||||
get :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, format: :html
|
||||
expect(response.status).to redirect_to('/')
|
||||
expect(flash[:alert]).to eq('We tried to send a request to the provided URL but an error occurred: Bad test')
|
||||
describe "#test" do
|
||||
context 'success' do
|
||||
it "should redirect and show success message" do
|
||||
expect(service).to receive(:test).and_return({ success: true, result: 'done' })
|
||||
get :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, format: :html
|
||||
expect(response.status).to redirect_to('/')
|
||||
expect(flash[:notice]).to eq('We sent a request to the provided URL')
|
||||
end
|
||||
end
|
||||
|
||||
context 'failure' do
|
||||
it "should redirect and show failure message" do
|
||||
expect(service).to receive(:test).and_return({ success: false, result: 'Bad test' })
|
||||
get :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, format: :html
|
||||
expect(response.status).to redirect_to('/')
|
||||
expect(flash[:alert]).to eq('We tried to send a request to the provided URL but an error occurred: Bad test')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'referrer defined' do
|
||||
it_should_behave_like 'services controller' do
|
||||
let!(:referrer) { "/" }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'referrer undefined' do
|
||||
it_should_behave_like 'services controller' do
|
||||
let!(:referrer) { nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -88,4 +88,40 @@ describe Projects::TreeController do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create_dir' do
|
||||
render_views
|
||||
|
||||
before do
|
||||
post(:create_dir,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project.to_param,
|
||||
id: 'master',
|
||||
dir_name: path,
|
||||
new_branch: target_branch,
|
||||
commit_message: 'Test commit message')
|
||||
end
|
||||
|
||||
context 'successful creation' do
|
||||
let(:path) { 'files/new_dir'}
|
||||
let(:target_branch) { 'master-test'}
|
||||
|
||||
it 'redirects to the new directory' do
|
||||
expect(subject).
|
||||
to redirect_to("/#{project.path_with_namespace}/blob/#{target_branch}/#{path}")
|
||||
expect(flash[:notice]).to eq('The directory has been successfully created')
|
||||
end
|
||||
end
|
||||
|
||||
context 'unsuccessful creation' do
|
||||
let(:path) { 'README.md' }
|
||||
let(:target_branch) { 'master'}
|
||||
|
||||
it 'does not allow overwriting of existing files' do
|
||||
expect(subject).
|
||||
to redirect_to("/#{project.path_with_namespace}/blob/master")
|
||||
expect(flash[:alert]).to eq('Directory already exists as a file')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ describe Projects::UploadsController do
|
||||
|
||||
it 'returns a content with original filename, new link, and correct type.' do
|
||||
expect(response.body).to match '\"alt\":\"rails_sample\"'
|
||||
expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads"
|
||||
expect(response.body).to match "\"url\":\"/uploads"
|
||||
expect(response.body).to match '\"is_image\":true'
|
||||
end
|
||||
end
|
||||
@@ -49,7 +49,7 @@ describe Projects::UploadsController do
|
||||
|
||||
it 'returns a content with original filename, new link, and correct type.' do
|
||||
expect(response.body).to match '\"alt\":\"doc_sample.txt\"'
|
||||
expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads"
|
||||
expect(response.body).to match "\"url\":\"/uploads"
|
||||
expect(response.body).to match '\"is_image\":false'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,6 +21,71 @@ describe ProjectsController do
|
||||
expect(response.body).to include("content='#{content}'")
|
||||
end
|
||||
end
|
||||
|
||||
context "rendering default project view" do
|
||||
render_views
|
||||
|
||||
it "renders the activity view" do
|
||||
allow(controller).to receive(:current_user).and_return(user)
|
||||
allow(user).to receive(:project_view).and_return('activity')
|
||||
|
||||
get :show, namespace_id: public_project.namespace.path, id: public_project.path
|
||||
expect(response).to render_template('_activity')
|
||||
end
|
||||
|
||||
it "renders the readme view" do
|
||||
allow(controller).to receive(:current_user).and_return(user)
|
||||
allow(user).to receive(:project_view).and_return('readme')
|
||||
|
||||
get :show, namespace_id: public_project.namespace.path, id: public_project.path
|
||||
expect(response).to render_template('_readme')
|
||||
end
|
||||
|
||||
it "renders the files view" do
|
||||
allow(controller).to receive(:current_user).and_return(user)
|
||||
allow(user).to receive(:project_view).and_return('files')
|
||||
|
||||
get :show, namespace_id: public_project.namespace.path, id: public_project.path
|
||||
expect(response).to render_template('_files')
|
||||
end
|
||||
end
|
||||
|
||||
context "when requested with case sensitive namespace and project path" do
|
||||
context "when there is a match with the same casing" do
|
||||
it "loads the project" do
|
||||
get :show, namespace_id: public_project.namespace.path, id: public_project.path
|
||||
|
||||
expect(assigns(:project)).to eq(public_project)
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is a match with different casing" do
|
||||
it "redirects to the normalized path" do
|
||||
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
|
||||
|
||||
expect(assigns(:project)).to eq(public_project)
|
||||
expect(response).to redirect_to("/#{public_project.path_with_namespace}")
|
||||
end
|
||||
|
||||
|
||||
# MySQL queries are case insensitive by default, so this spec would fail.
|
||||
if Gitlab::Database.postgresql?
|
||||
context "when there is also a match with the same casing" do
|
||||
|
||||
let!(:other_project) { create(:project, :public, namespace: public_project.namespace, path: public_project.path.upcase) }
|
||||
|
||||
it "loads the exactly matched project" do
|
||||
|
||||
get :show, namespace_id: public_project.namespace.path, id: public_project.path.upcase
|
||||
|
||||
expect(assigns(:project)).to eq(other_project)
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST #toggle_star" do
|
||||
@@ -48,4 +113,50 @@ describe ProjectsController do
|
||||
expect(user.starred?(public_project)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE remove_fork" do
|
||||
context 'when signed in' do
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'with forked project' do
|
||||
let(:project_fork) { create(:project, namespace: user.namespace) }
|
||||
|
||||
before do
|
||||
create(:forked_project_link, forked_to_project: project_fork)
|
||||
end
|
||||
|
||||
it 'should remove fork from project' do
|
||||
delete(:remove_fork,
|
||||
namespace_id: project_fork.namespace.to_param,
|
||||
id: project_fork.to_param, format: :js)
|
||||
|
||||
expect(project_fork.forked?).to be_falsey
|
||||
expect(flash[:notice]).to eq('The fork relationship has been removed.')
|
||||
expect(response).to render_template(:remove_fork)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project not forked' do
|
||||
let(:unforked_project) { create(:project, namespace: user.namespace) }
|
||||
|
||||
it 'should do nothing if project was not forked' do
|
||||
delete(:remove_fork,
|
||||
namespace_id: unforked_project.namespace.to_param,
|
||||
id: unforked_project.to_param, format: :js)
|
||||
|
||||
expect(flash[:notice]).to be_nil
|
||||
expect(response).to render_template(:remove_fork)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "does nothing if user is not signed in" do
|
||||
delete(:remove_fork,
|
||||
namespace_id: project.namespace.to_param,
|
||||
id: project.to_param, format: :js)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ describe RootController do
|
||||
allow(subject).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'who has customized their dashboard setting' do
|
||||
context 'who has customized their dashboard setting for starred projects' do
|
||||
before do
|
||||
user.update_attribute(:dashboard, 'stars')
|
||||
end
|
||||
@@ -21,6 +21,28 @@ describe RootController do
|
||||
end
|
||||
end
|
||||
|
||||
context 'who has customized their dashboard setting for project activities' do
|
||||
before do
|
||||
user.update_attribute(:dashboard, 'project_activity')
|
||||
end
|
||||
|
||||
it 'redirects to the activity list' do
|
||||
get :index
|
||||
expect(response).to redirect_to activity_dashboard_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'who has customized their dashboard setting for starred project activities' do
|
||||
before do
|
||||
user.update_attribute(:dashboard, 'starred_project_activity')
|
||||
end
|
||||
|
||||
it 'redirects to the activity list' do
|
||||
get :index
|
||||
expect(response).to redirect_to activity_dashboard_path(filter: 'starred')
|
||||
end
|
||||
end
|
||||
|
||||
context 'who uses the default dashboard setting' do
|
||||
it 'renders the default dashboard' do
|
||||
get :index
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :ci_build, class: Ci::Build do
|
||||
name 'test'
|
||||
ref 'master'
|
||||
tag false
|
||||
started_at 'Di 29. Okt 09:51:28 CET 2013'
|
||||
finished_at 'Di 29. Okt 09:53:28 CET 2013'
|
||||
commands 'ls -a'
|
||||
@@ -43,5 +46,9 @@ FactoryGirl.define do
|
||||
started_at nil
|
||||
finished_at nil
|
||||
end
|
||||
|
||||
factory :ci_build_tag do
|
||||
tag true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,58 +17,32 @@
|
||||
|
||||
# Read about factories at https://github.com/thoughtbot/factory_girl
|
||||
FactoryGirl.define do
|
||||
factory :ci_commit, class: Ci::Commit do
|
||||
ref 'master'
|
||||
before_sha '76de212e80737a608d939f648d959671fb0a0142'
|
||||
factory :ci_empty_commit, class: Ci::Commit do
|
||||
sha '97de212e80737a608d939f648d959671fb0a0142'
|
||||
push_data do
|
||||
{
|
||||
ref: 'refs/heads/master',
|
||||
before: '76de212e80737a608d939f648d959671fb0a0142',
|
||||
after: '97de212e80737a608d939f648d959671fb0a0142',
|
||||
user_name: 'Git User',
|
||||
user_email: 'git@example.com',
|
||||
repository: {
|
||||
name: 'test-data',
|
||||
url: 'ssh://git@gitlab.com/test/test-data.git',
|
||||
description: '',
|
||||
homepage: 'http://gitlab.com/test/test-data'
|
||||
},
|
||||
commits: [
|
||||
{
|
||||
id: '97de212e80737a608d939f648d959671fb0a0142',
|
||||
message: 'Test commit message',
|
||||
timestamp: '2014-09-23T13:12:25+02:00',
|
||||
url: 'https://gitlab.com/test/test-data/commit/97de212e80737a608d939f648d959671fb0a0142',
|
||||
author: {
|
||||
name: 'Git User',
|
||||
email: 'git@user.com'
|
||||
}
|
||||
}
|
||||
],
|
||||
total_commits_count: 1,
|
||||
ci_yaml_file: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
|
||||
}
|
||||
end
|
||||
|
||||
gl_project factory: :empty_project
|
||||
|
||||
factory :ci_commit_without_jobs do
|
||||
after(:create) do |commit, evaluator|
|
||||
commit.push_data[:ci_yaml_file] = YAML.dump({})
|
||||
commit.save
|
||||
after(:build) do |commit|
|
||||
allow(commit).to receive(:ci_yaml_file) { YAML.dump({}) }
|
||||
end
|
||||
end
|
||||
|
||||
factory :ci_commit_with_one_job do
|
||||
after(:create) do |commit, evaluator|
|
||||
commit.push_data[:ci_yaml_file] = YAML.dump({ rspec: { script: "ls" } })
|
||||
commit.save
|
||||
after(:build) do |commit|
|
||||
allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" } }) }
|
||||
end
|
||||
end
|
||||
|
||||
factory :ci_commit_with_two_jobs do
|
||||
after(:create) do |commit, evaluator|
|
||||
commit.push_data[:ci_yaml_file] = YAML.dump({ rspec: { script: "ls" }, spinach: { script: "ls" } })
|
||||
commit.save
|
||||
after(:build) do |commit|
|
||||
allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" }, spinach: { script: "ls" } }) }
|
||||
end
|
||||
end
|
||||
|
||||
factory :ci_commit do
|
||||
after(:build) do |commit|
|
||||
allow(commit).to receive(:ci_yaml_file) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,21 +29,9 @@
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :ci_project_without_token, class: Ci::Project do
|
||||
sequence :name do |n|
|
||||
"GitLab / gitlab-shell#{n}"
|
||||
end
|
||||
|
||||
default_ref 'master'
|
||||
|
||||
sequence :path do |n|
|
||||
"gitlab/gitlab-shell#{n}"
|
||||
end
|
||||
|
||||
sequence :ssh_url_to_repo do |n|
|
||||
"git@demo.gitlab.com:gitlab/gitlab-shell#{n}.git"
|
||||
end
|
||||
|
||||
gl_project factory: :project
|
||||
gl_project factory: :empty_project
|
||||
|
||||
factory :ci_project do
|
||||
token 'iPWx6WM4lhHNedGfBpPJNP'
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
FactoryGirl.define do
|
||||
factory :commit_status, class: CommitStatus do
|
||||
started_at 'Di 29. Okt 09:51:28 CET 2013'
|
||||
finished_at 'Di 29. Okt 09:53:28 CET 2013'
|
||||
name 'default'
|
||||
status 'success'
|
||||
description 'commit status'
|
||||
commit factory: :ci_commit
|
||||
|
||||
factory :generic_commit_status, class: GenericCommitStatus do
|
||||
name 'generic'
|
||||
description 'external commit status'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -111,6 +111,27 @@ describe "Admin::Users", feature: true do
|
||||
expect(page).to have_content(@user.name)
|
||||
end
|
||||
|
||||
describe 'Login as another user' do
|
||||
it 'should show login button for other users and check that it works' do
|
||||
another_user = create(:user)
|
||||
|
||||
visit admin_user_path(another_user)
|
||||
|
||||
click_link 'Log in as this user'
|
||||
|
||||
expect(page).to have_content("Logged in as #{another_user.username}")
|
||||
|
||||
page.within '.sidebar-user .username' do
|
||||
expect(page).to have_content(another_user.username)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should not show login button for admin itself' do
|
||||
visit admin_user_path(@user)
|
||||
expect(page).not_to have_content('Log in as this user')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Two-factor Authentication status' do
|
||||
it 'shows when enabled' do
|
||||
@user.update_attribute(:two_factor_enabled, true)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Builds" do
|
||||
before do
|
||||
login_as(:user)
|
||||
@commit = FactoryGirl.create :ci_commit
|
||||
@build = FactoryGirl.create :ci_build, commit: @commit
|
||||
@gl_project = @commit.project.gl_project
|
||||
@gl_project.team << [@user, :master]
|
||||
end
|
||||
|
||||
describe "GET /:project/builds" do
|
||||
context "Running scope" do
|
||||
before do
|
||||
@build.run!
|
||||
visit namespace_project_builds_path(@gl_project.namespace, @gl_project)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'Running' }
|
||||
it { expect(page).to have_content 'Cancel all' }
|
||||
it { expect(page).to have_content @build.short_sha }
|
||||
it { expect(page).to have_content @build.ref }
|
||||
it { expect(page).to have_content @build.name }
|
||||
end
|
||||
|
||||
context "Finished scope" do
|
||||
before do
|
||||
@build.run!
|
||||
visit namespace_project_builds_path(@gl_project.namespace, @gl_project, scope: :finished)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'No builds to show' }
|
||||
it { expect(page).to have_content 'Cancel all' }
|
||||
end
|
||||
|
||||
context "All builds" do
|
||||
before do
|
||||
@gl_project.ci_builds.running_or_pending.each(&:success)
|
||||
visit namespace_project_builds_path(@gl_project.namespace, @gl_project, scope: :all)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'All' }
|
||||
it { expect(page).to have_content @build.short_sha }
|
||||
it { expect(page).to have_content @build.ref }
|
||||
it { expect(page).to have_content @build.name }
|
||||
it { expect(page).to_not have_content 'Cancel all' }
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /:project/builds/:id/cancel_all" do
|
||||
before do
|
||||
@build.run!
|
||||
visit cancel_all_namespace_project_builds_path(@gl_project.namespace, @gl_project)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'No builds to show' }
|
||||
it { expect(page).to_not have_content 'Cancel all' }
|
||||
end
|
||||
|
||||
describe "GET /:project/builds/:id" do
|
||||
before do
|
||||
visit namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @commit.sha[0..7] }
|
||||
it { expect(page).to have_content @commit.git_commit_message }
|
||||
it { expect(page).to have_content @commit.git_author_name }
|
||||
end
|
||||
|
||||
describe "GET /:project/builds/:id/cancel" do
|
||||
before do
|
||||
@build.run!
|
||||
visit cancel_namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'canceled' }
|
||||
it { expect(page).to have_content 'Retry' }
|
||||
end
|
||||
|
||||
describe "POST /:project/builds/:id/retry" do
|
||||
before do
|
||||
visit cancel_namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
|
||||
click_link 'Retry'
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'pending' }
|
||||
it { expect(page).to have_content 'Cancel' }
|
||||
end
|
||||
end
|
||||
@@ -1,8 +1,7 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Admin Builds" do
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
let(:build) { FactoryGirl.create :ci_build, commit: commit }
|
||||
|
||||
before do
|
||||
@@ -22,10 +21,10 @@ describe "Admin Builds" do
|
||||
|
||||
describe "Tabs" do
|
||||
it "shows all builds" do
|
||||
build = FactoryGirl.create :ci_build, commit: commit, status: "pending"
|
||||
build1 = FactoryGirl.create :ci_build, commit: commit, status: "running"
|
||||
build2 = FactoryGirl.create :ci_build, commit: commit, status: "success"
|
||||
build3 = FactoryGirl.create :ci_build, commit: commit, status: "failed"
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "pending"
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "running"
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "success"
|
||||
FactoryGirl.create :ci_build, commit: commit, status: "failed"
|
||||
|
||||
visit ci_admin_builds_path
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@ require 'spec_helper'
|
||||
|
||||
describe "Admin Runners" do
|
||||
before do
|
||||
skip_ci_admin_auth
|
||||
login_as :user
|
||||
login_as :admin
|
||||
end
|
||||
|
||||
describe "Runners page" do
|
||||
@@ -20,16 +19,16 @@ describe "Admin Runners" do
|
||||
|
||||
describe 'search' do
|
||||
before do
|
||||
FactoryGirl.create :ci_runner, description: 'foo'
|
||||
FactoryGirl.create :ci_runner, description: 'bar'
|
||||
FactoryGirl.create :ci_runner, description: 'runner-foo'
|
||||
FactoryGirl.create :ci_runner, description: 'runner-bar'
|
||||
|
||||
search_form = find('#runners-search')
|
||||
search_form.fill_in 'search', with: 'foo'
|
||||
search_form.fill_in 'search', with: 'runner-foo'
|
||||
search_form.click_button 'Search'
|
||||
end
|
||||
|
||||
it { expect(page).to have_content("foo") }
|
||||
it { expect(page).not_to have_content("bar") }
|
||||
it { expect(page).to have_content("runner-foo") }
|
||||
it { expect(page).not_to have_content("runner-bar") }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,8 +36,8 @@ describe "Admin Runners" do
|
||||
let(:runner) { FactoryGirl.create :ci_runner }
|
||||
|
||||
before do
|
||||
FactoryGirl.create(:ci_project, name: "foo")
|
||||
FactoryGirl.create(:ci_project, name: "bar")
|
||||
@project1 = FactoryGirl.create(:ci_project)
|
||||
@project2 = FactoryGirl.create(:ci_project)
|
||||
visit ci_admin_runner_path(runner)
|
||||
end
|
||||
|
||||
@@ -47,19 +46,19 @@ describe "Admin Runners" do
|
||||
end
|
||||
|
||||
describe 'projects' do
|
||||
it { expect(page).to have_content("foo") }
|
||||
it { expect(page).to have_content("bar") }
|
||||
it { expect(page).to have_content(@project1.name_with_namespace) }
|
||||
it { expect(page).to have_content(@project2.name_with_namespace) }
|
||||
end
|
||||
|
||||
describe 'search' do
|
||||
before do
|
||||
search_form = find('#runner-projects-search')
|
||||
search_form.fill_in 'search', with: 'foo'
|
||||
search_form.fill_in 'search', with: @project1.gl_project.name
|
||||
search_form.click_button 'Search'
|
||||
end
|
||||
|
||||
it { expect(page).to have_content("foo") }
|
||||
it { expect(page).not_to have_content("bar") }
|
||||
it { expect(page).to have_content(@project1.name_with_namespace) }
|
||||
it { expect(page).not_to have_content(@project2.name_with_namespace) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Builds" do
|
||||
context :private_project do
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@commit = FactoryGirl.create :ci_commit, project: @project
|
||||
@build = FactoryGirl.create :ci_build, commit: @commit
|
||||
login_as :user
|
||||
@project.gl_project.team << [@user, :master]
|
||||
end
|
||||
|
||||
describe "GET /:project/builds/:id" do
|
||||
before do
|
||||
visit ci_project_build_path(@project, @build)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @commit.sha[0..7] }
|
||||
it { expect(page).to have_content @commit.git_commit_message }
|
||||
it { expect(page).to have_content @commit.git_author_name }
|
||||
end
|
||||
|
||||
describe "GET /:project/builds/:id/cancel" do
|
||||
before do
|
||||
@build.run!
|
||||
visit cancel_ci_project_build_path(@project, @build)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'canceled' }
|
||||
it { expect(page).to have_content 'Retry' }
|
||||
end
|
||||
|
||||
describe "POST /:project/builds/:id/retry" do
|
||||
before do
|
||||
@build.cancel!
|
||||
visit ci_project_build_path(@project, @build)
|
||||
click_link 'Retry'
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'pending' }
|
||||
it { expect(page).to have_content 'Cancel' }
|
||||
end
|
||||
end
|
||||
|
||||
context :public_project do
|
||||
describe "Show page public accessible" do
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_public_project
|
||||
@commit = FactoryGirl.create :ci_commit, project: @project
|
||||
@runner = FactoryGirl.create :ci_specific_runner
|
||||
@build = FactoryGirl.create :ci_build, commit: @commit, runner: @runner
|
||||
|
||||
stub_gitlab_calls
|
||||
visit ci_project_build_path(@project, @build)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @commit.sha[0..7] }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,69 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Commits" do
|
||||
include Ci::CommitsHelper
|
||||
|
||||
context "Authenticated user" do
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@commit = FactoryGirl.create :ci_commit, project: @project
|
||||
@build = FactoryGirl.create :ci_build, commit: @commit
|
||||
login_as :user
|
||||
@project.gl_project.team << [@user, :master]
|
||||
end
|
||||
|
||||
describe "GET /:project/commits/:sha" do
|
||||
before do
|
||||
visit ci_commit_path(@commit)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @commit.sha[0..7] }
|
||||
it { expect(page).to have_content @commit.git_commit_message }
|
||||
it { expect(page).to have_content @commit.git_author_name }
|
||||
end
|
||||
|
||||
describe "Cancel commit" do
|
||||
it "cancels commit" do
|
||||
visit ci_commit_path(@commit)
|
||||
click_on "Cancel"
|
||||
|
||||
expect(page).to have_content "canceled"
|
||||
end
|
||||
end
|
||||
|
||||
describe ".gitlab-ci.yml not found warning" do
|
||||
it "does not show warning" do
|
||||
visit ci_commit_path(@commit)
|
||||
|
||||
expect(page).not_to have_content ".gitlab-ci.yml not found in this commit"
|
||||
end
|
||||
|
||||
it "shows warning" do
|
||||
@commit.push_data[:ci_yaml_file] = nil
|
||||
@commit.save
|
||||
|
||||
visit ci_commit_path(@commit)
|
||||
|
||||
expect(page).to have_content ".gitlab-ci.yml not found in this commit"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Public pages" do
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_public_project
|
||||
@commit = FactoryGirl.create :ci_commit, project: @project
|
||||
@build = FactoryGirl.create :ci_build, commit: @commit
|
||||
end
|
||||
|
||||
describe "GET /:project/commits/:sha" do
|
||||
before do
|
||||
visit ci_commit_path(@commit)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @commit.sha[0..7] }
|
||||
it { expect(page).to have_content @commit.git_commit_message }
|
||||
it { expect(page).to have_content @commit.git_author_name }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,38 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Projects" do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
@project = FactoryGirl.create :ci_project, name: "GitLab / gitlab-shell"
|
||||
@project.gl_project.team << [user, :master]
|
||||
end
|
||||
|
||||
describe "GET /ci/projects/:id" do
|
||||
before do
|
||||
visit ci_project_path(@project)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @project.name }
|
||||
it { expect(page).to have_content 'All commits' }
|
||||
end
|
||||
|
||||
describe "GET /ci/projects/:id/edit" do
|
||||
before do
|
||||
visit edit_ci_project_path(@project)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @project.name }
|
||||
it { expect(page).to have_content 'Build Schedule' }
|
||||
|
||||
it "updates configuration" do
|
||||
fill_in 'Timeout', with: '70'
|
||||
click_button 'Save changes'
|
||||
|
||||
expect(page).to have_content 'was successfully updated'
|
||||
|
||||
expect(find_field('Timeout').value).to eq '70'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "CI settings" do
|
||||
let(:user) { create(:user) }
|
||||
before { login_as(user) }
|
||||
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@gl_project = @project.gl_project
|
||||
@gl_project.team << [user, :master]
|
||||
visit edit_namespace_project_ci_settings_path(@gl_project.namespace, @gl_project)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content 'Build Schedule' }
|
||||
|
||||
it "updates configuration" do
|
||||
fill_in 'Timeout', with: '70'
|
||||
click_button 'Save changes'
|
||||
expect(page).to have_content 'was successfully updated'
|
||||
expect(find_field('Timeout').value).to eq '70'
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'CI web hooks' do
|
||||
let(:user) { create(:user) }
|
||||
before { login_as(user) }
|
||||
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@gl_project = @project.gl_project
|
||||
@gl_project.team << [user, :master]
|
||||
visit namespace_project_ci_web_hooks_path(@gl_project.namespace, @gl_project)
|
||||
end
|
||||
|
||||
context 'create a trigger' do
|
||||
before do
|
||||
fill_in 'web_hook_url', with: 'http://example.com'
|
||||
click_on 'Add Web Hook'
|
||||
end
|
||||
|
||||
it { expect(@project.web_hooks.count).to eq(1) }
|
||||
|
||||
it 'revokes the trigger' do
|
||||
click_on 'Remove'
|
||||
expect(@project.web_hooks.count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Commits" do
|
||||
include CiStatusHelper
|
||||
|
||||
let(:project) { create(:project) }
|
||||
|
||||
describe "CI" do
|
||||
before do
|
||||
login_as :user
|
||||
project.team << [@user, :master]
|
||||
@ci_project = project.ensure_gitlab_ci_project
|
||||
@commit = FactoryGirl.create :ci_commit, gl_project: project, sha: project.commit.sha
|
||||
@build = FactoryGirl.create :ci_build, commit: @commit
|
||||
@generic_status = FactoryGirl.create :generic_commit_status, commit: @commit
|
||||
end
|
||||
|
||||
before do
|
||||
stub_ci_commit_to_return_yaml_file
|
||||
end
|
||||
|
||||
describe "GET /:project/commits/:sha" do
|
||||
before do
|
||||
visit ci_status_path(@commit)
|
||||
end
|
||||
|
||||
it { expect(page).to have_content @commit.sha[0..7] }
|
||||
it { expect(page).to have_content @commit.git_commit_message }
|
||||
it { expect(page).to have_content @commit.git_author_name }
|
||||
end
|
||||
|
||||
describe "Cancel all builds" do
|
||||
it "cancels commit" do
|
||||
visit ci_status_path(@commit)
|
||||
click_on "Cancel all"
|
||||
expect(page).to have_content "canceled"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Cancel build" do
|
||||
it "cancels build" do
|
||||
visit ci_status_path(@commit)
|
||||
click_on "Cancel"
|
||||
expect(page).to have_content "canceled"
|
||||
end
|
||||
end
|
||||
|
||||
describe ".gitlab-ci.yml not found warning" do
|
||||
it "does not show warning" do
|
||||
visit ci_status_path(@commit)
|
||||
expect(page).not_to have_content ".gitlab-ci.yml not found in this commit"
|
||||
end
|
||||
|
||||
it "shows warning" do
|
||||
stub_ci_commit_yaml_file(nil)
|
||||
visit ci_status_path(@commit)
|
||||
expect(page).to have_content ".gitlab-ci.yml not found in this commit"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -95,7 +95,7 @@ feature 'Login', feature: true do
|
||||
user = create(:user, password: 'not-the-default')
|
||||
|
||||
login_with(user)
|
||||
expect(page).to have_content('Invalid email or password.')
|
||||
expect(page).to have_content('Invalid login or password.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -220,7 +220,7 @@ describe 'GitLab Markdown', feature: true do
|
||||
end
|
||||
end
|
||||
|
||||
# `markdown` calls these two methods
|
||||
# Fake a `current_user` helper
|
||||
def current_user
|
||||
@feat.user
|
||||
end
|
||||
|
||||
@@ -1,53 +1,43 @@
|
||||
require 'spec_helper'
|
||||
|
||||
feature 'Password reset', feature: true do
|
||||
def forgot_password
|
||||
describe 'throttling' do
|
||||
it 'sends reset instructions when not previously sent' do
|
||||
visit root_path
|
||||
forgot_password(create(:user))
|
||||
|
||||
expect(page).to have_content(I18n.t('devise.passwords.send_instructions'))
|
||||
expect(current_path).to eq new_user_session_path
|
||||
end
|
||||
|
||||
it 'sends reset instructions when previously sent more than a minute ago' do
|
||||
user = create(:user)
|
||||
user.send_reset_password_instructions
|
||||
user.update_attribute(:reset_password_sent_at, 5.minutes.ago)
|
||||
|
||||
visit root_path
|
||||
forgot_password(user)
|
||||
|
||||
expect(page).to have_content(I18n.t('devise.passwords.send_instructions'))
|
||||
expect(current_path).to eq new_user_session_path
|
||||
end
|
||||
|
||||
it "throttles multiple resets in a short timespan" do
|
||||
user = create(:user)
|
||||
user.send_reset_password_instructions
|
||||
|
||||
visit root_path
|
||||
forgot_password(user)
|
||||
|
||||
expect(page).to have_content(I18n.t('devise.passwords.recently_reset'))
|
||||
expect(current_path).to eq new_user_password_path
|
||||
end
|
||||
end
|
||||
|
||||
def forgot_password(user)
|
||||
click_on 'Forgot your password?'
|
||||
fill_in 'Email', with: user.email
|
||||
click_button 'Reset password'
|
||||
user.reload
|
||||
end
|
||||
|
||||
def get_reset_token
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
body = mail.body.encoded
|
||||
body.scan(/reset_password_token=(.+)\"/).flatten.first
|
||||
end
|
||||
|
||||
def reset_password(password = 'password')
|
||||
visit edit_user_password_path(reset_password_token: get_reset_token)
|
||||
|
||||
fill_in 'New password', with: password
|
||||
fill_in 'Confirm new password', with: password
|
||||
click_button 'Change your password'
|
||||
end
|
||||
|
||||
describe 'with two-factor authentication' do
|
||||
let(:user) { create(:user, :two_factor) }
|
||||
|
||||
it 'requires login after password reset' do
|
||||
visit root_path
|
||||
|
||||
forgot_password
|
||||
reset_password
|
||||
|
||||
expect(page).to have_content("Your password was changed successfully.")
|
||||
expect(page).not_to have_content("You are now signed in.")
|
||||
expect(current_path).to eq new_user_session_path
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without two-factor authentication' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'automatically logs in after password reset' do
|
||||
visit root_path
|
||||
|
||||
forgot_password
|
||||
reset_password
|
||||
|
||||
expect(current_path).to eq root_path
|
||||
expect(page).to have_content("Your password was changed successfully. You are now signed in.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,6 +34,27 @@ feature 'Project', feature: true do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'remove forked relationship', js: true do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, namespace: user.namespace) }
|
||||
|
||||
before do
|
||||
login_with user
|
||||
create(:forked_project_link, forked_to_project: project)
|
||||
visit edit_namespace_project_path(project.namespace, project)
|
||||
end
|
||||
|
||||
it 'should remove fork' do
|
||||
expect(page).to have_content 'Remove fork relationship'
|
||||
|
||||
remove_with_confirm('Remove fork relationship', project.path)
|
||||
|
||||
expect(page).to have_content 'The fork relationship has been removed.'
|
||||
expect(project.forked?).to be_falsey
|
||||
expect(page).not_to have_content 'Remove fork relationship'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'removal', js: true do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, namespace: user.namespace) }
|
||||
@@ -45,13 +66,13 @@ feature 'Project', feature: true do
|
||||
end
|
||||
|
||||
it 'should remove project' do
|
||||
expect { remove_project }.to change {Project.count}.by(-1)
|
||||
expect { remove_with_confirm('Remove project', project.path) }.to change {Project.count}.by(-1)
|
||||
end
|
||||
end
|
||||
|
||||
def remove_project
|
||||
click_link "Remove project"
|
||||
fill_in 'confirm_name_input', with: project.path
|
||||
def remove_with_confirm(button_text, confirm_with)
|
||||
click_button button_text
|
||||
fill_in 'confirm_name_input', with: confirm_with
|
||||
click_button 'Confirm'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Runners" do
|
||||
let(:user) { create(:user) }
|
||||
include GitlabRoutingHelper
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
let(:user) { create(:user) }
|
||||
before { login_as(user) }
|
||||
|
||||
describe "specific runners" do
|
||||
before do
|
||||
@@ -20,18 +19,17 @@ describe "Runners" do
|
||||
@specific_runner2 = FactoryGirl.create :ci_specific_runner
|
||||
@project.runners << @specific_runner
|
||||
@project2.runners << @specific_runner2
|
||||
|
||||
visit runners_path(@project.gl_project)
|
||||
end
|
||||
|
||||
it "places runners in right places" do
|
||||
visit ci_project_runners_path(@project)
|
||||
expect(page.find(".available-specific-runners")).to have_content(@specific_runner2.display_name)
|
||||
expect(page.find(".activated-specific-runners")).to have_content(@specific_runner.display_name)
|
||||
expect(page.find(".available-shared-runners")).to have_content(@shared_runner.display_name)
|
||||
end
|
||||
|
||||
it "enables specific runner for project" do
|
||||
visit ci_project_runners_path(@project)
|
||||
|
||||
within ".available-specific-runners" do
|
||||
click_on "Enable for this project"
|
||||
end
|
||||
@@ -41,8 +39,7 @@ describe "Runners" do
|
||||
|
||||
it "disables specific runner for project" do
|
||||
@project2.runners << @specific_runner
|
||||
|
||||
visit ci_project_runners_path(@project)
|
||||
visit runners_path(@project.gl_project)
|
||||
|
||||
within ".activated-specific-runners" do
|
||||
click_on "Disable for this project"
|
||||
@@ -52,8 +49,6 @@ describe "Runners" do
|
||||
end
|
||||
|
||||
it "removes specific runner for project if this is last project for that runners" do
|
||||
visit ci_project_runners_path(@project)
|
||||
|
||||
within ".activated-specific-runners" do
|
||||
click_on "Remove runner"
|
||||
end
|
||||
@@ -66,13 +61,11 @@ describe "Runners" do
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@project.gl_project.team << [user, :master]
|
||||
visit runners_path(@project.gl_project)
|
||||
end
|
||||
|
||||
it "enables shared runners" do
|
||||
visit ci_project_runners_path(@project)
|
||||
|
||||
click_on "Enable shared runners"
|
||||
|
||||
expect(@project.reload.shared_runners_enabled).to be_truthy
|
||||
end
|
||||
end
|
||||
@@ -83,13 +76,11 @@ describe "Runners" do
|
||||
@project.gl_project.team << [user, :master]
|
||||
@specific_runner = FactoryGirl.create :ci_specific_runner
|
||||
@project.runners << @specific_runner
|
||||
visit runners_path(@project.gl_project)
|
||||
end
|
||||
|
||||
it "shows runner information" do
|
||||
visit ci_project_runners_path(@project)
|
||||
|
||||
click_on @specific_runner.short_sha
|
||||
|
||||
expect(page).to have_content(@specific_runner.platform)
|
||||
end
|
||||
end
|
||||
@@ -1,13 +1,14 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'Triggers' do
|
||||
let(:user) { create(:user) }
|
||||
let(:user) { create(:user) }
|
||||
before { login_as(user) }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@project.gl_project.team << [user, :master]
|
||||
visit ci_project_triggers_path(@project)
|
||||
@gl_project = @project.gl_project
|
||||
@gl_project.team << [user, :master]
|
||||
visit namespace_project_triggers_path(@gl_project.namespace, @gl_project)
|
||||
end
|
||||
|
||||
context 'create a trigger' do
|
||||
@@ -1,6 +1,8 @@
|
||||
require 'spec_helper'
|
||||
|
||||
feature 'Users', feature: true do
|
||||
let(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') }
|
||||
|
||||
scenario 'GET /users/sign_in creates a new user account' do
|
||||
visit new_user_session_path
|
||||
fill_in 'user_name', with: 'Name Surname'
|
||||
@@ -11,7 +13,6 @@ feature 'Users', feature: true do
|
||||
end
|
||||
|
||||
scenario 'Successful user signin invalidates password reset token' do
|
||||
user = create(:user)
|
||||
expect(user.reset_password_token).to be_nil
|
||||
|
||||
visit new_user_password_path
|
||||
@@ -28,7 +29,6 @@ feature 'Users', feature: true do
|
||||
expect(user.reset_password_token).to be_nil
|
||||
end
|
||||
|
||||
let!(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') }
|
||||
scenario 'Should show one error if email is already taken' do
|
||||
visit new_user_session_path
|
||||
fill_in 'user_name', with: 'Another user name'
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Variables" do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
let(:user) { create(:user) }
|
||||
before { login_as(user) }
|
||||
|
||||
describe "specific runners" do
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@project.gl_project.team << [user, :master]
|
||||
@gl_project = @project.gl_project
|
||||
@gl_project.team << [user, :master]
|
||||
end
|
||||
|
||||
it "creates variable", js: true do
|
||||
visit ci_project_variables_path(@project)
|
||||
visit namespace_project_variables_path(@gl_project.namespace, @gl_project)
|
||||
click_on "Add a variable"
|
||||
fill_in "Key", with: "SECRET_KEY"
|
||||
fill_in "Value", with: "SECRET_VALUE"
|
||||
click_on "Save changes"
|
||||
|
||||
|
||||
expect(page).to have_content("Variables were successfully updated.")
|
||||
expect(@project.variables.count).to eq(1)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -6,9 +6,11 @@ describe IssuesFinder do
|
||||
let(:project1) { create(:project) }
|
||||
let(:project2) { create(:project) }
|
||||
let(:milestone) { create(:milestone, project: project1) }
|
||||
let(:label) { create(:label, project: project2) }
|
||||
let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) }
|
||||
let(:issue2) { create(:issue, author: user, assignee: user, project: project2) }
|
||||
let(:issue3) { create(:issue, author: user2, assignee: user2, project: project2) }
|
||||
let!(:label_link) { create(:label_link, label: label, target: issue2) }
|
||||
|
||||
before do
|
||||
project1.team << [user, :master]
|
||||
@@ -48,6 +50,24 @@ describe IssuesFinder do
|
||||
expect(issues).to eq([issue1])
|
||||
end
|
||||
|
||||
it 'should filter by no milestone id' do
|
||||
params = { scope: "all", milestone_title: Milestone::None.title, state: 'opened' }
|
||||
issues = IssuesFinder.new(user, params).execute
|
||||
expect(issues).to match_array([issue2, issue3])
|
||||
end
|
||||
|
||||
it 'should filter by label name' do
|
||||
params = { scope: "all", label_name: label.title, state: 'opened' }
|
||||
issues = IssuesFinder.new(user, params).execute
|
||||
expect(issues).to eq([issue2])
|
||||
end
|
||||
|
||||
it 'should filter by no label name' do
|
||||
params = { scope: "all", label_name: Label::None.title, state: 'opened' }
|
||||
issues = IssuesFinder.new(user, params).execute
|
||||
expect(issues).to match_array([issue1, issue3])
|
||||
end
|
||||
|
||||
it 'should be empty for unauthorized user' do
|
||||
params = { scope: "all", state: 'opened' }
|
||||
issues = IssuesFinder.new(nil, params).execute
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe TrendingProjectsFinder do
|
||||
let(:user) { build(:user) }
|
||||
|
||||
describe '#execute' do
|
||||
describe 'without an explicit start date' do
|
||||
subject { described_class.new }
|
||||
|
||||
it 'returns the trending projects' do
|
||||
relation = double(:ar_relation)
|
||||
|
||||
allow(subject).to receive(:projects_for)
|
||||
.with(user)
|
||||
.and_return(relation)
|
||||
|
||||
allow(relation).to receive(:trending)
|
||||
.with(an_instance_of(ActiveSupport::TimeWithZone))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with an explicit start date' do
|
||||
let(:date) { 2.months.ago }
|
||||
|
||||
subject { described_class.new }
|
||||
|
||||
it 'returns the trending projects' do
|
||||
relation = double(:ar_relation)
|
||||
|
||||
allow(subject).to receive(:projects_for)
|
||||
.with(user)
|
||||
.and_return(relation)
|
||||
|
||||
allow(relation).to receive(:trending)
|
||||
.with(date)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -99,6 +99,15 @@ describe ApplicationHelper do
|
||||
|
||||
helper.avatar_icon('foo@example.com', 20, 2)
|
||||
end
|
||||
|
||||
describe 'using a User' do
|
||||
it 'should return an URL for the avatar' do
|
||||
user = create(:user, avatar: File.open(avatar_file_path))
|
||||
|
||||
expect(helper.avatar_icon(user).to_s).
|
||||
to match("/uploads/user/avatar/#{user.id}/banana_sample.gif")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'gravatar_icon' do
|
||||
|
||||
@@ -11,12 +11,15 @@ describe GitlabMarkdownHelper do
|
||||
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
|
||||
let(:snippet) { create(:project_snippet, project: project) }
|
||||
|
||||
# Helper expects a current_user method.
|
||||
let(:current_user) { user }
|
||||
|
||||
before do
|
||||
# Ensure the generated reference links aren't redacted
|
||||
project.team << [user, :master]
|
||||
|
||||
# Helper expects a @project instance variable
|
||||
@project = project
|
||||
helper.instance_variable_set(:@project, project)
|
||||
|
||||
# Stub the `current_user` helper
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
describe "#markdown" do
|
||||
@@ -25,23 +28,23 @@ describe GitlabMarkdownHelper do
|
||||
|
||||
it "should link to the merge request" do
|
||||
expected = namespace_project_merge_request_path(project.namespace, project, merge_request)
|
||||
expect(markdown(actual)).to match(expected)
|
||||
expect(helper.markdown(actual)).to match(expected)
|
||||
end
|
||||
|
||||
it "should link to the commit" do
|
||||
expected = namespace_project_commit_path(project.namespace, project, commit)
|
||||
expect(markdown(actual)).to match(expected)
|
||||
expect(helper.markdown(actual)).to match(expected)
|
||||
end
|
||||
|
||||
it "should link to the issue" do
|
||||
expected = namespace_project_issue_path(project.namespace, project, issue)
|
||||
expect(markdown(actual)).to match(expected)
|
||||
expect(helper.markdown(actual)).to match(expected)
|
||||
end
|
||||
end
|
||||
|
||||
describe "override default project" do
|
||||
let(:actual) { issue.to_reference }
|
||||
let(:second_project) { create(:project) }
|
||||
let(:second_project) { create(:project, :public) }
|
||||
let(:second_issue) { create(:issue, project: second_project) }
|
||||
|
||||
it 'should link to the issue' do
|
||||
@@ -56,7 +59,7 @@ describe GitlabMarkdownHelper do
|
||||
let(:issues) { create_list(:issue, 2, project: project) }
|
||||
|
||||
it 'should handle references nested in links with all the text' do
|
||||
actual = link_to_gfm("This should finally fix #{issues[0].to_reference} and #{issues[1].to_reference} for real", commit_path)
|
||||
actual = helper.link_to_gfm("This should finally fix #{issues[0].to_reference} and #{issues[1].to_reference} for real", commit_path)
|
||||
doc = Nokogiri::HTML.parse(actual)
|
||||
|
||||
# Make sure we didn't create invalid markup
|
||||
@@ -86,7 +89,7 @@ describe GitlabMarkdownHelper do
|
||||
end
|
||||
|
||||
it 'should forward HTML options' do
|
||||
actual = link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo')
|
||||
actual = helper.link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo')
|
||||
doc = Nokogiri::HTML.parse(actual)
|
||||
|
||||
expect(doc.css('a')).to satisfy do |v|
|
||||
@@ -97,15 +100,21 @@ describe GitlabMarkdownHelper do
|
||||
|
||||
it "escapes HTML passed in as the body" do
|
||||
actual = "This is a <h1>test</h1> - see #{issues[0].to_reference}"
|
||||
expect(link_to_gfm(actual, commit_path)).
|
||||
expect(helper.link_to_gfm(actual, commit_path)).
|
||||
to match('<h1>test</h1>')
|
||||
end
|
||||
|
||||
it 'ignores reference links when they are the entire body' do
|
||||
text = issues[0].to_reference
|
||||
act = link_to_gfm(text, '/foo')
|
||||
act = helper.link_to_gfm(text, '/foo')
|
||||
expect(act).to eq %Q(<a href="/foo">#{issues[0].to_reference}</a>)
|
||||
end
|
||||
|
||||
it 'should replace commit message with emoji to link' do
|
||||
actual = link_to_gfm(':book:Book', '/foo')
|
||||
expect(actual).
|
||||
to eq %Q(<img class="emoji" title=":book:" alt=":book:" src="http://localhost/assets/emoji/1F4D6.png" height="20" width="20" align="absmiddle"><a href="/foo">Book</a>)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#render_wiki_content' do
|
||||
|
||||
@@ -117,4 +117,14 @@ describe IssuesHelper do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#merge_requests_sentence" do
|
||||
subject { merge_requests_sentence(merge_requests)}
|
||||
let(:merge_requests) do
|
||||
[ build(:merge_request, iid: 1), build(:merge_request, iid: 2),
|
||||
build(:merge_request, iid: 3)]
|
||||
end
|
||||
|
||||
it { is_expected.to eq("!1, !2, or !3") }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe MergeRequestsHelper do
|
||||
describe :issues_sentence do
|
||||
subject { issues_sentence(issues) }
|
||||
let(:issues) do
|
||||
[build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)]
|
||||
end
|
||||
|
||||
it { is_expected.to eq('#1, #2, and #3') }
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe MergeRequestsHelper do
|
||||
describe "#issues_sentence" do
|
||||
subject { issues_sentence(issues) }
|
||||
let(:issues) do
|
||||
[build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)]
|
||||
end
|
||||
|
||||
it { is_expected.to eq('#1, #2, and #3') }
|
||||
end
|
||||
|
||||
describe "#format_mr_branch_names" do
|
||||
describe "within the same project" do
|
||||
let(:merge_request) { create(:merge_request) }
|
||||
subject { format_mr_branch_names(merge_request) }
|
||||
|
||||
it { is_expected.to eq([merge_request.source_branch, merge_request.target_branch]) }
|
||||
end
|
||||
|
||||
describe "within different projects" do
|
||||
let(:project) { create(:project) }
|
||||
let(:fork_project) { create(:project, forked_from_project: project) }
|
||||
let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) }
|
||||
subject { format_mr_branch_names(merge_request) }
|
||||
let(:source_title) { "#{fork_project.path_with_namespace}:#{merge_request.source_branch}" }
|
||||
let(:target_title) { "#{project.path_with_namespace}:#{merge_request.target_branch}" }
|
||||
|
||||
it { is_expected.to eq([source_title, target_title]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -8,14 +8,18 @@ describe PreferencesHelper do
|
||||
end
|
||||
|
||||
it 'raises an exception when defined choices may be using the wrong key' do
|
||||
expect(User).to receive(:dashboards).and_return(foo: 'foo', bar: 'bar')
|
||||
dashboards = User.dashboards.dup
|
||||
dashboards[:projects_changed] = dashboards.delete :projects
|
||||
expect(User).to receive(:dashboards).and_return(dashboards)
|
||||
expect { helper.dashboard_choices }.to raise_error(KeyError)
|
||||
end
|
||||
|
||||
it 'provides better option descriptions' do
|
||||
expect(helper.dashboard_choices).to match_array [
|
||||
['Your Projects (default)', 'projects'],
|
||||
['Starred Projects', 'stars']
|
||||
['Starred Projects', 'stars'],
|
||||
["Your Projects' Activity", 'project_activity'],
|
||||
["Starred Projects' Activity", 'starred_project_activity']
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -61,13 +61,27 @@ describe ProjectsHelper do
|
||||
end
|
||||
|
||||
it "returns a valid cach key" do
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.id}-#{project.commit.id}-readme")
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.path_with_namespace}-#{project.commit.id}-readme")
|
||||
end
|
||||
|
||||
it "returns a valid cache key if HEAD does not exist" do
|
||||
allow(project).to receive(:commit) { nil }
|
||||
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.id}-nil-readme")
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.path_with_namespace}-nil-readme")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'link_to_member' do
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:empty_project, group: group) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
describe 'using the default options' do
|
||||
it 'returns an HTML link to the user' do
|
||||
link = helper.link_to_member(project, user)
|
||||
|
||||
expect(link).to match(%r{/u/#{user.username}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ci::RunnersHelper do
|
||||
describe RunnersHelper do
|
||||
it "returns - not contacted yet" do
|
||||
runner = FactoryGirl.build :ci_runner
|
||||
expect(runner_status_icon(runner)).to include("not connected yet")
|
||||
@@ -12,7 +12,7 @@ describe Ci::RunnersHelper do
|
||||
end
|
||||
|
||||
it "returns online text" do
|
||||
runner = FactoryGirl.build(:ci_runner, contacted_at: 1.hour.ago, active: true)
|
||||
runner = FactoryGirl.build(:ci_runner, contacted_at: 1.second.ago, active: true)
|
||||
expect(runner_status_icon(runner)).to include("Runner is online")
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ci::ApplicationHelper do
|
||||
describe TimeHelper do
|
||||
describe "#duration_in_words" do
|
||||
it "returns minutes and seconds" do
|
||||
intervals_in_words = {
|
||||
@@ -0,0 +1,70 @@
|
||||
#= require behaviors/quick_submit
|
||||
|
||||
describe 'Quick Submit behavior', ->
|
||||
fixture.preload('behaviors/quick_submit.html')
|
||||
|
||||
beforeEach ->
|
||||
fixture.load('behaviors/quick_submit.html')
|
||||
|
||||
# Prevent a form submit from moving us off the testing page
|
||||
$('form').submit (e) -> e.preventDefault()
|
||||
|
||||
@spies = {
|
||||
submit: spyOnEvent('form', 'submit')
|
||||
}
|
||||
|
||||
it 'does not respond to other keyCodes', ->
|
||||
$('input').trigger(keydownEvent(keyCode: 32))
|
||||
|
||||
expect(@spies.submit).not.toHaveBeenTriggered()
|
||||
|
||||
it 'does not respond to Enter alone', ->
|
||||
$('input').trigger(keydownEvent(ctrlKey: false, metaKey: false))
|
||||
|
||||
expect(@spies.submit).not.toHaveBeenTriggered()
|
||||
|
||||
it 'does not respond to repeated events', ->
|
||||
$('input').trigger(keydownEvent(repeat: true))
|
||||
|
||||
expect(@spies.submit).not.toHaveBeenTriggered()
|
||||
|
||||
it 'disables submit buttons', ->
|
||||
$('textarea').trigger(keydownEvent())
|
||||
|
||||
expect($('input[type=submit]')).toBeDisabled()
|
||||
expect($('button[type=submit]')).toBeDisabled()
|
||||
|
||||
# We cannot stub `navigator.userAgent` for CI's `rake teaspoon` task, so we'll
|
||||
# only run the tests that apply to the current platform
|
||||
if navigator.userAgent.match(/Macintosh/)
|
||||
it 'responds to Meta+Enter', ->
|
||||
$('input').trigger(keydownEvent())
|
||||
|
||||
expect(@spies.submit).toHaveBeenTriggered()
|
||||
|
||||
it 'excludes other modifier keys', ->
|
||||
$('input').trigger(keydownEvent(altKey: true))
|
||||
$('input').trigger(keydownEvent(ctrlKey: true))
|
||||
$('input').trigger(keydownEvent(shiftKey: true))
|
||||
|
||||
expect(@spies.submit).not.toHaveBeenTriggered()
|
||||
else
|
||||
it 'responds to Ctrl+Enter', ->
|
||||
$('input').trigger(keydownEvent())
|
||||
|
||||
expect(@spies.submit).toHaveBeenTriggered()
|
||||
|
||||
it 'excludes other modifier keys', ->
|
||||
$('input').trigger(keydownEvent(altKey: true))
|
||||
$('input').trigger(keydownEvent(metaKey: true))
|
||||
$('input').trigger(keydownEvent(shiftKey: true))
|
||||
|
||||
expect(@spies.submit).not.toHaveBeenTriggered()
|
||||
|
||||
keydownEvent = (options) ->
|
||||
if navigator.userAgent.match(/Macintosh/)
|
||||
defaults = { keyCode: 13, metaKey: true }
|
||||
else
|
||||
defaults = { keyCode: 13, ctrlKey: true }
|
||||
|
||||
$.Event('keydown', $.extend({}, defaults, options))
|
||||
@@ -0,0 +1,6 @@
|
||||
%form{ action: '/foo' }
|
||||
%input.js-quick-submit{ type: 'text' }
|
||||
%textarea.js-quick-submit
|
||||
|
||||
%input{ type: 'submit'} Submit
|
||||
%button.btn{ type: 'submit' } Submit
|
||||
@@ -1,4 +1,4 @@
|
||||
#tree-content-holder
|
||||
#blob-content-holder
|
||||
.file-content
|
||||
.line-numbers
|
||||
- 1.upto(25) do |i|
|
||||
|
||||
@@ -39,7 +39,7 @@ describe 'LineHighlighter', ->
|
||||
expect(spy).toHaveBeenPrevented()
|
||||
|
||||
it 'handles garbage input from the hash', ->
|
||||
func = -> new LineHighlighter('#tree-content-holder')
|
||||
func = -> new LineHighlighter('#blob-content-holder')
|
||||
expect(func).not.toThrow()
|
||||
|
||||
describe '#clickHandler', ->
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
# require the specific files that are being used in the spec that tests them.
|
||||
|
||||
#= require jquery
|
||||
#= require jquery.turbolinks
|
||||
#= require bootstrap
|
||||
#= require underscore
|
||||
|
||||
|
||||
@@ -4,13 +4,12 @@ describe "Charts" do
|
||||
|
||||
context "build_times" do
|
||||
before do
|
||||
@project = FactoryGirl.create(:ci_project)
|
||||
@commit = FactoryGirl.create(:ci_commit, project: @project)
|
||||
@commit = FactoryGirl.create(:ci_commit)
|
||||
FactoryGirl.create(:ci_build, commit: @commit)
|
||||
end
|
||||
|
||||
it 'should return build times in minutes' do
|
||||
chart = Ci::Charts::BuildTime.new(@project)
|
||||
chart = Ci::Charts::BuildTime.new(@commit.project)
|
||||
expect(chart.build_times).to eq([2])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,13 +17,15 @@ module Ci
|
||||
expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(1)
|
||||
expect(config_processor.builds_for_stage_and_ref(type, "master").first).to eq({
|
||||
stage: "test",
|
||||
stage_idx: 1,
|
||||
except: nil,
|
||||
name: :rspec,
|
||||
only: nil,
|
||||
script: "pwd\nrspec",
|
||||
tags: [],
|
||||
commands: "pwd\nrspec",
|
||||
tag_list: [],
|
||||
options: {},
|
||||
allow_failure: false
|
||||
allow_failure: false,
|
||||
when: "on_success"
|
||||
})
|
||||
end
|
||||
|
||||
@@ -115,15 +117,17 @@ module Ci
|
||||
expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
|
||||
except: nil,
|
||||
stage: "test",
|
||||
stage_idx: 1,
|
||||
name: :rspec,
|
||||
only: nil,
|
||||
script: "pwd\nrspec",
|
||||
tags: [],
|
||||
commands: "pwd\nrspec",
|
||||
tag_list: [],
|
||||
options: {
|
||||
image: "ruby:2.1",
|
||||
services: ["mysql"]
|
||||
},
|
||||
allow_failure: false
|
||||
allow_failure: false,
|
||||
when: "on_success"
|
||||
})
|
||||
end
|
||||
|
||||
@@ -141,15 +145,17 @@ module Ci
|
||||
expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
|
||||
except: nil,
|
||||
stage: "test",
|
||||
stage_idx: 1,
|
||||
name: :rspec,
|
||||
only: nil,
|
||||
script: "pwd\nrspec",
|
||||
tags: [],
|
||||
commands: "pwd\nrspec",
|
||||
tag_list: [],
|
||||
options: {
|
||||
image: "ruby:2.5",
|
||||
services: ["postgresql"]
|
||||
},
|
||||
allow_failure: false
|
||||
allow_failure: false,
|
||||
when: "on_success"
|
||||
})
|
||||
end
|
||||
end
|
||||
@@ -171,6 +177,21 @@ module Ci
|
||||
end
|
||||
end
|
||||
|
||||
describe "When" do
|
||||
%w(on_success on_failure always).each do |when_state|
|
||||
it "returns #{when_state} when defined" do
|
||||
config = YAML.dump({
|
||||
rspec: { script: "rspec", when: when_state }
|
||||
})
|
||||
|
||||
config_processor = GitlabCiYamlProcessor.new(config)
|
||||
builds = config_processor.builds_for_stage_and_ref("test", "master")
|
||||
expect(builds.size).to eq(1)
|
||||
expect(builds.first[:when]).to eq(when_state)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Error handling" do
|
||||
it "indicates that object is invalid" do
|
||||
expect{GitlabCiYamlProcessor.new("invalid_yaml\n!ccdvlf%612334@@@@")}.to raise_error(GitlabCiYamlProcessor::ValidationError)
|
||||
@@ -197,6 +218,20 @@ module Ci
|
||||
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "image should be a string")
|
||||
end
|
||||
|
||||
it "returns errors if job name is blank" do
|
||||
config = YAML.dump({ '' => { script: "test" } })
|
||||
expect do
|
||||
GitlabCiYamlProcessor.new(config)
|
||||
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "job name should be non-empty string")
|
||||
end
|
||||
|
||||
it "returns errors if job name is non-string" do
|
||||
config = YAML.dump({ 10 => { script: "test" } })
|
||||
expect do
|
||||
GitlabCiYamlProcessor.new(config)
|
||||
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "job name should be non-empty string")
|
||||
end
|
||||
|
||||
it "returns errors if job image parameter is invalid" do
|
||||
config = YAML.dump({ rspec: { script: "test", image: ["test"] } })
|
||||
expect do
|
||||
@@ -308,6 +343,13 @@ module Ci
|
||||
GitlabCiYamlProcessor.new(config)
|
||||
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "variables should be a map of key-valued strings")
|
||||
end
|
||||
|
||||
it "returns errors if job when is not on_success, on_failure or always" do
|
||||
config = YAML.dump({ rspec: { script: "test", when: 1 } })
|
||||
expect do
|
||||
GitlabCiYamlProcessor.new(config)
|
||||
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: when parameter should be on_success, on_failure or always")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -151,14 +151,14 @@ describe Grack::Auth do
|
||||
end
|
||||
|
||||
it "repeated attempts followed by successful attempt" do
|
||||
for n in 0..maxretry 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
|
||||
|
||||
for n in 0..maxretry do
|
||||
maxretry.times.each do
|
||||
expect(attempt_login(false)).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,4 +15,17 @@ describe Gitlab::Shell do
|
||||
it { is_expected.to respond_to :fork_repository }
|
||||
|
||||
it { expect(gitlab_shell.url_to_repo('diaspora')).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git") }
|
||||
|
||||
describe Gitlab::Shell::KeyAdder do
|
||||
describe '#add_key' do
|
||||
it 'normalizes space characters in the key' do
|
||||
io = spy
|
||||
adder = described_class.new(io)
|
||||
|
||||
adder.add_key('key-42', "sha-rsa foo\tbar\tbaz")
|
||||
|
||||
expect(io).to have_received(:puts).with("key-42\tsha-rsa foo bar baz")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -140,28 +140,28 @@ describe Gitlab::ClosingIssueExtractor do
|
||||
message = "Closes #{reference} and fix #{reference2}"
|
||||
|
||||
expect(subject.closed_by_message(message)).
|
||||
to eq([issue, other_issue])
|
||||
to match_array([issue, other_issue])
|
||||
end
|
||||
|
||||
it 'fetches comma-separated issues references in single line message' do
|
||||
message = "Closes #{reference}, closes #{reference2}"
|
||||
|
||||
expect(subject.closed_by_message(message)).
|
||||
to eq([issue, other_issue])
|
||||
to match_array([issue, other_issue])
|
||||
end
|
||||
|
||||
it 'fetches comma-separated issues numbers in single line message' do
|
||||
message = "Closes #{reference}, #{reference2} and #{reference3}"
|
||||
|
||||
expect(subject.closed_by_message(message)).
|
||||
to eq([issue, other_issue, third_issue])
|
||||
to match_array([issue, other_issue, third_issue])
|
||||
end
|
||||
|
||||
it 'fetches issues in multi-line message' do
|
||||
message = "Awesome commit (closes #{reference})\nAlso fixes #{reference2}"
|
||||
|
||||
expect(subject.closed_by_message(message)).
|
||||
to eq([issue, other_issue])
|
||||
to match_array([issue, other_issue])
|
||||
end
|
||||
|
||||
it 'fetches issues in hybrid message' do
|
||||
@@ -169,7 +169,7 @@ describe Gitlab::ClosingIssueExtractor do
|
||||
"Also fixing issues #{reference2}, #{reference3} and #4"
|
||||
|
||||
expect(subject.closed_by_message(message)).
|
||||
to eq([issue, other_issue, third_issue])
|
||||
to match_array([issue, other_issue, third_issue])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Database do
|
||||
# These are just simple smoke tests to check if the methods work (regardless
|
||||
# of what they may return).
|
||||
describe '.mysql?' do
|
||||
subject { described_class.mysql? }
|
||||
|
||||
it { is_expected.to satisfy { |val| val == true || val == false } }
|
||||
end
|
||||
|
||||
describe '.postgresql?' do
|
||||
subject { described_class.postgresql? }
|
||||
|
||||
it { is_expected.to satisfy { |val| val == true || val == false } }
|
||||
end
|
||||
end
|
||||
@@ -13,7 +13,6 @@ describe Gitlab::Email::AttachmentUploader do
|
||||
expect(link).not_to be_nil
|
||||
expect(link[:is_image]).to be_truthy
|
||||
expect(link[:alt]).to eq("bricks")
|
||||
expect(link[:url]).to include("/#{project.path_with_namespace}")
|
||||
expect(link[:url]).to include("bricks.png")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,6 +13,17 @@ describe Gitlab::LDAP::User do
|
||||
let(:auth_hash) do
|
||||
OmniAuth::AuthHash.new(uid: 'my-uid', provider: 'ldapmain', info: info)
|
||||
end
|
||||
let(:ldap_user_upper_case) { Gitlab::LDAP::User.new(auth_hash_upper_case) }
|
||||
let(:info_upper_case) do
|
||||
{
|
||||
name: 'John',
|
||||
email: 'John@Example.com', # Email address has upper case chars
|
||||
nickname: 'john'
|
||||
}
|
||||
end
|
||||
let(:auth_hash_upper_case) do
|
||||
OmniAuth::AuthHash.new(uid: 'my-uid', provider: 'ldapmain', info: info_upper_case)
|
||||
end
|
||||
|
||||
describe :changed? do
|
||||
it "marks existing ldap user as changed" do
|
||||
@@ -57,6 +68,16 @@ describe Gitlab::LDAP::User do
|
||||
expect(existing_user.id).to eql ldap_user.gl_user.id
|
||||
end
|
||||
|
||||
it 'connects to existing ldap user if the extern_uid changes and email address has upper case characters' do
|
||||
existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'old-uid', provider: 'ldapmain')
|
||||
expect{ ldap_user_upper_case.save }.not_to change{ User.count }
|
||||
|
||||
existing_user.reload
|
||||
expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid'
|
||||
expect(existing_user.ldap_identity.provider).to eql 'ldapmain'
|
||||
expect(existing_user.id).to eql ldap_user.gl_user.id
|
||||
end
|
||||
|
||||
it 'maintains an identity per provider' do
|
||||
existing_user = create(:omniauth_user, email: 'john@example.com', provider: 'twitter')
|
||||
expect(existing_user.identities.count).to eql(1)
|
||||
|
||||
@@ -4,7 +4,7 @@ module Gitlab::Markdown
|
||||
describe CommitRangeReferenceFilter do
|
||||
include FilterSpecHelper
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:commit1) { project.commit }
|
||||
let(:commit2) { project.commit("HEAD~2") }
|
||||
|
||||
@@ -75,12 +75,20 @@ module Gitlab::Markdown
|
||||
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit_range'
|
||||
end
|
||||
|
||||
it 'includes a data-project-id attribute' do
|
||||
it 'includes a data-project attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-project-id')
|
||||
expect(link.attr('data-project-id')).to eq project.id.to_s
|
||||
expect(link).to have_attribute('data-project')
|
||||
expect(link.attr('data-project')).to eq project.id.to_s
|
||||
end
|
||||
|
||||
it 'includes a data-commit-range attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-commit-range')
|
||||
expect(link.attr('data-commit-range')).to eq range.to_reference
|
||||
end
|
||||
|
||||
it 'supports an :only_path option' do
|
||||
@@ -92,59 +100,45 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("See #{reference}")
|
||||
result = reference_pipeline_result("See #{reference}")
|
||||
expect(result[:references][:commit_range]).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'cross-project reference' do
|
||||
let(:namespace) { create(:namespace, name: 'cross-reference') }
|
||||
let(:project2) { create(:project, namespace: namespace) }
|
||||
let(:project2) { create(:project, :public, namespace: namespace) }
|
||||
let(:reference) { range.to_reference(project) }
|
||||
|
||||
before do
|
||||
range.project = project2
|
||||
end
|
||||
|
||||
context 'when user can access reference' do
|
||||
before { allow_cross_reference! }
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param)
|
||||
end
|
||||
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Fixed (#{reference}.)")
|
||||
|
||||
exp = Regexp.escape("#{project2.to_reference}@#{range.to_s}")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{exp}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores invalid commit IDs on the referenced project' do
|
||||
exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
|
||||
exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("See #{reference}")
|
||||
expect(result[:references][:commit_range]).not_to be_empty
|
||||
end
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param)
|
||||
end
|
||||
|
||||
context 'when user cannot access reference' do
|
||||
before { disallow_cross_reference! }
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Fixed (#{reference}.)")
|
||||
|
||||
it 'ignores valid references' do
|
||||
exp = act = "See #{reference}"
|
||||
exp = Regexp.escape("#{project2.to_reference}@#{range.to_s}")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{exp}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
it 'ignores invalid commit IDs on the referenced project' do
|
||||
exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
|
||||
exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = reference_pipeline_result("See #{reference}")
|
||||
expect(result[:references][:commit_range]).not_to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ module Gitlab::Markdown
|
||||
describe CommitReferenceFilter do
|
||||
include FilterSpecHelper
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:commit) { project.commit }
|
||||
|
||||
it 'requires project context' do
|
||||
@@ -71,12 +71,20 @@ module Gitlab::Markdown
|
||||
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit'
|
||||
end
|
||||
|
||||
it 'includes a data-project-id attribute' do
|
||||
it 'includes a data-project attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-project-id')
|
||||
expect(link.attr('data-project-id')).to eq project.id.to_s
|
||||
expect(link).to have_attribute('data-project')
|
||||
expect(link.attr('data-project')).to eq project.id.to_s
|
||||
end
|
||||
|
||||
it 'includes a data-commit attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-commit')
|
||||
expect(link.attr('data-commit')).to eq commit.id
|
||||
end
|
||||
|
||||
it 'supports an :only_path context' do
|
||||
@@ -88,53 +96,39 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("See #{reference}")
|
||||
result = reference_pipeline_result("See #{reference}")
|
||||
expect(result[:references][:commit]).not_to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'cross-project reference' do
|
||||
let(:namespace) { create(:namespace, name: 'cross-reference') }
|
||||
let(:project2) { create(:project, namespace: namespace) }
|
||||
let(:project2) { create(:project, :public, namespace: namespace) }
|
||||
let(:commit) { project2.commit }
|
||||
let(:reference) { commit.to_reference(project) }
|
||||
|
||||
context 'when user can access reference' do
|
||||
before { allow_cross_reference! }
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id)
|
||||
end
|
||||
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Fixed (#{reference}.)")
|
||||
|
||||
exp = Regexp.escape(project2.to_reference)
|
||||
expect(doc.to_html).to match(/\(<a.+>#{exp}@#{commit.short_id}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores invalid commit IDs on the referenced project' do
|
||||
exp = act = "Committed #{invalidate_reference(reference)}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("See #{reference}")
|
||||
expect(result[:references][:commit]).not_to be_empty
|
||||
end
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id)
|
||||
end
|
||||
|
||||
context 'when user cannot access reference' do
|
||||
before { disallow_cross_reference! }
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Fixed (#{reference}.)")
|
||||
|
||||
it 'ignores valid references' do
|
||||
exp = act = "See #{reference}"
|
||||
exp = Regexp.escape(project2.to_reference)
|
||||
expect(doc.to_html).to match(/\(<a.+>#{exp}@#{commit.short_id}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
it 'ignores invalid commit IDs on the referenced project' do
|
||||
exp = act = "Committed #{invalidate_reference(reference)}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = reference_pipeline_result("See #{reference}")
|
||||
expect(result[:references][:commit]).not_to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,20 +2,16 @@ require 'spec_helper'
|
||||
|
||||
module Gitlab::Markdown
|
||||
describe CrossProjectReference do
|
||||
# context in the html-pipeline sense, not in the rspec sense
|
||||
let(:context) do
|
||||
{
|
||||
current_user: double('user'),
|
||||
project: double('project')
|
||||
}
|
||||
end
|
||||
|
||||
include described_class
|
||||
|
||||
describe '#project_from_ref' do
|
||||
context 'when no project was referenced' do
|
||||
it 'returns the project from context' do
|
||||
expect(project_from_ref(nil)).to eq context[:project]
|
||||
project = double
|
||||
|
||||
allow(self).to receive(:context).and_return({ project: project })
|
||||
|
||||
expect(project_from_ref(nil)).to eq project
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,29 +22,13 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
context 'when referenced project exists' do
|
||||
let(:project2) { double('referenced project') }
|
||||
it 'returns the referenced project' do
|
||||
project2 = double('referenced project')
|
||||
|
||||
before do
|
||||
expect(Project).to receive(:find_with_namespace).
|
||||
with('cross/reference').and_return(project2)
|
||||
end
|
||||
|
||||
context 'and the user has permission to read it' do
|
||||
it 'returns the referenced project' do
|
||||
expect(self).to receive(:user_can_reference_project?).
|
||||
with(project2).and_return(true)
|
||||
|
||||
expect(project_from_ref('cross/reference')).to eq project2
|
||||
end
|
||||
end
|
||||
|
||||
context 'and the user does not have permission to read it' do
|
||||
it 'returns nil' do
|
||||
expect(self).to receive(:user_can_reference_project?).
|
||||
with(project2).and_return(false)
|
||||
|
||||
expect(project_from_ref('cross/reference')).to be_nil
|
||||
end
|
||||
expect(project_from_ref('cross/reference')).to eq project2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ module Gitlab::Markdown
|
||||
IssuesHelper
|
||||
end
|
||||
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
|
||||
it 'requires project context' do
|
||||
@@ -68,12 +68,20 @@ module Gitlab::Markdown
|
||||
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue'
|
||||
end
|
||||
|
||||
it 'includes a data-project-id attribute' do
|
||||
it 'includes a data-project attribute' do
|
||||
doc = filter("Issue #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-project-id')
|
||||
expect(link.attr('data-project-id')).to eq project.id.to_s
|
||||
expect(link).to have_attribute('data-project')
|
||||
expect(link.attr('data-project')).to eq project.id.to_s
|
||||
end
|
||||
|
||||
it 'includes a data-issue attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-issue')
|
||||
expect(link.attr('data-issue')).to eq issue.id.to_s
|
||||
end
|
||||
|
||||
it 'supports an :only_path context' do
|
||||
@@ -85,60 +93,46 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Fixed #{reference}")
|
||||
result = reference_pipeline_result("Fixed #{reference}")
|
||||
expect(result[:references][:issue]).to eq [issue]
|
||||
end
|
||||
end
|
||||
|
||||
context 'cross-project reference' do
|
||||
let(:namespace) { create(:namespace, name: 'cross-reference') }
|
||||
let(:project2) { create(:empty_project, namespace: namespace) }
|
||||
let(:project2) { create(:empty_project, :public, namespace: namespace) }
|
||||
let(:issue) { create(:issue, project: project2) }
|
||||
let(:reference) { issue.to_reference(project) }
|
||||
|
||||
context 'when user can access reference' do
|
||||
before { allow_cross_reference! }
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
exp = act = "Issue #{reference}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq helper.url_for_issue(issue.iid, project2)
|
||||
end
|
||||
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Fixed (#{reference}.)")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores invalid issue IDs on the referenced project' do
|
||||
exp = act = "Fixed #{invalidate_reference(reference)}"
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Fixed #{reference}")
|
||||
expect(result[:references][:issue]).to eq [issue]
|
||||
end
|
||||
exp = act = "Issue #{reference}"
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
context 'when user cannot access reference' do
|
||||
before { disallow_cross_reference! }
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
it 'ignores valid references' do
|
||||
exp = act = "See #{reference}"
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq helper.url_for_issue(issue.iid, project2)
|
||||
end
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Fixed (#{reference}.)")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores invalid issue IDs on the referenced project' do
|
||||
exp = act = "Fixed #{invalidate_reference(reference)}"
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = reference_pipeline_result("Fixed #{reference}")
|
||||
expect(result[:references][:issue]).to eq [issue]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ module Gitlab::Markdown
|
||||
describe LabelReferenceFilter do
|
||||
include FilterSpecHelper
|
||||
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
let(:label) { create(:label, project: project) }
|
||||
let(:reference) { label.to_reference }
|
||||
|
||||
@@ -25,12 +25,20 @@ module Gitlab::Markdown
|
||||
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-label'
|
||||
end
|
||||
|
||||
it 'includes a data-project-id attribute' do
|
||||
it 'includes a data-project attribute' do
|
||||
doc = filter("Label #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-project-id')
|
||||
expect(link.attr('data-project-id')).to eq project.id.to_s
|
||||
expect(link).to have_attribute('data-project')
|
||||
expect(link.attr('data-project')).to eq project.id.to_s
|
||||
end
|
||||
|
||||
it 'includes a data-label attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-label')
|
||||
expect(link.attr('data-label')).to eq label.id.to_s
|
||||
end
|
||||
|
||||
it 'supports an :only_path context' do
|
||||
@@ -42,7 +50,7 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Label #{reference}")
|
||||
result = reference_pipeline_result("Label #{reference}")
|
||||
expect(result[:references][:label]).to eq [label]
|
||||
end
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ module Gitlab::Markdown
|
||||
describe MergeRequestReferenceFilter do
|
||||
include FilterSpecHelper
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:merge) { create(:merge_request, source_project: project) }
|
||||
|
||||
it 'requires project context' do
|
||||
@@ -56,12 +56,20 @@ module Gitlab::Markdown
|
||||
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-merge_request'
|
||||
end
|
||||
|
||||
it 'includes a data-project-id attribute' do
|
||||
it 'includes a data-project attribute' do
|
||||
doc = filter("Merge #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-project-id')
|
||||
expect(link.attr('data-project-id')).to eq project.id.to_s
|
||||
expect(link).to have_attribute('data-project')
|
||||
expect(link.attr('data-project')).to eq project.id.to_s
|
||||
end
|
||||
|
||||
it 'includes a data-merge-request attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-merge-request')
|
||||
expect(link.attr('data-merge-request')).to eq merge.id.to_s
|
||||
end
|
||||
|
||||
it 'supports an :only_path context' do
|
||||
@@ -73,53 +81,39 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Merge #{reference}")
|
||||
result = reference_pipeline_result("Merge #{reference}")
|
||||
expect(result[:references][:merge_request]).to eq [merge]
|
||||
end
|
||||
end
|
||||
|
||||
context 'cross-project reference' do
|
||||
let(:namespace) { create(:namespace, name: 'cross-reference') }
|
||||
let(:project2) { create(:project, namespace: namespace) }
|
||||
let(:project2) { create(:project, :public, namespace: namespace) }
|
||||
let(:merge) { create(:merge_request, source_project: project2) }
|
||||
let(:reference) { merge.to_reference(project) }
|
||||
|
||||
context 'when user can access reference' do
|
||||
before { allow_cross_reference! }
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_merge_request_url(project2.namespace,
|
||||
project, merge)
|
||||
end
|
||||
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Merge (#{reference}.)")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores invalid merge IDs on the referenced project' do
|
||||
exp = act = "Merge #{invalidate_reference(reference)}"
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Merge #{reference}")
|
||||
expect(result[:references][:merge_request]).to eq [merge]
|
||||
end
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_merge_request_url(project2.namespace,
|
||||
project, merge)
|
||||
end
|
||||
|
||||
context 'when user cannot access reference' do
|
||||
before { disallow_cross_reference! }
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("Merge (#{reference}.)")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores valid references' do
|
||||
exp = act = "See #{reference}"
|
||||
it 'ignores invalid merge IDs on the referenced project' do
|
||||
exp = act = "Merge #{invalidate_reference(reference)}"
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = reference_pipeline_result("Merge #{reference}")
|
||||
expect(result[:references][:merge_request]).to eq [merge]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module Gitlab::Markdown
|
||||
describe RedactorFilter do
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include FilterSpecHelper
|
||||
|
||||
it 'ignores non-GFM links' do
|
||||
html = %(See <a href="https://google.com/">Google</a>)
|
||||
doc = filter(html, current_user: double)
|
||||
|
||||
expect(doc.css('a').length).to eq 1
|
||||
end
|
||||
|
||||
def reference_link(data)
|
||||
link_to('text', '', class: 'gfm', data: data)
|
||||
end
|
||||
|
||||
context 'with data-project' do
|
||||
it 'removes unpermitted Project references' do
|
||||
user = create(:user)
|
||||
project = create(:empty_project)
|
||||
|
||||
link = reference_link(project: project.id, reference_filter: Gitlab::Markdown::ReferenceFilter.name)
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').length).to eq 0
|
||||
end
|
||||
|
||||
it 'allows permitted Project references' do
|
||||
user = create(:user)
|
||||
project = create(:empty_project)
|
||||
project.team << [user, :master]
|
||||
|
||||
link = reference_link(project: project.id, reference_filter: Gitlab::Markdown::ReferenceFilter.name)
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').length).to eq 1
|
||||
end
|
||||
|
||||
it 'handles invalid Project references' do
|
||||
link = reference_link(project: 12345, reference_filter: Gitlab::Markdown::ReferenceFilter.name)
|
||||
|
||||
expect { filter(link) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "for user references" do
|
||||
|
||||
context 'with data-group' do
|
||||
it 'removes unpermitted Group references' do
|
||||
user = create(:user)
|
||||
group = create(:group)
|
||||
|
||||
link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').length).to eq 0
|
||||
end
|
||||
|
||||
it 'allows permitted Group references' do
|
||||
user = create(:user)
|
||||
group = create(:group)
|
||||
group.add_developer(user)
|
||||
|
||||
link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').length).to eq 1
|
||||
end
|
||||
|
||||
it 'handles invalid Group references' do
|
||||
link = reference_link(group: 12345, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
|
||||
expect { filter(link) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'with data-user' do
|
||||
it 'allows any User reference' do
|
||||
user = create(:user)
|
||||
|
||||
link = reference_link(user: user.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
doc = filter(link)
|
||||
|
||||
expect(doc.css('a').length).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,89 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module Gitlab::Markdown
|
||||
describe ReferenceGathererFilter do
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include FilterSpecHelper
|
||||
|
||||
def reference_link(data)
|
||||
link_to('text', '', class: 'gfm', data: data)
|
||||
end
|
||||
|
||||
context "for issue references" do
|
||||
|
||||
context 'with data-project' do
|
||||
it 'removes unpermitted Project references' do
|
||||
user = create(:user)
|
||||
project = create(:empty_project)
|
||||
issue = create(:issue, project: project)
|
||||
|
||||
link = reference_link(project: project.id, issue: issue.id, reference_filter: Gitlab::Markdown::IssueReferenceFilter.name)
|
||||
result = pipeline_result(link, current_user: user)
|
||||
|
||||
expect(result[:references][:issue]).to be_empty
|
||||
end
|
||||
|
||||
it 'allows permitted Project references' do
|
||||
user = create(:user)
|
||||
project = create(:empty_project)
|
||||
issue = create(:issue, project: project)
|
||||
project.team << [user, :master]
|
||||
|
||||
link = reference_link(project: project.id, issue: issue.id, reference_filter: Gitlab::Markdown::IssueReferenceFilter.name)
|
||||
result = pipeline_result(link, current_user: user)
|
||||
|
||||
expect(result[:references][:issue]).to eq([issue])
|
||||
end
|
||||
|
||||
it 'handles invalid Project references' do
|
||||
link = reference_link(project: 12345, issue: 12345, reference_filter: Gitlab::Markdown::IssueReferenceFilter.name)
|
||||
|
||||
expect { pipeline_result(link) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "for user references" do
|
||||
|
||||
context 'with data-group' do
|
||||
it 'removes unpermitted Group references' do
|
||||
user = create(:user)
|
||||
group = create(:group)
|
||||
|
||||
link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
result = pipeline_result(link, current_user: user)
|
||||
|
||||
expect(result[:references][:user]).to be_empty
|
||||
end
|
||||
|
||||
it 'allows permitted Group references' do
|
||||
user = create(:user)
|
||||
group = create(:group)
|
||||
group.add_developer(user)
|
||||
|
||||
link = reference_link(group: group.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
result = pipeline_result(link, current_user: user)
|
||||
|
||||
expect(result[:references][:user]).to eq([user])
|
||||
end
|
||||
|
||||
it 'handles invalid Group references' do
|
||||
link = reference_link(group: 12345, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
|
||||
expect { pipeline_result(link) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'with data-user' do
|
||||
it 'allows any User reference' do
|
||||
user = create(:user)
|
||||
|
||||
link = reference_link(user: user.id, reference_filter: Gitlab::Markdown::UserReferenceFilter.name)
|
||||
result = pipeline_result(link)
|
||||
|
||||
expect(result[:references][:user]).to eq([user])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@ module Gitlab::Markdown
|
||||
describe SnippetReferenceFilter do
|
||||
include FilterSpecHelper
|
||||
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
let(:snippet) { create(:project_snippet, project: project) }
|
||||
let(:reference) { snippet.to_reference }
|
||||
|
||||
@@ -55,12 +55,20 @@ module Gitlab::Markdown
|
||||
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet'
|
||||
end
|
||||
|
||||
it 'includes a data-project-id attribute' do
|
||||
it 'includes a data-project attribute' do
|
||||
doc = filter("Snippet #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-project-id')
|
||||
expect(link.attr('data-project-id')).to eq project.id.to_s
|
||||
expect(link).to have_attribute('data-project')
|
||||
expect(link.attr('data-project')).to eq project.id.to_s
|
||||
end
|
||||
|
||||
it 'includes a data-snippet attribute' do
|
||||
doc = filter("See #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-snippet')
|
||||
expect(link.attr('data-snippet')).to eq snippet.id.to_s
|
||||
end
|
||||
|
||||
it 'supports an :only_path context' do
|
||||
@@ -72,52 +80,38 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Snippet #{reference}")
|
||||
result = reference_pipeline_result("Snippet #{reference}")
|
||||
expect(result[:references][:snippet]).to eq [snippet]
|
||||
end
|
||||
end
|
||||
|
||||
context 'cross-project reference' do
|
||||
let(:namespace) { create(:namespace, name: 'cross-reference') }
|
||||
let(:project2) { create(:empty_project, namespace: namespace) }
|
||||
let(:project2) { create(:empty_project, :public, namespace: namespace) }
|
||||
let(:snippet) { create(:project_snippet, project: project2) }
|
||||
let(:reference) { snippet.to_reference(project) }
|
||||
|
||||
context 'when user can access reference' do
|
||||
before { allow_cross_reference! }
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
it 'links to a valid reference' do
|
||||
doc = filter("See #{reference}")
|
||||
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet)
|
||||
end
|
||||
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("See (#{reference}.)")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores invalid snippet IDs on the referenced project' do
|
||||
exp = act = "See #{invalidate_reference(reference)}"
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Snippet #{reference}")
|
||||
expect(result[:references][:snippet]).to eq [snippet]
|
||||
end
|
||||
expect(doc.css('a').first.attr('href')).
|
||||
to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet)
|
||||
end
|
||||
|
||||
context 'when user cannot access reference' do
|
||||
before { disallow_cross_reference! }
|
||||
it 'links with adjacent text' do
|
||||
doc = filter("See (#{reference}.)")
|
||||
expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(reference)}<\/a>\.\)/)
|
||||
end
|
||||
|
||||
it 'ignores valid references' do
|
||||
exp = act = "See #{reference}"
|
||||
it 'ignores invalid snippet IDs on the referenced project' do
|
||||
exp = act = "See #{invalidate_reference(reference)}"
|
||||
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
expect(filter(act).to_html).to eq exp
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = reference_pipeline_result("Snippet #{reference}")
|
||||
expect(result[:references][:snippet]).to eq [snippet]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
module Gitlab::Markdown
|
||||
describe UploadLinkFilter do
|
||||
def filter(doc, contexts = {})
|
||||
contexts.reverse_merge!({
|
||||
project: project
|
||||
})
|
||||
|
||||
described_class.call(doc, contexts)
|
||||
end
|
||||
|
||||
def image(path)
|
||||
%(<img src="#{path}" />)
|
||||
end
|
||||
|
||||
def link(path)
|
||||
%(<a href="#{path}">#{path}</a>)
|
||||
end
|
||||
|
||||
let(:project) { create(:project) }
|
||||
|
||||
shared_examples :preserve_unchanged do
|
||||
it 'does not modify any relative URL in anchor' do
|
||||
doc = filter(link('README.md'))
|
||||
expect(doc.at_css('a')['href']).to eq 'README.md'
|
||||
end
|
||||
|
||||
it 'does not modify any relative URL in image' do
|
||||
doc = filter(image('files/images/logo-black.png'))
|
||||
expect(doc.at_css('img')['src']).to eq 'files/images/logo-black.png'
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not raise an exception on invalid URIs' do
|
||||
act = link("://foo")
|
||||
expect { filter(act) }.not_to raise_error
|
||||
end
|
||||
|
||||
context 'with a valid repository' do
|
||||
it 'rebuilds relative URL for a link' do
|
||||
doc = filter(link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg'))
|
||||
expect(doc.at_css('a')['href']).
|
||||
to eq "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg"
|
||||
end
|
||||
|
||||
it 'rebuilds relative URL for an image' do
|
||||
doc = filter(link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg'))
|
||||
expect(doc.at_css('a')['href']).
|
||||
to eq "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg"
|
||||
end
|
||||
|
||||
it 'does not modify absolute URL' do
|
||||
doc = filter(link('http://example.com'))
|
||||
expect(doc.at_css('a')['href']).to eq 'http://example.com'
|
||||
end
|
||||
|
||||
it 'supports Unicode filenames' do
|
||||
path = '/uploads/한글.png'
|
||||
escaped = Addressable::URI.escape(path)
|
||||
|
||||
# Stub these methods so the file doesn't actually need to be in the repo
|
||||
allow_any_instance_of(described_class).
|
||||
to receive(:file_exists?).and_return(true)
|
||||
allow_any_instance_of(described_class).
|
||||
to receive(:image?).with(path).and_return(true)
|
||||
|
||||
doc = filter(image(escaped))
|
||||
expect(doc.at_css('img')['src']).to match "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/%ED%95%9C%EA%B8%80.png"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@ module Gitlab::Markdown
|
||||
describe UserReferenceFilter do
|
||||
include FilterSpecHelper
|
||||
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
let(:user) { create(:user) }
|
||||
let(:reference) { user.to_reference }
|
||||
|
||||
@@ -39,7 +39,7 @@ module Gitlab::Markdown
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Hey #{reference}")
|
||||
result = reference_pipeline_result("Hey #{reference}")
|
||||
expect(result[:references][:user]).to eq [project.creator]
|
||||
end
|
||||
end
|
||||
@@ -64,59 +64,40 @@ module Gitlab::Markdown
|
||||
expect(doc.css('a').length).to eq 1
|
||||
end
|
||||
|
||||
it 'includes a data-user-id attribute' do
|
||||
it 'includes a data-user attribute' do
|
||||
doc = filter("Hey #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-user-id')
|
||||
expect(link.attr('data-user-id')).to eq user.namespace.owner_id.to_s
|
||||
expect(link).to have_attribute('data-user')
|
||||
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Hey #{reference}")
|
||||
result = reference_pipeline_result("Hey #{reference}")
|
||||
expect(result[:references][:user]).to eq [user]
|
||||
end
|
||||
end
|
||||
|
||||
context 'mentioning a group' do
|
||||
let(:group) { create(:group) }
|
||||
let(:user) { create(:user) }
|
||||
let(:reference) { group.to_reference }
|
||||
|
||||
context 'that the current user can read' do
|
||||
before do
|
||||
group.add_developer(user)
|
||||
end
|
||||
|
||||
it 'links to the Group' do
|
||||
doc = filter("Hey #{reference}", current_user: user)
|
||||
expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
|
||||
end
|
||||
|
||||
it 'includes a data-group-id attribute' do
|
||||
doc = filter("Hey #{reference}", current_user: user)
|
||||
link = doc.css('a').first
|
||||
|
||||
expect(link).to have_attribute('data-group-id')
|
||||
expect(link.attr('data-group-id')).to eq group.id.to_s
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = pipeline_result("Hey #{reference}", current_user: user)
|
||||
expect(result[:references][:user]).to eq group.users
|
||||
end
|
||||
it 'links to the Group' do
|
||||
doc = filter("Hey #{reference}")
|
||||
expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
|
||||
end
|
||||
|
||||
context 'that the current user cannot read' do
|
||||
it 'ignores references to the Group' do
|
||||
doc = filter("Hey #{reference}", current_user: user)
|
||||
expect(doc.to_html).to eq "Hey #{reference}"
|
||||
end
|
||||
it 'includes a data-group attribute' do
|
||||
doc = filter("Hey #{reference}")
|
||||
link = doc.css('a').first
|
||||
|
||||
it 'does not add to the results hash' do
|
||||
result = pipeline_result("Hey #{reference}", current_user: user)
|
||||
expect(result[:references][:user]).to eq []
|
||||
end
|
||||
expect(link).to have_attribute('data-group')
|
||||
expect(link.attr('data-group')).to eq group.id.to_s
|
||||
end
|
||||
|
||||
it 'adds to the results hash' do
|
||||
result = reference_pipeline_result("Hey #{reference}")
|
||||
expect(result[:references][:user]).to eq group.users
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -19,10 +19,6 @@ describe Gitlab::OAuth::User do
|
||||
let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
|
||||
|
||||
it "finds an existing user based on uid and provider (facebook)" do
|
||||
# FIXME (rspeicher): It's unlikely that this test is actually doing anything
|
||||
# `auth` is never used and removing it entirely doesn't break the test, so
|
||||
# what's it doing?
|
||||
auth = double(info: double(name: 'John'), uid: 'my-uid', provider: 'my-provider')
|
||||
expect( oauth_user.persisted? ).to be_truthy
|
||||
end
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ describe Gitlab::ReferenceExtractor do
|
||||
project.team << [@u_bar, :guest]
|
||||
|
||||
subject.analyze('@foo, @baduser, @bar, and @offteam')
|
||||
expect(subject.users).to eq([@u_foo, @u_bar, @u_offteam])
|
||||
expect(subject.users).to match_array([@u_foo, @u_bar, @u_offteam])
|
||||
end
|
||||
|
||||
it 'ignores user mentions inside specific elements' do
|
||||
@@ -37,7 +37,7 @@ describe Gitlab::ReferenceExtractor do
|
||||
|
||||
> @offteam
|
||||
})
|
||||
expect(subject.users).to eq([])
|
||||
expect(subject.users).to match_array([])
|
||||
end
|
||||
|
||||
it 'accesses valid issue objects' do
|
||||
@@ -45,7 +45,7 @@ describe Gitlab::ReferenceExtractor do
|
||||
@i1 = create(:issue, project: project)
|
||||
|
||||
subject.analyze("#{@i0.to_reference}, #{@i1.to_reference}, and #{Issue.reference_prefix}999.")
|
||||
expect(subject.issues).to eq([@i0, @i1])
|
||||
expect(subject.issues).to match_array([@i0, @i1])
|
||||
end
|
||||
|
||||
it 'accesses valid merge requests' do
|
||||
@@ -53,7 +53,7 @@ describe Gitlab::ReferenceExtractor do
|
||||
@m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'feature_conflict')
|
||||
|
||||
subject.analyze("!999, !#{@m1.iid}, and !#{@m0.iid}.")
|
||||
expect(subject.merge_requests).to eq([@m1, @m0])
|
||||
expect(subject.merge_requests).to match_array([@m1, @m0])
|
||||
end
|
||||
|
||||
it 'accesses valid labels' do
|
||||
@@ -62,7 +62,7 @@ describe Gitlab::ReferenceExtractor do
|
||||
@l2 = create(:label)
|
||||
|
||||
subject.analyze("~#{@l0.id}, ~999, ~#{@l2.id}, ~#{@l1.id}")
|
||||
expect(subject.labels).to eq([@l0, @l1])
|
||||
expect(subject.labels).to match_array([@l0, @l1])
|
||||
end
|
||||
|
||||
it 'accesses valid snippets' do
|
||||
@@ -71,7 +71,7 @@ describe Gitlab::ReferenceExtractor do
|
||||
@s2 = create(:project_snippet)
|
||||
|
||||
subject.analyze("$#{@s0.id}, $999, $#{@s2.id}, $#{@s1.id}")
|
||||
expect(subject.snippets).to eq([@s0, @s1])
|
||||
expect(subject.snippets).to match_array([@s0, @s1])
|
||||
end
|
||||
|
||||
it 'accesses valid commits' do
|
||||
@@ -109,7 +109,7 @@ describe Gitlab::ReferenceExtractor do
|
||||
subject.analyze("this refers issue #{issue.to_reference(project)}")
|
||||
extracted = subject.issues
|
||||
expect(extracted.size).to eq(1)
|
||||
expect(extracted).to eq([issue])
|
||||
expect(extracted).to match_array([issue])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::UploadsTransfer do
|
||||
before do
|
||||
@root_dir = File.join(Rails.root, "public", "uploads")
|
||||
@upload_transfer = Gitlab::UploadsTransfer.new
|
||||
|
||||
@project_path_was = "test_project_was"
|
||||
@project_path = "test_project"
|
||||
@namespace_path_was = "test_namespace_was"
|
||||
@namespace_path = "test_namespace"
|
||||
end
|
||||
|
||||
after do
|
||||
FileUtils.rm_rf([
|
||||
File.join(@root_dir, @namespace_path),
|
||||
File.join(@root_dir, @namespace_path_was)
|
||||
])
|
||||
end
|
||||
|
||||
describe '#move_project' do
|
||||
it "moves project upload to another namespace" do
|
||||
FileUtils.mkdir_p(File.join(@root_dir, @namespace_path_was, @project_path))
|
||||
@upload_transfer.move_project(@project_path, @namespace_path_was, @namespace_path)
|
||||
|
||||
expected_path = File.join(@root_dir, @namespace_path, @project_path)
|
||||
expect(Dir.exist?(expected_path)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#rename_project' do
|
||||
it "renames project" do
|
||||
FileUtils.mkdir_p(File.join(@root_dir, @namespace_path, @project_path_was))
|
||||
@upload_transfer.rename_project(@project_path_was, @project_path, @namespace_path)
|
||||
|
||||
expected_path = File.join(@root_dir, @namespace_path, @project_path)
|
||||
expect(Dir.exist?(expected_path)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#rename_namespace' do
|
||||
it "renames namespace" do
|
||||
FileUtils.mkdir_p(File.join(@root_dir, @namespace_path_was, @project_path))
|
||||
@upload_transfer.rename_namespace(@namespace_path_was, @namespace_path)
|
||||
|
||||
expected_path = File.join(@root_dir, @namespace_path, @project_path)
|
||||
expect(Dir.exist?(expected_path)).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,8 +5,7 @@ describe Ci::Notify do
|
||||
include EmailSpec::Matchers
|
||||
|
||||
before do
|
||||
@project = FactoryGirl.create :ci_project
|
||||
@commit = FactoryGirl.create :ci_commit, project: @project
|
||||
@commit = FactoryGirl.create :ci_commit
|
||||
@build = FactoryGirl.create :ci_build, commit: @commit
|
||||
end
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ describe Notify do
|
||||
end
|
||||
|
||||
it 'has headers that reference an existing thread' do
|
||||
is_expected.to have_header 'Message-ID', /<(.*)@#{Gitlab.config.gitlab.host}>/
|
||||
is_expected.to have_header 'References', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
|
||||
is_expected.to have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
|
||||
is_expected.to have_header 'X-GitLab-Project', /#{project.name}/
|
||||
@@ -399,7 +400,7 @@ describe Notify do
|
||||
describe 'project was moved' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
subject { Notify.project_was_moved_email(project.id, user.id) }
|
||||
subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
|
||||
|
||||
it_behaves_like 'an email sent from GitLab'
|
||||
|
||||
|
||||
@@ -16,4 +16,16 @@ RSpec.describe AbuseReport, type: :model do
|
||||
subject { create(:abuse_report) }
|
||||
|
||||
it { expect(subject).to be_valid }
|
||||
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:reporter).class_name('User') }
|
||||
it { is_expected.to belong_to(:user) }
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
it { is_expected.to validate_presence_of(:reporter) }
|
||||
it { is_expected.to validate_presence_of(:user) }
|
||||
it { is_expected.to validate_presence_of(:message) }
|
||||
it { is_expected.to validate_uniqueness_of(:user_id) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,12 +27,12 @@ describe BroadcastMessage do
|
||||
end
|
||||
|
||||
it "should return nil if time not come" do
|
||||
broadcast_message = create(:broadcast_message, starts_at: Time.now.tomorrow, ends_at: Time.now + 2.days)
|
||||
create(:broadcast_message, starts_at: Time.now.tomorrow, ends_at: Time.now + 2.days)
|
||||
expect(BroadcastMessage.current).to be_nil
|
||||
end
|
||||
|
||||
it "should return nil if time has passed" do
|
||||
broadcast_message = create(:broadcast_message, starts_at: Time.now - 2.days, ends_at: Time.now.yesterday)
|
||||
create(:broadcast_message, starts_at: Time.now - 2.days, ends_at: Time.now.yesterday)
|
||||
expect(BroadcastMessage.current).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,16 +27,12 @@ require 'spec_helper'
|
||||
|
||||
describe Ci::Build do
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
|
||||
let(:build) { FactoryGirl.create :ci_build, commit: commit }
|
||||
|
||||
it { is_expected.to belong_to(:commit) }
|
||||
it { is_expected.to validate_presence_of :status }
|
||||
it { is_expected.to validate_presence_of :ref }
|
||||
|
||||
it { is_expected.to respond_to :success? }
|
||||
it { is_expected.to respond_to :failed? }
|
||||
it { is_expected.to respond_to :running? }
|
||||
it { is_expected.to respond_to :pending? }
|
||||
it { is_expected.to respond_to :trace_html }
|
||||
|
||||
describe :first_pending do
|
||||
@@ -63,72 +59,6 @@ describe Ci::Build do
|
||||
end
|
||||
end
|
||||
|
||||
describe :started? do
|
||||
subject { build.started? }
|
||||
|
||||
context 'without started_at' do
|
||||
before { build.started_at = nil }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
%w(running success failed).each do |status|
|
||||
context "if build status is #{status}" do
|
||||
before { build.status = status }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
%w(pending canceled).each do |status|
|
||||
context "if build status is #{status}" do
|
||||
before { build.status = status }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :active? do
|
||||
subject { build.active? }
|
||||
|
||||
%w(pending running).each do |state|
|
||||
context "if build.status is #{state}" do
|
||||
before { build.status = state }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
%w(success failed canceled).each do |state|
|
||||
context "if build.status is #{state}" do
|
||||
before { build.status = state }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :complete? do
|
||||
subject { build.complete? }
|
||||
|
||||
%w(success failed canceled).each do |state|
|
||||
context "if build.status is #{state}" do
|
||||
before { build.status = state }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
%w(pending running).each do |state|
|
||||
context "if build.status is #{state}" do
|
||||
before { build.status = state }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :ignored? do
|
||||
subject { build.ignored? }
|
||||
|
||||
@@ -177,6 +107,17 @@ describe Ci::Build do
|
||||
it { is_expected.to include(text) }
|
||||
it { expect(subject.length).to be >= text.length }
|
||||
end
|
||||
|
||||
context 'if build.trace hides token' do
|
||||
let(:token) { 'my_secret_token' }
|
||||
|
||||
before do
|
||||
build.project.update_attributes(token: token)
|
||||
build.update_attributes(trace: token)
|
||||
end
|
||||
|
||||
it { is_expected.to_not include(token) }
|
||||
end
|
||||
end
|
||||
|
||||
describe :timeout do
|
||||
@@ -185,31 +126,6 @@ describe Ci::Build do
|
||||
it { is_expected.to eq(commit.project.timeout) }
|
||||
end
|
||||
|
||||
describe :duration do
|
||||
subject { build.duration }
|
||||
|
||||
it { is_expected.to eq(120.0) }
|
||||
|
||||
context 'if the building process has not started yet' do
|
||||
before do
|
||||
build.started_at = nil
|
||||
build.finished_at = nil
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'if the building process has started' do
|
||||
before do
|
||||
build.started_at = Time.now - 1.minute
|
||||
build.finished_at = nil
|
||||
end
|
||||
|
||||
it { is_expected.to be_a(Float) }
|
||||
it { is_expected.to be > 0.0 }
|
||||
end
|
||||
end
|
||||
|
||||
describe :options do
|
||||
let(:options) do
|
||||
{
|
||||
@@ -224,30 +140,6 @@ describe Ci::Build do
|
||||
it { is_expected.to eq(options) }
|
||||
end
|
||||
|
||||
describe :ref do
|
||||
subject { build.ref }
|
||||
|
||||
it { is_expected.to eq(commit.ref) }
|
||||
end
|
||||
|
||||
describe :sha do
|
||||
subject { build.sha }
|
||||
|
||||
it { is_expected.to eq(commit.sha) }
|
||||
end
|
||||
|
||||
describe :short_sha do
|
||||
subject { build.short_sha }
|
||||
|
||||
it { is_expected.to eq(commit.short_sha) }
|
||||
end
|
||||
|
||||
describe :before_sha do
|
||||
subject { build.before_sha }
|
||||
|
||||
it { is_expected.to eq(commit.before_sha) }
|
||||
end
|
||||
|
||||
describe :allow_git_fetch do
|
||||
subject { build.allow_git_fetch }
|
||||
|
||||
@@ -308,13 +200,34 @@ describe Ci::Build do
|
||||
context 'returns variables' do
|
||||
subject { build.variables }
|
||||
|
||||
let(:variables) do
|
||||
let(:predefined_variables) do
|
||||
[
|
||||
{ key: :CI_BUILD_NAME, value: 'test', public: true },
|
||||
{ key: :CI_BUILD_STAGE, value: 'stage', public: true },
|
||||
]
|
||||
end
|
||||
|
||||
let(:yaml_variables) do
|
||||
[
|
||||
{ key: :DB_NAME, value: 'postgres', public: true }
|
||||
]
|
||||
end
|
||||
|
||||
it { is_expected.to eq(variables) }
|
||||
before { build.update_attributes(stage: 'stage') }
|
||||
|
||||
it { is_expected.to eq(predefined_variables + yaml_variables) }
|
||||
|
||||
context 'for tag' do
|
||||
let(:tag_variable) do
|
||||
[
|
||||
{ key: :CI_BUILD_TAG, value: 'master', public: true }
|
||||
]
|
||||
end
|
||||
|
||||
before { build.update_attributes(tag: true) }
|
||||
|
||||
it { is_expected.to eq(tag_variable + predefined_variables + yaml_variables) }
|
||||
end
|
||||
|
||||
context 'and secure variables' do
|
||||
let(:secure_variables) do
|
||||
@@ -327,7 +240,7 @@ describe Ci::Build do
|
||||
build.project.variables << Ci::Variable.new(key: 'SECRET_KEY', value: 'secret_value')
|
||||
end
|
||||
|
||||
it { is_expected.to eq(variables + secure_variables) }
|
||||
it { is_expected.to eq(predefined_variables + yaml_variables + secure_variables) }
|
||||
|
||||
context 'and trigger variables' do
|
||||
let(:trigger) { FactoryGirl.create :ci_trigger, project: project }
|
||||
@@ -337,14 +250,154 @@ describe Ci::Build do
|
||||
{ key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false }
|
||||
]
|
||||
end
|
||||
let(:predefined_trigger_variable) do
|
||||
[
|
||||
{ key: :CI_BUILD_TRIGGERED, value: 'true', public: true }
|
||||
]
|
||||
end
|
||||
|
||||
before do
|
||||
build.trigger_request = trigger_request
|
||||
end
|
||||
|
||||
it { is_expected.to eq(variables + secure_variables + trigger_variables) }
|
||||
it { is_expected.to eq(predefined_variables + predefined_trigger_variable + yaml_variables + secure_variables + trigger_variables) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :project_recipients do
|
||||
let(:pusher_email) { 'pusher@gitlab.test' }
|
||||
let(:user) { User.new(notification_email: pusher_email) }
|
||||
subject { build.project_recipients }
|
||||
|
||||
before do
|
||||
build.update_attributes(user: user)
|
||||
end
|
||||
|
||||
it 'should return pusher_email as only recipient when no additional recipients are given' do
|
||||
project.update_attributes(email_add_pusher: true,
|
||||
email_recipients: '')
|
||||
is_expected.to eq([pusher_email])
|
||||
end
|
||||
|
||||
it 'should return pusher_email and additional recipients' do
|
||||
project.update_attributes(email_add_pusher: true,
|
||||
email_recipients: 'rec1 rec2')
|
||||
is_expected.to eq(['rec1', 'rec2', pusher_email])
|
||||
end
|
||||
|
||||
it 'should return recipients' do
|
||||
project.update_attributes(email_add_pusher: false,
|
||||
email_recipients: 'rec1 rec2')
|
||||
is_expected.to eq(['rec1', 'rec2'])
|
||||
end
|
||||
|
||||
it 'should return unique recipients only' do
|
||||
project.update_attributes(email_add_pusher: true,
|
||||
email_recipients: "rec1 rec1 #{pusher_email}")
|
||||
is_expected.to eq(['rec1', pusher_email])
|
||||
end
|
||||
end
|
||||
|
||||
describe :can_be_served? do
|
||||
let(:runner) { FactoryGirl.create :ci_specific_runner }
|
||||
|
||||
before { build.project.runners << runner }
|
||||
|
||||
context 'runner without tags' do
|
||||
it 'can handle builds without tags' do
|
||||
expect(build.can_be_served?(runner)).to be_truthy
|
||||
end
|
||||
|
||||
it 'cannot handle build with tags' do
|
||||
build.tag_list = ['aa']
|
||||
expect(build.can_be_served?(runner)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context 'runner with tags' do
|
||||
before { runner.tag_list = ['bb', 'cc'] }
|
||||
|
||||
it 'can handle builds without tags' do
|
||||
expect(build.can_be_served?(runner)).to be_truthy
|
||||
end
|
||||
|
||||
it 'can handle build with matching tags' do
|
||||
build.tag_list = ['bb']
|
||||
expect(build.can_be_served?(runner)).to be_truthy
|
||||
end
|
||||
|
||||
it 'cannot handle build with not matching tags' do
|
||||
build.tag_list = ['aa']
|
||||
expect(build.can_be_served?(runner)).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :any_runners_online? do
|
||||
subject { build.any_runners_online? }
|
||||
|
||||
context 'when no runners' do
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
context 'if there are runner' do
|
||||
let(:runner) { FactoryGirl.create :ci_specific_runner }
|
||||
|
||||
before do
|
||||
build.project.runners << runner
|
||||
runner.update_attributes(contacted_at: 1.second.ago)
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
|
||||
it 'that is inactive' do
|
||||
runner.update_attributes(active: false)
|
||||
is_expected.to be_falsey
|
||||
end
|
||||
|
||||
it 'that is not online' do
|
||||
runner.update_attributes(contacted_at: nil)
|
||||
is_expected.to be_falsey
|
||||
end
|
||||
|
||||
it 'that cannot handle build' do
|
||||
expect_any_instance_of(Ci::Build).to receive(:can_be_served?).and_return(false)
|
||||
is_expected.to be_falsey
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe :show_warning? do
|
||||
subject { build.show_warning? }
|
||||
|
||||
%w(pending).each do |state|
|
||||
context "if commit_status.status is #{state}" do
|
||||
before { build.status = state }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
|
||||
context "and there are specific runner" do
|
||||
let(:runner) { FactoryGirl.create :ci_specific_runner, contacted_at: 1.second.ago }
|
||||
|
||||
before do
|
||||
build.project.runners << runner
|
||||
runner.save
|
||||
end
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%w(success failed canceled running).each do |state|
|
||||
context "if commit_status.status is #{state}" do
|
||||
before { build.status = state }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
+265
-112
@@ -19,21 +19,37 @@ require 'spec_helper'
|
||||
|
||||
describe Ci::Commit do
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:commit_with_project) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:config_processor) { Ci::GitlabCiYamlProcessor.new(gitlab_ci_yaml) }
|
||||
let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
|
||||
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to belong_to(:gl_project) }
|
||||
it { is_expected.to have_many(:statuses) }
|
||||
it { is_expected.to have_many(:trigger_requests) }
|
||||
it { is_expected.to have_many(:builds) }
|
||||
it { is_expected.to validate_presence_of :before_sha }
|
||||
it { is_expected.to validate_presence_of :sha }
|
||||
it { is_expected.to validate_presence_of :ref }
|
||||
it { is_expected.to validate_presence_of :push_data }
|
||||
|
||||
it { is_expected.to respond_to :git_author_name }
|
||||
it { is_expected.to respond_to :git_author_email }
|
||||
it { is_expected.to respond_to :short_sha }
|
||||
|
||||
describe :ordered do
|
||||
let(:project) { FactoryGirl.create :empty_project }
|
||||
|
||||
it 'returns ordered list of commits' do
|
||||
commit1 = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: project
|
||||
commit2 = FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, gl_project: project
|
||||
expect(project.ci_commits.ordered).to eq([commit2, commit1])
|
||||
end
|
||||
|
||||
it 'returns commits ordered by committed_at and id, with nulls last' do
|
||||
commit1 = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: project
|
||||
commit2 = FactoryGirl.create :ci_commit, committed_at: nil, gl_project: project
|
||||
commit3 = FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, gl_project: project
|
||||
commit4 = FactoryGirl.create :ci_commit, committed_at: nil, gl_project: project
|
||||
expect(project.ci_commits.ordered).to eq([commit2, commit4, commit3, commit1])
|
||||
end
|
||||
end
|
||||
|
||||
describe :last_build do
|
||||
subject { commit.last_build }
|
||||
before do
|
||||
@@ -51,53 +67,12 @@ describe Ci::Commit do
|
||||
@second = FactoryGirl.create :ci_build, commit: commit
|
||||
end
|
||||
|
||||
it "creates new build" do
|
||||
it "creates only a new build" do
|
||||
expect(commit.builds.count(:all)).to eq 2
|
||||
expect(commit.statuses.count(:all)).to eq 2
|
||||
commit.retry
|
||||
expect(commit.builds.count(:all)).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
describe :project_recipients do
|
||||
|
||||
context 'always sending notification' do
|
||||
it 'should return commit_pusher_email as only recipient when no additional recipients are given' do
|
||||
project = FactoryGirl.create :ci_project,
|
||||
email_add_pusher: true,
|
||||
email_recipients: ''
|
||||
commit = FactoryGirl.create :ci_commit, project: project
|
||||
expected = 'commit_pusher_email'
|
||||
allow(commit).to receive(:push_data) { { user_email: expected } }
|
||||
expect(commit.project_recipients).to eq([expected])
|
||||
end
|
||||
|
||||
it 'should return commit_pusher_email and additional recipients' do
|
||||
project = FactoryGirl.create :ci_project,
|
||||
email_add_pusher: true,
|
||||
email_recipients: 'rec1 rec2'
|
||||
commit = FactoryGirl.create :ci_commit, project: project
|
||||
expected = 'commit_pusher_email'
|
||||
allow(commit).to receive(:push_data) { { user_email: expected } }
|
||||
expect(commit.project_recipients).to eq(['rec1', 'rec2', expected])
|
||||
end
|
||||
|
||||
it 'should return recipients' do
|
||||
project = FactoryGirl.create :ci_project,
|
||||
email_add_pusher: false,
|
||||
email_recipients: 'rec1 rec2'
|
||||
commit = FactoryGirl.create :ci_commit, project: project
|
||||
expect(commit.project_recipients).to eq(['rec1', 'rec2'])
|
||||
end
|
||||
|
||||
it 'should return unique recipients only' do
|
||||
project = FactoryGirl.create :ci_project,
|
||||
email_add_pusher: true,
|
||||
email_recipients: 'rec1 rec1 rec2'
|
||||
commit = FactoryGirl.create :ci_commit, project: project
|
||||
expected = 'rec2'
|
||||
allow(commit).to receive(:push_data) { { user_email: expected } }
|
||||
expect(commit.project_recipients).to eq(['rec1', 'rec2'])
|
||||
end
|
||||
expect(commit.statuses.count(:all)).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
@@ -112,23 +87,6 @@ describe Ci::Commit do
|
||||
end
|
||||
end
|
||||
|
||||
describe :compare? do
|
||||
subject { commit_with_project.compare? }
|
||||
|
||||
context 'if commit.before_sha are not nil' do
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe :short_sha do
|
||||
subject { commit.short_before_sha }
|
||||
|
||||
it 'has 8 items' do
|
||||
expect(subject.size).to eq(8)
|
||||
end
|
||||
it { expect(commit.before_sha).to start_with(subject) }
|
||||
end
|
||||
|
||||
describe :short_sha do
|
||||
subject { commit.short_sha }
|
||||
|
||||
@@ -138,37 +96,113 @@ describe Ci::Commit do
|
||||
it { expect(commit.sha).to start_with(subject) }
|
||||
end
|
||||
|
||||
describe :create_next_builds do
|
||||
describe :stage do
|
||||
subject { commit.stage }
|
||||
|
||||
before do
|
||||
allow(commit).to receive(:config_processor).and_return(config_processor)
|
||||
@second = FactoryGirl.create :commit_status, commit: commit, name: 'deploy', stage: 'deploy', stage_idx: 1, status: 'pending'
|
||||
@first = FactoryGirl.create :commit_status, commit: commit, name: 'test', stage: 'test', stage_idx: 0, status: 'pending'
|
||||
end
|
||||
|
||||
it "creates builds for next type" do
|
||||
expect(commit.create_builds).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(2)
|
||||
it 'returns first running stage' do
|
||||
is_expected.to eq('test')
|
||||
end
|
||||
|
||||
expect(commit.create_next_builds(nil)).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(4)
|
||||
context 'first build succeeded' do
|
||||
before do
|
||||
@first.success
|
||||
end
|
||||
|
||||
expect(commit.create_next_builds(nil)).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(5)
|
||||
it 'returns last running stage' do
|
||||
is_expected.to eq('deploy')
|
||||
end
|
||||
end
|
||||
|
||||
expect(commit.create_next_builds(nil)).to be_falsey
|
||||
context 'all builds succeeded' do
|
||||
before do
|
||||
@first.success
|
||||
@second.success
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
is_expected.to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :create_next_builds do
|
||||
end
|
||||
|
||||
describe :refs do
|
||||
subject { commit.refs }
|
||||
|
||||
before do
|
||||
FactoryGirl.create :commit_status, commit: commit, name: 'deploy'
|
||||
FactoryGirl.create :commit_status, commit: commit, name: 'deploy', ref: 'develop'
|
||||
FactoryGirl.create :commit_status, commit: commit, name: 'deploy', ref: 'master'
|
||||
end
|
||||
|
||||
it 'returns all refs' do
|
||||
is_expected.to contain_exactly('master', 'develop', nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe :retried do
|
||||
subject { commit.retried }
|
||||
|
||||
before do
|
||||
@commit1 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy'
|
||||
@commit2 = FactoryGirl.create :ci_build, commit: commit, name: 'deploy'
|
||||
end
|
||||
|
||||
it 'returns old builds' do
|
||||
is_expected.to contain_exactly(@commit1)
|
||||
end
|
||||
end
|
||||
|
||||
describe :create_builds do
|
||||
before do
|
||||
allow(commit).to receive(:config_processor).and_return(config_processor)
|
||||
let!(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
|
||||
|
||||
def create_builds(trigger_request = nil)
|
||||
commit.create_builds('master', false, nil, trigger_request)
|
||||
end
|
||||
|
||||
def create_next_builds
|
||||
commit.create_next_builds(commit.builds.order(:id).last)
|
||||
end
|
||||
|
||||
it 'creates builds' do
|
||||
expect(commit.create_builds).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(2)
|
||||
expect(create_builds).to be_truthy
|
||||
commit.builds.update_all(status: "success")
|
||||
expect(commit.builds.count(:all)).to eq(2)
|
||||
|
||||
expect(create_next_builds).to be_truthy
|
||||
commit.builds.update_all(status: "success")
|
||||
expect(commit.builds.count(:all)).to eq(4)
|
||||
|
||||
expect(create_next_builds).to be_truthy
|
||||
commit.builds.update_all(status: "success")
|
||||
expect(commit.builds.count(:all)).to eq(5)
|
||||
|
||||
expect(create_next_builds).to be_falsey
|
||||
end
|
||||
|
||||
context 'for different ref' do
|
||||
def create_develop_builds
|
||||
commit.create_builds('develop', false, nil, nil)
|
||||
end
|
||||
|
||||
it 'creates builds' do
|
||||
expect(create_builds).to be_truthy
|
||||
commit.builds.update_all(status: "success")
|
||||
expect(commit.builds.count(:all)).to eq(2)
|
||||
|
||||
expect(create_develop_builds).to be_truthy
|
||||
commit.builds.update_all(status: "success")
|
||||
expect(commit.builds.count(:all)).to eq(4)
|
||||
expect(commit.refs.size).to eq(2)
|
||||
expect(commit.builds.pluck(:name).uniq.size).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'for build triggers' do
|
||||
@@ -176,61 +210,179 @@ describe Ci::Commit do
|
||||
let(:trigger_request) { FactoryGirl.create :ci_trigger_request, commit: commit, trigger: trigger }
|
||||
|
||||
it 'creates builds' do
|
||||
expect(commit.create_builds(trigger_request)).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(2)
|
||||
expect(create_builds(trigger_request)).to be_truthy
|
||||
expect(commit.builds.count(:all)).to eq(2)
|
||||
end
|
||||
|
||||
it 'rebuilds commit' do
|
||||
expect(commit.create_builds).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(2)
|
||||
expect(create_builds).to be_truthy
|
||||
expect(commit.builds.count(:all)).to eq(2)
|
||||
|
||||
expect(commit.create_builds(trigger_request)).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(4)
|
||||
expect(create_builds(trigger_request)).to be_truthy
|
||||
expect(commit.builds.count(:all)).to eq(4)
|
||||
end
|
||||
|
||||
it 'creates next builds' do
|
||||
expect(commit.create_builds(trigger_request)).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(2)
|
||||
expect(create_builds(trigger_request)).to be_truthy
|
||||
expect(commit.builds.count(:all)).to eq(2)
|
||||
commit.builds.update_all(status: "success")
|
||||
|
||||
expect(commit.create_next_builds(trigger_request)).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(4)
|
||||
expect(create_next_builds).to be_truthy
|
||||
expect(commit.builds.count(:all)).to eq(4)
|
||||
end
|
||||
|
||||
context 'for [ci skip]' do
|
||||
before do
|
||||
commit.push_data[:commits][0][:message] = 'skip this commit [ci skip]'
|
||||
commit.save
|
||||
allow(commit).to receive(:git_commit_message) { 'message [ci skip]' }
|
||||
end
|
||||
|
||||
it 'rebuilds commit' do
|
||||
expect(commit.status).to eq('skipped')
|
||||
expect(commit.create_builds(trigger_request)).to be_truthy
|
||||
commit.builds.reload
|
||||
expect(commit.builds.size).to eq(2)
|
||||
expect(commit.status).to eq('pending')
|
||||
expect(create_builds).to be_truthy
|
||||
|
||||
# since everything in Ci::Commit is cached we need to fetch a new object
|
||||
new_commit = Ci::Commit.find_by_id(commit.id)
|
||||
expect(new_commit.status).to eq('pending')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'properly creates builds when "when" is defined' do
|
||||
let(:yaml) do
|
||||
{
|
||||
stages: ["build", "test", "test_failure", "deploy", "cleanup"],
|
||||
build: {
|
||||
stage: "build",
|
||||
script: "BUILD",
|
||||
},
|
||||
test: {
|
||||
stage: "test",
|
||||
script: "TEST",
|
||||
},
|
||||
test_failure: {
|
||||
stage: "test_failure",
|
||||
script: "ON test failure",
|
||||
when: "on_failure",
|
||||
},
|
||||
deploy: {
|
||||
stage: "deploy",
|
||||
script: "PUBLISH",
|
||||
},
|
||||
cleanup: {
|
||||
stage: "cleanup",
|
||||
script: "TIDY UP",
|
||||
when: "always",
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
stub_ci_commit_yaml_file(YAML.dump(yaml))
|
||||
end
|
||||
|
||||
it 'properly creates builds' do
|
||||
expect(create_builds).to be_truthy
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'pending')
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy', 'cleanup')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'success', 'pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'success', 'success')
|
||||
expect(commit.status).to eq('success')
|
||||
end
|
||||
|
||||
it 'properly creates builds when test fails' do
|
||||
expect(create_builds).to be_truthy
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
|
||||
commit.builds.running_or_pending.each(&:drop)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'success', 'pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'success', 'success')
|
||||
expect(commit.status).to eq('failed')
|
||||
end
|
||||
|
||||
it 'properly creates builds when test and test_failure fails' do
|
||||
expect(create_builds).to be_truthy
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
|
||||
commit.builds.running_or_pending.each(&:drop)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'pending')
|
||||
commit.builds.running_or_pending.each(&:drop)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'failed', 'pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'test_failure', 'cleanup')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'failed', 'failed', 'success')
|
||||
expect(commit.status).to eq('failed')
|
||||
end
|
||||
|
||||
it 'properly creates builds when deploy fails' do
|
||||
expect(create_builds).to be_truthy
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'pending')
|
||||
commit.builds.running_or_pending.each(&:drop)
|
||||
|
||||
expect(commit.builds.pluck(:name)).to contain_exactly('build', 'test', 'deploy', 'cleanup')
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'failed', 'pending')
|
||||
commit.builds.running_or_pending.each(&:success)
|
||||
|
||||
expect(commit.builds.pluck(:status)).to contain_exactly('success', 'success', 'failed', 'success')
|
||||
expect(commit.status).to eq('failed')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#finished_at" do
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
|
||||
it "returns finished_at of latest build" do
|
||||
build = FactoryGirl.create :ci_build, commit: commit, finished_at: Time.now - 60
|
||||
build1 = FactoryGirl.create :ci_build, commit: commit, finished_at: Time.now - 120
|
||||
FactoryGirl.create :ci_build, commit: commit, finished_at: Time.now - 120
|
||||
|
||||
expect(commit.finished_at.to_i).to eq(build.finished_at.to_i)
|
||||
end
|
||||
|
||||
it "returns nil if there is no finished build" do
|
||||
build = FactoryGirl.create :ci_not_started_build, commit: commit
|
||||
FactoryGirl.create :ci_not_started_build, commit: commit
|
||||
|
||||
expect(commit.finished_at).to be_nil
|
||||
end
|
||||
@@ -238,7 +390,8 @@ describe Ci::Commit do
|
||||
|
||||
describe "coverage" do
|
||||
let(:project) { FactoryGirl.create :ci_project, coverage_regex: "/.*/" }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
|
||||
|
||||
it "calculates average when there are two builds with coverage" do
|
||||
FactoryGirl.create :ci_build, name: "rspec", coverage: 30, commit: commit
|
||||
|
||||
@@ -3,72 +3,37 @@ require 'spec_helper'
|
||||
describe Ci::HipChatMessage do
|
||||
subject { Ci::HipChatMessage.new(build) }
|
||||
|
||||
let(:project) { FactoryGirl.create(:ci_project) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs) }
|
||||
|
||||
context "One build" do
|
||||
let(:commit) { FactoryGirl.create(:ci_commit_with_one_job, project: project) }
|
||||
let(:build) do
|
||||
commit.builds.first
|
||||
end
|
||||
|
||||
let(:build) do
|
||||
commit.create_builds
|
||||
commit.builds.first
|
||||
end
|
||||
context 'when all matrix builds succeed' do
|
||||
it 'returns a successful message' do
|
||||
commit.create_builds('master', false, nil)
|
||||
commit.builds.update_all(status: "success")
|
||||
commit.reload
|
||||
|
||||
context 'when build succeeds' do
|
||||
it 'returns a successful message' do
|
||||
build.update(status: "success")
|
||||
|
||||
expect( subject.status_color ).to eq 'green'
|
||||
expect( subject.notify? ).to be_falsey
|
||||
expect( subject.to_s ).to match(/Build '[^']+' #\d+/)
|
||||
expect( subject.to_s ).to match(/Successful in \d+ second\(s\)\./)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build fails' do
|
||||
it 'returns a failure message' do
|
||||
build.update(status: "failed")
|
||||
|
||||
expect( subject.status_color ).to eq 'red'
|
||||
expect( subject.notify? ).to be_truthy
|
||||
expect( subject.to_s ).to match(/Build '[^']+' #\d+/)
|
||||
expect( subject.to_s ).to match(/Failed in \d+ second\(s\)\./)
|
||||
end
|
||||
expect(subject.status_color).to eq 'green'
|
||||
expect(subject.notify?).to be_falsey
|
||||
expect(subject.to_s).to match(/Commit #\d+/)
|
||||
expect(subject.to_s).to match(/Successful in \d+ second\(s\)\./)
|
||||
end
|
||||
end
|
||||
|
||||
context "Several builds" do
|
||||
let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs, project: project) }
|
||||
context 'when at least one matrix build fails' do
|
||||
it 'returns a failure message' do
|
||||
commit.create_builds('master', false, nil)
|
||||
first_build = commit.builds.first
|
||||
second_build = commit.builds.last
|
||||
first_build.update(status: "success")
|
||||
second_build.update(status: "failed")
|
||||
|
||||
let(:build) do
|
||||
commit.builds.first
|
||||
end
|
||||
|
||||
context 'when all matrix builds succeed' do
|
||||
it 'returns a successful message' do
|
||||
commit.create_builds
|
||||
commit.builds.update_all(status: "success")
|
||||
commit.reload
|
||||
|
||||
expect( subject.status_color ).to eq 'green'
|
||||
expect( subject.notify? ).to be_falsey
|
||||
expect( subject.to_s ).to match(/Commit #\d+/)
|
||||
expect( subject.to_s ).to match(/Successful in \d+ second\(s\)\./)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when at least one matrix build fails' do
|
||||
it 'returns a failure message' do
|
||||
commit.create_builds
|
||||
first_build = commit.builds.first
|
||||
second_build = commit.builds.last
|
||||
first_build.update(status: "success")
|
||||
second_build.update(status: "failed")
|
||||
|
||||
expect( subject.status_color ).to eq 'red'
|
||||
expect( subject.notify? ).to be_truthy
|
||||
expect( subject.to_s ).to match(/Commit #\d+/)
|
||||
expect( subject.to_s ).to match(/Failed in \d+ second\(s\)\./)
|
||||
end
|
||||
expect(subject.status_color).to eq 'red'
|
||||
expect(subject.notify?).to be_truthy
|
||||
expect(subject.to_s).to match(/Commit #\d+/)
|
||||
expect(subject.to_s).to match(/Failed in \d+ second\(s\)\./)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,15 +33,14 @@ describe Ci::HipChatService do
|
||||
describe "Execute" do
|
||||
|
||||
let(:service) { Ci::HipChatService.new }
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
let(:build) { FactoryGirl.create :ci_build, commit: commit, status: 'failed' }
|
||||
let(:api_url) { 'https://api.hipchat.com/v2/room/123/notification?auth_token=a1b2c3d4e5f6' }
|
||||
|
||||
before do
|
||||
allow(service).to receive_messages(
|
||||
project: project,
|
||||
project_id: project.id,
|
||||
project: commit.project,
|
||||
project_id: commit.project_id,
|
||||
notify_only_broken_builds: false,
|
||||
hipchat_room: 123,
|
||||
hipchat_token: 'a1b2c3d4e5f6'
|
||||
|
||||
+19
-12
@@ -29,11 +29,13 @@ describe Ci::MailService do
|
||||
|
||||
describe 'Sends email for' do
|
||||
let(:mail) { Ci::MailService.new }
|
||||
let(:user) { User.new(notification_email: 'git@example.com')}
|
||||
|
||||
describe 'failed build' do
|
||||
let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, project: project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit) }
|
||||
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: 'failed', commit: commit, user: user) }
|
||||
|
||||
before do
|
||||
allow(mail).to receive_messages(
|
||||
@@ -54,8 +56,9 @@ describe Ci::MailService do
|
||||
|
||||
describe 'successfull build' do
|
||||
let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true, email_only_broken_builds: false) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, project: project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) }
|
||||
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
|
||||
|
||||
before do
|
||||
allow(mail).to receive_messages(
|
||||
@@ -81,8 +84,9 @@ describe Ci::MailService do
|
||||
email_only_broken_builds: false,
|
||||
email_recipients: "jeroen@example.com")
|
||||
end
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, project: project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) }
|
||||
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
|
||||
|
||||
before do
|
||||
allow(mail).to receive_messages(
|
||||
@@ -109,8 +113,9 @@ describe Ci::MailService do
|
||||
email_only_broken_builds: true,
|
||||
email_recipients: "jeroen@example.com")
|
||||
end
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, project: project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) }
|
||||
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
|
||||
|
||||
before do
|
||||
allow(mail).to receive_messages(
|
||||
@@ -137,8 +142,9 @@ describe Ci::MailService do
|
||||
email_only_broken_builds: false,
|
||||
email_recipients: "jeroen@example.com")
|
||||
end
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, project: project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) }
|
||||
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: 'success', commit: commit, user: user) }
|
||||
|
||||
before do
|
||||
allow(mail).to receive_messages(
|
||||
@@ -159,8 +165,9 @@ describe Ci::MailService do
|
||||
email_only_broken_builds: true,
|
||||
email_recipients: "jeroen@example.com")
|
||||
end
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, project: project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit) }
|
||||
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
|
||||
let(:build) { FactoryGirl.create(:ci_build, status: 'failed', commit: commit, user: user) }
|
||||
|
||||
before do
|
||||
allow(mail).to receive_messages(
|
||||
@@ -3,82 +3,41 @@ require 'spec_helper'
|
||||
describe Ci::SlackMessage do
|
||||
subject { Ci::SlackMessage.new(commit) }
|
||||
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs) }
|
||||
|
||||
context "One build" do
|
||||
let(:commit) { FactoryGirl.create(:ci_commit_with_one_job, project: project) }
|
||||
context 'when all matrix builds succeeded' do
|
||||
let(:color) { 'good' }
|
||||
|
||||
let(:build) do
|
||||
commit.create_builds
|
||||
commit.builds.first
|
||||
end
|
||||
it 'returns a message with success' do
|
||||
commit.create_builds('master', false, nil)
|
||||
commit.builds.update_all(status: "success")
|
||||
commit.reload
|
||||
|
||||
context 'when build succeeded' do
|
||||
let(:color) { 'good' }
|
||||
|
||||
it 'returns a message with succeeded build' do
|
||||
build.update(status: "success")
|
||||
|
||||
expect(subject.color).to eq(color)
|
||||
expect(subject.fallback).to include('Build')
|
||||
expect(subject.fallback).to include("\##{build.id}")
|
||||
expect(subject.fallback).to include('succeeded')
|
||||
expect(subject.attachments.first[:fields]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build failed' do
|
||||
let(:color) { 'danger' }
|
||||
|
||||
it 'returns a message with failed build' do
|
||||
build.update(status: "failed")
|
||||
|
||||
expect(subject.color).to eq(color)
|
||||
expect(subject.fallback).to include('Build')
|
||||
expect(subject.fallback).to include("\##{build.id}")
|
||||
expect(subject.fallback).to include('failed')
|
||||
expect(subject.attachments.first[:fields]).to be_empty
|
||||
end
|
||||
expect(subject.color).to eq(color)
|
||||
expect(subject.fallback).to include('Commit')
|
||||
expect(subject.fallback).to include("\##{commit.id}")
|
||||
expect(subject.fallback).to include('succeeded')
|
||||
expect(subject.attachments.first[:fields]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context "Several builds" do
|
||||
let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs, project: project) }
|
||||
context 'when one of matrix builds failed' do
|
||||
let(:color) { 'danger' }
|
||||
|
||||
context 'when all matrix builds succeeded' do
|
||||
let(:color) { 'good' }
|
||||
it 'returns a message with information about failed build' do
|
||||
commit.create_builds('master', false, nil)
|
||||
first_build = commit.builds.first
|
||||
second_build = commit.builds.last
|
||||
first_build.update(status: "success")
|
||||
second_build.update(status: "failed")
|
||||
|
||||
it 'returns a message with success' do
|
||||
commit.create_builds
|
||||
commit.builds.update_all(status: "success")
|
||||
commit.reload
|
||||
|
||||
expect(subject.color).to eq(color)
|
||||
expect(subject.fallback).to include('Commit')
|
||||
expect(subject.fallback).to include("\##{commit.id}")
|
||||
expect(subject.fallback).to include('succeeded')
|
||||
expect(subject.attachments.first[:fields]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when one of matrix builds failed' do
|
||||
let(:color) { 'danger' }
|
||||
|
||||
it 'returns a message with information about failed build' do
|
||||
commit.create_builds
|
||||
first_build = commit.builds.first
|
||||
second_build = commit.builds.last
|
||||
first_build.update(status: "success")
|
||||
second_build.update(status: "failed")
|
||||
|
||||
expect(subject.color).to eq(color)
|
||||
expect(subject.fallback).to include('Commit')
|
||||
expect(subject.fallback).to include("\##{commit.id}")
|
||||
expect(subject.fallback).to include('failed')
|
||||
expect(subject.attachments.first[:fields].size).to eq(1)
|
||||
expect(subject.attachments.first[:fields].first[:title]).to eq(second_build.name)
|
||||
expect(subject.attachments.first[:fields].first[:value]).to include("\##{second_build.id}")
|
||||
end
|
||||
expect(subject.color).to eq(color)
|
||||
expect(subject.fallback).to include('Commit')
|
||||
expect(subject.fallback).to include("\##{commit.id}")
|
||||
expect(subject.fallback).to include('failed')
|
||||
expect(subject.attachments.first[:fields].size).to eq(1)
|
||||
expect(subject.attachments.first[:fields].first[:title]).to eq(second_build.name)
|
||||
expect(subject.attachments.first[:fields].first[:value]).to include("\##{second_build.id}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,16 +31,15 @@ describe Ci::SlackService do
|
||||
|
||||
describe "Execute" do
|
||||
let(:slack) { Ci::SlackService.new }
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
let(:build) { FactoryGirl.create :ci_build, commit: commit, status: 'failed' }
|
||||
let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
|
||||
let(:notify_only_broken_builds) { false }
|
||||
|
||||
before do
|
||||
allow(slack).to receive_messages(
|
||||
project: project,
|
||||
project_id: project.id,
|
||||
project: commit.project,
|
||||
project_id: commit.project_id,
|
||||
webhook: webhook_url,
|
||||
notify_only_broken_builds: notify_only_broken_builds
|
||||
)
|
||||
|
||||
@@ -28,13 +28,20 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ci::Project do
|
||||
subject { FactoryGirl.build :ci_project }
|
||||
let(:gl_project) { FactoryGirl.create :empty_project }
|
||||
let(:project) { FactoryGirl.create :ci_project, gl_project: gl_project }
|
||||
subject { project }
|
||||
|
||||
it { is_expected.to have_many(:commits) }
|
||||
it { is_expected.to have_many(:runner_projects) }
|
||||
it { is_expected.to have_many(:runners) }
|
||||
it { is_expected.to have_many(:web_hooks) }
|
||||
it { is_expected.to have_many(:events) }
|
||||
it { is_expected.to have_many(:variables) }
|
||||
it { is_expected.to have_many(:triggers) }
|
||||
it { is_expected.to have_many(:services) }
|
||||
|
||||
it { is_expected.to validate_presence_of :name }
|
||||
it { is_expected.to validate_presence_of :timeout }
|
||||
it { is_expected.to validate_presence_of :default_ref }
|
||||
it { is_expected.to validate_presence_of :gitlab_id }
|
||||
|
||||
describe 'before_validation' do
|
||||
it 'should set an random token if none provided' do
|
||||
@@ -48,43 +55,89 @@ describe Ci::Project do
|
||||
end
|
||||
end
|
||||
|
||||
describe "ordered_by_last_commit_date" do
|
||||
it "returns ordered projects" do
|
||||
newest_project = FactoryGirl.create :ci_project
|
||||
oldest_project = FactoryGirl.create :ci_project
|
||||
project_without_commits = FactoryGirl.create :ci_project
|
||||
describe :name_with_namespace do
|
||||
subject { project.name_with_namespace }
|
||||
|
||||
FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, project: newest_project
|
||||
FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, project: oldest_project
|
||||
|
||||
expect(Ci::Project.ordered_by_last_commit_date).to eq([newest_project, oldest_project, project_without_commits])
|
||||
end
|
||||
it { is_expected.to eq(project.name) }
|
||||
it { is_expected.to eq(gl_project.name_with_namespace) }
|
||||
end
|
||||
|
||||
describe 'ordered commits' do
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
describe :path_with_namespace do
|
||||
subject { project.path_with_namespace }
|
||||
|
||||
it 'returns ordered list of commits' do
|
||||
commit1 = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, project: project
|
||||
commit2 = FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, project: project
|
||||
expect(project.commits).to eq([commit2, commit1])
|
||||
it { is_expected.to eq(project.path) }
|
||||
it { is_expected.to eq(gl_project.path_with_namespace) }
|
||||
end
|
||||
|
||||
describe :path_with_namespace do
|
||||
subject { project.web_url }
|
||||
|
||||
it { is_expected.to eq(gl_project.web_url) }
|
||||
end
|
||||
|
||||
describe :web_url do
|
||||
subject { project.web_url }
|
||||
|
||||
it { is_expected.to eq(project.gitlab_url) }
|
||||
it { is_expected.to eq(gl_project.web_url) }
|
||||
end
|
||||
|
||||
describe :http_url_to_repo do
|
||||
subject { project.http_url_to_repo }
|
||||
|
||||
it { is_expected.to eq(gl_project.http_url_to_repo) }
|
||||
end
|
||||
|
||||
describe :ssh_url_to_repo do
|
||||
subject { project.ssh_url_to_repo }
|
||||
|
||||
it { is_expected.to eq(gl_project.ssh_url_to_repo) }
|
||||
end
|
||||
|
||||
describe :commits do
|
||||
subject { project.commits }
|
||||
|
||||
before do
|
||||
FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: gl_project
|
||||
end
|
||||
|
||||
it 'returns commits ordered by committed_at and id, with nulls last' do
|
||||
commit1 = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, project: project
|
||||
commit2 = FactoryGirl.create :ci_commit, committed_at: nil, project: project
|
||||
commit3 = FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, project: project
|
||||
commit4 = FactoryGirl.create :ci_commit, committed_at: nil, project: project
|
||||
expect(project.commits).to eq([commit2, commit4, commit3, commit1])
|
||||
it { is_expected.to eq(gl_project.ci_commits) }
|
||||
end
|
||||
|
||||
describe :builds do
|
||||
subject { project.builds }
|
||||
|
||||
before do
|
||||
commit = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: gl_project
|
||||
FactoryGirl.create :ci_build, commit: commit
|
||||
end
|
||||
|
||||
it { is_expected.to eq(gl_project.ci_builds) }
|
||||
end
|
||||
|
||||
describe "ordered_by_last_commit_date" do
|
||||
it "returns ordered projects" do
|
||||
newest_project = FactoryGirl.create :empty_project
|
||||
newest_ci_project = newest_project.ensure_gitlab_ci_project
|
||||
oldest_project = FactoryGirl.create :empty_project
|
||||
oldest_ci_project = oldest_project.ensure_gitlab_ci_project
|
||||
project_without_commits = FactoryGirl.create :empty_project
|
||||
ci_project_without_commits = project_without_commits.ensure_gitlab_ci_project
|
||||
|
||||
FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: newest_project
|
||||
FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, gl_project: oldest_project
|
||||
|
||||
expect(Ci::Project.ordered_by_last_commit_date).to eq([newest_ci_project, oldest_ci_project, ci_project_without_commits])
|
||||
end
|
||||
end
|
||||
|
||||
context :valid_project do
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create(:ci_commit) }
|
||||
|
||||
context :project_with_commit_and_builds do
|
||||
let(:project) { commit.project }
|
||||
|
||||
before do
|
||||
commit = FactoryGirl.create(:ci_commit, project: project)
|
||||
FactoryGirl.create(:ci_build, commit: commit)
|
||||
end
|
||||
|
||||
@@ -165,13 +218,6 @@ describe Ci::Project do
|
||||
it { is_expected.to include(project.gitlab_url[7..-1]) }
|
||||
end
|
||||
|
||||
describe :search do
|
||||
let!(:project) { FactoryGirl.create(:ci_project, name: "foo") }
|
||||
|
||||
it { expect(Ci::Project.search('fo')).to include(project) }
|
||||
it { expect(Ci::Project.search('bar')).to be_empty }
|
||||
end
|
||||
|
||||
describe :any_runners do
|
||||
it "there are no runners available" do
|
||||
project = FactoryGirl.create(:ci_project)
|
||||
@@ -195,5 +241,18 @@ describe Ci::Project do
|
||||
FactoryGirl.create(:ci_shared_runner)
|
||||
expect(project.any_runners?).to be_falsey
|
||||
end
|
||||
|
||||
it "checks the presence of specific runner" do
|
||||
project = FactoryGirl.create(:ci_project)
|
||||
specific_runner = FactoryGirl.create(:ci_specific_runner)
|
||||
project.runners << specific_runner
|
||||
expect(project.any_runners? { |runner| runner == specific_runner }).to be_truthy
|
||||
end
|
||||
|
||||
it "checks the presence of shared runner" do
|
||||
project = FactoryGirl.create(:ci_project, shared_runners_enabled: true)
|
||||
shared_runner = FactoryGirl.create(:ci_shared_runner)
|
||||
expect(project.any_runners? { |runner| runner == shared_runner }).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ describe Ci::Runner do
|
||||
end
|
||||
|
||||
it 'should return the token if the description is an empty string' do
|
||||
runner = FactoryGirl.build(:ci_runner, description: '')
|
||||
runner = FactoryGirl.build(:ci_runner, description: '', token: 'token')
|
||||
expect(runner.display_name).to eq runner.token
|
||||
end
|
||||
end
|
||||
@@ -48,6 +48,71 @@ describe Ci::Runner do
|
||||
it { expect(shared_runner.only_for?(project)).to be_truthy }
|
||||
end
|
||||
|
||||
describe :online do
|
||||
subject { Ci::Runner.online }
|
||||
|
||||
before do
|
||||
@runner1 = FactoryGirl.create(:ci_shared_runner, contacted_at: 1.year.ago)
|
||||
@runner2 = FactoryGirl.create(:ci_shared_runner, contacted_at: 1.second.ago)
|
||||
end
|
||||
|
||||
it { is_expected.to eq([@runner2])}
|
||||
end
|
||||
|
||||
describe :online? do
|
||||
let(:runner) { FactoryGirl.create(:ci_shared_runner) }
|
||||
|
||||
subject { runner.online? }
|
||||
|
||||
context 'never contacted' do
|
||||
before { runner.contacted_at = nil }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
context 'contacted long time ago time' do
|
||||
before { runner.contacted_at = 1.year.ago }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
context 'contacted 1s ago' do
|
||||
before { runner.contacted_at = 1.second.ago }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe :status do
|
||||
let(:runner) { FactoryGirl.create(:ci_shared_runner, contacted_at: 1.second.ago) }
|
||||
|
||||
subject { runner.status }
|
||||
|
||||
context 'never connected' do
|
||||
before { runner.contacted_at = nil }
|
||||
|
||||
it { is_expected.to eq(:not_connected) }
|
||||
end
|
||||
|
||||
context 'contacted 1s ago' do
|
||||
before { runner.contacted_at = 1.second.ago }
|
||||
|
||||
it { is_expected.to eq(:online) }
|
||||
end
|
||||
|
||||
context 'contacted long time ago' do
|
||||
before { runner.contacted_at = 1.year.ago }
|
||||
|
||||
it { is_expected.to eq(:offline) }
|
||||
end
|
||||
|
||||
context 'inactive' do
|
||||
before { runner.active = false }
|
||||
|
||||
it { is_expected.to eq(:paused) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "belongs_to_one_project?" do
|
||||
it "returns false if there are two projects runner assigned to" do
|
||||
runner = FactoryGirl.create(:ci_specific_runner)
|
||||
|
||||
@@ -29,13 +29,12 @@ describe Ci::Service do
|
||||
end
|
||||
|
||||
describe "Testable" do
|
||||
let(:project) { FactoryGirl.create :ci_project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit, project: project }
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
let(:build) { FactoryGirl.create :ci_build, commit: commit }
|
||||
|
||||
before do
|
||||
allow(@service).to receive_messages(
|
||||
project: project
|
||||
project: commit.project
|
||||
)
|
||||
build
|
||||
@testable = @service.can_test?
|
||||
|
||||
@@ -89,9 +89,9 @@ eos
|
||||
end
|
||||
|
||||
it_behaves_like 'a mentionable' do
|
||||
subject { commit }
|
||||
subject { create(:project).commit }
|
||||
|
||||
let(:author) { create(:user, email: commit.author_email) }
|
||||
let(:author) { create(:user, email: subject.author_email) }
|
||||
let(:backref_text) { "commit #{subject.id}" }
|
||||
let(:set_mentionable_text) do
|
||||
->(txt) { allow(subject).to receive(:safe_message).and_return(txt) }
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe CommitStatus do
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
let(:commit_status) { FactoryGirl.create :commit_status, commit: commit }
|
||||
|
||||
it { is_expected.to belong_to(:commit) }
|
||||
it { is_expected.to belong_to(:user) }
|
||||
it { is_expected.to validate_presence_of(:name) }
|
||||
it { is_expected.to validate_inclusion_of(:status).in_array(%w(pending running failed success canceled)) }
|
||||
|
||||
it { is_expected.to delegate_method(:sha).to(:commit) }
|
||||
it { is_expected.to delegate_method(:short_sha).to(:commit) }
|
||||
it { is_expected.to delegate_method(:gl_project).to(:commit) }
|
||||
|
||||
it { is_expected.to respond_to :success? }
|
||||
it { is_expected.to respond_to :failed? }
|
||||
it { is_expected.to respond_to :running? }
|
||||
it { is_expected.to respond_to :pending? }
|
||||
|
||||
describe :author do
|
||||
subject { commit_status.author }
|
||||
before { commit_status.author = User.new }
|
||||
|
||||
it { is_expected.to eq(commit_status.user) }
|
||||
end
|
||||
|
||||
describe :started? do
|
||||
subject { commit_status.started? }
|
||||
|
||||
context 'without started_at' do
|
||||
before { commit_status.started_at = nil }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
%w(running success failed).each do |status|
|
||||
context "if commit status is #{status}" do
|
||||
before { commit_status.status = status }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
%w(pending canceled).each do |status|
|
||||
context "if commit status is #{status}" do
|
||||
before { commit_status.status = status }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :active? do
|
||||
subject { commit_status.active? }
|
||||
|
||||
%w(pending running).each do |state|
|
||||
context "if commit_status.status is #{state}" do
|
||||
before { commit_status.status = state }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
%w(success failed canceled).each do |state|
|
||||
context "if commit_status.status is #{state}" do
|
||||
before { commit_status.status = state }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :complete? do
|
||||
subject { commit_status.complete? }
|
||||
|
||||
%w(success failed canceled).each do |state|
|
||||
context "if commit_status.status is #{state}" do
|
||||
before { commit_status.status = state }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
%w(pending running).each do |state|
|
||||
context "if commit_status.status is #{state}" do
|
||||
before { commit_status.status = state }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :duration do
|
||||
subject { commit_status.duration }
|
||||
|
||||
it { is_expected.to eq(120.0) }
|
||||
|
||||
context 'if the building process has not started yet' do
|
||||
before do
|
||||
commit_status.started_at = nil
|
||||
commit_status.finished_at = nil
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'if the building process has started' do
|
||||
before do
|
||||
commit_status.started_at = Time.now - 1.minute
|
||||
commit_status.finished_at = nil
|
||||
end
|
||||
|
||||
it { is_expected.to be_a(Float) }
|
||||
it { is_expected.to be > 0.0 }
|
||||
end
|
||||
end
|
||||
|
||||
describe :latest do
|
||||
subject { CommitStatus.latest.order(:id) }
|
||||
|
||||
before do
|
||||
@commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
|
||||
@commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
|
||||
@commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'cc', status: 'success'
|
||||
@commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'bb', status: 'success'
|
||||
@commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'success'
|
||||
end
|
||||
|
||||
it 'return unique statuses' do
|
||||
is_expected.to eq([@commit2, @commit3, @commit4, @commit5])
|
||||
end
|
||||
end
|
||||
|
||||
describe :for_ref do
|
||||
subject { CommitStatus.for_ref('bb').order(:id) }
|
||||
|
||||
before do
|
||||
@commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
|
||||
@commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
|
||||
@commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: nil, status: 'success'
|
||||
end
|
||||
|
||||
it 'return statuses with equal and nil ref set' do
|
||||
is_expected.to eq([@commit1])
|
||||
end
|
||||
end
|
||||
|
||||
describe :running_or_pending do
|
||||
subject { CommitStatus.running_or_pending.order(:id) }
|
||||
|
||||
before do
|
||||
@commit1 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: 'bb', status: 'running'
|
||||
@commit2 = FactoryGirl.create :commit_status, commit: commit, name: 'cc', ref: 'cc', status: 'pending'
|
||||
@commit3 = FactoryGirl.create :commit_status, commit: commit, name: 'aa', ref: nil, status: 'success'
|
||||
@commit4 = FactoryGirl.create :commit_status, commit: commit, name: 'dd', ref: nil, status: 'failed'
|
||||
@commit5 = FactoryGirl.create :commit_status, commit: commit, name: 'ee', ref: nil, status: 'canceled'
|
||||
end
|
||||
|
||||
it 'return statuses that are running or pending' do
|
||||
is_expected.to eq([@commit1, @commit2])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,189 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe CaseSensitivity do
|
||||
describe '.iwhere' do
|
||||
let(:connection) { ActiveRecord::Base.connection }
|
||||
let(:model) { Class.new { include CaseSensitivity } }
|
||||
|
||||
describe 'using PostgreSQL' do
|
||||
before do
|
||||
allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
|
||||
allow(Gitlab::Database).to receive(:mysql?).and_return(false)
|
||||
end
|
||||
|
||||
describe 'with a single column/value pair' do
|
||||
it 'returns the criteria for a column and a value' do
|
||||
criteria = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:foo).
|
||||
and_return('"foo"')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar').
|
||||
and_return(criteria)
|
||||
|
||||
expect(model.iwhere(foo: 'bar')).to eq(criteria)
|
||||
end
|
||||
|
||||
it 'returns the criteria for a column with a table, and a value' do
|
||||
criteria = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:'foo.bar').
|
||||
and_return('"foo"."bar"')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar').
|
||||
and_return(criteria)
|
||||
|
||||
expect(model.iwhere(:'foo.bar' => 'bar')).to eq(criteria)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with multiple column/value pairs' do
|
||||
it 'returns the criteria for a column and a value' do
|
||||
initial = double(:criteria)
|
||||
final = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:foo).
|
||||
and_return('"foo"')
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:bar).
|
||||
and_return('"bar"')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar').
|
||||
and_return(initial)
|
||||
|
||||
expect(initial).to receive(:where).
|
||||
with(%q{LOWER("bar") = LOWER(:value)}, value: 'baz').
|
||||
and_return(final)
|
||||
|
||||
got = model.iwhere(foo: 'bar', bar: 'baz')
|
||||
|
||||
expect(got).to eq(final)
|
||||
end
|
||||
|
||||
it 'returns the criteria for a column with a table, and a value' do
|
||||
initial = double(:criteria)
|
||||
final = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:'foo.bar').
|
||||
and_return('"foo"."bar"')
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:'foo.baz').
|
||||
and_return('"foo"."baz"')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar').
|
||||
and_return(initial)
|
||||
|
||||
expect(initial).to receive(:where).
|
||||
with(%q{LOWER("foo"."baz") = LOWER(:value)}, value: 'baz').
|
||||
and_return(final)
|
||||
|
||||
got = model.iwhere(:'foo.bar' => 'bar',
|
||||
:'foo.baz' => 'baz')
|
||||
|
||||
expect(got).to eq(final)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using MySQL' do
|
||||
before do
|
||||
allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
|
||||
allow(Gitlab::Database).to receive(:mysql?).and_return(true)
|
||||
end
|
||||
|
||||
describe 'with a single column/value pair' do
|
||||
it 'returns the criteria for a column and a value' do
|
||||
criteria = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:foo).
|
||||
and_return('`foo`')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{`foo` = :value}, value: 'bar').
|
||||
and_return(criteria)
|
||||
|
||||
expect(model.iwhere(foo: 'bar')).to eq(criteria)
|
||||
end
|
||||
|
||||
it 'returns the criteria for a column with a table, and a value' do
|
||||
criteria = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:'foo.bar').
|
||||
and_return('`foo`.`bar`')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{`foo`.`bar` = :value}, value: 'bar').
|
||||
and_return(criteria)
|
||||
|
||||
expect(model.iwhere(:'foo.bar' => 'bar')).
|
||||
to eq(criteria)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with multiple column/value pairs' do
|
||||
it 'returns the criteria for a column and a value' do
|
||||
initial = double(:criteria)
|
||||
final = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:foo).
|
||||
and_return('`foo`')
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:bar).
|
||||
and_return('`bar`')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{`foo` = :value}, value: 'bar').
|
||||
and_return(initial)
|
||||
|
||||
expect(initial).to receive(:where).
|
||||
with(%q{`bar` = :value}, value: 'baz').
|
||||
and_return(final)
|
||||
|
||||
got = model.iwhere(foo: 'bar', bar: 'baz')
|
||||
|
||||
expect(got).to eq(final)
|
||||
end
|
||||
|
||||
it 'returns the criteria for a column with a table, and a value' do
|
||||
initial = double(:criteria)
|
||||
final = double(:criteria)
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:'foo.bar').
|
||||
and_return('`foo`.`bar`')
|
||||
|
||||
expect(connection).to receive(:quote_table_name).
|
||||
with(:'foo.baz').
|
||||
and_return('`foo`.`baz`')
|
||||
|
||||
expect(model).to receive(:where).
|
||||
with(%q{`foo`.`bar` = :value}, value: 'bar').
|
||||
and_return(initial)
|
||||
|
||||
expect(initial).to receive(:where).
|
||||
with(%q{`foo`.`baz` = :value}, value: 'baz').
|
||||
and_return(final)
|
||||
|
||||
got = model.iwhere(:'foo.bar' => 'bar',
|
||||
:'foo.baz' => 'baz')
|
||||
|
||||
expect(got).to eq(final)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -68,7 +68,6 @@ describe Issue, "Issuable" do
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "#to_hook_data" do
|
||||
let(:hook_data) { issue.to_hook_data(user) }
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ describe Issue, "Mentionable" do
|
||||
it 'correctly removes already-mentioned Commits' do
|
||||
expect(SystemNoteService).not_to receive(:cross_reference)
|
||||
|
||||
issue.create_cross_references!(project, author, [commit2])
|
||||
issue.create_cross_references!(author, [commit2])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe GenericCommitStatus do
|
||||
let(:commit) { FactoryGirl.create :ci_commit }
|
||||
let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, commit: commit }
|
||||
|
||||
describe :context do
|
||||
subject { generic_commit_status.context }
|
||||
before { generic_commit_status.context = 'my_context' }
|
||||
|
||||
it { is_expected.to eq(generic_commit_status.name) }
|
||||
end
|
||||
|
||||
describe :tags do
|
||||
subject { generic_commit_status.tags }
|
||||
|
||||
it { is_expected.to eq([:external]) }
|
||||
end
|
||||
|
||||
describe :set_default_values do
|
||||
before do
|
||||
generic_commit_status.context = nil
|
||||
generic_commit_status.stage = nil
|
||||
generic_commit_status.save
|
||||
end
|
||||
|
||||
describe :context do
|
||||
subject { generic_commit_status.context }
|
||||
|
||||
it { is_expected.to_not be_nil }
|
||||
end
|
||||
|
||||
describe :stage do
|
||||
subject { generic_commit_status.stage }
|
||||
|
||||
it { is_expected.to_not be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -22,7 +22,7 @@ describe ProjectHook do
|
||||
describe '.push_hooks' do
|
||||
it 'should return hooks for push events only' do
|
||||
hook = create(:project_hook, push_events: true)
|
||||
hook2 = create(:project_hook, push_events: false)
|
||||
create(:project_hook, push_events: false)
|
||||
expect(ProjectHook.push_hooks).to eq([hook])
|
||||
end
|
||||
end
|
||||
@@ -30,7 +30,7 @@ describe ProjectHook do
|
||||
describe '.tag_push_hooks' do
|
||||
it 'should return hooks for tag push events only' do
|
||||
hook = create(:project_hook, tag_push_events: true)
|
||||
hook2 = create(:project_hook, tag_push_events: false)
|
||||
create(:project_hook, tag_push_events: false)
|
||||
expect(ProjectHook.tag_push_hooks).to eq([hook])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,8 +39,6 @@ describe ServiceHook do
|
||||
end
|
||||
|
||||
it "POSTs the data as JSON" do
|
||||
json = @data.to_json
|
||||
|
||||
@service_hook.execute(@data)
|
||||
expect(WebMock).to have_requested(:post, @service_hook.url).with(
|
||||
headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'Service Hook' }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user