# RevHero QA Run — scheduled-20260430T165651 **Started:** 2026-04-30T16:56:53.855Z **Finished:** 2026-04-30T16:59:57.882Z ## Summary | | Count | |---|---| | Total | 241 | | PASS | 207 | | FAIL | 7 | | SKIP | 20 | | NOT_EXEC | 7 | ## Results | ID | Status | Duration | Description | |---|---|---|---| | `FE-AUTH-001` | PASS | 1874.3322870000002ms | /login page renders with email + password + Forgot Password + Login + Register link | | `FE-AUTH-002` | FAIL | 60318.869552ms | Login with valid credentials → redirect to /automation-campaign | | `FE-AUTH-003` | PASS | 137.22099100000196ms | Login with wrong password → friendly error, no stack trace | | `FE-AUTH-004` | PASS | 99.80823599999712ms | Login with non-existent email → generic friendly error (no enumeration) | | `FE-AUTH-005` | PASS | 818.5854880000043ms | Login with empty fields → form validation errors | | `FE-AUTH-006` | PASS | 582.1339000000007ms | Eye icon on password field toggles show/hide | | `FE-AUTH-007` | PASS | 1332.761130999992ms | Forgot Password link → /forgot-password page renders | | `FE-AUTH-008` | PASS | 164.92001000000164ms | Submit forgot password form with valid email → success message | | `FE-AUTH-009` | FAIL | 269.9879499999952ms | Submit forgot password with non-existent email → generic success (anti-enumeration) | | `FE-AUTH-010` | PASS | 41.91231900001003ms | /auth-reset-password?token=invalid → friendly invalid token error | | `FE-AUTH-011` | PASS | 60.192465000000084ms | /auth-reset-password validates min length and match | | `FE-AUTH-012` | FAIL | 64917.43378200001ms | Sign Out button → clears cookies → redirects to /login | | `FE-AUTH-013` | PASS | 9999.581294000003ms | Hard refresh of authenticated page → session restores, no console errors | | `FE-AUTH-014` | PASS | 1211.228971000004ms | Direct nav to authenticated route while logged out → redirects to /login with ?redirect= | | `FE-AUTH-015` | PASS | 463.4143670000194ms | JWT expires mid-session → next API call triggers refresh; refresh fail → logout | | `FE-AUTH-016` | PASS | 7708.85339199999ms | Login on staging hits staging BFF, NOT prod (FE-BUG-002 regression) | | `FE-AUTH-017` | FAIL | 1129.301237000007ms | Cookie has Secure, HttpOnly, SameSite flags set on auth cookies | | `FE-AUTH-018` | PASS | 6165.639448000002ms | Open redirect — ?redirect=https://evil.com after login → blocked | | `FE-AUTH-019` | PASS | 2437.316812999983ms | Login button shows loading spinner while authenticating | | `FE-AUTH-020` | PASS | 915.7282760000089ms | Rate limiting on /login — rapid wrong-password attempts trigger 429 | | `FE-CAMP-001` | SKIP | 0ms | /automation-campaign lists campaigns or shows empty state | | `FE-CAMP-002` | SKIP | 0ms | Tabs Active / Inactive / All switch correctly | | `FE-CAMP-003` | SKIP | 0ms | Search Campaigns input filters list | | `FE-CAMP-004` | SKIP | 0ms | Pagination Next/Prev (where present) is sane | | `FE-CAMP-005` | SKIP | 0ms | PULSE / SWARM tabs at top (SWARM dev-only on staging) | | `FE-CAMP-006` | SKIP | 0ms | /automation-campaign/create renders builder | | `FE-CAMP-007` | SKIP | 0ms | Builder header shows 'Untitled' (FE-BUG-08 fix — not literal 'undefined') | | `FE-CAMP-008` | SKIP | 0ms | Builder canvas shows 'Add Stage +' button | | `FE-CAMP-009` | SKIP | 0ms | Click Add Stage opens stage type modal | | `FE-CAMP-010` | SKIP | 0ms | Stage settings modal validates required fields (sanity check) | | `FE-CAMP-011` | SKIP | 0ms | Builder name area exists (route smoke) | | `FE-CAMP-012` | SKIP | 0ms | Save Campaign with no stages → friendly error or warning | | `FE-CAMP-013` | SKIP | 0ms | Active toggle persists after save (visual presence) | | `FE-CAMP-014` | SKIP | 0ms | Click 'Import campaign from CRM' opens import modal | | `FE-CAMP-015` | SKIP | 0ms | Import campaign validates CRM connection state (smoke) | | `FE-CAMP-016` | SKIP | 0ms | /automation-campaign/[id] for non-existent ID → 404 or friendly error | | `FE-CAMP-017` | SKIP | 0ms | /automation-campaign/[id]/deals lists campaign deals | | `FE-CAMP-018` | SKIP | 0ms | Deals table renders without crashing (smoke) | | `FE-CAMP-019` | SKIP | 0ms | Pull CRM State button triggers sync (button present) | | `FE-CAMP-020` | SKIP | 0ms | Stage drag-and-drop reorders without crashes (page renders) | | `FE-CROSS-001` | PASS | 4022.4775130000053ms | All staging API calls go to *.test.revhero.io (FE-BUG-002 regression) | | `FE-CROSS-002` | PASS | 1.934622999993735ms | Cloud-document uploads go to staging cloud-documents (smoke) | | `FE-CROSS-003` | PASS | 1569.1035640000046ms | Dev-only routes accessible on staging (proxy.ts hostname check) | | `FE-CROSS-004` | PASS | 0.4153760000044713ms | Same routes redirect to /automation-campaign on prod (skip on staging) | | `FE-CROSS-005` | PASS | 6.9334899999958ms | Free Plan signup completes without payment form (FE-BUG-001 regression) | | `FE-CROSS-006` | PASS | 0.2523010000004433ms | Plan-feature labels render numbers with thousands separators (smoke) | | `FE-CROSS-007` | PASS | 0.25177000000257976ms | Settings right-rail items don't truncate (smoke) | | `FE-CROSS-008` | PASS | 0.22494000000006054ms | Currency values show 2 decimals consistently (smoke) | | `FE-CROSS-009` | PASS | 0.2220039999956498ms | Campaign create header shows 'Untitled campaign' (FE-BUG-08 regression) | | `FE-CROSS-010` | PASS | 0.2748529999953462ms | Phone /sms doesn't get stuck on skeleton (FE-BUG-04 regression) | | `FE-DEAL-001` | PASS | 657.2955159999999ms | Sweep endpoint returns jobs_scheduled count | | `FE-DEAL-002` | PASS | 0.6446740000001228ms | Sweep moves a deal forward (smoke — needs seeded campaign) | | `FE-DEAL-003` | PASS | 0.783773999999994ms | Inactive campaign skips sweep (smoke) | | `FE-DEAL-004` | PASS | 3.2090539999999237ms | Inactive user's stages skipped (smoke) | | `FE-DEAL-005` | PASS | 1.1868970000000445ms | max_deals_to_move quota respected (smoke) | | `FE-DEAL-006` | PASS | 1.4577219999996487ms | Worker pops job within 5s (smoke) | | `FE-DEAL-007` | PASS | 0.29891799999995783ms | Worker triggers email/SMS action (smoke) | | `FE-DEAL-008` | PASS | 0.31439799999998286ms | Action returns 425 → deal rolled back (smoke) | | `FE-DEAL-009` | PASS | 0.38621100000000297ms | Action 5xx → exponential backoff retry (smoke) | | `FE-DEAL-010` | PASS | 0.4823919999998907ms | Successful move appears in BFF /v1/deals/filter (smoke) | | `FE-DEAL-011` | PASS | 0.26725900000019465ms | Successful move does NOT create activity row (smoke) | | `FE-DEAL-012` | PASS | 0.2555170000000544ms | CRM sync goroutine fires after move (smoke) | | `FE-DEAL-013` | PASS | 170.96049800000037ms | /v1/stages/scheduled endpoint reachable | | `FE-DEAL-014` | PASS | 132.3736140000001ms | /v1/stages/moved endpoint reachable | | `FE-DEAL-015` | PASS | 0.279262000000017ms | Redis isolation between staging and prod (smoke) | | `FE-DEAL-016` | PASS | 1.055923000000348ms | Super-admin sweeper button (smoke) | | `FE-DEAL-017` | PASS | 0.17175099999985832ms | next_move_date NULL → deal NOT picked up (smoke) | | `FE-DEAL-SEARCH-001` | PASS | 10756.174897ms | Type email into Search Deals input → table filters by email | | `FE-DEAL-SEARCH-002` | PASS | 9215.323186000001ms | Type partial first name → filter applies | | `FE-DEAL-SEARCH-003` | PASS | 5355.319487000001ms | Press Enter in search submits without page reload | | `FE-DEAL-SEARCH-004` | PASS | 6238.970571999995ms | Clear input → full deal list returns | | `FE-DEAL-SEARCH-005` | PASS | 11.449925000000803ms | Search persists across pagination | | `FE-DEAL-SEARCH-006` | PASS | 5166.979808000004ms | Include lost deals toggle ON/OFF persists | | `FE-EMAIL-001` | FAIL | 60504.006204000005ms | /email-system/email lists messages or empty state | | `FE-EMAIL-002` | PASS | 13273.069275000002ms | 'Mailbox not connected' empty state with Connect Mailbox CTA | | `FE-EMAIL-003` | PASS | 6234.841084999993ms | Connect Mailbox button opens OAuth flow (button presence) | | `FE-EMAIL-004` | PASS | 2175.794074000005ms | Email filters work (filter UI exists) | | `FE-EMAIL-005` | PASS | 5481.7413430000015ms | Search Emails input filters list | | `FE-EMAIL-006` | PASS | 5740.297267000002ms | '+' button opens compose / add modal | | `FE-EMAIL-007` | PASS | 9867.143613000007ms | /email-system/email/add page renders without crashing | | `FE-EMAIL-008` | PASS | 37353.640398999996ms | Compose form requires recipient + subject + body | | `FE-EMAIL-009` | PASS | 3.118043000024045ms | Send email triggers BFF call (network observation) | | `FE-EMAIL-010` | PASS | 4885.122066000011ms | /email-system/email/[id] shows email detail (route accessible) | | `FE-EMAIL-011` | PASS | 5072.022888999985ms | Email categories sidebar navigates | | `FE-EMAIL-012` | PASS | 0.36127500000293367ms | Pagination at top right (X of Y) updates with results | | `FE-EMAIL-IN-001` | PASS | 2.1228349999998954ms | Reply appears in FE thread within ~30s (smoke) | | `FE-EMAIL-IN-002` | PASS | 0.6515870000000632ms | email row has sentiment after scoring (smoke) | | `FE-EMAIL-IN-003` | PASS | 0.3438220000000456ms | 'unsubscribe' triggers NEGATIVE heuristic + deal-loss (smoke) | | `FE-EMAIL-IN-004` | PASS | 0.26641799999993054ms | OOO autoresponder → NEUTRAL + date extraction (smoke) | | `FE-EMAIL-IN-005` | PASS | 0.2971749999999247ms | Self-reply skips sentiment (smoke) | | `FE-EMAIL-IN-006` | PASS | 0.5095220000000609ms | Inbound XSS subject escapes on render (smoke) | | `FE-EMAIL-IN-007` | PASS | 0.43085500000006505ms | Bounce notification flags original send (smoke) | | `FE-EMAIL-IN-008` | PASS | 377.329972ms | POST /v1/emails/sentiment-webhook from public internet — must return 401/403/404 | | `FE-EMAIL-IN-009` | PASS | 0.5116659999998774ms | Mark inbound email Read/Unread/Favourite/Archive (smoke) | | `FE-EMAIL-IN-010` | PASS | 0.3260980000000018ms | Conversation history merges sent + received chronologically (smoke) | | `FE-EMAIL-IN-011` | PASS | 0.2170450000000983ms | Cross-tenant email isolation (smoke) | | `FE-EMAIL-OUT-001` | PASS | 1499.361405ms | Connect Gmail mailbox via OAuth (external-blocked) — assert URL request returns redirec... | | `FE-EMAIL-OUT-002` | PASS | 1578.6714259999999ms | Connect Microsoft mailbox same flow (external-blocked) | | `FE-EMAIL-OUT-003` | PASS | 0.8993499999996857ms | Disconnect mailbox via POST /v1/user-mailboxes/:id/disconnect (smoke) | | `FE-EMAIL-OUT-004` | PASS | 1144.9888039999996ms | Test Email (rate-limited 5/hr) endpoint exists | | `FE-EMAIL-OUT-005` | PASS | 0.4221789999992325ms | Test-Email button disabled when ai_personalization_enabled=false (FE check) | | `FE-EMAIL-OUT-006` | PASS | 0.2719569999999294ms | 6 test emails in 1 hour → 429 | | `FE-EMAIL-OUT-007` | PASS | 8326.520378000001ms | Send manual email with merge tags (composer renders) | | `FE-EMAIL-OUT-008` | PASS | 0.5885490000000573ms | Manual email to deal contact creates sent_email row (smoke) | | `FE-EMAIL-OUT-009` | PASS | 0.2896209999998973ms | Email signature appended to outbound (smoke) | | `FE-EMAIL-OUT-010` | PASS | 38958.709497ms | Empty subject → form validation rejects | | `FE-EMAIL-OUT-011` | PASS | 0.5789910000021337ms | Long body (>50 KB) handled (smoke — no 500) | | `FE-EMAIL-OUT-012` | PASS | 0.19478399999934481ms | XSS in subject + body sanitised (smoke — no script execution) | | `FE-HELP-001` | PASS | 3401.839321999999ms | /help renders FAQ section (dev-only on staging) | | `FE-HELP-002` | PASS | 0.751233000000866ms | Search articles input filters FAQ | | `FE-HELP-003` | PASS | 0.29256600000007893ms | Help category cards render | | `FE-HELP-004` | PASS | 0.2487039999996341ms | Contact Support button opens email/chat | | `FE-HELP-005` | PASS | 4334.918154000001ms | /getting-started checklist progress bar updates | | `FE-HELP-006` | PASS | 0.36422099999981583ms | Watch Video opens modal | | `FE-HELP-007` | PASS | 0.3749699999989389ms | Add Signature redirects to email signature settings | | `FE-HELP-008` | PASS | 0.28301699999974517ms | Start Guided Walkthrough triggers tour | | `FE-LAY-001` | FAIL | 61469.74696700001ms | Sidebar visible on every authenticated dashboard page | | `FE-LAY-002` | PASS | 44148.750461ms | Sidebar shows Dashboard / Campaign / Phone / Email / Settings (smoke) | | `FE-LAY-003` | PASS | 6118.222016ms | Header shows credit balance, notification bell, sign out | | `FE-LAY-004` | PASS | 1.607652999999118ms | Active sidebar item highlighted in primary color (smoke) | | `FE-LAY-005` | PASS | 0.610119000004488ms | Click sidebar item navigates without full page reload (smoke) | | `FE-LAY-006` | PASS | 0.3893169999937527ms | Mobile nav (<768px) collapses sidebar to hamburger (smoke) | | `FE-LAY-007` | PASS | 0.23613099999784026ms | Layout no CLS when notifications appear/dismiss (smoke) | | `FE-LAY-008` | PASS | 0.30721400000038557ms | Layout no CLS when modals open/close (smoke) | | `FE-NOTIF-001` | PASS | 3888.4669269999995ms | /notifications renders list with All / Read / Unread tabs | | `FE-NOTIF-002` | PASS | 1.352705999999671ms | Tabs filter notifications | | `FE-NOTIF-003` | PASS | 0.41942399999970803ms | Sub-tabs Email/SMS/LinkedIn/System filter by type | | `FE-NOTIF-004` | PASS | 0.294980000000578ms | Mark all as read clears unread | | `FE-NOTIF-005` | PASS | 0.2564590000001772ms | Per-row 'Mark as Read' updates row (smoke) | | `FE-NOTIF-006` | PASS | 0.38299499999993714ms | Notifications scoped to current account_id (smoke) | | `FE-NOTIF-007` | PASS | 0.31751299999996263ms | Bell icon shows unread badge (smoke) | | `FE-NOTIF-008` | PASS | 0.23981799999910436ms | Relative timestamps update (smoke) | | `FE-PHONE-001` | PASS | 6568.933844ms | /phone-system redirects to /phone-system/sms | | `FE-PHONE-002` | PASS | 7560.877745000001ms | /phone-system/sms renders empty state (FE-BUG-04 fix — no permanent skeleton) | | `FE-PHONE-003` | PASS | 4843.204596000001ms | Empty state shows 'Go to Phone System Settings' CTA (best-effort) | | `FE-PHONE-004` | PASS | 3446.074365999997ms | /phone-system/voicemails lists voicemails or empty state | | `FE-PHONE-005` | PASS | 0.4756580000030226ms | Brand registration flow accessible from phone system | | `FE-PHONE-006` | PASS | 0.36115500000232714ms | A2P status badge displays correct color/text (smoke) | | `FE-PHONE-007` | PASS | 0.20194700000138255ms | Phone Number purchase flow renders available numbers (smoke) | | `FE-PHONE-008` | PASS | 0.16244400000141468ms | Buy phone number button triggers purchase API call (smoke) | | `FE-PHONE-009` | PASS | 0.6984950000005483ms | Send SMS modal validates recipient + body (smoke) | | `FE-REG-001` | PASS | 2631.7421879999997ms | /signup step 1 renders register form (name, email, password, phone) | | `FE-REG-002` | PASS | 2015.829251ms | Submit empty form → field validation errors | | `FE-REG-003` | PASS | 2875.157332999999ms | Submit with invalid email format → validation error | | `FE-REG-004` | PASS | 2857.482134ms | Submit with weak password → strength meter + rejection | | `FE-REG-005` | PASS | 258.45168100000046ms | Submit with duplicate email → friendly 'email already registered' | | `FE-REG-006` | PASS | 22928.230438000002ms | Submit valid form → advances to step 2 (Select Plan) | | `FE-REG-007` | PASS | 779.963152999997ms | Step 2 shows Pulse Free + Pulse Pro side-by-side | | `FE-REG-008` | PASS | 481.9609039999996ms | Toggle Monthly / Annually switches plan prices | | `FE-REG-009` | PASS | 622.6757490000018ms | Click Free Plan → advances to step 4 (Order Information), skipping step 3 | | `FE-REG-010` | PASS | 330.97033199999714ms | Click Pulse Pro → advances to step 3 (Add-ons) | | `FE-REG-011` | PASS | 485.1150139999954ms | Step 4 (Free Plan) — Total Due $0.00, 'Continue' button (NOT 'Continue to Payment') | | `FE-REG-012` | PASS | 785.9626160000043ms | Step 4 (Free Plan) — promo code field hidden (FE-BUG-001 fix) | | `FE-REG-013` | PASS | 649.2131479999953ms | Step 4 (Free Plan) — clicking Continue skips payment form | | `FE-REG-014` | NOT_EXEC | 0ms | Step 4 (Paid plan) — Payment Information form shows card fields @paid | | `FE-REG-015` | NOT_EXEC | 0ms | Step 4 — apply promo code BETAOFFER → 100% discount → label changes @paid | | `FE-REG-016` | NOT_EXEC | 0ms | Step 4 — invalid promo code → friendly error @paid | | `FE-REG-017` | NOT_EXEC | 0ms | Step 4 — expired promo code → friendly error @paid | | `FE-REG-018` | NOT_EXEC | 0ms | Step 4 — payment form rejects invalid card number @paid | | `FE-REG-019` | NOT_EXEC | 0ms | Step 4 — payment form rejects expired card @paid | | `FE-REG-020` | NOT_EXEC | 0ms | Step 4 — payment form requires all billing address fields @paid | | `FE-REG-021` | PASS | 1517.528873999996ms | Browser back button mid-wizard preserves form state | | `FE-REG-022` | PASS | 2188.241041000001ms | Direct nav to ?step=4 without completing 1-3 → redirects | | `FE-REG-023` | PASS | 59720.458571ms | Already-authenticated user navigating to /signup → redirects to dashboard | | `FE-REG-024` | PASS | 1085.6997209999972ms | Wizard step indicator updates correctly per step | | `FE-SET-G-001` | FAIL | 61603.751827ms | /settings/general renders Billing section by default | | `FE-SET-G-002` | PASS | 43609.576764000005ms | Right sidebar nav items show full text (fe-ui-01 regression) | | `FE-SET-G-003` | PASS | 0.734932999999728ms | Right sidebar nav items list (smoke) | | `FE-SET-G-004` | PASS | 0.6768940000038128ms | Switching nav items updates panel without reload (smoke) | | `FE-SET-G-005` | PASS | 0.40599799998744857ms | Current Plan card shows plan name + price (smoke) | | `FE-SET-G-006` | PASS | 6288.956848000002ms | Plan features show numbers with thousands separators (fe-ui-02 regression) | | `FE-SET-G-007` | PASS | 0.4590079999907175ms | Promo code card shows discount + expiry + COPY (smoke) | | `FE-SET-G-008` | PASS | 0.2354909999994561ms | Manage Add-ons button opens manage-plans page (smoke) | | `FE-SET-G-009` | PASS | 0.21784800000023097ms | CRM API tab shows connected CRM with masked key (smoke) | | `FE-SET-G-010` | PASS | 0.23558000000775792ms | Sub-User Management lists invited users (smoke) | | `FE-SET-G-011` | PASS | 4.960605000000214ms | Sub-User Invite form validates email (smoke) | | `FE-SET-G-012` | PASS | 0.24179099999309983ms | Active Hours tab allows setting weekly schedule (smoke) | | `FE-SET-G-013` | PASS | 0.1912270000029821ms | Email Signatures tab renders editor + preview (smoke) | | `FE-SET-G-014` | PASS | 0.23422699999355245ms | Book Link tab persists URL (smoke) | | `FE-SET-G-015` | PASS | 0.15300500000012107ms | AI Customized Templates tab lists templates (smoke) | | `FE-SET-M-001` | PASS | 4284.093578999993ms | /settings/manage-plans renders manage add-ons section | | `FE-SET-M-002` | PASS | 0.45960899999772664ms | Existing add-ons list (smoke) | | `FE-SET-M-003` | PASS | 0.23292500000388827ms | Empty state friendly message (smoke) | | `FE-SET-M-004` | PASS | 0.2068250000011176ms | Available add-ons list (smoke) | | `FE-SET-M-005` | PASS | 5.760070000003907ms | Add new add-on triggers checkout flow (smoke) | | `FE-SET-M-006` | PASS | 0.2507800000021234ms | Cancel add-on triggers confirmation modal (smoke) | | `FE-SET-S-001` | PASS | 6014.4530330000125ms | /settings/system renders Brand Status + Phone Settings | | `FE-SET-S-002` | PASS | 0.4334800000069663ms | Right sidebar Phone / Email Settings (smoke) | | `FE-SET-S-003` | PASS | 0.6155600000056438ms | Brand Status badge color matches status (smoke) | | `FE-SET-S-004` | PASS | 6.972433000002638ms | Register Brand button opens modal (smoke) | | `FE-SET-S-005` | PASS | 0.25749099999666214ms | Phone Number Settings shows empty state (smoke) | | `FE-SET-S-006` | PASS | 0.2232570000051055ms | Email Settings shows OAuth connection state (smoke) | | `FE-SET-S-007` | PASS | 0.20994299999438226ms | Save Route button persists route preferences (smoke) | | `FE-SETUP-001` | PASS | 1136.1599270000002ms | /setup page renders for newly-signed-up users | | `FE-SETUP-002` | PASS | 2079.361729ms | Setup wizard captures business profile info (form renders) | | `FE-SETUP-003` | PASS | 1863.5586739999999ms | Skip onboarding via 'Skip for now' → dashboard with welcome modal (skip CTA exists) | | `FE-SETUP-004` | PASS | 2285.7225800000006ms | /getting-started shows checklist with at least one step | | `FE-SETUP-005` | PASS | 2833.380191ms | Welcome greeting renders user's first name | | `FE-SETUP-006` | PASS | 896.643086ms | setup_finished flag persists in DB for the test admin | | `FE-SETUP-007` | PASS | 4181.68866ms | /getting-started accessible even when setup_finished is true (onboarding route exception) | | `FE-SMS-TOKY-001` | PASS | 3.1853689999998096ms | BYOC card lists Toky in /settings/system (smoke) | | `FE-SMS-TOKY-002` | PASS | 1.1733219999996436ms | Save bogus Toky API key → red error (smoke) | | `FE-SMS-TOKY-003` | PASS | 0.367486000000099ms | Save real test API key creates carrier_credentials row (smoke) | | `FE-SMS-TOKY-004` | PASS | 0.4011190000001079ms | Save handshake registers webhook on Toky side (smoke) | | `FE-SMS-TOKY-005` | PASS | 0.2199100000002545ms | Re-save credential clears existing webhook auth (smoke) | | `FE-SMS-TOKY-006` | PASS | 0.6505750000001171ms | Add Toky Number lists user inventory (smoke) | | `FE-SMS-TOKY-007` | PASS | 0.2905230000001211ms | Import test number creates phonenumbers row (smoke) | | `FE-SMS-TOKY-008` | PASS | 0.2363709999999628ms | Send SMS via Toky doesn't decrement credits (smoke) | | `FE-SMS-TOKY-009` | PASS | 0.3312180000002627ms | Reply lands inbound within 10s (smoke) | | `FE-SMS-TOKY-010` | PASS | 968.2887729999998ms | Toky inbound webhook validates HTTP Basic auth | | `FE-SMS-TOKY-011` | PASS | 6.428017000000182ms | Toky payload is JSON array (smoke) | | `FE-SMS-TOKY-012` | PASS | 0.616410999999971ms | Toky inbound NEGATIVE sentiment marks deal LOST (smoke) | | `FE-SMS-TOKY-013` | PASS | 0.21619399999963207ms | Replay same payload twice → idempotent (smoke) | | `FE-SMS-TOKY-014` | PASS | 0.451904999999897ms | Disconnect Toky credential revokes webhook (smoke) | | `FE-SMS-TOKY-015` | PASS | 0.17195099999980812ms | Twilio + Toky number coexistence (smoke) | | `FE-SMS-TOKY-016` | PASS | 0.9348360000003595ms | AI personalization charges AI credits but not phone (smoke) | | `FE-SMS-TOKY-017` | PASS | 0.2847520000000259ms | Twilio regression after Toky enabled (smoke) | | `FE-SMS-TOKY-018` | PASS | 0.19273999999995794ms | Legacy provider=NULL treated as 'twilio' (smoke) | | `FE-SMS-TOKY-019` | PASS | 0.20152499999994689ms | Toky API key with zero numbers → empty inventory (smoke) | | `FE-SMS-TOKY-020` | PASS | 3.21253999999999ms | Webhook dedup respects DRF pagination shape (smoke) | | `FE-SMS-TW-001` | PASS | 3.3868760000000293ms | A2P brand registration starts from /settings/system (smoke) | | `FE-SMS-TW-002` | PASS | 0.6882849999999507ms | Phone-number purchase blocked when A2P != brand_approved | | `FE-SMS-TW-003` | PASS | 0.38359700000000885ms | Phone-number purchase succeeds when approved | | `FE-SMS-TW-004` | PASS | 0.25979499999994005ms | Send SMS from /phone-system/sms (smoke) | | `FE-SMS-TW-005` | PASS | 0.37038200000006327ms | Send SMS with merge tag rendered correctly | | `FE-SMS-TW-006` | PASS | 0.6154599999999846ms | Send SMS with no credits → 402 / out-of-credits | | `FE-SMS-TW-007` | PASS | 0.4231600000000526ms | Twilio API failure releases reserved credits | | `FE-SMS-TW-008` | PASS | 0.4304340000001048ms | Send SMS exceeds rate limit → 429 | | `FE-SMS-TW-009` | PASS | 0.3110309999999572ms | Inbound SMS appears in FE thread (smoke) | | `FE-SMS-TW-010` | PASS | 0.3308670000001257ms | Inbound negative sentiment marks deal LOST (smoke) | | `FE-SMS-TW-011` | PASS | 93.16416600000002ms | Twilio webhook with wrong bears_key → 401 | | `FE-SMS-TW-012` | PASS | 0.5316330000000562ms | Twilio status callback updates messages.status (smoke) | | `FE-USER-001` | PASS | 7460.729892999996ms | /user renders profile fields | | `FE-USER-002` | PASS | 7884.125643000007ms | Created date renders correctly (NOT 'Invalid Date') | | `FE-USER-003` | PASS | 0.4121799999848008ms | Change Password button opens modal (smoke) | | `FE-USER-004` | PASS | 0.2599259999988135ms | Password modal validates fields (smoke) | | `FE-USER-005` | PASS | 10.47241099999519ms | Wrong current password → friendly error (smoke) | | `FE-USER-006` | PASS | 0.5667479999829084ms | Password change success closes modal + toast (smoke) | | `UNKNOWN-7fx8gs` | PASS | 83.93166200000007ms | WEBHOOK-AUTH-002 — sms-service sentiment-webhook rejects without auth | | `UNKNOWN-nboa3h` | PASS | 270.10471299999995ms | WEBHOOK-AUTH-001 — email-ingress sentiment-webhook rejects without auth | | `UNKNOWN-nixsmx` | PASS | 139.0308329999998ms | WEBHOOK-AUTH-003 — deal-mover sweeper rejects without auth | ## Failures ### FE-AUTH-002 — Login with valid credentials → redirect to /automation-campaign ``` BFF /v1/auth/login returned 429: {"data":{"error":"too many login attempts; try again in 34s","retry_after_seconds":34,"scope":"email"},"message":"Too many login attempts. Please wait and try again."} ``` ### FE-AUTH-009 — Submit forgot password with non-existent email → generic success (anti-enumeration) ``` expected 500 to be 404 // Object.is equality ``` ### FE-AUTH-012 — Sign Out button → clears cookies → redirects to /login ``` locator.click: Timeout 30000ms exceeded. Call log: - waiting for getByRole('button', { name: /sign out|log out|logout/i }).first() - locator resolved to - attempting click action 2 × waiting for element to be visible, enabled and stable - element is visible, enabled and stable - scrolling into view if needed - done scrolling -