Files
sure/test/controllers/api/v1/push_subscriptions_controller_test.rb
T
0aa43de10a Add experimental Swift-native Sure Insights app (#3134)
* Add Swift-native Sure app

* Fix push subscriptions schema for CI

* Address native app review feedback

* Address remaining native app review feedback

* Use Flutter app logo for native icon

* Honor insight notification preferences and locale

---------

Co-authored-by: Juan Jose Mata <2v8shcb6pz@privaterelay.appleid.com>
Co-authored-by: sure-admin <sure-admin@splashblot.com>
2026-08-25 04:16:24 +02:00

161 lines
4.7 KiB
Ruby

require "test_helper"
class Api::V1::PushSubscriptionsControllerTest < ActionDispatch::IntegrationTest
setup do
@user = users(:family_admin)
key = ApiKey.generate_secure_key
@api_key = ApiKey.create!(
user: @user,
name: "Native push test",
key: key,
scopes: [ "read_write" ],
source: "mobile"
)
@headers = api_headers(@api_key)
@token = "ab" * 32
end
test "registers and refreshes an APNs token" do
assert_difference "PushSubscription.count", 1 do
post api_v1_push_subscriptions_url,
params: { token: @token, environment: "sandbox", platform: "ios" },
headers: @headers,
as: :json
end
assert_response :created
subscription = PushSubscription.find_by!(token: @token)
assert_equal @user, subscription.user
assert_equal "sandbox", subscription.environment
assert_no_difference "PushSubscription.count" do
post api_v1_push_subscriptions_url,
params: { token: @token, environment: "production", platform: "ios" },
headers: @headers,
as: :json
end
assert_equal "production", subscription.reload.environment
end
test "requires a read write API key" do
read_key_value = ApiKey.generate_secure_key
read_key = ApiKey.create!(
user: @user,
name: "Read-only native push test",
key: read_key_value,
scopes: [ "read" ],
source: "mobile"
)
post api_v1_push_subscriptions_url,
params: { token: @token, environment: "sandbox", platform: "ios" },
headers: api_headers(read_key),
as: :json
assert_response :forbidden
end
test "rejects malformed tokens" do
post api_v1_push_subscriptions_url,
params: { token: "not-a-device-token", environment: "sandbox", platform: "ios" },
headers: @headers,
as: :json
assert_response :unprocessable_entity
end
test "rejects an invalid APNs environment" do
post api_v1_push_subscriptions_url,
params: { token: @token, environment: "staging", platform: "ios" },
headers: @headers,
as: :json
assert_response :unprocessable_entity
end
test "normalizes APNs tokens before lookup and persistence" do
post api_v1_push_subscriptions_url,
params: { token: @token.upcase, environment: "sandbox", platform: "ios" },
headers: @headers,
as: :json
assert_response :created
assert PushSubscription.exists?(token: @token)
assert_no_difference "PushSubscription.count" do
post api_v1_push_subscriptions_url,
params: { token: @token, environment: "sandbox", platform: "ios" },
headers: @headers,
as: :json
end
end
test "does not transfer another user's token" do
other_user = users(:empty)
subscription = other_user.push_subscriptions.create!(
token: @token,
environment: "sandbox",
platform: "ios",
last_registered_at: Time.current
)
post api_v1_push_subscriptions_url,
params: { token: @token.upcase, environment: "production", platform: "ios" },
headers: @headers,
as: :json
assert_response :unprocessable_entity
assert_equal other_user, subscription.reload.user
assert_equal "sandbox", subscription.environment
end
test "returns a controlled response when concurrent token registration conflicts" do
PushSubscription.any_instance.stubs(:save!).raises(ActiveRecord::RecordNotUnique)
post api_v1_push_subscriptions_url,
params: { token: @token, environment: "sandbox", platform: "ios" },
headers: @headers,
as: :json
assert_response :unprocessable_entity
assert_equal "validation_error", response.parsed_body["error"]
end
test "removes the current user's token" do
subscription = @user.push_subscriptions.create!(
token: @token,
environment: "sandbox",
platform: "ios",
last_registered_at: Time.current
)
assert_difference "PushSubscription.count", -1 do
delete api_v1_push_subscription_url(subscription), headers: @headers
end
assert_response :no_content
end
test "does not remove another user's token" do
subscription = users(:empty).push_subscriptions.create!(
token: @token,
environment: "sandbox",
platform: "ios",
last_registered_at: Time.current
)
delete api_v1_push_subscription_url(subscription), headers: @headers
assert_response :not_found
assert PushSubscription.exists?(subscription.id)
end
test "requires authentication" do
post api_v1_push_subscriptions_url,
params: { token: @token, environment: "sandbox", platform: "ios" },
as: :json
assert_response :unauthorized
end
end