diff --git a/mac/run.sh b/mac/run.sh index 0614187..8142103 100755 --- a/mac/run.sh +++ b/mac/run.sh @@ -76,7 +76,6 @@ MOBILE_ALL=( "android|Samsung Galaxy S21 Ultra|11" "android|Samsung Galaxy S20|10" "android|Samsung Galaxy M32|11" - "android|Samsung Galaxy Note 20|10" "android|Samsung Galaxy S10|9" "android|Samsung Galaxy Tab S8|12" "android|Google Pixel 9|15" @@ -177,8 +176,6 @@ MOBILE_ALL=( ) - - APP_URL="" APP_PLATFORM="" # ios | android | all @@ -194,7 +191,7 @@ MOBILE_LOG_FILE="$LOG_DIR/mobile_run_result.log" mkdir -p "$LOG_DIR" # Clear old logs to start fresh -: > "$GLOBAL" +: > "$GLOBAL_LOG_FILE" : > "$WEB_LOG_FILE" : > "$MOBILE_LOG_FILE" @@ -233,20 +230,14 @@ show_spinner() { log_msg_to "✅ Done!" } -# ===== validate_prereqs shim (keeps compatibility with older code) ===== -validate_prereqs() { - # For backwards compatibility call validate_tech_stack_installed - validate_tech_stack_installed -} - # ===== Functions: baseline interactions ===== setup_workspace() { local full_path="$WORKSPACE_DIR/$PROJECT_FOLDER" if [ ! -d "$full_path" ]; then mkdir -p "$full_path" - log_msg_to "✅ Created Onboarding workspace: $full_path" "$GLOBAL" + log_msg_to "✅ Created Onboarding workspace: $full_path" "$GLOBAL_LOG_FILE" else - log_msg_to "ℹ️ Onboarding Workspace already exists: $full_path" "$GLOBAL" + log_msg_to "ℹ️ Onboarding Workspace already exists: $full_path" "$GLOBAL_LOG_FILE" fi } @@ -255,7 +246,7 @@ ask_browserstack_credentials() { BROWSERSTACK_USERNAME=$(osascript -e 'Tell application "System Events" to display dialog "Please enter your BrowserStack Username.\n\nNote: Locate it in your BrowserStack account profile page.\nhttps://www.browserstack.com/accounts/profile/details" default answer "" with title "BrowserStack Setup" buttons {"OK"} default button "OK"' \ -e 'text returned of result') if [ -z "$BROWSERSTACK_USERNAME" ]; then - log_msg_to "❌ Username empty" "$GLOBAL" + log_msg_to "❌ Username empty" "$GLOBAL_LOG_FILE" exit 1 fi @@ -263,89 +254,89 @@ ask_browserstack_credentials() { BROWSERSTACK_ACCESS_KEY=$(osascript -e 'Tell application "System Events" to display dialog "Please enter your BrowserStack Access Key.\n\nNote: Locate it in your BrowserStack account page.\nhttps://www.browserstack.com/accounts/profile/details" default answer "" with hidden answer with title "BrowserStack Setup" buttons {"OK"} default button "OK"' \ -e 'text returned of result') if [ -z "$BROWSERSTACK_ACCESS_KEY" ]; then - log_msg_to "❌ Access Key empty" "$GLOBAL" + log_msg_to "❌ Access Key empty" "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "✅ BrowserStack credentials captured (access key hidden)" "$GLOBAL" + log_msg_to "✅ BrowserStack credentials captured (access key hidden)" "$GLOBAL_LOG_FILE" } ask_tech_stack() { TECH_STACK=$(osascript -e 'Tell application "System Events" to display dialog "Select installed tech stack:" buttons {"Java", "Python", "NodeJS"} default button "Java" with title "Testing Framework Technology Stack"' \ -e 'button returned of result') - log_msg_to "✅ Selected Tech Stack: $TECH_STACK" "$GLOBAL" + log_msg_to "✅ Selected Tech Stack: $TECH_STACK" "$GLOBAL_LOG_FILE" } validate_tech_stack_installed() { - log_msg_to "ℹ️ Checking prerequisites for $TECH_STACK" "$GLOBAL" + log_msg_to "ℹ️ Checking prerequisites for $TECH_STACK" "$GLOBAL_LOG_FILE" case "$TECH_STACK" in Java) - log_msg_to "🔍 Checking if 'java' command exists..." "$GLOBAL" + log_msg_to "🔍 Checking if 'java' command exists..." "$GLOBAL_LOG_FILE" if ! command -v java >/dev/null 2>&1; then - log_msg_to "❌ Java command not found in PATH." "$GLOBAL" + log_msg_to "❌ Java command not found in PATH." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "🔍 Checking if Java runs correctly..." "$GLOBAL" + log_msg_to "🔍 Checking if Java runs correctly..." "$GLOBAL_LOG_FILE" if ! JAVA_VERSION_OUTPUT=$(java -version 2>&1); then - log_msg_to "❌ Java exists but failed to run." "$GLOBAL" + log_msg_to "❌ Java exists but failed to run." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "✅ Java is installed. Version details:" "$GLOBAL" - echo "$JAVA_VERSION_OUTPUT" | while read -r l; do log_msg_to " $l" "$GLOBAL"; done + log_msg_to "✅ Java is installed. Version details:" "$GLOBAL_LOG_FILE" + echo "$JAVA_VERSION_OUTPUT" | while read -r l; do log_msg_to " $l" "$GLOBAL_LOG_FILE"; done ;; Python) - log_msg_to "🔍 Checking if 'python3' command exists..." "$GLOBAL" + log_msg_to "🔍 Checking if 'python3' command exists..." "$GLOBAL_LOG_FILE" if ! command -v python3 >/dev/null 2>&1; then - log_msg_to "❌ Python3 command not found in PATH." "$GLOBAL" + log_msg_to "❌ Python3 command not found in PATH." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "🔍 Checking if Python3 runs correctly..." "$GLOBAL" + log_msg_to "🔍 Checking if Python3 runs correctly..." "$GLOBAL_LOG_FILE" if ! PYTHON_VERSION_OUTPUT=$(python3 --version 2>&1); then - log_msg_to "❌ Python3 exists but failed to run." "$GLOBAL" + log_msg_to "❌ Python3 exists but failed to run." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "✅ Python3 is installed: $PYTHON_VERSION_OUTPUT" "$GLOBAL" + log_msg_to "✅ Python3 is installed: $PYTHON_VERSION_OUTPUT" "$GLOBAL_LOG_FILE" ;; NodeJS) - log_msg_to "🔍 Checking if 'node' command exists..." "$GLOBAL" + log_msg_to "🔍 Checking if 'node' command exists..." "$GLOBAL_LOG_FILE" if ! command -v node >/dev/null 2>&1; then - log_msg_to "❌ Node.js command not found in PATH." "$GLOBAL" + log_msg_to "❌ Node.js command not found in PATH." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "🔍 Checking if 'npm' command exists..." "$GLOBAL" + log_msg_to "🔍 Checking if 'npm' command exists..." "$GLOBAL_LOG_FILE" if ! command -v npm >/dev/null 2>&1; then - log_msg_to "❌ npm command not found in PATH." "$GLOBAL" + log_msg_to "❌ npm command not found in PATH." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "🔍 Checking if Node.js runs correctly..." "$GLOBAL" + log_msg_to "🔍 Checking if Node.js runs correctly..." "$GLOBAL_LOG_FILE" if ! NODE_VERSION_OUTPUT=$(node -v 2>&1); then - log_msg_to "❌ Node.js exists but failed to run." "$GLOBAL" + log_msg_to "❌ Node.js exists but failed to run." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "🔍 Checking if npm runs correctly..." "$GLOBAL" + log_msg_to "🔍 Checking if npm runs correctly..." "$GLOBAL_LOG_FILE" if ! NPM_VERSION_OUTPUT=$(npm -v 2>&1); then - log_msg_to "❌ npm exists but failed to run." "$GLOBAL" + log_msg_to "❌ npm exists but failed to run." "$GLOBAL_LOG_FILE" exit 1 fi - log_msg_to "✅ Node.js is installed: $NODE_VERSION_OUTPUT" "$GLOBAL" - log_msg_to "✅ npm is installed: $NPM_VERSION_OUTPUT" "$GLOBAL" + log_msg_to "✅ Node.js is installed: $NODE_VERSION_OUTPUT" "$GLOBAL_LOG_FILE" + log_msg_to "✅ npm is installed: $NPM_VERSION_OUTPUT" "$GLOBAL_LOG_FILE" ;; *) - log_msg_to "❌ Unknown tech stack selected: $TECH_STACK" "$GLOBAL" + log_msg_to "❌ Unknown tech stack selected: $TECH_STACK" "$GLOBAL_LOG_FILE" exit 1 ;; esac - log_msg_to "✅ Prerequisites validated for $TECH_STACK" "$GLOBAL" + log_msg_to "✅ Prerequisites validated for $TECH_STACK" "$GLOBAL_LOG_FILE" } # ===== Ask user for test URL via UI prompt ===== @@ -354,10 +345,10 @@ ask_user_for_test_url() { -e 'text returned of result') if [ -n "$CX_TEST_URL" ]; then - log_msg_to "🌐 Using custom test URL: $CX_TEST_URL" "$PRE_RUN_LOG_FILE" + log_msg_to "🌐 Using custom test URL: $CX_TEST_URL" "$GLOBAL_LOG_FILE" else CX_TEST_URL="$DEFAULT_TEST_URL" - log_msg_to "⚠️ No URL entered. Falling back to default: $CX_TEST_URL" "$PRE_RUN_LOG_FILE" + log_msg_to "⚠️ No URL entered. Falling back to default: $CX_TEST_URL" "$GLOBAL_LOG_FILE" fi } @@ -372,16 +363,29 @@ ask_and_upload_app() { ' 2>/dev/null) if [[ "$CHOICE_RESPONSE" == *"Use Sample App"* ]]; then - log_msg_to "➡️ Using default sample app: bs://sample.app" "$GLOBAL" - APP_URL="bs://sample.app" - APP_PLATFORM="all" + log_msg_to "⬆️ Uploading sample app to BrowserStack..." "$GLOBAL_LOG_FILE" + UPLOAD_RESPONSE=$(curl -s -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \ + -X POST "https://api-cloud.browserstack.com/app-automate/upload" \ + -F "url=https://www.browserstack.com/app-automate/sample-apps/android/WikipediaSample.apk") + + APP_URL=$(echo "$UPLOAD_RESPONSE" | grep -o '"app_url":"[^"]*' | cut -d'"' -f4) + export BROWSERSTACK_APP=$APP_URL + log_msg_to "Exported BROWSERSTACK_APP=$BROWSERSTACK_APP" "$GLOBAL_LOG_FILE" + + if [ -z "$APP_URL" ]; then + log_msg_to "❌ Upload failed. Response: $UPLOAD_RESPONSE" "$GLOBAL_LOG_FILE" + return 1 + fi + + log_msg_to "✅ App uploaded successfully: $APP_URL" "$GLOBAL_LOG_FILE" + APP_PLATFORM="android" return 0 elif [[ "$CHOICE_RESPONSE" == *"Upload my App"* ]]; then APP_FILE_PATH=$(osascript -e 'POSIX path of (choose file with prompt "📱 Please select your .apk or .ipa app file")' 2>/dev/null) if [ -z "$APP_FILE_PATH" ]; then - log_msg_to "⚠️ File selection canceled. Aborting." "$GLOBAL" + log_msg_to "⚠️ File selection canceled. Aborting." "$GLOBAL_LOG_FILE" return 1 fi @@ -390,27 +394,28 @@ ask_and_upload_app() { elif [[ "$APP_FILE_PATH" == *.ipa ]]; then APP_PLATFORM="ios" else - log_msg_to "❌ Unsupported file type. Only .apk or .ipa allowed." "$GLOBAL" + log_msg_to "❌ Unsupported file type. Only .apk or .ipa allowed." "$GLOBAL_LOG_FILE" return 1 fi - log_msg_to "⬆️ Uploading $APP_FILE_PATH to BrowserStack..." "$GLOBAL" + log_msg_to "⬆️ Uploading $APP_FILE_PATH to BrowserStack..." "$GLOBAL_LOG_FILE" UPLOAD_RESPONSE=$(curl -s -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \ -X POST "https://api-cloud.browserstack.com/app-automate/upload" \ -F "file=@$APP_FILE_PATH") APP_URL=$(echo "$UPLOAD_RESPONSE" | grep -o '"app_url":"[^"]*' | cut -d'"' -f4) + export BROWSERSTACK_APP=$APP_URL if [ -z "$APP_URL" ]; then - log_msg_to "❌ Upload failed. Response: $UPLOAD_RESPONSE" "$GLOBAL" + log_msg_to "❌ Upload failed. Response: $UPLOAD_RESPONSE" "$GLOBAL_LOG_FILE" return 1 fi - log_msg_to "✅ App uploaded successfully: $APP_URL" "$GLOBAL" + log_msg_to "✅ App uploaded successfully: $APP_URL" "$GLOBAL_LOG_FILE" return 0 else - log_msg_to "🚫 Operation canceled by user." "$GLOBAL" + log_msg_to "🚫 Operation canceled by user." "$GLOBAL_LOG_FILE" return 1 fi } @@ -418,7 +423,7 @@ ask_and_upload_app() { ask_test_type() { TEST_TYPE=$(osascript -e 'Tell application "System Events" to display dialog "Select testing type:" buttons {"Web", "App", "Both"} default button "Web" with title "Testing Type"' \ -e 'button returned of result') - log_msg_to "✅ Selected Testing Type: $TEST_TYPE" "$GLOBAL" + log_msg_to "✅ Selected Testing Type: $TEST_TYPE" "$GLOBAL_LOG_FILE" case "$TEST_TYPE" in "Web") @@ -572,7 +577,7 @@ generate_mobile_caps_json() { } # ===== Fetch plan details (writes to GLOBAL) ===== fetch_plan_details() { - log_msg_to "ℹ️ Fetching BrowserStack Plan Details..." "$GLOBAL" + log_msg_to "ℹ️ Fetching BrowserStack Plan Details..." "$GLOBAL_LOG_FILE" local web_unauthorized=false local mobile_unauthorized=false @@ -583,9 +588,9 @@ fetch_plan_details() { if [ "$HTTP_CODE_WEB" == "200" ]; then WEB_PLAN_FETCHED=true TEAM_PARALLELS_MAX_ALLOWED_WEB=$(echo "$RESPONSE_WEB_BODY" | grep -o '"parallel_sessions_max_allowed":[0-9]*' | grep -o '[0-9]*') - log_msg_to "✅ Web Testing Plan fetched: Team max parallel sessions = $TEAM_PARALLELS_MAX_ALLOWED_WEB" "$GLOBAL" + log_msg_to "✅ Web Testing Plan fetched: Team max parallel sessions = $TEAM_PARALLELS_MAX_ALLOWED_WEB" "$GLOBAL_LOG_FILE" else - log_msg_to "❌ Web Testing Plan fetch failed ($HTTP_CODE_WEB)" "$GLOBAL" + log_msg_to "❌ Web Testing Plan fetch failed ($HTTP_CODE_WEB)" "$GLOBAL_LOG_FILE" [ "$HTTP_CODE_WEB" == "401" ] && web_unauthorized=true fi fi @@ -597,9 +602,9 @@ fetch_plan_details() { if [ "$HTTP_CODE_MOBILE" == "200" ]; then MOBILE_PLAN_FETCHED=true TEAM_PARALLELS_MAX_ALLOWED_MOBILE=$(echo "$RESPONSE_MOBILE_BODY" | grep -o '"parallel_sessions_max_allowed":[0-9]*' | grep -o '[0-9]*') - log_msg_to "✅ Mobile App Testing Plan fetched: Team max parallel sessions = $TEAM_PARALLELS_MAX_ALLOWED_MOBILE" "$GLOBAL" + log_msg_to "✅ Mobile App Testing Plan fetched: Team max parallel sessions = $TEAM_PARALLELS_MAX_ALLOWED_MOBILE" "$GLOBAL_LOG_FILE" else - log_msg_to "❌ Mobile App Testing Plan fetch failed ($HTTP_CODE_MOBILE)" "$GLOBAL" + log_msg_to "❌ Mobile App Testing Plan fetch failed ($HTTP_CODE_MOBILE)" "$GLOBAL_LOG_FILE" [ "$HTTP_CODE_MOBILE" == "401" ] && mobile_unauthorized=true fi fi @@ -607,7 +612,7 @@ fetch_plan_details() { if [[ "$TEST_TYPE" == "Web" && "$web_unauthorized" == true ]] || \ [[ "$TEST_TYPE" == "App" && "$mobile_unauthorized" == true ]] || \ [[ "$TEST_TYPE" == "Both" && "$web_unauthorized" == true && "$mobile_unauthorized" == true ]]; then - log_msg_to "❌ Unauthorized to fetch required plan(s). Exiting." "$GLOBAL" + log_msg_to "❌ Unauthorized to fetch required plan(s). Exiting." "$GLOBAL_LOG_FILE" exit 1 fi } @@ -656,19 +661,12 @@ setup_web_java() { mkdir -p "$WORKSPACE_DIR/$PROJECT_FOLDER" rm -rf $TARGET_DIR # === 1️⃣ Clone Repo === - log_msg_to "📦 Cloning repo $REPO into $TARGET_DIR" "$GLOBAL" "$WEB_LOG_FILE" - git clone https://github.com/browserstackCE/now-testng-browserstack.git "$TARGET_DIR" >> "$WEB_LOG_FILE" 2>&1 || true + log_msg_to "📦 Cloning repo $REPO into $TARGET_DIR" "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" + git clone https://github.com/browserstackCE/$REPO "$TARGET_DIR" >> "$WEB_LOG_FILE" 2>&1 || true - cd "$TARGET_DIR" || return 1 - # validate_prereqs || return 1 - + cd "$TARGET_DIR"|| return 1 - # === 3️⃣ Update Base URL === - if grep -qr "https://www.bstackdemo.com" .; then - log_msg_to "🌐 Updating base URL to $CX_TEST_URL" "$GLOBAL" "$WEB_LOG_FILE" - sed -i "s|https://www.bstackdemo.com|$CX_TEST_URL|g" $(grep -rl "https://www.bstackdemo.com" .) - fi if is_domain_private; then local_flag=true @@ -676,35 +674,33 @@ setup_web_java() { # === 4️⃣ Local Flag === if [ "$local_flag" = "true" ]; then - log_msg_to "✅ BrowserStack Local is ENABLED for this run." "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "✅ BrowserStack Local is ENABLED for this run." "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" else - log_msg_to "✅ BrowserStack Local is DISABLED for this run." "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "✅ BrowserStack Local is DISABLED for this run." "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" fi # === 5️⃣ YAML Setup === - log_msg_to "🧩 Generating YAML config (bstack.yml)" "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "🧩 Generating YAML config (bstack.yml)" "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" + + + # YAML config path + export BROWSERSTACK_CONFIG_FILE="./browserstack.yml" platform_yaml=$(generate_web_platforms_yaml "$TEAM_PARALLELS_MAX_ALLOWED_WEB") - cat > browserstack.yml <> "$BROWSERSTACK_CONFIG_FILE" <> "$WEB_LOG_FILE" 2>&1 || true - log_msg_to "🚀 Running 'mvn test -P sample-test'. This could take a few minutes. Follow the Automaton build here: https://automation.browserstack.com/" "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "🚀 Running 'mvn test -P sample-test'. This could take a few minutes. Follow the Automaton build here: https://automation.browserstack.com/" "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" mvn test -P sample-test >> "$WEB_LOG_FILE" 2>&1 & cmd_pid=$!|| true @@ -726,12 +722,11 @@ setup_web_python() { rm -rf $TARGET_DIR git clone https://github.com/browserstackCE/$REPO.git "$TARGET_DIR" >> "$WEB_LOG_FILE" 2>&1 || true - log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$PRE_RUN_LOG_FILE" + log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$GLOBAL_LOG_FILE" cd "$TARGET_DIR" || return 1 - #validate_prereqs || return 1 # Setup Python venv if [ ! -d "venv" ]; then @@ -757,11 +752,12 @@ setup_web_python() { # === 4️⃣ Local Flag === if [ "$local_flag" = "true" ]; then - log_msg_to "✅ BrowserStack Local is ENABLED for this run." "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "✅ BrowserStack Local is ENABLED for this run." "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" else - log_msg_to "✅ BrowserStack Local is DISABLED for this run." "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "✅ BrowserStack Local is DISABLED for this run." "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" fi + cat > browserstack.yml <> "$WEB_LOG_FILE" 2>&1 & cmd_pid=$!|| true @@ -810,18 +800,18 @@ setup_web_nodejs() { mkdir -p "$WORKSPACE_DIR/$PROJECT_FOLDER" # === 1️⃣ Clone Repo === - log_msg_to "📦 Cloning repo $REPO into $TARGET_DIR" "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "📦 Cloning repo $REPO into $TARGET_DIR" "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" git clone https://github.com/browserstackCE/$REPO.git "$TARGET_DIR" >> "$WEB_LOG_FILE" 2>&1 || true cd "$TARGET_DIR" || return 1 # === 2️⃣ Install Dependencies === - log_msg_to "⚙️ Running 'npm install'" "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "⚙️ Running 'npm install'" "$WEB_LOG_FILE" npm install >> "$WEB_LOG_FILE" 2>&1 || true # === 4️⃣ Generate Capabilities JSON === - log_msg_to "🧩 Generating browser/OS capabilities" "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "🧩 Generating browser/OS capabilities" "$WEB_LOG_FILE" local caps_json caps_json=$(generate_web_caps_json "$parallels") @@ -835,9 +825,9 @@ setup_web_nodejs() { #log_msg_to local flag status if [ "$local_flag" = "true" ]; then - log_msg_to "✅ BrowserStack Local is ENABLED for this run." "$PRE_RUN_LOG_FILE" + log_msg_to "✅ BrowserStack Local is ENABLED for this run." "$WEB_LOG_FILE" else - log_msg_to "✅ BrowserStack Local is DISABLED for this run." "$PRE_RUN_LOG_FILE" + log_msg_to "✅ BrowserStack Local is DISABLED for this run." "$WEB_LOG_FILE" fi # === 7️⃣ Export BrowserStack Credentials === @@ -847,10 +837,14 @@ setup_web_nodejs() { # === 8️⃣ Run Tests === log_msg_to "🚀 Running 'npm run test'. This could take a few minutes. Follow the Automaton build here: https://automation.browserstack.com/" "$WEB_LOG_FILE" - npm run test >> "$WEB_LOG_FILE" 2>&1 || true + npm run test >> "$WEB_LOG_FILE" 2>&1 || true & + cmd_pid=$!|| true + + show_spinner "$cmd_pid" + wait "$cmd_pid" # === 9️⃣ Wrap Up === - log_msg_to "✅ Web JS setup and test execution completed successfully." "$GLOBAL" "$WEB_LOG_FILE" + log_msg_to "✅ Web JS setup and test execution completed successfully." "$WEB_LOG_FILE" cd "$WORKSPACE_DIR/$PROJECT_FOLDER" return 0 @@ -873,7 +867,6 @@ setup_web() { local parallels_per_platform parallels_per_platform=$total_parallels - while [ "$attempt" -le 1 ]; do log_msg_to "[Web Setup]" "$WEB_LOG_FILE" case "$TECH_STACK" in @@ -885,14 +878,14 @@ setup_web() { ;; Python) setup_web_python "$local_flag" "$parallels_per_platform" "$WEB_LOG_FILE" - if (grep -qiE "BUILD FAILURE" "$WEB_LOG_FILE"); then + if (grep -qiE "BUILD FAILURE" "$WEB_LOG_FILE"); then ## needs to change based on pytest output success=false fi ;; NodeJS) setup_web_nodejs "$local_flag" "$parallels_per_platform" "$WEB_LOG_FILE" - if (grep -qiE "([1-9][0-9]*) passed, 0 failed" "$WEB_LOG_FILE"); then + if (grep -qiE "([1-9][0-9]*) passed, ([1-9]*) failed" "$WEB_LOG_FILE"); then success=false fi ;; @@ -903,11 +896,8 @@ setup_web() { if [ "$success" = true ]; then log_msg_to "✅ Web setup succeeded." "$WEB_LOG_FILE" break - elif [ "$SETUP_FAILURE" = true ]; then - log_msg_to "❌ Web test failed due to setup error. Check logs at: $WEB_LOG_FILE" "$WEB_LOG_FILE" - break else - log_msg_to "❌ Web setup ended without success; check $WEB_LOG_FILE for details" "$WEB_LOG_FILE" + log_msg_to "❌ Web setup failed. Check $WEB_LOG_FILE for details" "$WEB_LOG_FILE" break fi done @@ -922,9 +912,11 @@ setup_mobile_python() { REPO="pytest-appium-app-browserstack" TARGET_DIR="$WORKSPACE_DIR/$PROJECT_FOLDER/$REPO" + rm -rf $TARGET_DIR + # Clone repo if not present git clone https://github.com/browserstack/$REPO.git "$TARGET_DIR" - log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$PRE_RUN_LOG_FILE" + log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$GLOBAL_LOG_FILE" cd "$TARGET_DIR" || return 1 @@ -979,7 +971,7 @@ EOF APP_PLATFORM="$original_platform" - log_msg_to "✅ Wrote platform YAMLs to android/browserstack.yml and ios/browserstack.yml" "$PRE_RUN_LOG_FILE" + log_msg_to "✅ Wrote platform YAMLs to android/browserstack.yml and ios/browserstack.yml" "$MOBILE_LOG_FILE" # Replace sample tests in both android and ios with universal, locator-free test cat > android/bstack_sample.py <<'PYEOF' @@ -1033,9 +1025,9 @@ PYEOF # Log local flag status if [ "$local_flag" = "true" ]; then - log_msg_to "⚠️ BrowserStack Local is ENABLED for this run." + log_msg_to "✅ BrowserStack Local is ENABLED for this run." else - log_msg_to "⚠️ BrowserStack Local is DISABLED for this run." + log_msg_to "✅ BrowserStack Local is DISABLED for this run." fi # Run pytest with BrowserStack SDK from the chosen platform directory @@ -1044,11 +1036,6 @@ PYEOF cd "$run_dir" && browserstack-sdk pytest -s bstack_sample.py >> "$log_file" 2>&1 || true ) - # Copy first 200 lines of logs for visibility - [ -f "$log_file" ] && sed -n '1,200p' "$log_file" | while read -r l; do - log_msg_to "mobile (python): $l" "$PRE_RUN_LOG_FILE" - done - deactivate cd "$WORKSPACE_DIR/$PROJECT_FOLDER" return 0 @@ -1062,8 +1049,10 @@ setup_mobile_java() { REPO="now-testng-appium-app-browserstack" TARGET_DIR="$WORKSPACE_DIR/$PROJECT_FOLDER/$REPO" - git clone https://github.com/BrowserStackCE/$REPO.git "$TARGET_DIR" - log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$GLOBAL" "$MOBILE_LOG_FILE" + rm -rf $TARGET_DIR + + git clone https://github.com/BrowserStackCE/$REPO.git "$TARGET_DIR" >> "$WEB_LOG_FILE" 2>&1 || true + log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$GLOBAL_LOG_FILE" "$MOBILE_LOG_FILE" cd "$TARGET_DIR" || return 1 if [[ "$APP_PLATFORM" == "all" || "$APP_PLATFORM" == "android" ]]; then @@ -1072,7 +1061,6 @@ else cd ios/testng-examples fi - validate_prereqs || return 1 export BROWSERSTACK_USERNAME="$BROWSERSTACK_USERNAME" export BROWSERSTACK_ACCESS_KEY="$BROWSERSTACK_ACCESS_KEY" @@ -1088,26 +1076,20 @@ $platform_yaml EOF # Run Maven install first - log_msg_to "⚙️ Running 'mvn clean'" "$GLOBAL" "$MOBILE_LOG_FILE" - if ! mvn clean >> "$log_file" 2>&1; then - log_msg_to "❌ 'mvn clean' FAILED. See $log_file for details." "$GLOBAL" "$MOBILE_LOG_FILE" + log_msg_to "⚙️ Running 'mvn clean'" "$GLOBAL_LOG_FILE" "$MOBILE_LOG_FILE" + if ! mvn clean >> "$MOBILE_LOG_FILE" 2>&1; then + log_msg_to "❌ 'mvn clean' FAILED. See $log_file for details." "$GLOBAL_LOG_FILE" "$MOBILE_LOG_FILE" return 1 # Fail the function if clean fails fi - log_msg_to "🚀 mvn test -P sample-test'" "$GLOBAL" "$MOBILE_LOG_FILE" - if ! mvn test -P sample-test >> "$log_file" 2>&1; then - log_msg_to "❌ 'mvn test -P sample-test' FAILED. See $log_file for details." "$GLOBAL" "$MOBILE_LOG_FILE" - else - log_msg_to "✅ 'mvn test -P sample-test' complete." "$GLOBAL" "$MOBILE_LOG_FILE" - fi + log_msg_to "🚀 Running 'mvn test -P sample-test'. This could take a few minutes. Follow the Automaton build here: https://automation.browserstack.com/" "$GLOBAL_LOG_FILE" "$WEB_LOG_FILE" + mvn test -P sample-test >> "$MOBILE_LOG_FILE" 2>&1 & + cmd_pid=$!|| true - # Copy first 200 lines of logs for visibility - [ -f "$log_file" ] && sed -n '1,200p' "$log_file" | while read -r l; do - log_msg_to "mobile (java): $l" "$GLOBAL" "$MOBILE_LOG_FILE" - done + show_spinner "$cmd_pid" + wait "$cmd_pid" cd "$WORKSPACE_DIR/$PROJECT_FOLDER" - rm -rf "$TARGET_DIR" || return 1 return 0 } @@ -1117,25 +1099,21 @@ setup_mobile_nodejs() { local parallels=$2 local log_file=$3 + echo "Starting Mobile NodeJS setup with parallels: $parallels" >> "$log_file" 2>&1 + # cd $WORKSPACE_DIR/$PROJECT_FOLDER || return 1 REPO="now-webdriverio-appium-app-browserstack" TARGET_DIR="$WORKSPACE_DIR/$PROJECT_FOLDER/$REPO" - if [ ! -d "$REPO" ]; then - git clone -b sdk https://github.com/BrowserStackCE/$REPO - log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$GLOBAL" "$MOBILE_LOG_FILE" - fi - cd "$TARGET_DIR/test/" || return 1 - validate_prereqs || return 1 + rm -rf $TARGET_DIR + git clone https://github.com/BrowserStackCE/$REPO.git "$TARGET_DIR" >> "$WEB_LOG_FILE" 2>&1 || true + log_msg_to "✅ Cloned repository: $REPO into $TARGET_DIR" "$GLOBAL_LOG_FILE" "$MOBILE_LOG_FILE" + cd "$TARGET_DIR"/test || return 1 - log_msg_to "⚙️ Running 'npm install'" "$GLOBAL" "$MOBILE_LOG_FILE" - if ! npm install >> "$log_file" 2>&1; then - log_msg_to "❌ 'npm install' FAILED. See $log_file for details." "$GLOBAL" "$MOBILE_LOG_FILE" - return 1 # Fail the function if clean fails - else - log_msg_to "✅ 'npm install' complete." "$GLOBAL" "$MOBILE_LOG_FILE" - fi + # === 2️⃣ Install Dependencies === + log_msg_to "⚙️ Running 'npm install'" "$MOBILE_LOG_FILE" + npm install >> "$MOBILE_LOG_FILE" 2>&1 || true generate_mobile_caps_json "$parallels" @@ -1143,28 +1121,32 @@ setup_mobile_nodejs() { export BROWSERSTACK_ACCESS_KEY="$BROWSERSTACK_ACCESS_KEY" export BSTACK_PARALLELS=$parallels - if ! npm run test >> "$log_file" 2>&1; then - echo "❌ Error: Test execution failed. See $log_file for test results and failure details." - log_msg_to "❌ 'npm run test' FAILED. See $log_file for test report and failure details." "$GLOBAL" "$MOBILE_LOG_FILE" - return 1 - else - log_msg_to "✅ 'npm run test' complete." "$GLOBAL" "$MOBILE_LOG_FILE" - fi - - [ -f "$log_file" ] && sed -n '1,200p' "$log_file" | while read -r l; do log_msg_to "mobile: $l" "$GLOBAL"; done + echo "Parallels for NODEJS Repo: " $BSTACK_PARALLELS - rm -rf $TARGET_DIR || true +# === 8️⃣ Run Tests === + log_msg_to "🚀 Running 'npm run test'. This could take a few minutes. Follow the Automaton build here: https://automation.browserstack.com/" "$WEB_LOG_FILE" + npm run test >> "$MOBILE_LOG_FILE" 2>&1 || true & + cmd_pid=$!|| true + + show_spinner "$cmd_pid" + wait "$cmd_pid" + + # === 9️⃣ Wrap Up === + log_msg_to "✅ Mobile JS setup and test execution completed successfully." "$MOBILE_LOG_FILE" + + cd "$WORKSPACE_DIR/$PROJECT_FOLDER" return 0 } # ===== Mobile wrapper with retry logic (writes runtime logs to MOBILE_LOG_FILE) ===== setup_mobile() { - log_msg_to "Starting Mobile setup for $TECH_STACK" "$MOBILE_LOG_FILE" + log_msg_to "Starting Mobile setup for $TECH_STACK" "$WEB_LOG_FILE" - local local_flag=true + local local_flag=false local attempt=1 - local success=false - local log_file="$MOBILE_LOG_FILE" + local success=true + local log_file=$WEB_LOG_FILE + # don't pre-create; file will be created on first write by log_msg_to or command output redirection local total_parallels total_parallels=$(echo "$TEAM_PARALLELS_MAX_ALLOWED_MOBILE * $PARALLEL_PERCENTAGE" | bc | cut -d'.' -f1) @@ -1172,51 +1154,38 @@ setup_mobile() { local parallels_per_platform parallels_per_platform=$total_parallels + while [ "$attempt" -le 1 ]; do + log_msg_to "[Mobile Setup]" "$MOBILE_LOG_FILE" case "$TECH_STACK" in - Java) setup_mobile_java "$local_flag" "$parallels_per_platform" "$MOBILE_LOG_FILE" ;; - Python) setup_mobile_python "$local_flag" "$parallels_per_platform" "$MOBILE_LOG_FILE" ;; - NodeJS) setup_mobile_nodejs "$local_flag" "$parallels_per_platform" "$MOBILE_LOG_FILE" ;; - *) log_msg_to "Unknown TECH_STACK: $TECH_STACK" "$MOBILE_LOG_FILE"; return 1 ;; - esac - - LOG_CONTENT=$(<"$MOBILE_LOG_FILE" 2>/dev/null || true) - - # 2. !!FIX!! Reset ALL state flags at the start of each loop - LOCAL_FAILURE=false - SETUP_FAILURE=false - success=false - - # 3. !!FIX!! Use here-strings (<<<) instead of echo - for pattern in "${MOBILE_LOCAL_ERRORS[@]}"; do - grep -qiE "$pattern" <<< "$LOG_CONTENT" && LOCAL_FAILURE=true && break - done + Java) + setup_mobile_java "$local_flag" "$parallels_per_platform" "$MOBILE_LOG_FILE" + if (grep -qiE "BUILD FAILURE" "$MOBILE_LOG_FILE"); then + success=false + fi + ;; + Python) + setup_mobile_python "$local_flag" "$parallels_per_platform" "$MOBILE_LOG_FILE" + if (grep -qiE "BUILD FAILURE" "$MOBILE_LOG_FILE"); then ## needs to change based on pytest output + success=false + fi + ;; + - for pattern in "${MOBILE_SETUP_ERRORS[@]}"; do - grep -qiE "$pattern" <<< "$LOG_CONTENT" && SETUP_FAILURE=true && break - done + NodeJS) setup_mobile_nodejs "$local_flag" "$parallels_per_platform" "$MOBILE_LOG_FILE" + if (grep -qiE "([1-9][0-9]*) passed, ([1-9]*) failed" "$MOBILE_LOG_FILE"); then + success=false + fi + ;; - # 4. !!FIX!! Only check for success IF no failures were found - if [ "$LOCAL_FAILURE" = false ] && [ "$SETUP_FAILURE" = false ]; then - if grep -qiE "https://[a-zA-Z0-9./?=_-]*browserstack\.com/[a-zA-Z0-9./?=_-]*" <<< "$LOG_CONTENT"; then - success=true - fi - fi + *) log_msg_to "Unknown TECH_STACK: $TECH_STACK" "$MOBILE_LOG_FILE"; return 1 ;; + esac - # 5. !!FIX!! Re-ordered logic block to prioritize failures - if [ "$LOCAL_FAILURE" = true ] && [ "$attempt" -eq 1 ]; then - local_flag=false - attempt=$((attempt + 1)) - log_msg_to "⚠️ Mobile test failed due to Local tunnel error. Retrying..." "$MOBILE_LOG_FILE" - # (Note: 'continue' is implied here as we don't 'break') - elif [ "$SETUP_FAILURE" = true ]; then - log_msg_to "❌ Mobile test failed due to setup error. Check logs at: $log_file" "$MOBILE_LOG_FILE" - break - elif [ "$success" = true ]; then - log_msg_to "✅ Mobile setup succeeded" "$MOBILE_LOG_FILE" + if [ "$success" = true ]; then + log_msg_to "✅ Mobile setup succeeded." "$MOBILE_LOG_FILE" break else - log_msg_to "❌ Mobile setup ended without success; check $MOBILE_LOG_FILE for details" "$MOBILE_LOG_FILE" + log_msg_to "❌ Mobile setup failed. Check $MOBILE_LOG_FILE for details" "$MOBILE_LOG_FILE" break fi done @@ -1224,21 +1193,21 @@ setup_mobile() { # ===== Orchestration: decide what to run based on TEST_TYPE and plan fetch ===== run_setup() { - log_msg_to "Orchestration: TEST_TYPE=$TEST_TYPE, WEB_PLAN_FETCHED=$WEB_PLAN_FETCHED, MOBILE_PLAN_FETCHED=$MOBILE_PLAN_FETCHED" "$GLOBAL" + log_msg_to "Orchestration: TEST_TYPE=$TEST_TYPE, WEB_PLAN_FETCHED=$WEB_PLAN_FETCHED, MOBILE_PLAN_FETCHED=$MOBILE_PLAN_FETCHED" "$GLOBAL_LOG_FILE" case "$TEST_TYPE" in Web) if [ "$WEB_PLAN_FETCHED" == true ]; then setup_web else - log_msg_to "⚠️ Skipping Web setup — Web plan not fetched" "$GLOBAL" + log_msg_to "⚠️ Skipping Web setup — Web plan not fetched" "$GLOBAL_LOG_FILE" fi ;; App) if [ "$MOBILE_PLAN_FETCHED" == true ]; then setup_mobile else - log_msg_to "⚠️ Skipping Mobile setup — Mobile plan not fetched" "$GLOBAL" + log_msg_to "⚠️ Skipping Mobile setup — Mobile plan not fetched" "$GLOBAL_LOG_FILE" fi ;; Both) @@ -1247,21 +1216,21 @@ run_setup() { setup_web ran_any=true else - log_msg_to "⚠️ Skipping Web setup — Web plan not fetched" "$GLOBAL" + log_msg_to "⚠️ Skipping Web setup — Web plan not fetched" "$GLOBAL_LOG_FILE" fi if [ "$MOBILE_PLAN_FETCHED" == true ]; then setup_mobile ran_any=true else - log_msg_to "⚠️ Skipping Mobile setup — Mobile plan not fetched" "$GLOBAL" + log_msg_to "⚠️ Skipping Mobile setup — Mobile plan not fetched" "$GLOBAL_LOG_FILE" fi if [ "$ran_any" == false ]; then - log_msg_to "❌ Both Web and Mobile setup were skipped. Exiting." "$GLOBAL" + log_msg_to "❌ Both Web and Mobile setup were skipped. Exiting." "$GLOBAL_LOG_FILE" exit 1 fi ;; *) - log_msg_to "❌ Invalid TEST_TYPE: $TEST_TYPE" "$GLOBAL" + log_msg_to "❌ Invalid TEST_TYPE: $TEST_TYPE" "$GLOBAL_LOG_FILE" exit 1 ;; esac @@ -1273,15 +1242,12 @@ ask_browserstack_credentials ask_test_type ask_tech_stack validate_tech_stack_installed -# ask_user_for_test_url fetch_plan_details -# Plan summary in pre-run log -# log_msg_to "Plan summary: WEB_PLAN_FETCHED=$WEB_PLAN_FETCHED (team max=$TEAM_PARALLELS_MAX_ALLOWED_WEB), MOBILE_PLAN_FETCHED=$MOBILE_PLAN_FETCHED (team max=$TEAM_PARALLELS_MAX_ALLOWED_MOBILE)" "$GLOBAL" -log_msg_to "Plan summary: WEB_PLAN_FETCHED=$WEB_PLAN_FETCHED (team max=$TEAM_PARALLELS_MAX_ALLOWED_WEB), MOBILE_PLAN_FETCHED=$MOBILE_PLAN_FETCHED (team max=$TEAM_PARALLELS_MAX_ALLOWED_MOBILE)" "$GLOBAL" -log_msg_to "Checking proxy in environment" "$GLOBAL" -chmod +x proxy-check.sh -./proxy-check.sh -log_msg_to "Starting setup run..." "$GLOBAL" +log_msg_to "Plan summary: WEB_PLAN_FETCHED=$WEB_PLAN_FETCHED (team max=$TEAM_PARALLELS_MAX_ALLOWED_WEB), MOBILE_PLAN_FETCHED=$MOBILE_PLAN_FETCHED (team max=$TEAM_PARALLELS_MAX_ALLOWED_MOBILE)" "$GLOBAL_LOG_FILE" +log_msg_to "Checking proxy in environment" "$GLOBAL_LOG_FILE" +chmod +x ./mac/proxy-check.sh +./mac/proxy-check.sh +log_msg_to "Starting setup run..." "$GLOBAL_LOG_FILE" run_setup -log_msg_to "Setup run finished." "$GLOBAL" \ No newline at end of file +log_msg_to "Setup run finished." "$GLOBAL_LOG_FILE"