Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slack channels #1145

Merged
merged 7 commits into from Jan 4, 2017
19 changes: 16 additions & 3 deletions app/models/notification_services/slack_service.rb
@@ -1,15 +1,27 @@
class NotificationServices::SlackService < NotificationService
CHANNEL_NAME_REGEXP = /^#[a-z\d_-]+$/
LABEL = "slack"
FIELDS += [
[:service_url, {
placeholder: 'Slack Hook URL (https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXX)',
label: 'Hook URL'
}],
[:room_id, {
placeholder: '#general',
label: 'Notification channel',
hint: 'If empty Errbit will use the default channel for the webook'
}]
]

# Make room_id optional in case users want to use the default channel
# setup on Slack when creating the webhook
def check_params
if FIELDS.detect { |f| self[f[0]].blank? }
errors.add :base, "You must specify your Slack Hook url."
if service_url.blank?
errors.add :service_url, "You must specify your Slack Hook url"
end

if room_id.present? && !CHANNEL_NAME_REGEXP.match(room_id)
errors.add :room_id, "Slack channel name must be lowercase, with no space, special character, or periods."
end
end

Expand All @@ -21,6 +33,7 @@ def post_payload(problem)
{
username: "Errbit",
icon_url: "https://raw.githubusercontent.com/errbit/errbit/master/docs/notifications/slack/errbit.png",
channel: room_id,
attachments: [
{
fallback: message_for_slack(problem),
Expand Down Expand Up @@ -52,7 +65,7 @@ def post_payload(problem)
]
}
]
}.to_json
}.compact.to_json # compact to remove empty channel in case it wasn't selected by user
end

def create_notification(problem)
Expand Down
2 changes: 2 additions & 0 deletions app/views/apps/_service_notification_fields.html.haml
Expand Up @@ -16,6 +16,8 @@
%div.notification_params{:class => (w.object.is_a?(notification_service) ? 'chosen ' : '') << notification_service.label}
- notification_service::FIELDS.each do |field, field_info|
= w.label field, field_info[:label] || field.to_s.titleize
- if field_info[:hint].present?
%em= field_info[:hint]
- field_type = field == :password ? :password_field : :text_field
- value = field == :notify_at_notices ? w.object.notify_at_notices.join(", ") : w.object.send(field)
= w.send field_type, field, :placeholder => field_info[:placeholder], :value => value
Expand Down
1 change: 1 addition & 0 deletions spec/fabricators/notification_service_fabricator.rb
Expand Up @@ -14,6 +14,7 @@

Fabricator :slack_notification_service, from: :notification_service, class_name: "NotificationServices::SlackService" do
service_url { sequence :word }
room_id { sequence(:room_id) { |i| "#room-#{i}" } }
end

Fabricator :hipchat_notification_service, from: :notification_service, class_name: "NotificationServices::HipchatService" do
Expand Down
81 changes: 67 additions & 14 deletions spec/models/notification_service/slack_service_spec.rb
@@ -1,26 +1,24 @@
describe NotificationServices::SlackService, type: 'model' do
let(:notice) { Fabricate :notice }
let(:problem) { notice.problem }
let(:service_url) do
"https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXX"
end

let(:service) do
Fabricate :slack_notification_service, app: notice.app,
service_url: service_url
service_url: service_url,
room_id: room_id
end

it "should have icon for slack" do
expect(Rails.root.join("docs/notifications/slack/errbit.png")).to exist
let(:room_id) do
"#general"
end

it "should send a notification to Slack with hook url" do
# setup
problem = notice.problem

# faraday stubbing
payload = {
# faraday stubbing
let(:payload_hash) do
{
username: "Errbit",
icon_url: "https://raw.githubusercontent.com/errbit/errbit/master/docs/notifications/slack/errbit.png",
channel: room_id,
attachments: [
{
fallback: service.message_for_slack(problem),
Expand Down Expand Up @@ -52,9 +50,64 @@
]
}
]
}.to_json
expect(HTTParty).to receive(:post).with(service.service_url, body: payload, headers: { "Content-Type" => "application/json" }).and_return(true)
}
end

it "should have icon for slack" do
expect(Rails.root.join("docs/notifications/slack/errbit.png")).to exist
end

context 'Validations' do
it 'validates presence of service_url' do
service.service_url = ""
service.valid?

expect(service.errors[:service_url]).
to include("You must specify your Slack Hook url")

service.service_url = service_url
service.valid?

expect(service.errors[:service_url]).to be_blank
end

it 'validates format of room_id' do
service.room_id = "INVALID NAME"
service.valid?

expect(service.errors[:room_id]).
to include("Slack channel name must be lowercase, with no space, special character, or periods.")

service.room_id = "#valid-room-name"
service.valid?

expect(service.errors[:room_id]).to be_blank
end
end

context 'with room_id' do
it "should send a notification to Slack with hook url and channel" do
payload = payload_hash.to_json

expect(HTTParty).to receive(:post).
with(service.service_url, body: payload, headers: { "Content-Type" => "application/json" }).
and_return(true)

service.create_notification(problem)
end
end

context 'without room_id' do
let(:room_id) { nil }

it "should send a notification to Slack with hook url and without channel" do
payload = payload_hash.except(:channel).to_json

expect(HTTParty).to receive(:post).
with(service.service_url, body: payload, headers: { "Content-Type" => "application/json" }).
and_return(true)

service.create_notification(problem)
service.create_notification(problem)
end
end
end