whisper-money/tests
Víctor Falcón d3ec96b845
fix(onboarding): stop the AI rule-suggestion step from hanging forever (#705)
## Problem

A user reported being stuck forever on the onboarding "Looking for
patterns" step (the "Polishing your suggestions…" spinner). Confirmed in
prod: their `suggestion_runs` row has been stuck in `processing` for a
week, and `failed_jobs` shows `TimeoutExceededException:
GenerateRuleSuggestionsJob has timed out`.

### Root cause

- The user has 4,163 transactions — the largest onboarding dataset (max
with a completed run was 3,481). The Gemini generation exceeded the
job's `$timeout = 120`.
- The worker timeout is raised **outside** the `try/catch` in
`GenerateRuleSuggestions::run()`, so the code that sets `status =
Failed` never ran.
- `GenerateRuleSuggestionsJob` had **no `failed()` handler** (5 other
jobs do), so nothing flipped the run to `Failed`. It stayed
`processing`, `show()` kept returning `processing`, and the client
polled every 3s forever.
- The timeout never reached Sentry, so it was invisible. Only 1 user
affected, but it's a latent bug that recurs on any large account.

## Fix

**Backend** — add `failed()` to `GenerateRuleSuggestionsJob`: mark the
run `Failed` (only if not already terminal) and `report()` the exception
so these surface in Sentry.

**Frontend** (`step-ai-suggestions.tsx`) — belt-and-suspenders so the
client never spins forever even if the worker dies before it can mark
the run:
- `poll()` now guards against transient errors (network blip / expired
session / 5xx) instead of silently dying.
- A client-side deadline (3 min, just beyond the "up to two minutes"
copy) surfaces the existing "couldn't generate" screen with **Try again
/ Skip**.

Not included: raising the timeout / capping the number of groups sent to
Gemini so large accounts *complete* instead of just being able to skip.
Follow-up if we want big accounts to get suggestions.

## Tests

- `tests/Feature/Ai/GenerateRuleSuggestionsJobTest.php` — `failed()`
marks the run `Failed` + reports; doesn't overwrite an already-terminal
run.
-
`resources/js/components/onboarding/step-ai-suggestions-timeout.test.tsx`
— after the deadline the spinner gives way to the failed screen.

Green locally: pint, prettier, eslint, backend + frontend tests.
2026-07-20 18:10:51 +00:00
..
.pest Speed up PR CI browser path (#365) 2026-05-07 20:40:13 +01:00
Browser feat(onboarding): auto-enable AI for connected banks, ask the rest (#618) 2026-07-01 07:26:52 +00:00
Feature fix(onboarding): stop the AI rule-suggestion step from hanging forever (#705) 2026-07-20 18:10:51 +00:00
Fixtures refactor: consolidate duplicated financial calculations (#643) 2026-07-04 22:26:44 +02:00
Performance feat(transactions): make new-transaction marker cross-device (#611) 2026-06-29 19:11:37 +02:00
Support test(open-banking): e2e coverage for Enable Banking connection flows (#509) 2026-06-09 11:58:50 +02:00
Unit refactor: extract duplicated money formatter into App\Support\Money (#680) 2026-07-15 09:47:53 +02:00
Pest.php chore: harden Inertia boundary, CI type-check, and test isolation (#640) 2026-07-04 18:57:58 +00:00
TestCase.php Remove encryption from browser tests and demo user (#129) 2026-02-17 11:45:27 +01:00
bootstrap.php chore: upgrade Laravel 12 to 13 (#242) 2026-03-25 12:56:33 +00:00