Skip to content
Snippets Groups Projects
Commit 36f255b2 authored by Alejandro Rodríguez's avatar Alejandro Rodríguez
Browse files

Merge remote-tracking branch 'ce/master' into ce-to-ee

parents add80eb9 66cddf34
No related branches found
No related tags found
No related merge requests found
Showing
with 419 additions and 312 deletions
Loading
Loading
@@ -22,7 +22,7 @@ describe Issue, models: true do
it { is_expected.to have_db_index(:deleted_at) }
end
 
describe 'visible_to_user' do
describe '.visible_to_user' do
let(:user) { create(:user) }
let(:authorized_user) { create(:user) }
let(:project) { create(:project, namespace: authorized_user.namespace) }
Loading
Loading
@@ -102,17 +102,17 @@ describe Issue, models: true do
it 'returns the merge request to close this issue' do
mr
 
expect(issue.closed_by_merge_requests).to eq([mr])
expect(issue.closed_by_merge_requests(mr.author)).to eq([mr])
end
 
it "returns an empty array when the merge request is closed already" do
closed_mr
 
expect(issue.closed_by_merge_requests).to eq([])
expect(issue.closed_by_merge_requests(closed_mr.author)).to eq([])
end
 
it "returns an empty array when the current issue is closed already" do
expect(closed_issue.closed_by_merge_requests).to eq([])
expect(closed_issue.closed_by_merge_requests(closed_issue.author)).to eq([])
end
end
 
Loading
Loading
@@ -218,7 +218,7 @@ describe Issue, models: true do
source_project: subject.project,
source_branch: "#{subject.iid}-branch" })
merge_request.create_cross_references!(user)
expect(subject.referenced_merge_requests).not_to be_empty
expect(subject.referenced_merge_requests(user)).not_to be_empty
expect(subject.related_branches(user)).to eq([subject.to_branch_name])
end
 
Loading
Loading
@@ -314,6 +314,22 @@ describe Issue, models: true do
end
 
describe '#visible_to_user?' do
context 'without a user' do
let(:issue) { build(:issue) }
it 'returns true when the issue is publicly visible' do
expect(issue).to receive(:publicly_visible?).and_return(true)
expect(issue.visible_to_user?).to eq(true)
end
it 'returns false when the issue is not publicly visible' do
expect(issue).to receive(:publicly_visible?).and_return(false)
expect(issue.visible_to_user?).to eq(false)
end
end
context 'with a user' do
let(:user) { build(:user) }
let(:issue) { build(:issue) }
Loading
Loading
@@ -329,26 +345,24 @@ describe Issue, models: true do
 
expect(issue.visible_to_user?(user)).to eq(false)
end
end
 
context 'without a user' do
let(:issue) { build(:issue) }
it 'returns false when feature is disabled' do
expect(issue).not_to receive(:readable_by?)
 
it 'returns true when the issue is publicly visible' do
expect(issue).to receive(:publicly_visible?).and_return(true)
issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
 
expect(issue.visible_to_user?).to eq(true)
expect(issue.visible_to_user?(user)).to eq(false)
end
 
it 'returns false when the issue is not publicly visible' do
expect(issue).to receive(:publicly_visible?).and_return(false)
it 'returns false when restricted for members' do
expect(issue).not_to receive(:readable_by?)
 
expect(issue.visible_to_user?).to eq(false)
issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::PRIVATE)
expect(issue.visible_to_user?(user)).to eq(false)
end
end
end
 
describe '#readable_by?' do
describe 'with a regular user that is not a team member' do
let(:user) { create(:user) }
 
Loading
Loading
@@ -358,13 +372,13 @@ describe Issue, models: true do
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
 
it 'returns false for a confidential issue' do
issue = build(:issue, project: project, confidential: true)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(false)
end
end
 
Loading
Loading
@@ -375,13 +389,13 @@ describe Issue, models: true do
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
 
it 'returns false for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(false)
end
end
 
Loading
Loading
@@ -393,13 +407,13 @@ describe Issue, models: true do
it 'returns false for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(false)
end
 
it 'returns false for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(false)
end
end
end
Loading
Loading
@@ -410,26 +424,28 @@ describe Issue, models: true do
it 'returns false for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(false)
end
 
it 'returns false for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(false)
end
 
context 'when the user is the project owner' do
before { project.team << [user, :master] }
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
 
it 'returns true for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).not_to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
end
end
Loading
Loading
@@ -447,13 +463,13 @@ describe Issue, models: true do
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
 
it 'returns true for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
end
 
Loading
Loading
@@ -467,13 +483,13 @@ describe Issue, models: true do
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
 
it 'returns true for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
end
 
Loading
Loading
@@ -487,13 +503,13 @@ describe Issue, models: true do
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
 
it 'returns true for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
end
end
Loading
Loading
@@ -505,13 +521,13 @@ describe Issue, models: true do
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
 
it 'returns true for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).to be_readable_by(user)
expect(issue.visible_to_user?(user)).to eq(true)
end
end
end
Loading
Loading
@@ -523,13 +539,13 @@ describe Issue, models: true do
it 'returns true for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).to be_publicly_visible
expect(issue).to be_truthy
end
 
it 'returns false for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).not_to be_publicly_visible
expect(issue).not_to be_falsy
end
end
 
Loading
Loading
@@ -539,13 +555,13 @@ describe Issue, models: true do
it 'returns false for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).not_to be_publicly_visible
expect(issue).not_to be_falsy
end
 
it 'returns false for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).not_to be_publicly_visible
expect(issue).not_to be_falsy
end
end
 
Loading
Loading
@@ -555,13 +571,13 @@ describe Issue, models: true do
it 'returns false for a regular issue' do
issue = build(:issue, project: project)
 
expect(issue).not_to be_publicly_visible
expect(issue).not_to be_falsy
end
 
it 'returns false for a confidential issue' do
issue = build(:issue, :confidential, project: project)
 
expect(issue).not_to be_publicly_visible
expect(issue).not_to be_falsy
end
end
end
Loading
Loading
Loading
Loading
@@ -13,7 +13,7 @@ describe PipelinesEmailService do
end
 
before do
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
end
 
describe 'Validations' do
Loading
Loading
@@ -23,14 +23,6 @@ describe PipelinesEmailService do
end
 
it { is_expected.to validate_presence_of(:recipients) }
context 'when pusher is added' do
before do
subject.add_pusher = true
end
it { is_expected.not_to validate_presence_of(:recipients) }
end
end
 
context 'when service is inactive' do
Loading
Loading
@@ -66,8 +58,7 @@ describe PipelinesEmailService do
end
 
it 'sends email' do
sent_to = ActionMailer::Base.deliveries.flat_map(&:to)
expect(sent_to).to contain_exactly(recipient)
should_only_email(double(notification_email: recipient), kind: :bcc)
end
end
 
Loading
Loading
@@ -79,7 +70,7 @@ describe PipelinesEmailService do
end
 
it 'does not send email' do
expect(ActionMailer::Base.deliveries).to be_empty
should_not_email_anyone
end
end
 
Loading
Loading
Loading
Loading
@@ -48,6 +48,17 @@ describe API::API, api: true do
end['username']).to eq(username)
end
 
it "returns an array of blocked users" do
ldap_blocked_user
create(:user, state: 'blocked')
get api("/users?blocked=true", user)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response).to all(include('state' => /(blocked|ldap_blocked)/))
end
it "returns one user" do
get api("/users?username=#{omniauth_user.username}", user)
expect(response).to have_http_status(200)
Loading
Loading
@@ -69,6 +80,16 @@ describe API::API, api: true do
expect(json_response.first.keys).to include 'last_sign_in_at'
expect(json_response.first.keys).to include 'confirmed_at'
end
it "returns an array of external users" do
create(:user, external: true)
get api("/users?external=true", admin)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response).to all(include('external' => true))
end
end
 
context "when authenticated and ldap is enabled" do
Loading
Loading
Loading
Loading
@@ -147,6 +147,7 @@ describe 'Git HTTP requests', lib: true do
end
end
end
<<<<<<< HEAD
end
 
context "when Kerberos token is provided" do
Loading
Loading
@@ -257,6 +258,8 @@ describe 'Git HTTP requests', lib: true do
expect(response).to have_http_status(403)
end
end
=======
>>>>>>> ce/master
end
 
context "when the project is private" do
Loading
Loading
Loading
Loading
@@ -20,7 +20,7 @@ describe JwtController do
end
end
 
context 'when using authorized request' do
context 'when using authenticated request' do
context 'using CI token' do
let(:build) { create(:ci_build, :running) }
let(:project) { build.project }
Loading
Loading
@@ -65,7 +65,7 @@ describe JwtController do
let(:access_token) { create(:personal_access_token, user: user) }
let(:headers) { { authorization: credentials(user.username, access_token.token) } }
 
it 'rejects the authorization attempt' do
it 'accepts the authorization attempt' do
expect(response).to have_http_status(200)
end
end
Loading
Loading
@@ -81,6 +81,20 @@ describe JwtController do
end
end
 
context 'when using unauthenticated request' do
it 'accepts the authorization attempt' do
get '/jwt/auth', parameters
expect(response).to have_http_status(200)
end
it 'allows read access' do
expect(service).to receive(:execute).with(authentication_abilities: Gitlab::Auth.read_authentication_abilities)
get '/jwt/auth', parameters
end
end
context 'unknown service' do
subject! { get '/jwt/auth', service: 'unknown' }
 
Loading
Loading
require 'spec_helper'
describe Ci::SendPipelineNotificationService, services: true do
let(:pipeline) do
create(:ci_pipeline,
project: project,
sha: project.commit('master').sha,
user: user,
status: status)
end
let(:project) { create(:project) }
let(:user) { create(:user) }
subject{ described_class.new(pipeline) }
describe '#execute' do
before do
reset_delivered_emails!
end
shared_examples 'sending emails' do
it 'sends an email to pipeline user' do
perform_enqueued_jobs do
subject.execute([user.email])
end
email = ActionMailer::Base.deliveries.last
expect(email.subject).to include(email_subject)
expect(email.to).to eq([user.email])
end
end
context 'with success pipeline' do
let(:status) { 'success' }
let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" }
it_behaves_like 'sending emails'
end
context 'with failed pipeline' do
let(:status) { 'failed' }
let(:email_subject) { "Pipeline ##{pipeline.id} has failed" }
it_behaves_like 'sending emails'
end
end
end
Loading
Loading
@@ -17,7 +17,7 @@ describe NotificationService, services: true do
 
it 'sends no emails when no new mentions are present' do
send_notifications
expect(ActionMailer::Base.deliveries).to be_empty
should_not_email_anyone
end
 
it 'emails new mentions with a watch level higher than participant' do
Loading
Loading
@@ -27,7 +27,7 @@ describe NotificationService, services: true do
 
it 'does not email new mentions with a watch level equal to or less than participant' do
send_notifications(@u_participating, @u_mentioned)
expect(ActionMailer::Base.deliveries).to be_empty
should_not_email_anyone
end
end
 
Loading
Loading
@@ -79,7 +79,7 @@ describe NotificationService, services: true do
# Ensure create SentNotification by noteable = issue 6 times, not noteable = note
expect(SentNotification).to receive(:record).with(issue, any_args).exactly(8).times
 
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
 
notification.new_note(note)
 
Loading
Loading
@@ -111,7 +111,7 @@ describe NotificationService, services: true do
context 'participating' do
context 'by note' do
before do
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
note.author = @u_lazy_participant
note.save
notification.new_note(note)
Loading
Loading
@@ -134,7 +134,7 @@ describe NotificationService, services: true do
@u_watcher.notification_settings_for(note.project).participating!
@u_watcher.notification_settings_for(note.project.group).global!
update_custom_notification(:new_note, @u_custom_global)
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
end
 
it do
Loading
Loading
@@ -173,7 +173,7 @@ describe NotificationService, services: true do
 
expect(SentNotification).to receive(:record).with(confidential_issue, any_args).exactly(4).times
 
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
 
notification.new_note(note)
 
Loading
Loading
@@ -196,7 +196,7 @@ describe NotificationService, services: true do
before do
build_team(note.project)
note.project.team << [note.author, :master]
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
end
 
describe '#new_note' do
Loading
Loading
@@ -238,7 +238,7 @@ describe NotificationService, services: true do
before do
build_team(note.project)
note.project.team << [note.author, :master]
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
end
 
describe '#new_note' do
Loading
Loading
@@ -273,7 +273,7 @@ describe NotificationService, services: true do
 
before do
build_team(note.project)
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer)
update_custom_notification(:new_note, @u_guest_custom, project)
update_custom_notification(:new_note, @u_custom_global)
Loading
Loading
@@ -348,7 +348,7 @@ describe NotificationService, services: true do
before do
build_team(issue.project)
add_users_with_subscription(issue.project, issue)
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
update_custom_notification(:new_issue, @u_guest_custom, project)
update_custom_notification(:new_issue, @u_custom_global)
end
Loading
Loading
@@ -408,7 +408,7 @@ describe NotificationService, services: true do
label.toggle_subscription(guest)
label.toggle_subscription(admin)
 
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
 
notification.new_issue(confidential_issue, @u_disabled)
 
Loading
Loading
@@ -604,7 +604,7 @@ describe NotificationService, services: true do
label_2.toggle_subscription(guest)
label_2.toggle_subscription(admin)
 
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
 
notification.relabeled_issue(confidential_issue, [label_2], @u_disabled)
 
Loading
Loading
@@ -733,7 +733,7 @@ describe NotificationService, services: true do
add_users_with_subscription(merge_request.target_project, merge_request)
update_custom_notification(:new_merge_request, @u_guest_custom, project)
update_custom_notification(:new_merge_request, @u_custom_global)
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
end
 
describe '#new_merge_request' do
Loading
Loading
@@ -1146,7 +1146,7 @@ describe NotificationService, services: true do
 
before do
build_team(project)
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
end
 
describe '#project_was_moved' do
Loading
Loading
Loading
Loading
@@ -49,7 +49,8 @@ module CycleAnalyticsHelpers
end
 
def merge_merge_requests_closing_issue(issue)
merge_requests = issue.closed_by_merge_requests
merge_requests = issue.closed_by_merge_requests(user)
merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) }
end
 
Loading
Loading
module EmailHelpers
def sent_to_user?(user)
ActionMailer::Base.deliveries.map(&:to).flatten.count(user.email) == 1
def sent_to_user?(user, recipients = email_recipients)
recipients.include?(user.notification_email)
end
 
def reset_delivered_emails!
ActionMailer::Base.deliveries.clear
end
 
def should_only_email(*users)
users.each {|user| should_email(user) }
recipients = ActionMailer::Base.deliveries.flat_map(&:to)
def should_only_email(*users, kind: :to)
recipients = email_recipients(kind: kind)
users.each { |user| should_email(user, recipients) }
expect(recipients.count).to eq(users.count)
end
 
def should_email(user)
expect(sent_to_user?(user)).to be_truthy
def should_email(user, recipients = email_recipients)
expect(sent_to_user?(user, recipients)).to be_truthy
end
def should_not_email(user, recipients = email_recipients)
expect(sent_to_user?(user, recipients)).to be_falsey
end
def should_not_email_anyone
expect(ActionMailer::Base.deliveries).to be_empty
end
 
def should_not_email(user)
expect(sent_to_user?(user)).to be_falsey
def email_recipients(kind: :to)
ActionMailer::Base.deliveries.flat_map(&kind)
end
end
Loading
Loading
@@ -7,7 +7,7 @@ shared_context 'gitlab email notification' do
let(:new_user_address) { 'newguy@example.com' }
 
before do
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
email = recipient.emails.create(email: "notifications@example.com")
recipient.update_attribute(:notification_email, email.email)
stub_incoming_email_setting(enabled: true, address: "reply+%{key}@#{Gitlab.config.gitlab.host}")
Loading
Loading
shared_examples 'project features apply to issuables' do |klass|
let(:described_class) { klass }
let(:group) { create(:group) }
let(:user_in_group) { create(:group_member, :developer, user: create(:user), group: group ).user }
let(:user_outside_group) { create(:user) }
let(:project) { create(:empty_project, :public, project_args) }
def project_args
feature = "#{described_class.model_name.plural}_access_level".to_sym
args = { group: group }
args[feature] = access_level
args
end
before do
_ = issuable
login_as(user)
visit path
end
context 'public access level' do
let(:access_level) { ProjectFeature::ENABLED }
context 'group member' do
let(:user) { user_in_group }
it { expect(page).to have_content(issuable.title) }
end
context 'non-member' do
let(:user) { user_outside_group }
it { expect(page).to have_content(issuable.title) }
end
end
context 'private access level' do
let(:access_level) { ProjectFeature::PRIVATE }
context 'group member' do
let(:user) { user_in_group }
it { expect(page).to have_content(issuable.title) }
end
context 'non-member' do
let(:user) { user_outside_group }
it { expect(page).not_to have_content(issuable.title) }
end
end
end
RSpec.shared_examples "referenced feature visibility" do |*related_features|
let(:feature_fields) do
related_features.map { |feature| (feature + "_access_level").to_sym }
end
before { link['data-project'] = project.id.to_s }
context "when feature is disabled" do
it "does not create reference" do
set_features_fields_to(ProjectFeature::DISABLED)
expect(subject.nodes_visible_to_user(user, [link])).to eq([])
end
end
context "when feature is enabled only for team members" do
before { set_features_fields_to(ProjectFeature::PRIVATE) }
it "does not create reference for non member" do
non_member = create(:user)
expect(subject.nodes_visible_to_user(non_member, [link])).to eq([])
end
it "creates reference for member" do
project.team << [user, :developer]
expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
end
end
context "when feature is enabled" do
# The project is public
it "creates reference" do
set_features_fields_to(ProjectFeature::ENABLED)
expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
end
end
def set_features_fields_to(visibility_level)
feature_fields.each { |field| project.project_feature.update_attribute(field, visibility_level) }
end
end
require 'rake_helper'
describe 'gitlab:ldap:check rake task' do
include LdapHelpers
before do
Rake.application.rake_require 'tasks/gitlab/check'
stub_warn_user_is_not_gitlab
end
context 'when LDAP is not enabled' do
it 'does not attempt to bind or search for users' do
expect(Gitlab::LDAP::Config).not_to receive(:providers)
expect(Gitlab::LDAP::Adapter).not_to receive(:open)
run_rake_task('gitlab:ldap:check')
end
end
context 'when LDAP is enabled' do
let(:ldap) { double(:ldap) }
let(:adapter) { ldap_adapter('ldapmain', ldap) }
before do
allow(Gitlab::LDAP::Config)
.to receive_messages(
enabled?: true,
providers: ['ldapmain']
)
allow(Gitlab::LDAP::Adapter).to receive(:open).and_yield(adapter)
allow(adapter).to receive(:users).and_return([])
end
it 'attempts to bind using credentials' do
stub_ldap_config(has_auth?: true)
expect(ldap).to receive(:bind)
run_rake_task('gitlab:ldap:check')
end
it 'searches for 100 LDAP users' do
stub_ldap_config(uid: 'uid')
expect(adapter).to receive(:users).with('uid', '*', 100)
run_rake_task('gitlab:ldap:check')
end
end
end
Loading
Loading
@@ -24,7 +24,7 @@ describe BuildEmailWorker do
end
 
it "gracefully handles an input SMTP error" do
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
allow(Notify).to receive(:build_success_email).and_raise(Net::SMTPFatalError)
 
subject.perform(build.id, [user.email], data.stringify_keys)
Loading
Loading
Loading
Loading
@@ -87,7 +87,7 @@ describe EmailsOnPushWorker do
 
context "when there is an SMTP error" do
before do
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
allow(Notify).to receive(:repository_push_email).and_raise(Net::SMTPFatalError)
allow(subject).to receive_message_chain(:logger, :info)
perform
Loading
Loading
@@ -112,7 +112,7 @@ describe EmailsOnPushWorker do
original.call(Mail.new(mail.encoded))
end
 
ActionMailer::Base.deliveries.clear
reset_delivered_emails!
end
 
it "sends the mail to each of the recipients" do
Loading
Loading
require 'spec_helper'
describe PipelineNotificationWorker do
let(:pipeline) do
create(:ci_pipeline,
project: project,
sha: project.commit('master').sha,
user: pusher,
status: status)
end
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:pusher) { user }
let(:watcher) { pusher }
describe '#execute' do
before do
reset_delivered_emails!
pipeline.project.team << [pusher, Gitlab::Access::DEVELOPER]
end
context 'when watcher has developer access' do
before do
pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER]
end
shared_examples 'sending emails' do
it 'sends emails' do
perform_enqueued_jobs do
subject.perform(pipeline.id)
end
emails = ActionMailer::Base.deliveries
actual = emails.flat_map(&:bcc).sort
expected_receivers = receivers.map(&:email).uniq.sort
expect(actual).to eq(expected_receivers)
expect(emails.size).to eq(1)
expect(emails.last.subject).to include(email_subject)
end
end
context 'with success pipeline' do
let(:status) { 'success' }
let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" }
let(:receivers) { [pusher, watcher] }
it_behaves_like 'sending emails'
context 'with pipeline from someone else' do
let(:pusher) { create(:user) }
let(:watcher) { user }
context 'with success pipeline notification on' do
before do
watcher.global_notification_setting.
update(level: 'custom', success_pipeline: true)
end
it_behaves_like 'sending emails'
end
context 'with success pipeline notification off' do
let(:receivers) { [pusher] }
before do
watcher.global_notification_setting.
update(level: 'custom', success_pipeline: false)
end
it_behaves_like 'sending emails'
end
end
context 'with failed pipeline' do
let(:status) { 'failed' }
let(:email_subject) { "Pipeline ##{pipeline.id} has failed" }
it_behaves_like 'sending emails'
context 'with pipeline from someone else' do
let(:pusher) { create(:user) }
let(:watcher) { user }
context 'with failed pipeline notification on' do
before do
watcher.global_notification_setting.
update(level: 'custom', failed_pipeline: true)
end
it_behaves_like 'sending emails'
end
context 'with failed pipeline notification off' do
let(:receivers) { [pusher] }
before do
watcher.global_notification_setting.
update(level: 'custom', failed_pipeline: false)
end
it_behaves_like 'sending emails'
end
end
end
end
end
context 'when watcher has no read_build access' do
let(:status) { 'failed' }
let(:email_subject) { "Pipeline ##{pipeline.id} has failed" }
let(:watcher) { create(:user) }
before do
pipeline.project.team << [watcher, Gitlab::Access::GUEST]
watcher.global_notification_setting.
update(level: 'custom', failed_pipeline: true)
perform_enqueued_jobs do
subject.perform(pipeline.id)
end
end
it 'does not send emails' do
should_only_email(pusher, kind: :bcc)
end
end
end
end
/* eslint-disable */
/**
* Timeago is a jQuery plugin that makes it easy to support automatically
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* @name timeago
* @version 1.1.0
* @requires jQuery v1.2.3+
* @author Ryan McGeary
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*
* For usage and examples, visit:
* http://timeago.yarp.com/
*
* Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
$.timeago = function(timestamp) {
if (timestamp instanceof Date) {
return inWords(timestamp);
} else if (typeof timestamp === "string") {
return inWords($.timeago.parse(timestamp));
} else if (typeof timestamp === "number") {
return inWords(new Date(timestamp));
} else {
return inWords($.timeago.datetime(timestamp));
}
};
var $t = $.timeago;
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
allowFuture: false,
strings: {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "ago",
suffixFromNow: "from now",
seconds: "less than a minute",
minute: "about a minute",
minutes: "%d minutes",
hour: "about an hour",
hours: "about %d hours",
day: "a day",
days: "%d days",
month: "about a month",
months: "%d months",
year: "about a year",
years: "%d years",
wordSeparator: " ",
numbers: []
}
},
inWords: function(distanceMillis) {
var $l = this.settings.strings;
var prefix = $l.prefixAgo;
var suffix = $l.suffixAgo;
if (this.settings.allowFuture) {
if (distanceMillis < 0) {
prefix = $l.prefixFromNow;
suffix = $l.suffixFromNow;
}
}
var seconds = Math.abs(distanceMillis) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
return string.replace(/%d/i, value);
}
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
seconds < 90 && substitute($l.minute, 1) ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
minutes < 90 && substitute($l.hour, 1) ||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
hours < 42 && substitute($l.day, 1) ||
days < 30 && substitute($l.days, Math.round(days)) ||
days < 45 && substitute($l.month, 1) ||
days < 365 && substitute($l.months, Math.round(days / 30)) ||
years < 1.5 && substitute($l.year, 1) ||
substitute($l.years, Math.round(years));
var separator = $l.wordSeparator || "";
if ($l.wordSeparator === undefined) { separator = " "; }
return $.trim([prefix, words, suffix].join(separator));
},
parse: function(iso8601) {
var s = $.trim(iso8601);
s = s.replace(/\.\d+/,""); // remove milliseconds
s = s.replace(/-/,"/").replace(/-/,"/");
s = s.replace(/T/," ").replace(/Z/," UTC");
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
return new Date(s);
},
datetime: function(elem) {
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
return $t.parse(iso8601);
},
isTime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
}
});
// functions that can be called via $(el).timeago('action')
// init is default when no action is given
// functions are called with context of a single element
var functions = {
init: function(){
var refresh_el = $.proxy(refresh, this);
refresh_el();
var $s = $t.settings;
if ($s.refreshMillis > 0) {
setInterval(refresh_el, $s.refreshMillis);
}
},
update: function(time){
$(this).data('timeago', { datetime: $t.parse(time) });
refresh.apply(this);
}
};
$.fn.timeago = function(action, options) {
var fn = action ? functions[action] : functions.init;
if(!fn){
throw new Error("Unknown function name '"+ action +"' for timeago");
}
// each over objects here and call the requested function
this.each(function(){
fn.call(this, options);
});
return this;
};
function refresh() {
var data = prepareData(this);
if (!isNaN(data.datetime)) {
$(this).text(inWords(data.datetime));
}
return this;
}
function prepareData(element) {
element = $(element);
if (!element.data("timeago")) {
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
element.attr("title", text);
}
}
return element.data("timeago");
}
function inWords(date) {
return $t.inWords(distance(date));
}
function distance(date) {
return (new Date().getTime() - date.getTime());
}
// fix for IE6 suckage
document.createElement("abbr");
document.createElement("time");
}));
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment