diff --git a/.github/workflows/e2e-reusable.yml b/.github/workflows/e2e-reusable.yml index 7b50dfc8c9..85e5fb1698 100644 --- a/.github/workflows/e2e-reusable.yml +++ b/.github/workflows/e2e-reusable.yml @@ -150,16 +150,37 @@ jobs: - name: Run E2E (full suite) if: ${{ inputs.full }} + env: + E2E_BAIL_ON_FAILURE: ${{ vars.E2E_BAIL_ON_FAILURE || '' }} run: | + BAIL_FLAG="" + if [[ "${E2E_BAIL_ON_FAILURE:-}" == "1" ]]; then + BAIL_FLAG="--bail" + fi xvfb-run -a --server-args="-screen 0 1280x960x24" \ - bash app/scripts/e2e-run-session.sh - - # Artifact uploads intentionally omitted — this reusable workflow - # is invoked from release-staging.yml and release-production.yml, - # and uploaded logs can carry mock-backend payloads, env-var - # echoes, and CDP transcripts that we don't want pinned to a - # release artifact. Local repro: rerun the spec via Docker and - # the same logs land in /tmp. + bash app/scripts/e2e-run-all-flows.sh --skip-preflight $BAIL_FLAG + + - name: Upload E2E failure artifacts + if: failure() + uses: actions/upload-artifact@v5 + with: + name: e2e-failure-logs-${{ runner.os }}-${{ github.run_id }} + path: | + /tmp/openhuman-e2e-app-*.log + app/test/e2e/artifacts/ + retention-days: 7 + if-no-files-found: ignore + + - name: Write job summary + if: always() + run: | + echo "## E2E Results (${{ runner.os }})" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ -f /tmp/e2e-summary.txt ]; then + cat /tmp/e2e-summary.txt >> $GITHUB_STEP_SUMMARY + else + echo "No summary file found." >> $GITHUB_STEP_SUMMARY + fi # Rust-side E2E counterpart to the Tauri runs above. Same Linux-only # scope (CI does not run this on macOS or Windows — the Rust core is diff --git a/app/scripts/e2e-preflight.sh b/app/scripts/e2e-preflight.sh new file mode 100755 index 0000000000..d50897e980 --- /dev/null +++ b/app/scripts/e2e-preflight.sh @@ -0,0 +1,195 @@ +#!/usr/bin/env bash +# +# e2e-preflight.sh — Pre-flight environment validation for the E2E test suite. +# +# Checks: +# 1. The E2E app binary/bundle exists for the current platform. +# 2. Node.js and pnpm are available. +# 3. Appium is installed (and the chromium driver is registered). +# 4. Ports 19222, 4723, and 18473 are not blocked by stale processes. +# +# Exits 0 if all hard requirements are met. +# Exits 1 if any hard requirement is missing. +# Warnings are printed for soft issues (occupied ports, missing chromium driver) +# but do not fail the script. +# +set -uo pipefail + +# --------------------------------------------------------------------------- +# Color helpers — only when stdout is a terminal. +# --------------------------------------------------------------------------- +if [ -t 1 ]; then + RED='\033[0;31m' + YELLOW='\033[1;33m' + GREEN='\033[0;32m' + BOLD='\033[1m' + RESET='\033[0m' +else + RED='' YELLOW='' GREEN='' BOLD='' RESET='' +fi + +info() { printf "%b[preflight]%b %s\n" "$BOLD" "$RESET" "$*"; } +ok() { printf "%b[preflight] ✓%b %s\n" "$GREEN" "$RESET" "$*"; } +warn() { printf "%b[preflight] ⚠%b %s\n" "$YELLOW" "$RESET" "$*" >&2; } +fail() { printf "%b[preflight] ✗%b %s\n" "$RED" "$RESET" "$*" >&2; } + +ERRORS=0 +_fail() { fail "$*"; (( ERRORS++ )) || true; } + +APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +info "Starting E2E pre-flight checks..." +echo "" + +# --------------------------------------------------------------------------- +# 1. App binary / bundle +# --------------------------------------------------------------------------- +info "Checking E2E app bundle..." + +PLATFORM="$(uname -s)" +BINARY_FOUND=0 +BINARY_PATH="" + +case "$PLATFORM" in + Darwin) + MACOS_BUNDLE="$APP_DIR/src-tauri/target/debug/bundle/macos/OpenHuman.app" + if [[ -d "$MACOS_BUNDLE" ]]; then + BINARY_FOUND=1 + BINARY_PATH="$MACOS_BUNDLE" + fi + ;; + Linux) + LINUX_BIN="$APP_DIR/src-tauri/target/debug/openhuman" + LINUX_DEB="$APP_DIR/src-tauri/target/debug/bundle/deb" + if [[ -f "$LINUX_BIN" ]]; then + BINARY_FOUND=1 + BINARY_PATH="$LINUX_BIN" + elif [[ -d "$LINUX_DEB" ]]; then + BINARY_FOUND=1 + BINARY_PATH="$LINUX_DEB" + fi + ;; + MINGW*|MSYS*|CYGWIN*|Windows*) + WIN_BIN="$APP_DIR/src-tauri/target/debug/openhuman.exe" + if [[ -f "$WIN_BIN" ]]; then + BINARY_FOUND=1 + BINARY_PATH="$WIN_BIN" + fi + ;; + *) + warn "Unknown platform '$PLATFORM' — cannot verify app bundle path." + BINARY_FOUND=1 # don't block on unknown platforms + ;; +esac + +if [[ $BINARY_FOUND -eq 1 ]]; then + ok "App bundle found: $BINARY_PATH" +else + _fail "E2E build not found for $PLATFORM." + case "$PLATFORM" in + Darwin) + fail " Expected: $MACOS_BUNDLE" + ;; + Linux) + fail " Expected: $LINUX_BIN" + ;; + MINGW*|MSYS*|CYGWIN*) + fail " Expected: $WIN_BIN" + ;; + esac + fail " Run: pnpm --filter openhuman-app test:e2e:build" +fi + +echo "" + +# --------------------------------------------------------------------------- +# 2. Node.js + pnpm +# --------------------------------------------------------------------------- +info "Checking Node.js and pnpm..." + +if command -v node >/dev/null 2>&1; then + NODE_VERSION="$(node --version 2>/dev/null || echo 'unknown')" + ok "node found: $NODE_VERSION" +else + _fail "node not found. Node.js is required to run WDIO." +fi + +if command -v pnpm >/dev/null 2>&1; then + PNPM_VERSION="$(pnpm --version 2>/dev/null || echo 'unknown')" + ok "pnpm found: $PNPM_VERSION" +else + _fail "pnpm not found. Install via: npm install -g pnpm" +fi + +echo "" + +# --------------------------------------------------------------------------- +# 3. Appium + chromium driver +# --------------------------------------------------------------------------- +info "Checking Appium..." + +if command -v appium >/dev/null 2>&1; then + APPIUM_VERSION="$(appium --version 2>/dev/null || echo 'unknown')" + ok "appium found: $APPIUM_VERSION" + + # Check for the chromium driver — warn only (e2e-run-session.sh handles this) + CHROMIUM_INSTALLED=0 + if appium driver list --installed 2>&1 | grep -qi "chromium"; then + CHROMIUM_INSTALLED=1 + ok "Appium chromium driver is installed" + fi + if [[ $CHROMIUM_INSTALLED -eq 0 ]]; then + warn "Appium chromium driver not found in 'appium driver list --installed'." + warn " To install: appium driver install --source=npm appium-chromium-driver" + warn " (e2e-run-session.sh will attempt idempotent install at runtime.)" + fi +else + _fail "Appium not found." + fail " Install: npm install -g appium@3" + fail " Then: appium driver install --source=npm appium-chromium-driver" +fi + +echo "" + +# --------------------------------------------------------------------------- +# 4. Port availability (warnings only — stale processes are soft blockers) +# --------------------------------------------------------------------------- +info "Checking port availability..." + +_check_port() { + local port="$1" + local label="$2" + local pid="" + # Try lsof first (macOS/Linux), fall back to ss (Linux only) + if command -v lsof >/dev/null 2>&1; then + pid=$(lsof -ti tcp:"$port" 2>/dev/null | head -1 || true) + elif command -v ss >/dev/null 2>&1; then + pid=$(ss -tlnp "sport = :$port" 2>/dev/null | awk 'NR>1 {match($NF,/pid=([0-9]+)/,a); print a[1]}' | head -1 || true) + fi + + if [[ -n "$pid" ]]; then + warn "Port $port ($label) is occupied by PID $pid." + warn " If this is a stale process from a prior run, kill it:" + warn " kill $pid" + else + ok "Port $port ($label) is free" + fi +} + +_check_port 19222 "CEF CDP" +_check_port 4723 "Appium" +_check_port 18473 "mock backend (can be pre-running — OK if deliberate)" + +echo "" + +# --------------------------------------------------------------------------- +# Summary +# --------------------------------------------------------------------------- +if [[ $ERRORS -gt 0 ]]; then + printf "%b[preflight] PRE-FLIGHT FAILED%b — %d error(s) above must be resolved before running E2E tests.\n" \ + "$RED" "$RESET" "$ERRORS" >&2 + exit 1 +fi + +printf "%b[preflight] Pre-flight passed%b — environment looks good.\n" "$GREEN" "$RESET" +exit 0 diff --git a/app/scripts/e2e-run-all-flows.sh b/app/scripts/e2e-run-all-flows.sh index fb6afd3fcd..49e1664a51 100755 --- a/app/scripts/e2e-run-all-flows.sh +++ b/app/scripts/e2e-run-all-flows.sh @@ -1,159 +1,457 @@ #!/usr/bin/env bash # -# Run all E2E WDIO specs sequentially (Appium restarted per spec). -# Requires a prior E2E app build: pnpm --filter openhuman-app test:e2e:build +# e2e-run-all-flows.sh — Master E2E orchestrator for all 66 WDIO specs. # -# Each spec runs to completion regardless of prior failures; a pass/fail -# summary is printed at the end and the script exits non-zero if any spec -# failed. (Previously `set -e` caused the first failure to abort the run -# and made the terminal appear to crash.) +# USAGE: +# bash app/scripts/e2e-run-all-flows.sh [OPTIONS] +# +# OPTIONS: +# --suite=SUITE Run only one suite category. Valid values: +# auth, navigation, chat, skills, notifications, +# webhooks, providers, payments, settings, system, +# journeys, all (default: all) +# --bail Stop after the first spec failure (default: run all) +# --skip-preflight Skip the pre-flight environment check +# +# ENVIRONMENT: +# E2E_ARTIFACTS_DIR Directory where failure logs are copied. +# Default: app/test/e2e/artifacts/YYYYMMDD-HHMMSS +# +# REQUIREMENTS: +# pnpm --filter openhuman-app test:e2e:build (must be run first) +# +# Each spec runs to completion regardless of prior failures unless --bail is +# passed. A per-category mini-summary and a full summary are printed at the +# end. The script exits non-zero if any spec failed. +# +# (Previously `set -e` caused the first failure to abort the run and made +# the terminal appear to crash. `set -uo pipefail` preserves error detection +# without aborting mid-run.) # set -uo pipefail APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -cd "$APP_DIR" || { echo "FATAL: could not cd to $APP_DIR" >&2; exit 1; } +REPO_DIR="$(cd "$APP_DIR/.." && pwd)" +cd "$APP_DIR" || { + echo "[e2e-run-all-flows] Failed to cd into $APP_DIR" >&2 + exit 1 +} + +# --------------------------------------------------------------------------- +# Argument parsing +# --------------------------------------------------------------------------- +SUITE="all" +BAIL=0 +SKIP_PREFLIGHT=0 + +for arg in "$@"; do + case "$arg" in + --suite=*) SUITE="${arg#--suite=}" ;; + --bail) BAIL=1 ;; + --skip-preflight) SKIP_PREFLIGHT=1 ;; + *) + echo "Unknown option: $arg" >&2 + echo "Usage: bash app/scripts/e2e-run-all-flows.sh [--suite=SUITE] [--bail] [--skip-preflight]" >&2 + exit 1 + ;; + esac +done + +VALID_SUITES="auth navigation chat skills notifications webhooks providers payments settings system journeys all" +SUITE_VALID=0 +for s in $VALID_SUITES; do + [[ "$SUITE" == "$s" ]] && SUITE_VALID=1 && break +done +if [[ $SUITE_VALID -eq 0 ]]; then + echo "Invalid suite: '$SUITE'. Valid values: $VALID_SUITES" >&2 + exit 1 +fi -# Parallel arrays: names + exit codes collected during the run. +# --------------------------------------------------------------------------- +# Artifacts directory +# --------------------------------------------------------------------------- +E2E_ARTIFACTS_DIR="${E2E_ARTIFACTS_DIR:-$APP_DIR/test/e2e/artifacts/$(date +%Y%m%d-%H%M%S)}" +export E2E_ARTIFACTS_DIR + +# --------------------------------------------------------------------------- +# Run tracking: parallel arrays indexed by position. +# _spec_suite[i] — suite name this spec belongs to +# _spec_names[i] — human-readable label +# _spec_results[i] — 0 (pass) or 1 (fail) +# _spec_duration[i] — wall-clock seconds (integer) +# --------------------------------------------------------------------------- +_spec_suite=() _spec_names=() _spec_results=() +_spec_duration=() + +_BAILED=0 +_RUN_START_EPOCH=$(date +%s) +# --------------------------------------------------------------------------- +# run SPEC LABEL SUITE +# +# Records start time, runs e2e-run-spec.sh, records end time and result. +# Respects --bail: once _BAILED=1 all subsequent run() calls are no-ops +# that record a synthetic skip (exit 2) so the finish summary is still full. +# --------------------------------------------------------------------------- run() { local spec="$1" local label="${2:-$1}" + local suite="${3:-unknown}" + + _spec_suite+=("$suite") _spec_names+=("$label") + + if [[ $_BAILED -eq 1 ]]; then + _spec_results+=(2) # 2 = skipped due to bail + _spec_duration+=(0) + return + fi + + local t_start t_end duration + t_start=$(date +%s) if "$APP_DIR/scripts/e2e-run-spec.sh" "$spec" "$label"; then _spec_results+=(0) else _spec_results+=(1) + if [[ $BAIL -eq 1 ]]; then + echo "" + echo "[e2e-run-all-flows] --bail: stopping after first failure ($label)" + _BAILED=1 + fi + # Copy any failure logs into the artifacts directory + _copy_failure_logs "$label" + fi + t_end=$(date +%s) + duration=$(( t_end - t_start )) + _spec_duration+=("$duration") +} + +# --------------------------------------------------------------------------- +# _copy_failure_logs LABEL +# Copies /tmp/openhuman-e2e-app-*.log files into E2E_ARTIFACTS_DIR on failure. +# --------------------------------------------------------------------------- +_copy_failure_logs() { + local label="$1" + local logs + logs=$(ls /tmp/openhuman-e2e-app-*.log 2>/dev/null || true) + if [[ -z "$logs" ]]; then + return fi + mkdir -p "$E2E_ARTIFACTS_DIR" + for f in $logs; do + local dest="$E2E_ARTIFACTS_DIR/$(basename "$f" .log)-${label}.log" + cp "$f" "$dest" 2>/dev/null || true + done + echo "[e2e-run-all-flows] Failure logs copied to $E2E_ARTIFACTS_DIR" } -# Print summary and exit with the appropriate code. +# --------------------------------------------------------------------------- +# _mini_summary SUITE_NAME +# Prints a one-line pass/fail summary for a completed suite. +# --------------------------------------------------------------------------- +_mini_summary() { + local suite="$1" + local pass=0 fail=0 skip=0 + for i in "${!_spec_names[@]}"; do + if [[ "${_spec_suite[$i]}" != "$suite" ]]; then continue; fi + case "${_spec_results[$i]:-2}" in + 0) (( pass++ )) || true ;; + 1) (( fail++ )) || true ;; + 2) (( skip++ )) || true ;; + esac + done + local total=$(( pass + fail + skip )) + if [[ $fail -gt 0 ]]; then + printf " [%s] %d/%d passed (%d failed)\n" "$suite" "$pass" "$total" "$fail" + elif [[ $skip -gt 0 ]]; then + printf " [%s] %d/%d passed (%d skipped/bailed)\n" "$suite" "$pass" "$total" "$skip" + else + printf " [%s] %d/%d passed\n" "$suite" "$pass" "$total" + fi +} + +# --------------------------------------------------------------------------- +# finish — print per-category table, totals, wall time, and hints. +# Writes a Markdown summary to /tmp/e2e-summary.txt for CI job summaries. +# --------------------------------------------------------------------------- finish() { - local pass=0 fail=0 + local t_end_epoch + t_end_epoch=$(date +%s) + local wall=$(( t_end_epoch - _RUN_START_EPOCH )) + local wall_min=$(( wall / 60 )) + local wall_sec=$(( wall % 60 )) + + local pass=0 fail=0 skip=0 echo "" - echo "══════════════════════════════════════════════" - echo " E2E run summary ($(uname -s))" - echo "══════════════════════════════════════════════" + echo "══════════════════════════════════════════════════════════════════" + printf " E2E run summary ($(uname -s)) suite=%s\n" "$SUITE" + echo "══════════════════════════════════════════════════════════════════" + + # --- per-spec rows --- + local prev_suite="" for i in "${!_spec_names[@]}"; do - if [[ "${_spec_results[$i]}" -eq 0 ]]; then - printf " ✓ %s\n" "${_spec_names[$i]}" - (( pass++ )) || true - else - printf " ✗ %s\n" "${_spec_names[$i]}" - (( fail++ )) || true + local cur_suite="${_spec_suite[$i]}" + if [[ "$cur_suite" != "$prev_suite" ]]; then + echo "" + printf " ## %s\n" "$cur_suite" + prev_suite="$cur_suite" fi + local dur="${_spec_duration[$i]:-0}" + case "${_spec_results[$i]:-2}" in + 0) + printf " ✓ %-45s %3ds\n" "${_spec_names[$i]}" "$dur" + (( pass++ )) || true + ;; + 1) + printf " ✗ %-45s %3ds\n" "${_spec_names[$i]}" "$dur" + (( fail++ )) || true + ;; + 2) + printf " - %-45s (skipped/bailed)\n" "${_spec_names[$i]}" + (( skip++ )) || true + ;; + esac done - echo "──────────────────────────────────────────────" - printf " Passed: %d Failed: %d Total: %d\n" "$pass" "$fail" "${#_spec_names[@]}" - echo "══════════════════════════════════════════════" + + local total=$(( pass + fail + skip )) + echo "" + echo "──────────────────────────────────────────────────────────────────" + printf " Passed: %-4d Failed: %-4d Skipped: %-4d Total: %d\n" \ + "$pass" "$fail" "$skip" "$total" + printf " Wall time: %dm %02ds\n" "$wall_min" "$wall_sec" + echo "══════════════════════════════════════════════════════════════════" + + if [[ $fail -gt 0 ]]; then + echo "" + echo " To re-run a single failing spec:" + echo " bash app/scripts/e2e-run-session.sh test/e2e/specs/SPEC.spec.ts" + echo "" + echo " Artifacts (if any):" + echo " $E2E_ARTIFACTS_DIR" + echo "" + fi + + # --- write /tmp/e2e-summary.txt for CI job summary --- + { + printf "## E2E Results ($(uname -s)) — suite=%s\n\n" "$SUITE" + printf "| Result | Count |\n" + printf "|--------|-------|\n" + printf "| Passed | %d |\n" "$pass" + printf "| Failed | %d |\n" "$fail" + printf "| Skipped | %d |\n" "$skip" + printf "| **Total** | **%d** |\n" "$total" + printf "\n**Wall time:** %dm %02ds\n\n" "$wall_min" "$wall_sec" + + if [[ $fail -gt 0 ]]; then + printf "### Failed specs\n\n" + for i in "${!_spec_names[@]}"; do + if [[ "${_spec_results[$i]}" -eq 1 ]]; then + printf -- "- \`%s\`\n" "${_spec_names[$i]}" + fi + done + printf "\n" + fi + } > /tmp/e2e-summary.txt + if [[ $fail -gt 0 ]]; then exit 1 fi } trap finish EXIT +# --------------------------------------------------------------------------- +# Pre-flight check (unless --skip-preflight) +# --------------------------------------------------------------------------- +if [[ $SKIP_PREFLIGHT -eq 0 ]]; then + if [[ -f "$APP_DIR/scripts/e2e-preflight.sh" ]]; then + echo "[e2e-run-all-flows] Running pre-flight checks..." + if ! bash "$APP_DIR/scripts/e2e-preflight.sh"; then + echo "[e2e-run-all-flows] Pre-flight failed. Aborting." >&2 + exit 1 + fi + else + echo "[e2e-run-all-flows] Pre-flight script not found or not executable, skipping." + fi +fi + +# --------------------------------------------------------------------------- +# Helpers: should_run_suite SUITE_NAME +# Returns 0 (true) if this suite should run given --suite flag. +# --------------------------------------------------------------------------- +should_run_suite() { + [[ "$SUITE" == "all" || "$SUITE" == "$1" ]] +} + # --------------------------------------------------------------------------- # Auth & onboarding # --------------------------------------------------------------------------- -run "test/e2e/specs/smoke.spec.ts" "smoke" -run "test/e2e/specs/login-flow.spec.ts" "login" -run "test/e2e/specs/auth-access-control.spec.ts" "auth" -run "test/e2e/specs/logout-relogin-onboarding.spec.ts" "logout-relogin" -run "test/e2e/specs/onboarding-modes.spec.ts" "onboarding-modes" -run "test/e2e/specs/runtime-picker-login.spec.ts" "runtime-picker-login" +if should_run_suite "auth"; then + echo "" + echo "## Running suite: auth" + run "test/e2e/specs/smoke.spec.ts" "smoke" "auth" + run "test/e2e/specs/login-flow.spec.ts" "login" "auth" + run "test/e2e/specs/auth-access-control.spec.ts" "auth" "auth" + run "test/e2e/specs/logout-relogin-onboarding.spec.ts" "logout-relogin" "auth" + run "test/e2e/specs/onboarding-modes.spec.ts" "onboarding-modes" "auth" + run "test/e2e/specs/runtime-picker-login.spec.ts" "runtime-picker-login" "auth" + _mini_summary "auth" +fi # --------------------------------------------------------------------------- # Navigation & core UI # --------------------------------------------------------------------------- -run "test/e2e/specs/navigation.spec.ts" "navigation" -run "test/e2e/specs/command-palette.spec.ts" "command-palette" -run "test/e2e/specs/channels-smoke.spec.ts" "channels-smoke" -run "test/e2e/specs/insights-dashboard.spec.ts" "insights-dashboard" +if should_run_suite "navigation"; then + echo "" + echo "## Running suite: navigation" + run "test/e2e/specs/navigation.spec.ts" "navigation" "navigation" + run "test/e2e/specs/navigation-smoothness.spec.ts" "navigation-smoothness" "navigation" + run "test/e2e/specs/navigation-settings-panels.spec.ts" "navigation-settings" "navigation" + run "test/e2e/specs/command-palette.spec.ts" "command-palette" "navigation" + run "test/e2e/specs/channels-smoke.spec.ts" "channels-smoke" "navigation" + run "test/e2e/specs/insights-dashboard.spec.ts" "insights-dashboard" "navigation" + _mini_summary "navigation" +fi # --------------------------------------------------------------------------- # Chat & agent harness # --------------------------------------------------------------------------- -run "test/e2e/specs/chat-harness-send-stream.spec.ts" "chat-send-stream" -run "test/e2e/specs/chat-harness-cancel.spec.ts" "chat-cancel" -run "test/e2e/specs/chat-harness-scroll-render.spec.ts" "chat-scroll-render" -run "test/e2e/specs/chat-harness-subagent.spec.ts" "chat-subagent" -run "test/e2e/specs/chat-harness-wallet-flow.spec.ts" "chat-wallet" -run "test/e2e/specs/agent-review.spec.ts" "agent-review" -run "test/e2e/specs/mega-flow.spec.ts" "mega-flow" +if should_run_suite "chat"; then + echo "" + echo "## Running suite: chat" + run "test/e2e/specs/chat-harness-send-stream.spec.ts" "chat-send-stream" "chat" + run "test/e2e/specs/chat-harness-cancel.spec.ts" "chat-cancel" "chat" + run "test/e2e/specs/chat-harness-scroll-render.spec.ts" "chat-scroll-render" "chat" + run "test/e2e/specs/chat-harness-subagent.spec.ts" "chat-subagent" "chat" + run "test/e2e/specs/chat-harness-wallet-flow.spec.ts" "chat-wallet" "chat" + run "test/e2e/specs/chat-tool-call-flow.spec.ts" "chat-tool-call" "chat" + run "test/e2e/specs/chat-multi-tool-round.spec.ts" "chat-multi-tool" "chat" + run "test/e2e/specs/chat-tool-error-recovery.spec.ts" "chat-error-recovery" "chat" + run "test/e2e/specs/agent-review.spec.ts" "agent-review" "chat" + run "test/e2e/specs/mega-flow.spec.ts" "mega-flow" "chat" + _mini_summary "chat" +fi # --------------------------------------------------------------------------- # Skills # --------------------------------------------------------------------------- -run "test/e2e/specs/skills-registry.spec.ts" "skills-registry" -run "test/e2e/specs/skill-execution-flow.spec.ts" "skill-execution" -run "test/e2e/specs/skill-lifecycle.spec.ts" "skill-lifecycle" -run "test/e2e/specs/skill-multi-round.spec.ts" "skill-multi-round" -run "test/e2e/specs/skill-oauth.spec.ts" "skill-oauth" -run "test/e2e/specs/skill-socket-reconnect.spec.ts" "skill-socket-reconnect" +if should_run_suite "skills"; then + echo "" + echo "## Running suite: skills" + run "test/e2e/specs/skills-registry.spec.ts" "skills-registry" "skills" + run "test/e2e/specs/skill-execution-flow.spec.ts" "skill-execution" "skills" + run "test/e2e/specs/skill-lifecycle.spec.ts" "skill-lifecycle" "skills" + run "test/e2e/specs/skill-multi-round.spec.ts" "skill-multi-round" "skills" + run "test/e2e/specs/skill-oauth.spec.ts" "skill-oauth" "skills" + run "test/e2e/specs/skill-socket-reconnect.spec.ts" "skill-socket-reconnect" "skills" + _mini_summary "skills" +fi # --------------------------------------------------------------------------- # Notifications, memory, cron # --------------------------------------------------------------------------- -run "test/e2e/specs/notifications.spec.ts" "notifications" -run "test/e2e/specs/memory-roundtrip.spec.ts" "memory-roundtrip" -run "test/e2e/specs/cron-jobs-flow.spec.ts" "cron-jobs" -run "test/e2e/specs/autocomplete-flow.spec.ts" "autocomplete" +if should_run_suite "notifications"; then + echo "" + echo "## Running suite: notifications" + run "test/e2e/specs/notifications.spec.ts" "notifications" "notifications" + run "test/e2e/specs/memory-roundtrip.spec.ts" "memory-roundtrip" "notifications" + run "test/e2e/specs/cron-jobs-flow.spec.ts" "cron-jobs" "notifications" + run "test/e2e/specs/autocomplete-flow.spec.ts" "autocomplete" "notifications" + _mini_summary "notifications" +fi # --------------------------------------------------------------------------- # Webhooks & tools # --------------------------------------------------------------------------- -run "test/e2e/specs/webhooks-ingress-flow.spec.ts" "webhooks-ingress" -run "test/e2e/specs/webhooks-tunnel-flow.spec.ts" "webhooks-tunnel" -run "test/e2e/specs/tool-browser-flow.spec.ts" "tool-browser" -run "test/e2e/specs/tool-filesystem-flow.spec.ts" "tool-filesystem" -run "test/e2e/specs/tool-shell-git-flow.spec.ts" "tool-shell-git" +if should_run_suite "webhooks"; then + echo "" + echo "## Running suite: webhooks" + run "test/e2e/specs/webhooks-ingress-flow.spec.ts" "webhooks-ingress" "webhooks" + run "test/e2e/specs/webhooks-tunnel-flow.spec.ts" "webhooks-tunnel" "webhooks" + run "test/e2e/specs/tool-browser-flow.spec.ts" "tool-browser" "webhooks" + run "test/e2e/specs/tool-filesystem-flow.spec.ts" "tool-filesystem" "webhooks" + run "test/e2e/specs/tool-shell-git-flow.spec.ts" "tool-shell-git" "webhooks" + _mini_summary "webhooks" +fi # --------------------------------------------------------------------------- # Provider flows # --------------------------------------------------------------------------- -run "test/e2e/specs/telegram-flow.spec.ts" "telegram" -run "test/e2e/specs/gmail-flow.spec.ts" "gmail" -run "test/e2e/specs/slack-flow.spec.ts" "slack" -run "test/e2e/specs/whatsapp-flow.spec.ts" "whatsapp" -run "test/e2e/specs/conversations-web-channel-flow.spec.ts" "conversations" -run "test/e2e/specs/composio-triggers-flow.spec.ts" "composio-triggers" +if should_run_suite "providers"; then + echo "" + echo "## Running suite: providers" + run "test/e2e/specs/telegram-flow.spec.ts" "telegram" "providers" + run "test/e2e/specs/gmail-flow.spec.ts" "gmail" "providers" + run "test/e2e/specs/accounts-provider-modal.spec.ts" "accounts-providers" "providers" + run "test/e2e/specs/slack-flow.spec.ts" "slack" "providers" + run "test/e2e/specs/whatsapp-flow.spec.ts" "whatsapp" "providers" + # notion-flow.spec.ts was removed; skip to avoid "spec not found" failure. + # run "test/e2e/specs/notion-flow.spec.ts" "notion" "providers" + run "test/e2e/specs/conversations-web-channel-flow.spec.ts" "conversations" "providers" + run "test/e2e/specs/composio-triggers-flow.spec.ts" "composio-triggers" "providers" + _mini_summary "providers" +fi # --------------------------------------------------------------------------- # Payments & rewards # --------------------------------------------------------------------------- -run "test/e2e/specs/card-payment-flow.spec.ts" "card-payment" -run "test/e2e/specs/crypto-payment-flow.spec.ts" "crypto-payment" -run "test/e2e/specs/rewards-unlock-flow.spec.ts" "rewards-unlock" -run "test/e2e/specs/rewards-progression-persistence.spec.ts" "rewards-progression" +if should_run_suite "payments"; then + echo "" + echo "## Running suite: payments" + run "test/e2e/specs/card-payment-flow.spec.ts" "card-payment" "payments" + run "test/e2e/specs/crypto-payment-flow.spec.ts" "crypto-payment" "payments" + run "test/e2e/specs/rewards-unlock-flow.spec.ts" "rewards-unlock" "payments" + run "test/e2e/specs/rewards-progression-persistence.spec.ts" "rewards-progression" "payments" + _mini_summary "payments" +fi # --------------------------------------------------------------------------- # Settings panels # --------------------------------------------------------------------------- -run "test/e2e/specs/settings-channels-permissions.spec.ts" "settings-channels" -run "test/e2e/specs/settings-data-management.spec.ts" "settings-data" -run "test/e2e/specs/settings-dev-options.spec.ts" "settings-dev" -run "test/e2e/specs/settings-ai-skills.spec.ts" "settings-ai-skills" -run "test/e2e/specs/settings-account-preferences.spec.ts" "settings-account" -run "test/e2e/specs/settings-advanced-config.spec.ts" "settings-advanced" -run "test/e2e/specs/settings-feature-preferences.spec.ts" "settings-features" +if should_run_suite "settings"; then + echo "" + echo "## Running suite: settings" + run "test/e2e/specs/settings-channels-permissions.spec.ts" "settings-channels" "settings" + run "test/e2e/specs/settings-data-management.spec.ts" "settings-data" "settings" + run "test/e2e/specs/settings-dev-options.spec.ts" "settings-dev" "settings" + run "test/e2e/specs/settings-ai-skills.spec.ts" "settings-ai-skills" "settings" + run "test/e2e/specs/settings-account-preferences.spec.ts" "settings-account" "settings" + run "test/e2e/specs/settings-advanced-config.spec.ts" "settings-advanced" "settings" + run "test/e2e/specs/settings-feature-preferences.spec.ts" "settings-features" "settings" + _mini_summary "settings" +fi # --------------------------------------------------------------------------- -# AI, voice & screen +# System / AI / voice / screen / Tauri +# linux-cef-deb-runtime.spec.ts is Linux-only (tests /usr/bin path resolution +# for .deb package installs) — skipped on macOS/Windows. # --------------------------------------------------------------------------- -run "test/e2e/specs/local-model-runtime.spec.ts" "local-model" -run "test/e2e/specs/voice-mode.spec.ts" "voice-mode" -run "test/e2e/specs/audio-toolkit-flow.spec.ts" "audio-toolkit" +if should_run_suite "system"; then + echo "" + echo "## Running suite: system" + run "test/e2e/specs/local-model-runtime.spec.ts" "local-model" "system" + run "test/e2e/specs/voice-mode.spec.ts" "voice-mode" "system" + run "test/e2e/specs/screen-intelligence.spec.ts" "screen-intelligence" "system" + run "test/e2e/specs/audio-toolkit-flow.spec.ts" "audio-toolkit" "system" + run "test/e2e/specs/tauri-commands.spec.ts" "tauri-commands" "system" + # service-connectivity-flow tests the old sidecar service model removed in + # PR #1061 (core is now in-process). Skip by not setting OPENHUMAN_SERVICE_MOCK=1. + run "test/e2e/specs/service-connectivity-flow.spec.ts" "service-connectivity" "system" + if [[ "$(uname -s)" == "Linux" ]]; then + run "test/e2e/specs/linux-cef-deb-runtime.spec.ts" "linux-cef-deb-runtime" "system" + fi + _mini_summary "system" +fi # --------------------------------------------------------------------------- -# System / Tauri +# User journeys # --------------------------------------------------------------------------- -run "test/e2e/specs/tauri-commands.spec.ts" "tauri-commands" -OPENHUMAN_SERVICE_MOCK=1 \ - run "test/e2e/specs/service-connectivity-flow.spec.ts" "service-connectivity" - -# linux-cef-deb-runtime.spec.ts is Linux-only (tests /usr/bin path resolution -# for .deb package installs) — skipped on macOS/Windows. -if [[ "$(uname -s)" == "Linux" ]]; then - run "test/e2e/specs/linux-cef-deb-runtime.spec.ts" "linux-cef-deb-runtime" +if should_run_suite "journeys"; then + echo "" + echo "## Running suite: journeys" + run "test/e2e/specs/user-journey-full-task.spec.ts" "journey-full-task" "journeys" + run "test/e2e/specs/user-journey-settings-round-trip.spec.ts" "journey-settings" "journeys" + run "test/e2e/specs/chat-conversation-history.spec.ts" "chat-history" "journeys" + _mini_summary "journeys" fi diff --git a/app/scripts/e2e-run-session.sh b/app/scripts/e2e-run-session.sh index 195d6d6ff2..e463da3d4a 100755 --- a/app/scripts/e2e-run-session.sh +++ b/app/scripts/e2e-run-session.sh @@ -199,6 +199,11 @@ fi cat > "$E2E_CONFIG_FILE" << TOMLEOF api_url = "http://127.0.0.1:${E2E_MOCK_PORT}" primary_cloud = "p_e2e_mock" +default_model = "e2e-mock-model" +chat_provider = "e2e:e2e-mock-model" +reasoning_provider = "e2e:e2e-mock-model" +agentic_provider = "e2e:e2e-mock-model" +coding_provider = "e2e:e2e-mock-model" [[cloud_providers]] id = "p_e2e_mock" @@ -206,6 +211,7 @@ slug = "e2e" label = "E2E Mock" endpoint = "http://127.0.0.1:${E2E_MOCK_PORT}/openai/v1" auth_style = "none" +default_model = "e2e-mock-model" TOMLEOF echo "[runner] Wrote E2E config.toml routing inference to mock at http://127.0.0.1:${E2E_MOCK_PORT}" diff --git a/app/src/components/accounts/AddAccountModal.tsx b/app/src/components/accounts/AddAccountModal.tsx index 99b7d79734..96596d56ef 100644 --- a/app/src/components/accounts/AddAccountModal.tsx +++ b/app/src/components/accounts/AddAccountModal.tsx @@ -33,15 +33,19 @@ const AddAccountModal = ({ open, onClose, onPick, connectedProviders }: AddAccou return (
e.stopPropagation()}>
-

+

{t('accounts.addModal.title')}