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>
93 lines
3.8 KiB
YAML
93 lines
3.8 KiB
YAML
# onboarding/new-user-streak-guard.yaml
|
|
#
|
|
# REGRESSION GUARD for the current bug:
|
|
# current_days=0 for all users because the streak calculation never runs.
|
|
#
|
|
# Journey: Launch → Welcome → Privacy → Nickname (skip via DiGA-No path) →
|
|
# Plan (Pro, Dev-Trial-CTA) → Payment (Dev-Skip) → Protection (skip
|
|
# via CTABar if dialog appears) → Done → App Home → Home screen
|
|
# must show streak day > 0 (NOT "0 Tage clean" or "Starte deinen ersten Tag"
|
|
# when the test user already has a streak).
|
|
#
|
|
# Strategy: The test user (claude-android-test) has an existing account with
|
|
# onboardingStep='done' so onboarding will NOT replay — _layout.tsx
|
|
# routes directly to /(app). We assert the streak widget shows a
|
|
# positive day count as the regression guard.
|
|
# For a brand new user test, a separate dedicated account is needed
|
|
# (see BLOCKER in notes at bottom). This flow covers the post-onboarding
|
|
# regression scenario.
|
|
#
|
|
# Pre-requisite:
|
|
# - App installed (Dev-Build OR TestFlight).
|
|
# - E2E_TEST_USER account on staging with onboardingStep='done' and streak_start set.
|
|
# - Staging backend running.
|
|
# Env-Vars: E2E_TEST_USER, E2E_TEST_PASSWORD
|
|
#
|
|
# Expected outcome: After login, the home screen streak widget shows a day count
|
|
# that is NOT "0 Tage" (i.e. current_days is being calculated).
|
|
# If it shows "0 Tage clean" or "Starte deinen ersten Tag" when
|
|
# the account has a real streak — the regression is present.
|
|
#
|
|
# IMPORTANT: Text selectors use hardcoded de.json values. If device locale ≠ 'de',
|
|
# run with a German locale device or force-set language to 'de' before test.
|
|
|
|
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
|
|
|
|
# --- Home screen reached ---
|
|
- assertVisible:
|
|
text: "ReBreak"
|
|
|
|
# The streak widget is in the Home screen (app/index.tsx or a HomeStreakCard).
|
|
# home.streak_days_one = "Tag clean"
|
|
# home.streak_days_other = "Tage clean"
|
|
# home.streak_start = "Starte deinen ersten Tag"
|
|
#
|
|
# REGRESSION CHECK: if current_days is never calculated, the widget always shows
|
|
# "0 Tage clean". We assert "Tage clean" is visible (which is true for any count
|
|
# including 0) and additionally assert "Starte deinen ersten Tag" is NOT visible
|
|
# (which would only appear for day=0 / null streak start).
|
|
#
|
|
# This catches the "always 0" bug: when current_days=0 the UI renders
|
|
# "0 Tage clean" or "Starte deinen ersten Tag" even for users with real streaks.
|
|
- assertVisible:
|
|
text: "clean"
|
|
|
|
# The key assertion: "Starte deinen ersten Tag" must NOT be visible for an
|
|
# established test-user. If this fires — the streak calculation bug is present.
|
|
- assertNotVisible:
|
|
text: "Starte deinen ersten Tag"
|
|
|
|
# Secondary guard: assert that "0 Tage" is not the streak count.
|
|
# "0 Tage clean" is the de.json rendering for 0 days via streak_days_other.
|
|
# NOTE: Maestro assertNotVisible matches substring — "0 Tage" catches both
|
|
# "0 Tage clean" (streak_days_other) and any "0 Tag clean" variant.
|
|
- assertNotVisible:
|
|
text: "0 Tage"
|
|
|
|
# NOTE FOR FULL ONBOARDING TEST (new account flow):
|
|
# A completely fresh account (onboardingStep='welcome') is needed to exercise
|
|
# the Welcome → Privacy → Nickname → Plan → Payment → Protection → Done flow.
|
|
# That requires a separate test account that is reset to onboardingStep='welcome'
|
|
# before each run (via Service-Role PATCH). This is not automated here yet.
|
|
# See TODO in SETUP.md Phase B.
|