eletrotupi / tcc/ frontend/scripts/e2e.sh468cada260c6f4e13d66b237b935fb36b05ff0f1
3.5 KB | 122 lines Raw
1
#!/usr/bin/env bash
2
#
3
# E2E harness for the nexo frontend: Maestro flows on a physical Android
4
# device over adb (no emulator)
5
#
6
# The app talks to whatever API `EXPO_PUBLIC_API_BASE_URL` points at, so there is
7
# no second API service to boot here: bring the normal stack up and point Metro
8
# at it:
9
#
10
#   docker compose up -d db valkey api
11
#   cd api && npm run seed                  # known e2e user (idempotent)
12
#   cd frontend && npx expo start           # with .env.local set (see print-env)
13
#
14
# Usage: e2e.sh [test|print-env]
15
#   test       prep the device (adb) and run the tagged Maestro flows
16
#   print-env  print the EXPO_PUBLIC_* vars to set before `expo start`
17
#
18
# Optional env: HOST_IP (LAN IP of this machine) is auto-detected when unset
19
set -euo pipefail
20

21
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
22
FRONTEND="$ROOT/frontend"
23

24
# The app under test: the dev build (`eas build --profile development`)
25
APP_ID="${APP_ID:-com.eletrotupi.orbit}"
26
EXPO_PORT="${EXPO_PORT:-8081}"
27
E2E_EMAIL="${E2E_EMAIL:-e2e@example.com}"
28
E2E_PASSWORD="${E2E_PASSWORD:-e2e-password}"
29

30
die() { echo "e2e: $*" >&2; exit 1; }
31

32
detect_host_ip() {
33
  if [[ -n "${HOST_IP:-}" ]]; then
34
    echo "$HOST_IP"
35
    return
36
  fi
37

38
  local ip=""
39
  ip="$(ip route get 1 2>/dev/null | awk '/src/{for (i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}')"
40

41
  [[ -z "$ip" ]] && ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
42
  [[ -z "$ip" ]] && die "could not detect LAN IP; export HOST_IP=<lan-ip>"
43

44
  echo "$ip"
45
}
46

47
adb_prepare() {
48
  command -v adb >/dev/null || die "adb not found; install android-tools"
49
  echo "e2e: waiting for an Android device (up to 15s)..."
50

51
  local i state=""
52

53
  for i in $(seq 1 15); do
54
    state="$(adb get-state 2>/dev/null)"
55
    [[ "$state" == "device" ]] && break
56
    sleep 1
57
  done
58

59
  if [[ "$state" != "device" ]]; then
60
    adb devices >&2 || true
61
    die "no Android device attached. Connect one over USB/wireless debugging (or set ANDROID_SERIAL when several are connected) and re-run"
62
  fi
63

64
  echo "e2e: adb devices:"
65

66
  adb devices
67

68
  # No `pm clear` here: each flow starts with Maestro `clearState`, which needs no
69
  # host-side help, and clearing here only re-triggered the expo-dev-client
70
  # first-run overlays. Granting the runtime permission is still worth it:
71
  # clearState resets it and the app asks for notifications right after login
72
  adb shell pm grant "$APP_ID" android.permission.POST_NOTIFICATIONS >/dev/null 2>&1 || true
73
  # Disable animations for speed and stability
74

75
  adb shell settings put global window_animation_scale 0 >/dev/null
76
  adb shell settings put global transition_animation_scale 0 >/dev/null
77
  adb shell settings put global animator_duration_scale 0 >/dev/null
78
}
79

80
run_maestro() {
81
  command -v maestro >/dev/null || die "maestro not found; install via https://get.maestro.mobile.dev"
82
  local host_ip
83
  host_ip="$(detect_host_ip)"
84

85
  (
86
    cd "$FRONTEND"
87
    maestro test e2e \
88
      --include-tags=smoke \
89
      --env HOST_IP="$host_ip" \
90
      --env PORT="$EXPO_PORT" \
91
      --env E2E_EMAIL="$E2E_EMAIL" \
92
      --env E2E_PASSWORD="$E2E_PASSWORD"
93
  )
94
}
95

96
print_env() {
97
  local host_ip
98
  host_ip="$(detect_host_ip)"
99

100
  cat <<EOF
101
Put this in frontend/.env.local (gitignored) before starting Metro:
102

103
  EXPO_PUBLIC_API_BASE_URL=http://$host_ip:3000
104
  EXPO_PUBLIC_TOKEN_KEY=orbit-jwt
105

106
  npx expo start --port $EXPO_PORT
107
EOF
108
}
109

110
case "${1:-}" in
111
  test)
112
    adb_prepare
113
    run_maestro
114
    ;;
115
  print-env)
116
    print_env
117
    ;;
118
  *)
119
    echo "usage: $0 [test|print-env]" >&2
120
    exit 1
121
    ;;
122
esac