Files
fizzy/saas/test/controllers/devices_controller_test.rb
T
Rosa Gutierrez 9d32f3e845 Refactor devices controller and extract registration to model
- Remove Users namespace from DevicesController (now just DevicesController)
- Create ApplicationPushDevice model extending ActionPushNative::Device
- Move device registration logic (find_or_initialize + update) to model
- Update User::Devices concern to use ApplicationPushDevice
- Fix push notification tests (endpoint validation, job count expectations)
- Update push_config_test to use ActionPushNative.config

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-25 19:31:13 +01:00

246 lines
5.8 KiB
Ruby

require "test_helper"
class DevicesControllerTest < ActionDispatch::IntegrationTest
setup do
@user = users(:david)
sign_in_as @user
end
# === Index (Web) ===
test "index shows user devices" do
@user.devices.create!(token: "test_token_123", platform: "apple", name: "iPhone 15 Pro")
get devices_path
assert_response :success
assert_select "strong", "iPhone 15 Pro"
assert_select "li", /iOS/
end
test "index shows empty state when no devices" do
@user.devices.delete_all
get devices_path
assert_response :success
assert_select "p", /No devices registered/
end
test "index requires authentication" do
sign_out
get devices_path
assert_response :redirect
end
# === Create (API) ===
test "creates a new device via api" do
token = SecureRandom.hex(32)
assert_difference "ActionPushNative::Device.count", 1 do
post devices_path, params: {
token: token,
platform: "apple",
name: "iPhone 15 Pro"
}, as: :json
end
assert_response :created
device = ActionPushNative::Device.last
assert_equal token, device.token
assert_equal "apple", device.platform
assert_equal "iPhone 15 Pro", device.name
assert_equal @user, device.owner
end
test "creates android device" do
post devices_path, params: {
token: SecureRandom.hex(32),
platform: "google",
name: "Pixel 8"
}, as: :json
assert_response :created
device = ActionPushNative::Device.last
assert_equal "google", device.platform
end
test "same token can be registered by multiple users" do
shared_token = "shared_push_token_123"
other_user = users(:kevin)
# Other user registers the token first
other_device = other_user.devices.create!(
token: shared_token,
platform: "apple",
name: "Kevin's iPhone"
)
# Current user registers the same token with their own device
assert_difference "ActionPushNative::Device.count", 1 do
post devices_path, params: {
token: shared_token,
platform: "apple",
name: "David's iPhone"
}, as: :json
end
assert_response :created
# Both users have their own device records
assert_equal shared_token, other_device.reload.token
assert_equal other_user, other_device.owner
davids_device = @user.devices.last
assert_equal shared_token, davids_device.token
assert_equal @user, davids_device.owner
end
test "rejects invalid platform" do
post devices_path, params: {
token: SecureRandom.hex(32),
platform: "windows",
name: "Surface"
}, as: :json
assert_response :bad_request
end
test "rejects missing token" do
post devices_path, params: {
platform: "apple",
name: "iPhone"
}, as: :json
assert_response :bad_request
end
test "create requires authentication" do
sign_out
post devices_path, params: {
token: SecureRandom.hex(32),
platform: "apple"
}, as: :json
assert_response :redirect
end
# === Destroy (Web) ===
test "destroys device by id" do
device = @user.devices.create!(
token: "token_to_delete",
platform: "apple",
name: "iPhone"
)
assert_difference "ActionPushNative::Device.count", -1 do
delete device_path(device)
end
assert_redirected_to devices_path
assert_not ActionPushNative::Device.exists?(device.id)
end
test "does nothing when device not found by id" do
assert_no_difference "ActionPushNative::Device.count" do
delete device_path(id: "nonexistent")
end
assert_redirected_to devices_path
end
test "cannot destroy another user's device by id" do
other_user = users(:kevin)
device = other_user.devices.create!(
token: "other_users_token",
platform: "apple",
name: "Other iPhone"
)
assert_no_difference "ActionPushNative::Device.count" do
delete device_path(device)
end
assert_redirected_to devices_path
assert ActionPushNative::Device.exists?(device.id)
end
test "destroy by id requires authentication" do
device = @user.devices.create!(
token: "my_token",
platform: "apple",
name: "iPhone"
)
sign_out
delete device_path(device)
assert_response :redirect
assert ActionPushNative::Device.exists?(device.id)
end
# === Destroy by Token (API) ===
test "destroys device by token" do
device = @user.devices.create!(
token: "token_to_unregister",
platform: "apple",
name: "iPhone"
)
assert_difference "ActionPushNative::Device.count", -1 do
delete unregister_devices_path, params: { token: "token_to_unregister" }, as: :json
end
assert_response :no_content
assert_not ActionPushNative::Device.exists?(device.id)
end
test "does nothing when device not found by token" do
assert_no_difference "ActionPushNative::Device.count" do
delete unregister_devices_path, params: { token: "nonexistent_token" }, as: :json
end
assert_response :no_content
end
test "cannot destroy another user's device by token" do
other_user = users(:kevin)
device = other_user.devices.create!(
token: "other_users_token",
platform: "apple",
name: "Other iPhone"
)
assert_no_difference "ActionPushNative::Device.count" do
delete unregister_devices_path, params: { token: "other_users_token" }, as: :json
end
assert_response :no_content
assert ActionPushNative::Device.exists?(device.id)
end
test "destroy by token requires authentication" do
device = @user.devices.create!(
token: "my_token",
platform: "apple",
name: "iPhone"
)
sign_out
delete unregister_devices_path, params: { token: "my_token" }, as: :json
assert_response :redirect
assert ActionPushNative::Device.exists?(device.id)
end
end