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>
118 lines
4.5 KiB
YAML
118 lines
4.5 KiB
YAML
# calls/incoming-call-screen.yaml
|
|
#
|
|
# Tests: CallScreen renders correctly for an INCOMING call state.
|
|
#
|
|
# Context: A series of bugs were fixed around the call screen disappearing
|
|
# immediately after appearing (Phantom-Call-Bug, stale PKPushRegistry, race
|
|
# conditions). This flow verifies the call UI stays visible and the
|
|
# accept/decline buttons are present.
|
|
#
|
|
# LIMITATION — This is a UI state verification, not a live call test.
|
|
# Triggering a real VoIP push requires a second device + server-side signaling.
|
|
# That E2E scenario (two-device call) needs the Maestro multi-device capability
|
|
# and is NOT covered here (Phase B / Cloud).
|
|
#
|
|
# APPROACH for single-device verification:
|
|
# The CallScreen renders based on useCallStore state. To reach it in a test:
|
|
# 1. Navigate to a DM with the test peer.
|
|
# 2. Tap the call button in the DM header.
|
|
# This triggers an OUTGOING call state → router.push('/call') → CallScreen.
|
|
#
|
|
# We verify:
|
|
# - The /call screen navigates to and stays visible (>250ms grace period passes).
|
|
# - The peer name area and call status subtitle render.
|
|
# - The hang-up button is present (for outgoing/connecting state).
|
|
#
|
|
# For incoming call UI verification (accept/decline buttons), this currently
|
|
# requires a real second device triggering the VoIP push or a debug-trigger
|
|
# mechanism. BLOCKED: needs test infrastructure decision from Orchestrator.
|
|
# See notes at bottom.
|
|
#
|
|
# Pre-requisite:
|
|
# - App installed. Test-user exists. A second user (the "test peer") must
|
|
# exist in the staging DB and be a DM contact of the test user.
|
|
# - E2E_TEST_PEER_USER env var = nickname or user lookup string for the peer.
|
|
# Env-Vars: E2E_TEST_USER, E2E_TEST_PASSWORD, E2E_TEST_PEER_USER (optional)
|
|
|
|
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"
|
|
|
|
# --- Navigate to Chat tab ---
|
|
# tabs.chat = "Chat" (de.json line 135)
|
|
- tapOn:
|
|
text: "Chat"
|
|
- waitForAnimationToEnd:
|
|
timeout: 3000
|
|
|
|
# chat.title = "Chat" — screen is loaded
|
|
- assertVisible:
|
|
text: "Chat"
|
|
|
|
# chat.dms = "Direktnachrichten" (de.json line 1065) — section header in chat list
|
|
- assertVisible:
|
|
text: "Direktnachrichten"
|
|
|
|
# --- Open a DM conversation ---
|
|
# We need to tap into an existing DM conversation. The test user should have
|
|
# at least one prior DM with a peer from staging setup.
|
|
# The peer's nickname is unknown at flow-write time — we scroll to find any
|
|
# DM entry and tap it. If no DMs exist, the flow will fail at assertVisible
|
|
# on the DM screen elements, clearly indicating the setup gap.
|
|
#
|
|
# If E2E_TEST_PEER_USER is set, tap on that user's name directly.
|
|
# Otherwise: tap first visible DM entry below the "Direktnachrichten" header.
|
|
# FRAGILE: no testID on DM list items. The DM list shows peer nicknames as
|
|
# the primary text in each row — we use text match on the first visible name.
|
|
# For now we skip to the PARTIAL SMOKE TEST below.
|
|
|
|
# PARTIAL SMOKE (does not require an existing DM):
|
|
# Navigate to the Chat tab and verify the call infrastructure is present
|
|
# by checking that the Chat screen renders without crash. Full call E2E needs
|
|
# a pre-seeded DM contact. This is noted as a BLOCKER below.
|
|
|
|
# --- BLOCKER NOTE ---
|
|
# Full incoming call test requires one of:
|
|
# A) Two-device Maestro run (Maestro Cloud multi-device matrix) — Phase B.
|
|
# B) A debug endpoint `POST /api/debug/trigger-incoming-call` that sets
|
|
# callStore state directly (requires dev-build + debug flag). Not yet built.
|
|
# C) The DM screen has a "call" button in the header → tap → outgoing call state
|
|
# → CallScreen navigates in → verify screen stays open ≥ 2s (race guard).
|
|
# This requires a known peer userId in the DM URL param.
|
|
#
|
|
# Escalate to Orchestrator: Which approach for call E2E? Proceed with option C?
|
|
# That requires E2E_TEST_PEER_USER_ID env var + the peer having a DM row
|
|
# already loaded in the Chat list.
|
|
|
|
# Verify chat tab renders cleanly (no crash = passing for now):
|
|
- assertVisible:
|
|
text: "Direktnachrichten"
|
|
|
|
# Also verify the call-related strings are not showing error states.
|
|
# chat.call_missed = "Verpasster Anruf" should NOT appear without a real missed call.
|
|
# (This is a sanity check — it fires only if the chat list pre-populates
|
|
# a missed call notification for the test user incorrectly.)
|
|
- assertNotVisible:
|
|
text: "Verpasster Anruf"
|