discourse/spec/services/push_notification_pusher_spec.rb
Sam 7b4e338c0e
FIX: fallback to default push notification icon if none exists (#16961)
Due to some changes we started notifying via push notifications on other
families of notifications. There are a total of about 30 or so possible
notification you could get, some can be pushed.

This fallback means that if for any reason we are unable to find an icon
for a push notification we just fallback to the Discourse logo.

Also go with a simple reply icon for watching first post.

Note, that in production `image_url` can return an exception if an image is
missing. This is not the case in test / development.
2022-06-01 12:00:05 +10:00

128 lines
3.9 KiB
Ruby

# frozen_string_literal: true
RSpec.describe PushNotificationPusher do
it "returns badges url by default" do
expect(PushNotificationPusher.get_badge).to eq("/assets/push-notifications/discourse.png")
end
it "returns custom badges url" do
upload = Fabricate(:upload)
SiteSetting.push_notifications_icon = upload
expect(PushNotificationPusher.get_badge)
.to eq(UrlHelper.absolute(upload.url))
end
context "with user" do
fab!(:user) { Fabricate(:user) }
def create_subscription
data = <<~JSON
{
"endpoint": "endpoint",
"keys": {
"p256dh": "p256dh",
"auth": "auth"
}
}
JSON
PushSubscription.create!(user_id: user.id, data: data)
end
def execute_push(notification_type: 1)
PushNotificationPusher.push(user, {
topic_title: 'Topic',
username: 'system',
excerpt: 'description',
topic_id: 1,
post_url: "https://example.com/t/1/2",
notification_type: notification_type
})
end
it "correctly guesses an image if missing" do
message = execute_push(notification_type: -1)
expect(message[:icon]).to eq("/assets/push-notifications/discourse.png")
end
it "correctly finds image if exists" do
message = execute_push(notification_type: 1)
expect(message[:icon]).to eq("/assets/push-notifications/mentioned.png")
end
it "sends notification in user's locale" do
SiteSetting.allow_user_locale = true
user.update!(locale: 'pt_BR')
TranslationOverride.upsert!("pt_BR", "discourse_push_notifications.popup.mentioned", "pt_BR notification")
Webpush.expects(:payload_send).with do |*args|
JSON.parse(args.first[:message])["title"] == "pt_BR notification"
end.once
create_subscription
execute_push
end
it "deletes subscriptions which are erroring regularly" do
start = freeze_time
sub = create_subscription
response = Struct.new(:body, :inspect, :message).new("test", "test", "failed")
error = Webpush::ResponseError.new(response, "localhost")
Webpush.expects(:payload_send).raises(error).times(4)
# 3 failures in more than 24 hours
3.times do
execute_push
freeze_time 1.minute.from_now
end
sub.reload
expect(sub.error_count).to eq(3)
expect(sub.first_error_at).to eq_time(start)
freeze_time(2.days.from_now)
execute_push
expect(PushSubscription.where(id: sub.id).exists?).to eq(false)
end
it "deletes invalid subscriptions during send" do
missing_endpoint = PushSubscription.create!(user_id: user.id, data:
{ p256dh: "public ECDH key", keys: { auth: "private ECDH key" } }.to_json)
missing_p256dh = PushSubscription.create!(user_id: user.id, data:
{ endpoint: "endpoint 1", keys: { auth: "private ECDH key" } }.to_json)
missing_auth = PushSubscription.create!(user_id: user.id, data:
{ endpoint: "endpoint 2", keys: { p256dh: "public ECDH key" } }.to_json)
valid_subscription = PushSubscription.create!(user_id: user.id, data:
{ endpoint: "endpoint 3", keys: { p256dh: "public ECDH key", auth: "private ECDH key" } }.to_json)
expect(PushSubscription.where(user_id: user.id)).to contain_exactly(missing_endpoint, missing_p256dh, missing_auth, valid_subscription)
Webpush.expects(:payload_send).with(has_entries(endpoint: "endpoint 3", p256dh: "public ECDH key", auth: "private ECDH key")).once
execute_push
expect(PushSubscription.where(user_id: user.id)).to contain_exactly(valid_subscription)
end
it "handles timeouts" do
Webpush.expects(:payload_send).raises(Net::ReadTimeout.new)
subscription = create_subscription
expect { execute_push }.to_not raise_exception
subscription.reload
expect(subscription.error_count).to eq(1)
end
end
end