Browse Source
- Add test scripts for Android and iOS platforms - Create prerequisite checker for mobile development setup - Add device/simulator availability checks - Update test-all command to include mobile tests - Add granular test commands for web and mobile The changes improve testing by: 1. Adding structured mobile test runners 2. Validating development environment setup 3. Separating web and mobile test flows 4. Adding device availability checks 5. Providing detailed test documentation Added scripts: - check-prerequisites.js: Validates dev environment - test-android.js: Runs Android tests - test-ios.js: Runs iOS tests - run-available-mobile-tests.js: Smart platform detectionpull/127/head
5 changed files with 509 additions and 1 deletions
@ -0,0 +1,185 @@ |
|||
/** |
|||
* @fileoverview Prerequisites checker for mobile development environment |
|||
* |
|||
* This script verifies that all necessary tools and configurations are in place |
|||
* for mobile app development, including both Android and iOS platforms. |
|||
* |
|||
* Features: |
|||
* - Validates development environment setup |
|||
* - Checks required command-line tools |
|||
* - Verifies Android SDK and device connectivity |
|||
* - Confirms iOS development tools and simulator status |
|||
* |
|||
* Prerequisites checked: |
|||
* - Node.js and npm installation |
|||
* - Gradle for Android builds |
|||
* - Xcode and command line tools for iOS |
|||
* - ANDROID_HOME environment variable |
|||
* - Android platform files |
|||
* - Connected Android devices/emulators |
|||
* - iOS platform files |
|||
* - Running iOS simulators |
|||
* |
|||
* Exit codes: |
|||
* - 0: All checks passed |
|||
* - 1: One or more checks failed |
|||
* |
|||
* @example |
|||
* // Run directly
|
|||
* node scripts/check-prerequisites.js |
|||
* |
|||
* // Run via npm script
|
|||
* npm run test:prerequisites |
|||
* |
|||
* @author TimeSafari Team |
|||
* @license MIT |
|||
*/ |
|||
|
|||
const { execSync } = require('child_process'); |
|||
const { existsSync } = require('fs'); |
|||
|
|||
/** |
|||
* Checks if a command-line tool is available by attempting to run its --version command |
|||
* |
|||
* @param {string} command - The command to check (e.g., 'node', 'npm', 'gradle') |
|||
* @param {string} errorMessage - The error message to display if the command is not available |
|||
* @returns {boolean} - True if the command exists and is executable, false otherwise |
|||
* |
|||
* @example |
|||
* checkCommand('node', 'Node.js is required') |
|||
* // Returns true if node is available, false otherwise
|
|||
*/ |
|||
function checkCommand(command, errorMessage) { |
|||
try { |
|||
execSync(command + ' --version', { stdio: 'ignore' }); |
|||
return true; |
|||
} catch (e) { |
|||
console.error(`❌ ${errorMessage}`); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Verifies Android development environment setup |
|||
* |
|||
* Checks for: |
|||
* 1. ANDROID_HOME environment variable |
|||
* 2. Android platform files in project |
|||
* 3. Connected Android devices or running emulators |
|||
* |
|||
* @returns {boolean} - True if Android setup is complete and valid, false otherwise |
|||
* |
|||
* @example |
|||
* if (!checkAndroidSetup()) { |
|||
* console.error('Android prerequisites not met'); |
|||
* } |
|||
*/ |
|||
function checkAndroidSetup() { |
|||
// Check ANDROID_HOME environment variable
|
|||
// This is required for Android SDK tools access
|
|||
if (!process.env.ANDROID_HOME) { |
|||
console.error('❌ ANDROID_HOME environment variable not set'); |
|||
return false; |
|||
} |
|||
|
|||
// Check if Android platform was added to the project
|
|||
// The 'android' directory should exist if platform was added via 'npx cap add android'
|
|||
if (!existsSync('android')) { |
|||
console.error('❌ Android platform not added. Run: npx cap add android'); |
|||
return false; |
|||
} |
|||
|
|||
// Check for connected devices or running emulators
|
|||
// Uses ADB (Android Debug Bridge) to list connected devices
|
|||
try { |
|||
const devices = execSync('adb devices').toString(); |
|||
// Parse ADB output - looking for lines ending with 'device' (not 'offline' or 'unauthorized')
|
|||
if (!devices.split('\n').slice(1).some(line => line.includes('device'))) { |
|||
console.error('❌ No Android devices connected'); |
|||
return false; |
|||
} |
|||
} catch (e) { |
|||
console.error('❌ ADB not available'); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* Verifies iOS development environment setup |
|||
* |
|||
* Checks for: |
|||
* 1. iOS platform files in project |
|||
* 2. Running iOS simulators |
|||
* 3. Xcode command line tools availability |
|||
* |
|||
* @returns {boolean} - True if iOS setup is complete and valid, false otherwise |
|||
* |
|||
* @example |
|||
* if (!checkIosSetup()) { |
|||
* console.error('iOS prerequisites not met'); |
|||
* } |
|||
*/ |
|||
function checkIosSetup() { |
|||
// Check if iOS platform was added to the project
|
|||
// The 'ios' directory should exist if platform was added via 'npx cap add ios'
|
|||
if (!existsSync('ios')) { |
|||
console.error('❌ iOS platform not added. Run: npx cap add ios'); |
|||
return false; |
|||
} |
|||
|
|||
// Check for available and running iOS simulators
|
|||
// Uses xcrun simctl to list simulator devices
|
|||
try { |
|||
const simulators = execSync('xcrun simctl list devices available').toString(); |
|||
if (!simulators.includes('Booted')) { |
|||
console.error('❌ No iOS simulator running'); |
|||
return false; |
|||
} |
|||
} catch (e) { |
|||
console.error('❌ Xcode command line tools not available'); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* Main function to check all prerequisites for mobile development |
|||
* |
|||
* Verifies: |
|||
* 1. Required command line tools (node, npm, gradle, xcodebuild) |
|||
* 2. Android development setup |
|||
* 3. iOS development setup |
|||
* |
|||
* Exits with code 1 if any checks fail |
|||
* |
|||
* @example |
|||
* // Run from package.json script:
|
|||
* // "test:prerequisites": "node scripts/check-prerequisites.js"
|
|||
*/ |
|||
function main() { |
|||
let success = true; |
|||
|
|||
// Check required command line tools
|
|||
// These are essential for building and testing the application
|
|||
success &= checkCommand('node', 'Node.js is required'); |
|||
success &= checkCommand('npm', 'npm is required'); |
|||
success &= checkCommand('gradle', 'Gradle is required for Android builds'); |
|||
success &= checkCommand('xcodebuild', 'Xcode is required for iOS builds'); |
|||
|
|||
// Check platform-specific development environments
|
|||
success &= checkAndroidSetup(); |
|||
success &= checkIosSetup(); |
|||
|
|||
// Exit with error if any checks failed
|
|||
if (!success) { |
|||
process.exit(1); |
|||
} |
|||
|
|||
console.log('✅ All prerequisites met!'); |
|||
} |
|||
|
|||
// Execute the checks
|
|||
main(); |
@ -0,0 +1,132 @@ |
|||
/** |
|||
* @fileoverview Runs mobile tests based on available platforms and devices |
|||
* |
|||
* This script intelligently detects available mobile platforms and their |
|||
* associated devices/simulators, then runs tests only for the available |
|||
* configurations. This allows for flexible testing across different |
|||
* development environments without failing when a platform is unavailable. |
|||
* |
|||
* Platform detection: |
|||
* - Android: Checks for SDK and connected devices/emulators |
|||
* - iOS: Checks for macOS, Xcode, and running simulators |
|||
* |
|||
* Features: |
|||
* - Smart platform detection |
|||
* - Graceful handling of unavailable platforms |
|||
* - Clear logging of test execution |
|||
* - Comprehensive error reporting |
|||
* |
|||
* Exit codes: |
|||
* - 0: Tests completed successfully on available platforms |
|||
* - 1: Tests failed or no platforms available |
|||
* |
|||
* @example |
|||
* // Run directly
|
|||
* node scripts/run-available-mobile-tests.js |
|||
* |
|||
* // Run via npm script
|
|||
* npm run test:mobile:available |
|||
* |
|||
* @requires child_process |
|||
* @requires fs |
|||
* |
|||
* @author TimeSafari Team |
|||
* @license MIT |
|||
*/ |
|||
|
|||
const { execSync } = require('child_process'); |
|||
const { existsSync } = require('fs'); |
|||
|
|||
/** |
|||
* Executes mobile tests on available platforms |
|||
* |
|||
* This function performs the following steps: |
|||
* 1. Checks Android environment and device availability |
|||
* 2. Checks iOS environment and simulator availability (on macOS) |
|||
* 3. Runs tests on available platforms |
|||
* 4. Reports results and handles errors |
|||
* |
|||
* Platform-specific checks: |
|||
* Android: |
|||
* - ANDROID_HOME environment variable |
|||
* - Android platform files existence |
|||
* - Connected devices via ADB |
|||
* |
|||
* iOS: |
|||
* - macOS operating system |
|||
* - iOS platform files existence |
|||
* - Running simulators via xcrun |
|||
* |
|||
* @async |
|||
* @throws {Error} If tests fail or no platforms are available |
|||
* |
|||
* @example |
|||
* runAvailableMobileTests().catch(error => { |
|||
* console.error('Test execution failed:', error); |
|||
* process.exit(1); |
|||
* }); |
|||
*/ |
|||
async function runAvailableMobileTests() { |
|||
try { |
|||
// Check Android availability
|
|||
// Requires both SDK (ANDROID_HOME) and platform files
|
|||
const androidAvailable = existsSync('android') && process.env.ANDROID_HOME; |
|||
let androidDeviceAvailable = false; |
|||
|
|||
if (androidAvailable) { |
|||
try { |
|||
// Check for connected devices using ADB
|
|||
const devices = execSync('adb devices').toString(); |
|||
// Parse ADB output for actually connected devices
|
|||
// Filters out unauthorized or offline devices
|
|||
androidDeviceAvailable = devices.split('\n').slice(1).some(line => line.includes('device')); |
|||
} catch (e) { |
|||
console.log('⚠️ Android SDK available but no devices connected'); |
|||
} |
|||
} |
|||
|
|||
// Check iOS availability
|
|||
// Only possible on macOS with Xcode installed
|
|||
const iosAvailable = process.platform === 'darwin' && existsSync('ios'); |
|||
let iosSimulatorAvailable = false; |
|||
|
|||
if (iosAvailable) { |
|||
try { |
|||
// Check for running simulators using xcrun
|
|||
const simulators = execSync('xcrun simctl list devices available').toString(); |
|||
// Look for 'Booted' state in simulator list
|
|||
iosSimulatorAvailable = simulators.includes('Booted'); |
|||
} catch (e) { |
|||
console.log('⚠️ iOS platform available but no simulator running'); |
|||
} |
|||
} |
|||
|
|||
// Execute tests for available platforms
|
|||
if (androidDeviceAvailable) { |
|||
console.log('🤖 Running Android tests...'); |
|||
// Run Android tests via npm script
|
|||
execSync('npm run test:android', { stdio: 'inherit' }); |
|||
} |
|||
|
|||
if (iosSimulatorAvailable) { |
|||
console.log('🍎 Running iOS tests...'); |
|||
// Run iOS tests via npm script
|
|||
execSync('npm run test:ios', { stdio: 'inherit' }); |
|||
} |
|||
|
|||
// Error if no platforms are available for testing
|
|||
if (!androidDeviceAvailable && !iosSimulatorAvailable) { |
|||
console.error('❌ No mobile platforms available for testing'); |
|||
process.exit(1); |
|||
} |
|||
|
|||
console.log('✅ Available mobile tests completed successfully'); |
|||
} catch (error) { |
|||
// Handle any errors during test execution
|
|||
console.error('❌ Mobile tests failed:', error); |
|||
process.exit(1); |
|||
} |
|||
} |
|||
|
|||
// Execute the test runner
|
|||
runAvailableMobileTests(); |
@ -0,0 +1,91 @@ |
|||
/** |
|||
* @fileoverview Android test runner for Capacitor-based mobile app |
|||
* |
|||
* This script handles the build, installation, and testing of the Android app. |
|||
* It ensures the app is properly synced, built, installed on a device/emulator, |
|||
* and runs the test suite. |
|||
* |
|||
* Process flow: |
|||
* 1. Sync Capacitor project with latest web build |
|||
* 2. Build debug APK |
|||
* 3. Install APK on connected device/emulator |
|||
* 4. Run instrumented tests |
|||
* |
|||
* Prerequisites: |
|||
* - Android SDK installed and ANDROID_HOME set |
|||
* - Gradle installed and in PATH |
|||
* - Connected Android device or running emulator |
|||
* - Capacitor Android platform added to project |
|||
* |
|||
* Exit codes: |
|||
* - 0: Tests completed successfully |
|||
* - 1: Build, installation, or test failure |
|||
* |
|||
* @example |
|||
* // Run directly
|
|||
* node scripts/test-android.js |
|||
* |
|||
* // Run via npm script
|
|||
* npm run test:android |
|||
* |
|||
* @requires child_process |
|||
* @requires path |
|||
* |
|||
* @author TimeSafari Team |
|||
* @license MIT |
|||
*/ |
|||
|
|||
const { execSync } = require('child_process'); |
|||
const { join } = require('path'); |
|||
|
|||
/** |
|||
* Runs the complete Android test suite including build, installation, and testing |
|||
* |
|||
* The function performs the following steps: |
|||
* 1. Syncs the Capacitor project with latest web build |
|||
* 2. Builds and installs debug version of the app |
|||
* 3. Runs instrumented Android tests |
|||
* |
|||
* @async |
|||
* @throws {Error} If any step in the build or test process fails |
|||
* |
|||
* @example |
|||
* runAndroidTests().catch(error => { |
|||
* console.error('Test execution failed:', error); |
|||
* process.exit(1); |
|||
* }); |
|||
*/ |
|||
async function runAndroidTests() { |
|||
try { |
|||
// Sync Capacitor project with latest web build
|
|||
// This ensures the Android project has the latest web assets
|
|||
execSync('npx cap sync android', { |
|||
stdio: 'inherit', |
|||
// Inherit stdio to show real-time output
|
|||
}); |
|||
|
|||
// Build and install debug version of the app
|
|||
// Uses Gradle wrapper to ensure consistent build environment
|
|||
execSync('cd android && ./gradlew assembleDebug installDebug', { |
|||
stdio: 'inherit', |
|||
// assembleDebug: Creates debug APK
|
|||
// installDebug: Installs APK on connected device
|
|||
}); |
|||
|
|||
// Run the instrumented Android tests
|
|||
// These are the tests defined in android/app/src/androidTest
|
|||
execSync('cd android && ./gradlew connectedAndroidTest', { |
|||
stdio: 'inherit', |
|||
// connectedAndroidTest: Runs tests on connected device
|
|||
}); |
|||
|
|||
console.log('✅ Android tests completed successfully'); |
|||
} catch (error) { |
|||
// Log the error and exit with failure code
|
|||
console.error('❌ Android tests failed:', error); |
|||
process.exit(1); |
|||
} |
|||
} |
|||
|
|||
// Execute the test suite
|
|||
runAndroidTests(); |
@ -0,0 +1,93 @@ |
|||
/** |
|||
* @fileoverview iOS test runner for Capacitor-based mobile app |
|||
* |
|||
* This script handles the build and testing of the iOS app using Xcode's |
|||
* command-line tools. It ensures the app is properly synced with the latest |
|||
* web build and runs the test suite on a specified iOS simulator. |
|||
* |
|||
* Process flow: |
|||
* 1. Sync Capacitor project with latest web build |
|||
* 2. Build app for iOS simulator |
|||
* 3. Run XCTest suite |
|||
* |
|||
* Prerequisites: |
|||
* - macOS operating system |
|||
* - Xcode installed with command line tools |
|||
* - iOS simulator available |
|||
* - Capacitor iOS platform added to project |
|||
* - Valid iOS development certificates |
|||
* |
|||
* Exit codes: |
|||
* - 0: Tests completed successfully |
|||
* - 1: Build or test failure |
|||
* |
|||
* @example |
|||
* // Run directly
|
|||
* node scripts/test-ios.js |
|||
* |
|||
* // Run via npm script
|
|||
* npm run test:ios |
|||
* |
|||
* @requires child_process |
|||
* @requires path |
|||
* |
|||
* @author TimeSafari Team |
|||
* @license MIT |
|||
*/ |
|||
|
|||
const { execSync } = require('child_process'); |
|||
const { join } = require('path'); |
|||
|
|||
/** |
|||
* Runs the complete iOS test suite including build and testing |
|||
* |
|||
* The function performs the following steps: |
|||
* 1. Syncs the Capacitor project with latest web build |
|||
* 2. Builds and tests the app using xcodebuild |
|||
* |
|||
* Note: This function requires a running iOS simulator. The test will |
|||
* fail if no simulator is available or if it's not in a booted state. |
|||
* |
|||
* @async |
|||
* @throws {Error} If any step in the build or test process fails |
|||
* |
|||
* @example |
|||
* runIosTests().catch(error => { |
|||
* console.error('Test execution failed:', error); |
|||
* process.exit(1); |
|||
* }); |
|||
*/ |
|||
async function runIosTests() { |
|||
try { |
|||
// Sync Capacitor project with latest web build
|
|||
// This ensures the iOS project has the latest web assets
|
|||
execSync('npx cap sync ios', { |
|||
stdio: 'inherit', |
|||
// Inherit stdio to show real-time output
|
|||
}); |
|||
|
|||
// Build and run tests using xcodebuild
|
|||
execSync( |
|||
'cd ios && xcodebuild test ' + |
|||
'-workspace App/App.xcworkspace ' + // Workspace containing the project
|
|||
'-scheme App ' + // The scheme to build and test
|
|||
'-destination "platform=iOS Simulator,name=iPhone 14"', // Target simulator
|
|||
{ |
|||
stdio: 'inherit', |
|||
// test: Builds and runs tests
|
|||
// -workspace: Specifies the Xcode workspace
|
|||
// -scheme: Specifies the scheme to test
|
|||
// -destination: Specifies the target simulator
|
|||
} |
|||
); |
|||
|
|||
console.log('✅ iOS tests completed successfully'); |
|||
} catch (error) { |
|||
// Log the error and exit with failure code
|
|||
console.error('❌ iOS tests failed:', error); |
|||
process.exit(1); |
|||
} |
|||
} |
|||
|
|||
// Execute the test suite
|
|||
runIosTests(); |
Loading…
Reference in new issue