mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 07:49:01 +00:00
feat(retirement): PR3b what-if KPIs + live forecast Turbo Stream
Surfaces the forecast on the page and makes the levers live. - KPI cards (_kpis): Freedom date, Coast FIRE, Money-lasts-to + terminal value, with a "set your birth year" prompt until a plan is projectable. Wrapped in #retirement_kpis for Turbo Stream replacement; money carries privacy-sensitive. - What-if form: birth_year / retire_age / target_spend / monthly_savings / real_return_pct. On input, retirement_what_if_controller debounces and POSTs the current values to PATCH /retirement/forecast, which recomputes against transient inputs and streams the KPI cards back WITHOUT persisting. "Save plan" submits to #update to persist retirement_params. - RetirementController gains #update (persist) and #forecast (transient recompute → turbo_stream). Both reuse merged_plan_params, which drops blank fields so a partial what-if doesn't clobber stored values. Tests: KPI section renders; update persists params; forecast streams #retirement_kpis without writing the slider value back. Rubocop + erb_lint + biome clean. PR4 replaces this minimal form with the designed slider rail + glide chart; the #forecast endpoint and the engine stay.
This commit is contained in:
@@ -55,4 +55,41 @@ class RetirementControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
assert_select "a[href=?]", retirement_path, count: 0
|
||||
end
|
||||
|
||||
test "show renders the KPI section" do
|
||||
get retirement_url
|
||||
assert_response :success
|
||||
assert_select "#retirement_kpis"
|
||||
end
|
||||
|
||||
test "show uses real translations, not humanized i18n keys" do
|
||||
get retirement_url
|
||||
assert_response :success
|
||||
assert_match I18n.t("retirement.show.sources_title"), response.body
|
||||
assert_no_match(/Sources Title/, response.body)
|
||||
end
|
||||
|
||||
test "update persists retirement params" do
|
||||
patch retirement_url, params: { retirement: {
|
||||
birth_year: 1985, retire_age: 62, monthly_savings: 1500, target_spend: 2800, real_return_pct: 5
|
||||
} }
|
||||
|
||||
assert_redirected_to retirement_path
|
||||
plan = Goal::Retirement.for_owner(@user)
|
||||
assert_equal "1985", plan.birth_year.to_s
|
||||
assert_equal "62", plan.retire_age.to_s
|
||||
end
|
||||
|
||||
test "forecast streams KPIs without persisting" do
|
||||
Goal::Retirement.for_owner(@user).update!(retirement_params: { "birth_year" => 1980 })
|
||||
|
||||
patch forecast_retirement_url,
|
||||
params: { retirement: { retire_age: 70 } },
|
||||
headers: { "Accept" => "text/vnd.turbo-stream.html" }
|
||||
|
||||
assert_response :success
|
||||
assert_match "retirement_kpis", response.body
|
||||
# transient: the slider value is not written back to the plan
|
||||
assert_nil Goal::Retirement.for_owner(@user).retire_age
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user