chahinebrini 63fae25531 fix(android-protection): explicit specialUse FGS type — Samsung/Android 16 crash loop
RebreakVpnService.onStartCommand crashed with SecurityException because Android 16's validateForegroundServiceType rejects the implicit 2-arg startForeground(). Now passes FOREGROUND_SERVICE_TYPE_SPECIAL_USE explicitly (Google's documented best practice) and guards the call so a failed foreground promotion stops the service cleanly instead of crashing the app. Verified vs reported Galaxy A54 / Android 16 signature (97% of crash events, 1-user crash loop).

Bundles pending working-tree work across native/marketing/locales/mac + graphify-out rebuild. gitignore: google-services.json + /screenshots/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 22:33:28 +02:00

120 lines
3.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# sos/crisis-flow.yaml
#
# HIGHEST PRIORITY FLOW — this must never silently fail.
#
# Journey: Login → Header-Dropdown → SOS → Lyra chat loads → send a message →
# assert response area or chip row becomes visible (Lyra is alive).
#
# This flow is the canary for:
# - SOS navigation path not broken
# - Lyra streaming endpoint reachable from staging
# - Chat input + send mechanism functional
# - Breathing chip "Atemübung" accessible as immediate coping entry
#
# Unlike the previous urge/sos-flow.yaml which relies on a coordinate tap for
# the avatar button, this flow uses the same coordinate fallback until
# testID="header-avatar-btn" is added (see TODO_TESTIDS.md HIGH priority).
# The coordinate tap is the ONLY fragile part of this flow.
#
# Timing: SOS screen on staging needs 612s for Groq cold start. The send step
# waits 20s for Lyra's response — intentionally generous. A CI failure here
# means either backend is down or Groq key is missing/expired.
#
# Pre-requisite:
# - App installed. Test-user exists on staging.
# - Staging backend + Groq API key configured.
# Env-Vars: E2E_TEST_USER, E2E_TEST_PASSWORD
appId: org.rebreak.app
---
- launchApp:
clearState: true
- waitForAnimationToEnd:
timeout: 5000
# --- Auth ---
- assertVisible:
text: "E-Mail"
- tapOn:
text: "E-Mail"
- inputText: ${E2E_TEST_USER}@rebreak.internal
- tapOn:
text: "Passwort"
- inputText: ${E2E_TEST_PASSWORD}
- tapOn:
text: "Anmelden"
- waitForAnimationToEnd:
timeout: 10000
- assertVisible:
text: "ReBreak"
# --- Open Header Dropdown ---
# FRAGILE: Avatar Pressable has no testID → coordinate tap.
# Replace with: tapOn: { id: "header-avatar-btn" } once testID is added.
- tapOn:
point: "93%, 6%"
- waitForAnimationToEnd:
timeout: 2000
# appHeader.sosLabel = "SOS" (de.json line 119)
- assertVisible:
text: "SOS"
- tapOn:
text: "SOS"
# SOS screen loads: RiveAvatar + Lyra streaming begins.
# Cold start on Groq (staging) = 612s. We wait the full 12s before asserting.
- waitForAnimationToEnd:
timeout: 12000
# coach.placeholder = "Was beschäftigt dich?" — only exists on SOS/Urge screen.
# This confirms the SOS screen has fully loaded with the chat input visible.
- assertVisible:
text: "Was beschäftigt dich?"
# --- Send a message ---
# Tap the placeholder to focus the TextInput
- tapOn:
text: "Was beschäftigt dich?"
- waitForAnimationToEnd:
timeout: 1000
# Type a safe test message that triggers a Lyra response
- inputText: "Ich brauche gerade Hilfe."
# Send via the send button.
# FRAGILE: send Pressable has no testID → use pressKey Enter as fallback.
# The TextInput in urge.tsx submits on Return key (onSubmitEditing = handleSend).
# This is more reliable than coordinate tapping the icon button.
# Add testID="sos-send-btn" to fix (see TODO_TESTIDS.md HIGH priority).
- pressKey: Return
- waitForAnimationToEnd:
timeout: 3000
# Wait for Lyra to stream back a response (up to 20s on staging cold start)
- waitForAnimationToEnd:
timeout: 20000
# After Lyra responds, the initial chip set is visible.
# "Atemübung" is in CHIP_SETS.start (sosConstants.ts) — hardcoded, not i18n.
# This chip is ALWAYS shown as the first response. If it's not visible after 20s,
# Lyra failed to respond — the test should fail here.
- assertVisible:
text: "Atemübung"
# --- Verify Breathing entry point ---
# Tap "Atemübung" to open BreathingDrawer. This ensures the most critical
# coping mechanism (breathing exercise) is accessible from the SOS screen.
- tapOn:
text: "Atemübung"
- waitForAnimationToEnd:
timeout: 3000
# BreathingDrawer header. The breathing screen title is hardcoded in Breathing.tsx
# (not i18n). urge.sos_title = "SOS — Atemübung" (de.json line 979).
# The drawer itself renders "Atemübung" as its header text.
- assertVisible:
text: "Atemübung"