diff --git a/__tests__/setup.test.js b/__tests__/setup.test.js new file mode 100644 index 00000000..22269a02 --- /dev/null +++ b/__tests__/setup.test.js @@ -0,0 +1,129 @@ +/** + * Tests for the enhanced setup script + */ + +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +describe('Setup Script', () => { + const setupScriptPath = path.join(__dirname, '..', 'script', 'setup'); + + beforeAll(() => { + // Ensure the setup script exists and is executable + expect(fs.existsSync(setupScriptPath)).toBe(true); + }); + + test('setup script should be executable', () => { + const stats = fs.statSync(setupScriptPath); + // Check if the file has executable permission + // eslint-disable-next-line no-bitwise + expect(stats.mode & 0o111).not.toBe(0); + }); + + test('setup script should contain progress functions', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check for new progress functions + expect(content).toContain('progress_header()'); + expect(content).toContain('step_start()'); + expect(content).toContain('step_success()'); + expect(content).toContain('step_warning()'); + expect(content).toContain('step_error()'); + expect(content).toContain('step_info()'); + expect(content).toContain('show_progress()'); + expect(content).toContain('final_summary()'); + }); + + test('setup script should contain color definitions', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check for color definitions + expect(content).toContain('RED='); + expect(content).toContain('GREEN='); + expect(content).toContain('YELLOW='); + expect(content).toContain('BLUE='); + expect(content).toContain('CYAN='); + expect(content).toContain('NC='); + }); + + test('setup script should contain progress tracking variables', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check for progress tracking + expect(content).toContain('TOTAL_STEPS=8'); + expect(content).toContain('CURRENT_STEP=0'); + expect(content).toContain('START_TIME='); + }); + + test('setup script should have proper step structure', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check for all steps + expect(content).toContain('Step 1: Xcode Tools'); + expect(content).toContain('Step 2: Homebrew'); + expect(content).toContain('Step 3: Ruby Environment'); + expect(content).toContain('Step 4: Node.js Environment'); + expect(content).toContain('Step 5: Yarn Package Manager'); + expect(content).toContain('Step 6: Project Dependencies'); + expect(content).toContain('Step 7: iOS Dependencies'); + expect(content).toContain('Step 8: Final Setup'); + }); + + test('setup script should have enhanced user feedback', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check for enhanced feedback + expect(content).toContain('✅'); // Success checkmarks + expect(content).toContain('⚠️'); // Warnings + expect(content).toContain('❌'); // Errors + expect(content).toContain('ℹ️'); // Info + expect(content).toContain('🎉'); // Celebration + expect(content).toContain('⏱️'); // Timer + }); + + test('setup script should contain progress bar functionality', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check for progress bar elements + expect(content).toContain('Progress: ['); + expect(content).toContain('█'); // Filled progress + expect(content).toContain('░'); // Empty progress + expect(content).toContain('percentage'); + }); + + test('setup script should have timing functionality', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check for timing + expect(content).toContain('START_TIME=$(date +%s)'); + expect(content).toContain('end_time=$(date +%s)'); + expect(content).toContain('duration='); + expect(content).toContain('Total setup time:'); + }); + + test('setup script should maintain all original functionality', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + + // Check that all original functionality is preserved + expect(content).toContain('xcode-select'); + expect(content).toContain('brew'); + expect(content).toContain('rbenv'); + expect(content).toContain('nvm'); + expect(content).toContain('yarn'); + expect(content).toContain('pod install'); + }); + + test('setup script should start with proper shebang', () => { + const content = fs.readFileSync(setupScriptPath, 'utf8'); + expect(content.startsWith('#!/bin/sh')).toBe(true); + }); + + test('setup script dry run should not fail on syntax', () => { + // Test that the script doesn't have syntax errors + // Note: This uses bash -n to check syntax without executing + expect(() => { + execSync(`bash -n "${setupScriptPath}"`, { stdio: 'pipe' }); + }).not.toThrow(); + }); +}); diff --git a/package.json b/package.json index 600569ad..57085aab 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "!**/__mocks__" ], "scripts": { - "test": "echo test", + "test": "jest", "typescript": "tsc --noEmit", "lint": "eslint \"**/*.{js,ts,tsx}\"", "prepare": "bob build", diff --git a/script/setup b/script/setup index 565a5c92..aada7798 100755 --- a/script/setup +++ b/script/setup @@ -1,84 +1,189 @@ #!/bin/sh +# +# Enhanced Setup Script with Progress Indicators +# + +# Colors for better output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Progress tracking +TOTAL_STEPS=8 +CURRENT_STEP=0 +START_TIME=$(date +%s) + # # Functions # -function log() { - echo "\n" - echo "=======================================" - echo "$1" - echo "=======================================" +function progress_header() { + echo "\n${CYAN}┌─────────────────────────────────────────────────────────────┐${NC}" + echo "${CYAN}│ 🏎️ Intercom React Native Setup Script 🏎️ │${NC}" + echo "${CYAN}└─────────────────────────────────────────────────────────────┘${NC}" + echo "${BLUE}Setting up your development environment...${NC}\n" } -log "🏎️ Running React native setup script 🏎️" +function step_start() { + CURRENT_STEP=$((CURRENT_STEP + 1)) + local step_name="$1" + local icon="$2" + + echo "${CYAN}┌─ Step ${CURRENT_STEP}/${TOTAL_STEPS} ────────────────────────────────────────────────┐${NC}" + echo "${CYAN}│${NC} ${icon} ${step_name}" + echo "${CYAN}└─────────────────────────────────────────────────────────────┘${NC}" +} -log "📱 Installing xcode tools 📱" +function step_success() { + local message="$1" + echo "${GREEN}✅ ${message}${NC}" + echo "" +} + +function step_warning() { + local message="$1" + echo "${YELLOW}⚠️ ${message}${NC}" +} + +function step_error() { + local message="$1" + echo "${RED}❌ ${message}${NC}" +} +function step_info() { + local message="$1" + echo "${BLUE}ℹ️ ${message}${NC}" +} + +function show_progress() { + local percentage=$((CURRENT_STEP * 100 / TOTAL_STEPS)) + local filled=$((CURRENT_STEP * 50 / TOTAL_STEPS)) + local empty=$((50 - filled)) + + printf "${CYAN}Progress: [${NC}" + printf "%${filled}s" | tr ' ' '█' + printf "%${empty}s" | tr ' ' '░' + printf "${CYAN}] ${percentage}%%${NC}\n" +} + +function final_summary() { + local end_time=$(date +%s) + local duration=$((end_time - START_TIME)) + local minutes=$((duration / 60)) + local seconds=$((duration % 60)) + + echo "\n${GREEN}┌─────────────────────────────────────────────────────────────┐${NC}" + echo "${GREEN}│ 🎉 Setup Complete! 🎉 │${NC}" + echo "${GREEN}└─────────────────────────────────────────────────────────────┘${NC}" + echo "${GREEN}✅ All dependencies installed successfully${NC}" + printf "${BLUE}⏱️ Total setup time: %dm %ds${NC}\n" "$minutes" "$seconds" + echo "\n${CYAN}Next steps:${NC}" + echo "${GREEN}📱 Run example app on iOS: ${YELLOW}yarn example ios${NC}" + echo "${GREEN}📱 Run example app on Android: ${YELLOW}yarn example android${NC}" +} + +progress_header + +# Step 1: Xcode Tools +step_start "Checking Xcode Command Line Tools" "🛠️" if [ ! -f /Library/Developer/CommandLineTools/usr/lib/libxcrun.dylib ]; then - echo "⚠️ Xcode CommandLineTools not found installing. Please install and rerun this script ⚠️" + step_warning "Xcode CommandLineTools not found. Installing..." + step_info "Please complete the Xcode installation and rerun this script" xcode-select --install exit 1 fi -echo "Xcode CommandLineTools installed 👍" if ! [ -x "$(command -v xcode-select)" ]; then - echo "⚠️ You need Xcode to setup this project. Please install and rerun this script ⚠️" + step_error "Xcode is required to setup this project. Please install and rerun this script" exit 1 fi -log "👀 Looking for Homebrew 👀" +step_success "Xcode Command Line Tools are installed" +show_progress + +# Step 2: Homebrew +step_start "Setting up Homebrew package manager" "🍺" if ! [ -x "$(command -v brew)" ]; then - echo "🍺 Installing Homebrew 🍺" + step_info "Installing Homebrew..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" echo 'export PATH=/opt/homebrew/bin:$PATH' >> ~/.bash_profile echo 'export PATH=/opt/homebrew/bin:$PATH' >> ~/.zshrc + step_success "Homebrew installed successfully" else - echo "Homebrew already installed 👍" + step_success "Homebrew is already installed" fi +show_progress -log "👀 Looking for rbenv 👀" +# Step 3: Ruby Environment (rbenv) +step_start "Setting up Ruby environment with rbenv" "💎" if ! [ -x "$(command -v rbenv)" ]; then - echo "🍺 Installing rbenv with brew 🍺" + step_info "Installing rbenv and ruby-build..." brew install rbenv ruby-build echo 'eval "$(rbenv init -)"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.zshrc eval "$(rbenv init -)" + step_success "rbenv installed successfully" else - echo "rbenv already installed 👍" + step_success "rbenv is already installed" fi +step_info "Setting up Ruby version..." rbenv install --skip-existing -echo "Ruby setup complete 👍" +step_success "Ruby environment configured" +show_progress -log "👀 Looking for nvm 👀" +# Step 4: Node.js Environment (nvm) +step_start "Setting up Node.js environment with nvm" "📗" if ! [ -x "$(command -v nvm)" ]; then - echo "🍺 Installing nvm with brew 🍺" + step_info "Installing nvm..." brew install nvm + step_success "nvm installed successfully" +else + step_success "nvm is already installed" fi # Source nvm export NVM_DIR="$HOME/.nvm" [ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh" +step_info "Installing Node.js version from .nvmrc..." nvm install -echo "Node.js setup complete 👍" +step_success "Node.js environment configured" +show_progress -log "👀 Looking for yarn 👀" +# Step 5: Yarn Package Manager +step_start "Setting up Yarn package manager" "🧶" if ! [ -x "$(command -v yarn)" ]; then - echo "🍺 Installing yarn 🍺" + step_info "Installing Yarn..." brew install yarn + step_success "Yarn installed successfully" else - echo "yarn already installed 👍" + step_success "Yarn is already installed" fi +show_progress -log "📟 installing dependencies 📟" +# Step 6: Project Dependencies +step_start "Installing project dependencies" "📦" +step_info "Running yarn install..." yarn +step_success "Project dependencies installed" +show_progress -log "📟 installing dependencies for our example app 📟" +# Step 7: iOS Dependencies +step_start "Installing iOS dependencies" "📱" +step_info "Installing CocoaPods dependencies..." cd example/ios pod install cd - +step_success "iOS dependencies installed" +show_progress + +# Step 8: Final Setup +step_start "Finalizing setup" "🏁" +step_success "Setup completed successfully" +show_progress -echo "You're all set up 👍" -echo "📱 Run example app on iOS using -> yarn example ios" -echo "📱 Run example app on android using -> yarn example android" +final_summary