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>
This commit is contained in:
Juan José Mata
2026-08-25 04:16:24 +02:00
committed by GitHub
co-authored by Juan Jose Mata sure-admin
parent 311f06e404
commit 0aa43de10a
51 changed files with 2633 additions and 4 deletions
@@ -0,0 +1,50 @@
require "test_helper"
class Api::V1::InsightsControllerTest < ActionDispatch::IntegrationTest
setup do
@user = users(:family_admin)
@user.update!(preferences: @user.preferences.merge("preview_features_enabled" => true))
key = ApiKey.generate_secure_key
@api_key = ApiKey.create!(
user: @user,
name: "Native insights test",
key: key,
scopes: [ "read" ],
source: "mobile"
)
@insight = @user.family.insights.create!(
insight_type: "idle_cash",
priority: "medium",
status: "active",
title: "Put idle cash to work",
body: "One account has more cash than usual.",
generated_at: Time.current,
dedup_key: "native-insights-test"
)
end
test "lists visible family insights" do
get api_v1_insights_url, headers: api_headers(@api_key)
assert_response :success
payload = response.parsed_body
row = payload.fetch("insights").find { |insight| insight.fetch("id") == @insight.id }
assert_equal "idle_cash", row.fetch("type")
assert_equal "Put idle cash to work", row.fetch("title")
end
test "rejects requests without an API key" do
get api_v1_insights_url
assert_response :unauthorized
end
test "does not expose insights when the API key owner opted out of preview features" do
@user.update!(preferences: @user.preferences.merge("preview_features_enabled" => false))
get api_v1_insights_url, headers: api_headers(@api_key)
assert_response :forbidden
assert_equal "feature_disabled", response.parsed_body.fetch("error")
end
end