perf + tests(goals): share account-ids across velocity windows + cover gaps

- Family#savings_inflow_windows wraps the current/prior 30d sums in a
  single helper that memoizes the linked-account-id lookup. The KPI tile
  on the goals index used to run the join+pluck twice per request.
- Replace two instance_variable_set pokes and one any_instance.stubs in
  the goal/controller tests. Refetching the goal exercises the real
  request lifecycle and stops the tests from leaning on implementation
  details. The 'All caught up' assertion now relies on a real reached
  state (target 1 vs the depository fixture's 5000 balance) rather than
  stubbing :status.
- Add tests covering: hex format validation on Goal#color, AASM cache
  reset (display_status reads the new state on the same instance after
  pause!), negative pledge amount rejection, expire! no-op on already-
  expired pledge, cancel! NotOpenError on non-open pledge, sweep job
  idempotency on a second pass, and strong-params rejection of state /
  family_id on goal create.
This commit is contained in:
Guillem Arias
2026-05-18 21:11:30 +02:00
parent fbcd13c44d
commit f672aae3cf
6 changed files with 131 additions and 24 deletions

View File

@@ -165,8 +165,10 @@ class GoalsControllerTest < ActionDispatch::IntegrationTest
test "index KPI swaps to 'All caught up' when every tracked goal is reached" do
family = users(:family_admin).family
family.goals.destroy_all
# Real reached state: target $1 against the depository fixture's
# $5000 balance. Stubbing :status hides whether the controller
# actually reads the right method on each goal.
build_goal(family, "Wedding", target_amount: 1, target_date: 1.year.from_now)
Goal.any_instance.stubs(:status).returns(:reached)
get goals_url
assert_response :success
@@ -184,6 +186,31 @@ class GoalsControllerTest < ActionDispatch::IntegrationTest
public
test "create ignores forbidden params (family_id, state)" do
family = users(:family_admin).family
other_family = Family.create!(name: "Other", currency: "USD", locale: "en", country: "US", timezone: "UTC")
assert_difference -> { family.goals.count }, 1 do
post goals_url, params: {
goal: {
name: "Hijack target",
target_amount: 100,
currency: "USD",
state: "archived",
family_id: other_family.id,
account_ids: [ @depository.id ]
}
}
end
goal = family.goals.order(:created_at).last
# Strong params must strip both `state` (AASM-managed) and `family_id`
# (cross-family pivot) — otherwise a crafted POST would create rows
# outside the current family or skip the active-state assumption.
assert_equal "active", goal.state
assert_equal family.id, goal.family_id
end
test "another family's goal returns 404" do
other_family = Family.create!(name: "Other", currency: "USD", locale: "en", country: "US", timezone: "UTC")
other_account = Account.create!(family: other_family, accountable: Depository.new, name: "Foreign", currency: "USD", balance: 100)