From 3eafa5e335517e955db14502b6fb65c7d2223861 Mon Sep 17 00:00:00 2001 From: Karina Kwiatek Date: Sat, 24 Dec 2022 16:41:21 +0000 Subject: [PATCH] Add tests for subscription management --- app/controllers/ajax/web_push_controller.rb | 8 +- .../ajax/web_push_controller_spec.rb | 200 ++++++++++++++++++ .../push_notifications_controller_spec.rb | 20 ++ 3 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 spec/controllers/ajax/web_push_controller_spec.rb create mode 100644 spec/controllers/settings/push_notifications_controller_spec.rb diff --git a/app/controllers/ajax/web_push_controller.rb b/app/controllers/ajax/web_push_controller.rb index 0d00b852..8f0408ad 100644 --- a/app/controllers/ajax/web_push_controller.rb +++ b/app/controllers/ajax/web_push_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Ajax::WebPushController < AjaxController + before_action :authenticate_user! + def key certificate = Rpush::Webpush::App.find_by(name: "webpush").certificate @@ -23,7 +25,7 @@ class Ajax::WebPushController < AjaxController def unsubscribe params.permit(:endpoint) - if params.key?(:endpoint) + removed = if params.key?(:endpoint) current_user.web_push_subscriptions.where("subscription ->> 'endpoint' = ?", params[:endpoint]).destroy_all else current_user.web_push_subscriptions.destroy_all @@ -31,8 +33,8 @@ class Ajax::WebPushController < AjaxController count = current_user.web_push_subscriptions.count - @response[:status] = :okay - @response[:success] = true + @response[:status] = removed.any? ? :okay : :err + @response[:success] = removed.any? @response[:message] = t(".subscription_count", count:) @response[:count] = count end diff --git a/spec/controllers/ajax/web_push_controller_spec.rb b/spec/controllers/ajax/web_push_controller_spec.rb new file mode 100644 index 00000000..dcac726a --- /dev/null +++ b/spec/controllers/ajax/web_push_controller_spec.rb @@ -0,0 +1,200 @@ +# frozen_string_literal: true + +require "rails_helper" + +describe Ajax::WebPushController, :ajax_controller, type: :controller do + before do + Rpush::Webpush::App.create( + name: "webpush", + certificate: { public_key: "AAAA", private_key: "BBBB", subject: "" }.to_json, + connections: 1 + ) + end + + describe "#key" do + subject { get :key, format: :json } + + let(:expected_response) do + { + "message" => "", + "status" => "okay", + "success" => true, + "key" => "AAAA" + } + end + + context "user signed in" do + let(:user) { FactoryBot.create(:user) } + + before { sign_in user } + + include_examples "returns the expected response" + end + end + + describe "#subscribe" do + subject { post :subscribe, params: } + + context "user signed in" do + let(:user) { FactoryBot.create(:user) } + + before { sign_in user } + + context "given a valid subscription" do + let(:params) do + { + subscription: { + endpoint: "https://some.webpush/endpoint", + keys: {} + } + } + end + let(:expected_response) do + { + "message" => I18n.t("settings.push_notifications.subscription_count.one"), + "status" => "okay", + "success" => true + } + end + + it "stores the subscription" do + expect { subject } + .to( + change { WebPushSubscription.count } + .by(1) + ) + end + + include_examples "returns the expected response" + end + end + + context "given no subscription param" do + let(:params) do + {} + end + end + end + + describe "#unsubscribe" do + subject { delete :unsubscribe, params: } + + shared_examples_for "does not remove any subscriptions" do + it "does not remove any subscriptions" do + expect { subject }.not_to(change { WebPushSubscription.count }) + end + end + + context "user signed in" do + let(:user) { FactoryBot.create(:user) } + + before { sign_in user } + + context "valid subscription" do + let(:endpoint) { "some endpoint" } + let!(:subscription) do + WebPushSubscription.create( + user:, + subscription: { endpoint:, keys: {} } + ) + end + let!(:other_subscription) do + WebPushSubscription.create( + user:, + subscription: { endpoint: "other endpoint", keys: {} } + ) + end + let(:params) do + { endpoint: } + end + let(:expected_response) do + { + "status" => "okay", + "success" => true, + "message" => I18n.t("ajax.web_push.subscription_count.one"), + "count" => 1 + } + end + + it "removes the subscription" do + subject + expect { subscription.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect { other_subscription.reload }.not_to raise_error(ActiveRecord::RecordNotFound) + end + + include_examples "returns the expected response" + end + + context "invalid subscription" do + let!(:subscription) do + WebPushSubscription.create( + user:, + subscription: { endpoint: "other endpoint", keys: {} } + ) + end + let(:params) do + { endpoint: "some endpoint" } + end + let(:expected_response) do + { + "status" => "err", + "success" => false, + "message" => I18n.t("ajax.web_push.subscription_count.one"), + "count" => 1 + } + end + + include_examples "does not remove any subscriptions" + include_examples "returns the expected response" + end + + context "someone else's subscription" do + let(:endpoint) { "some endpoint" } + let(:other_user) { FactoryBot.create(:user) } + let!(:subscription) do + WebPushSubscription.create( + user: other_user, + subscription: { endpoint:, keys: {} } + ) + end + let(:params) do + { endpoint: } + end + let(:expected_response) do + { + "status" => "err", + "success" => false, + "message" => I18n.t("ajax.web_push.subscription_count.zero"), + "count" => 0 + } + end + + include_examples "does not remove any subscriptions" + include_examples "returns the expected response" + end + + context "no subscription provided" do + let(:other_user) { FactoryBot.create(:user) } + let(:params) { {} } + + before do + 4.times do |i| + WebPushSubscription.create( + user: i.zero? ? other_user : user, + subscription: { endpoint: i, keys: {} } + ) + end + end + + it "removes all own subscriptions" do + expect { subject } + .to( + change { WebPushSubscription.count } + .from(4) + .to(1) + ) + end + end + end + end +end diff --git a/spec/controllers/settings/push_notifications_controller_spec.rb b/spec/controllers/settings/push_notifications_controller_spec.rb new file mode 100644 index 00000000..d78b7350 --- /dev/null +++ b/spec/controllers/settings/push_notifications_controller_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require "rails_helper" + +describe Settings::PushNotificationsController, type: :controller do + describe "#index" do + subject { get :index } + + context "user signed in" do + let(:user) { FactoryBot.create(:user) } + + before { sign_in user } + + it "renders the index template" do + subject + expect(response).to render_template(:index) + end + end + end +end