|
| 1 | +#!/usr/bin/env bash |
| 2 | +# One-time local setup for the Appium E2E runner. Idempotent — safe to re-run. |
| 3 | +# Installs everything run-local.sh's preflight checks for: |
| 4 | +# 1. .env (copied from .env.example if missing) |
| 5 | +# 2. appium (global npm install) |
| 6 | +# 3. appium drivers (xcuitest for iOS, uiautomator2 for Android) |
| 7 | +# 4. Vite+ (provides the vpx command; installs if vp/vpx absent) |
| 8 | +# 5. node_modules (bun install / vp install in the appium dir) |
| 9 | +set -uo pipefail |
| 10 | + |
| 11 | +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" |
| 12 | +APPIUM_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" |
| 13 | + |
| 14 | +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BOLD='\033[1m'; NC='\033[0m' |
| 15 | +info() { echo -e "${GREEN}[INFO]${NC} $*"; } |
| 16 | +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } |
| 17 | +err() { echo -e "${RED}[ERROR]${NC} $*"; } |
| 18 | +ok() { echo -e "${GREEN}[OK]${NC} $*"; } |
| 19 | + |
| 20 | +FAILED=0 |
| 21 | +NEEDS_ENV=0 |
| 22 | + |
| 23 | +echo -e "${BOLD}━━━ Appium E2E bootstrap ━━━${NC}" |
| 24 | + |
| 25 | +# ── 0. Prerequisites ────────────────────────────────────────────────────────── |
| 26 | +if ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then |
| 27 | + err "node/npm not found. Install Node.js first (https://nodejs.org), then re-run." |
| 28 | + exit 1 |
| 29 | +fi |
| 30 | +ok "node $(node -v) / npm $(npm -v)" |
| 31 | + |
| 32 | +# ── 1. .env ─────────────────────────────────────────────────────────────────── |
| 33 | +if [[ -f "$SCRIPT_DIR/.env" ]]; then |
| 34 | + ok ".env present" |
| 35 | +elif [[ -f "$SCRIPT_DIR/.env.example" ]]; then |
| 36 | + cp "$SCRIPT_DIR/.env.example" "$SCRIPT_DIR/.env" |
| 37 | + warn "Created .env from .env.example — set ONESIGNAL_APP_ID / ONESIGNAL_API_KEY before running tests." |
| 38 | + NEEDS_ENV=1 |
| 39 | +else |
| 40 | + warn ".env and .env.example both missing — create $SCRIPT_DIR/.env manually." |
| 41 | +fi |
| 42 | + |
| 43 | +# ── 2. appium ───────────────────────────────────────────────────────────────── |
| 44 | +if command -v appium >/dev/null 2>&1; then |
| 45 | + ok "appium $(appium -v 2>/dev/null) already installed" |
| 46 | +else |
| 47 | + info "Installing appium globally (npm i -g appium)..." |
| 48 | + if npm i -g appium; then ok "appium installed"; else err "appium install failed"; FAILED=1; fi |
| 49 | +fi |
| 50 | + |
| 51 | +# ── 3. appium drivers ───────────────────────────────────────────────────────── |
| 52 | +if command -v appium >/dev/null 2>&1; then |
| 53 | + installed="$(appium driver list --installed 2>&1)" |
| 54 | + for driver in xcuitest uiautomator2; do |
| 55 | + if grep -q "$driver" <<< "$installed"; then |
| 56 | + ok "driver '$driver' already installed" |
| 57 | + else |
| 58 | + info "Installing appium driver '$driver'..." |
| 59 | + if appium driver install "$driver"; then ok "driver '$driver' installed"; else err "driver '$driver' install failed"; FAILED=1; fi |
| 60 | + fi |
| 61 | + done |
| 62 | +else |
| 63 | + err "Skipping drivers — appium is not available."; FAILED=1 |
| 64 | +fi |
| 65 | + |
| 66 | +# ── 4. Vite+ (vpx) ──────────────────────────────────────────────────────────── |
| 67 | +# run-local.sh runs WebdriverIO via `vpx` (Vite+'s package-binary runner, akin |
| 68 | +# to npx). `vpx` is the `vp` binary invoked under an argv[0] alias, so it needs a |
| 69 | +# vpx symlink next to vp. The installer doesn't always create it (observed on |
| 70 | +# 0.2.5), so ensure it explicitly. Note: the npm package `vite-plus` ships only |
| 71 | +# vp/oxfmt/oxlint (no vpx) — the official installer is what we want. |
| 72 | +VP_HOME="$HOME/.vite-plus" |
| 73 | +if command -v vpx >/dev/null 2>&1; then |
| 74 | + ok "vpx already available ($(command -v vpx))" |
| 75 | +else |
| 76 | + if [[ ! -x "$VP_HOME/current/bin/vp" ]]; then |
| 77 | + info "Installing Vite+ (provides vp/vpx) — curl -fsSL https://vite.plus | bash ..." |
| 78 | + curl -fsSL https://vite.plus | bash || { err "Vite+ install failed — install manually: curl -fsSL https://vite.plus | bash"; FAILED=1; } |
| 79 | + fi |
| 80 | + if [[ -x "$VP_HOME/current/bin/vp" ]]; then |
| 81 | + if [[ ! -e "$VP_HOME/bin/vpx" ]]; then |
| 82 | + ln -sf ../current/bin/vp "$VP_HOME/bin/vpx" |
| 83 | + ok "created vpx symlink ($VP_HOME/bin/vpx -> ../current/bin/vp)" |
| 84 | + else |
| 85 | + ok "vpx symlink present ($VP_HOME/bin/vpx)" |
| 86 | + fi |
| 87 | + warn "Open a new shell (or run: source \"$VP_HOME/env\") so 'vpx' is on PATH." |
| 88 | + fi |
| 89 | +fi |
| 90 | + |
| 91 | +# ── 5. node_modules ─────────────────────────────────────────────────────────── |
| 92 | +if [[ -d "$APPIUM_DIR/node_modules" ]]; then |
| 93 | + ok "node_modules present in appium/" |
| 94 | +elif command -v bun >/dev/null 2>&1; then |
| 95 | + info "Installing test deps with bun..." |
| 96 | + (cd "$APPIUM_DIR" && bun install) && ok "deps installed (bun)" || { err "bun install failed"; FAILED=1; } |
| 97 | +elif command -v vp >/dev/null 2>&1; then |
| 98 | + info "Installing test deps with vp..." |
| 99 | + (cd "$APPIUM_DIR" && vp install) && ok "deps installed (vp)" || { err "vp install failed"; FAILED=1; } |
| 100 | +else |
| 101 | + warn "Skipping deps — neither bun nor vp available yet. run-local.sh installs node_modules on first run." |
| 102 | +fi |
| 103 | + |
| 104 | +# ── Summary ─────────────────────────────────────────────────────────────────── |
| 105 | +echo "" |
| 106 | +echo -e "${BOLD}━━━ Summary ━━━${NC}" |
| 107 | +if (( FAILED )); then |
| 108 | + err "Bootstrap finished with errors — resolve the items above and re-run." |
| 109 | + exit 1 |
| 110 | +fi |
| 111 | +ok "Bootstrap complete." |
| 112 | +(( NEEDS_ENV )) && warn "Remember to fill in your OneSignal credentials in $SCRIPT_DIR/.env" |
| 113 | +exit 0 |
0 commit comments