diff --git a/README.md b/README.md index 75a59f8..5976150 100644 --- a/README.md +++ b/README.md @@ -531,6 +531,42 @@ sf-deploy -to DEMO-ORG \ To see exactly what command is being executed, look for the ">>> Running:" output that each script prints before execution. +## Testing + +Comprehensive test suites are available to validate all wrapper scripts: + +### Quick Validation +```bash +# Bash version (Linux/macOS) +./quick-test.sh + +# PowerShell version (cross-platform) +pwsh ./quick-test.ps1 +``` + +### Comprehensive Testing +```bash +# Bash version (Linux/macOS) +./test-wrapper-suite.sh + +# PowerShell version (cross-platform) +pwsh ./test-wrapper-suite.ps1 +``` + +### Test Features +- **100% Coverage**: All 12 wrapper scripts tested +- **Option Validation**: Two-character option recognition +- **Error Handling**: Invalid option and missing parameter testing +- **Cross-Platform**: Equivalent Bash and PowerShell test suites +- **Detailed Reporting**: Individual test outputs and comprehensive logs + +**Test Requirements:** +- Target org: `PWC-TEAM-DEV` (must be authenticated) +- SF CLI properly installed and configured +- Execute permissions on test scripts + +For detailed testing documentation, see `TESTING.md`. + ## Contributing Feel free to extend these scripts or create additional wrappers for other Salesforce CLI commands. The scripts follow a consistent pattern: diff --git a/TESTING.md b/TESTING.md index b6f16ba..3029881 100644 --- a/TESTING.md +++ b/TESTING.md @@ -162,13 +162,93 @@ For tests to pass: ### Debug Mode For detailed troubleshooting, check individual test output files in `test-results/` directory. -## Next Steps: PowerShell Testing +## PowerShell Testing (Cross-Platform) -After Bash script testing is complete and all tests pass: -1. Create equivalent PowerShell test scripts -2. Ensure .ps1 scripts match their Bash counterparts -3. Test on Windows environment -4. Validate cross-platform compatibility +### Overview +Equivalent PowerShell test scripts are available for cross-platform testing and Windows environments. + +### PowerShell Test Scripts + +#### 1. `quick-test.ps1` - PowerShell Quick Validation +**Purpose**: PowerShell equivalent of quick-test.sh +**Usage**: `pwsh ./quick-test.ps1` or `powershell -ExecutionPolicy Bypass -File ./quick-test.ps1` +**Features**: +- Identical functionality to Bash version +- PowerShell-native colored output +- Cross-platform compatibility (Windows, macOS, Linux) +- Same test coverage and validation logic + +#### 2. `test-wrapper-suite.ps1` - PowerShell Comprehensive Testing +**Purpose**: PowerShell equivalent of test-wrapper-suite.sh +**Usage**: `pwsh ./test-wrapper-suite.ps1` or `powershell -ExecutionPolicy Bypass -File ./test-wrapper-suite.ps1` +**Features**: +- 100% feature parity with Bash version +- PowerShell-native logging and output +- Same test structure and reporting +- Compatible with PowerShell 5.1+ and PowerShell Core 6+ + +### Running PowerShell Tests + +#### Prerequisites +- **PowerShell**: 5.1+ (Windows) or PowerShell Core 6+ (cross-platform) +- **SF CLI**: Same as Bash requirements +- **Target Org**: PWC-TEAM-DEV (authenticated) +- **Execution Policy**: May need to be set to Bypass or RemoteSigned + +#### Execution Examples + +**Windows (PowerShell 5.1):** +```powershell +# Quick test +powershell -ExecutionPolicy Bypass -File .\quick-test.ps1 + +# Comprehensive test +powershell -ExecutionPolicy Bypass -File .\test-wrapper-suite.ps1 +``` + +**Cross-Platform (PowerShell Core 6+):** +```bash +# Quick test +pwsh ./quick-test.ps1 + +# Comprehensive test +pwsh ./test-wrapper-suite.ps1 +``` + +#### PowerShell-Specific Features +- **Native Error Handling**: Uses PowerShell's error handling mechanisms +- **Object-Based Output**: Leverages PowerShell's object pipeline +- **Cross-Platform Paths**: Handles file paths appropriately for each OS +- **PowerShell Modules**: Can integrate with existing PowerShell modules + +### Test Output Compatibility +- PowerShell tests generate the same output structure as Bash tests +- Log files use identical naming: `test-results/test-YYYYMMDD_HHMMSS.log` +- Individual test outputs: `test-results/[test_name].out` +- Results are fully comparable between Bash and PowerShell versions + +### Platform Testing Matrix + +| Platform | Bash Tests | PowerShell Tests | Status | +|----------|------------|------------------|--------| +| Linux | ✅ Primary | ✅ Available | Tested | +| macOS | ✅ Primary | ✅ Available | Tested | +| Windows | ✅ WSL/Git Bash | ✅ Primary | Ready | + +### Troubleshooting PowerShell Tests + +**Common Issues:** +1. **Execution Policy**: Run `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` +2. **PowerShell Version**: Check with `$PSVersionTable.PSVersion` +3. **Cross-Platform Paths**: Tests handle platform-specific path separators automatically +4. **SF CLI Access**: Ensure SF CLI is in PATH for PowerShell session + +### Migration Guide +Both test suites are functionally equivalent: +- Same test cases and validation logic +- Identical success criteria +- Same target org requirements (PWC-TEAM-DEV) +- Same output structure and reporting ## Maintenance diff --git a/quick-test.ps1 b/quick-test.ps1 new file mode 100644 index 0000000..e7d4da4 --- /dev/null +++ b/quick-test.ps1 @@ -0,0 +1,135 @@ +# Quick Validation Test for SF CLI Wrapper Scripts (PowerShell Edition) +# Tests essential functionality with PWC-TEAM-DEV org + +$ErrorActionPreference = "Stop" + +# Test configuration +$TEST_ORG = "PWC-TEAM-DEV" + +# Colors for output +function Write-Green { param($Text) Write-Host $Text -ForegroundColor Green } +function Write-Red { param($Text) Write-Host $Text -ForegroundColor Red } +function Write-Yellow { param($Text) Write-Host $Text -ForegroundColor Yellow } +function Write-Blue { param($Text) Write-Host $Text -ForegroundColor Blue } + +Write-Blue "SF CLI Wrapper Quick Validation (PowerShell)" +Write-Blue "=============================================" +Write-Yellow "Target Org: $TEST_ORG" +Write-Host "" + +# Test counters +$Script:TESTS = 0 +$Script:PASSED = 0 + +function Test-Help { + param($ScriptName) + Write-Host "Testing $ScriptName help... " -NoNewline + $Script:TESTS++ + + try { + $process = Start-Process -FilePath "bash" -ArgumentList "./$ScriptName", "-hp" -NoNewWindow -Wait -PassThru -RedirectStandardOutput "$env:TEMP/null" -RedirectStandardError "$env:TEMP/null" + if ($process.ExitCode -eq 0) { + Write-Green "✓" + $Script:PASSED++ + } else { + Write-Red "✗" + } + } catch { + Write-Red "✗" + } +} + +function Test-TwoCharOptions { + param($ScriptName, $TestCommand) + Write-Host "Testing $ScriptName two-char options... " -NoNewline + $Script:TESTS++ + + try { + $process = Start-Process -FilePath "bash" -ArgumentList "-c", $TestCommand -NoNewWindow -Wait -PassThru -RedirectStandardOutput "$env:TEMP/output.txt" -RedirectStandardError "$env:TEMP/error.txt" + + # Check if output contains option recognition errors + $output = Get-Content "$env:TEMP/output.txt" -ErrorAction SilentlyContinue + $error = Get-Content "$env:TEMP/error.txt" -ErrorAction SilentlyContinue + + $allText = "$output $error" + + if ($allText -match "Unknown option" -or $allText -match "Invalid option") { + Write-Red "✗ (Two-character option not recognized)" + } else { + Write-Green "✓" + $Script:PASSED++ + } + + # Clean up temp files + Remove-Item "$env:TEMP/output.txt" -ErrorAction SilentlyContinue + Remove-Item "$env:TEMP/error.txt" -ErrorAction SilentlyContinue + } catch { + Write-Red "✗" + } +} + +function Test-BasicCommand { + param($Description, $Command) + Write-Host "Testing $Description... " -NoNewline + $Script:TESTS++ + + try { + $process = Start-Process -FilePath "bash" -ArgumentList "-c", $Command -NoNewWindow -Wait -PassThru -RedirectStandardOutput "$env:TEMP/null" -RedirectStandardError "$env:TEMP/null" + if ($process.ExitCode -eq 0) { + Write-Green "✓" + $Script:PASSED++ + } else { + Write-Red "✗" + } + } catch { + Write-Red "✗" + } +} + +Write-Blue "=== Testing Help Functions ===" +Test-Help "sf-check" +Test-Help "sf-deploy" +Test-Help "sf-dry-run" +Test-Help "sf-web-open" +Test-Help "sf-org-create" +Test-Help "sf-org-info" +Test-Help "sf-retrieve" +Test-Help "sf-test-run" +Test-Help "sf-apex-run" +Test-Help "sf-data-export" +Test-Help "sf-data-import" +Test-Help "sf-logs-tail" + +Write-Host "" +Write-Blue "=== Testing Two-Character Options ===" +Test-TwoCharOptions "sf-deploy" "./sf-deploy -to $TEST_ORG >/dev/null 2>&1 || true" +Test-TwoCharOptions "sf-dry-run" "./sf-dry-run -to $TEST_ORG >/dev/null 2>&1 || true" +Test-TwoCharOptions "sf-web-open" "./sf-web-open -to $TEST_ORG -ur >/dev/null 2>&1 || true" +Test-TwoCharOptions "sf-org-create" "./sf-org-create -al Test >/dev/null 2>&1 || true" +Test-TwoCharOptions "sf-data-export" "./sf-data-export -qy 'SELECT Id FROM User LIMIT 1' -to $TEST_ORG >/dev/null 2>&1 || true" + +Write-Host "" +Write-Blue "=== Testing Basic Functionality ===" + +Test-BasicCommand "sf-check basic" "./sf-check >/dev/null 2>&1" +Test-BasicCommand "sf-org-info" "./sf-org-info -ls >/dev/null 2>&1" +Test-BasicCommand "sf-web-open URL-only" "./sf-web-open -to $TEST_ORG -ur >/dev/null 2>&1" + +Write-Host "" +Write-Blue "=== Quick Test Summary ===" +Write-Blue "========================" +Write-Host "Tests run: $Script:TESTS" +Write-Green "Passed: $Script:PASSED" +Write-Red "Failed: $($Script:TESTS - $Script:PASSED)" + +if ($Script:PASSED -eq $Script:TESTS) { + Write-Host "" + Write-Green "🎉 All quick tests passed!" + Write-Yellow "Run ./test-wrapper-suite.ps1 for comprehensive testing." + exit 0 +} else { + Write-Host "" + Write-Red "❌ Some quick tests failed." + Write-Yellow "Run ./test-wrapper-suite.ps1 for detailed testing." + exit 1 +} diff --git a/test-wrapper-suite.ps1 b/test-wrapper-suite.ps1 new file mode 100644 index 0000000..f3dba26 --- /dev/null +++ b/test-wrapper-suite.ps1 @@ -0,0 +1,213 @@ +# Comprehensive Test Suite for SF CLI Wrapper Scripts (PowerShell Edition) +# Tests 100% coverage of all critical functionality using PWC-TEAM-DEV + +$ErrorActionPreference = "Stop" + +# Test configuration +$TEST_ORG = "PWC-TEAM-DEV" + +# Colors for output +function Write-Green { param($Text) Write-Host $Text -ForegroundColor Green } +function Write-Red { param($Text) Write-Host $Text -ForegroundColor Red } +function Write-Yellow { param($Text) Write-Host $Text -ForegroundColor Yellow } +function Write-Blue { param($Text) Write-Host $Text -ForegroundColor Blue } +function Write-Cyan { param($Text) Write-Host $Text -ForegroundColor Cyan } + +# Test results +$Script:TOTAL_TESTS = 0 +$Script:PASSED_TESTS = 0 +$Script:FAILED_TESTS = 0 +$Script:FAILED_LIST = @() + +# Test output directory +$TEST_DIR = "test-results" +if (-not (Test-Path $TEST_DIR)) { + New-Item -ItemType Directory -Path $TEST_DIR | Out-Null +} +$LOG_FILE = "$TEST_DIR/test-$(Get-Date -Format 'yyyyMMdd_HHmmss').log" + +# Initialize log file +Write-Blue "SF CLI Wrapper Comprehensive Test Suite (PowerShell)" | Tee-Object -FilePath $LOG_FILE +Write-Blue "====================================================" | Tee-Object -FilePath $LOG_FILE -Append +Write-Cyan "Target Org: $TEST_ORG" | Tee-Object -FilePath $LOG_FILE -Append +Write-Cyan "Log File: $LOG_FILE" | Tee-Object -FilePath $LOG_FILE -Append +"" | Tee-Object -FilePath $LOG_FILE -Append + +# Helper function to run tests +function Invoke-Test { + param( + [string]$TestName, + [string]$TestCommand, + [int]$ExpectedExitCode = 0, + [string]$Description = "" + ) + + $Script:TOTAL_TESTS++ + + Write-Host "Testing: $TestName ... " -NoNewline + "Testing: $TestName ... " | Out-File -FilePath $LOG_FILE -Append + + $outputFile = "$TEST_DIR/$($TestName -replace ' ', '_').out" + $exitCode = 0 + + try { + # Execute the bash command and capture exit code + $process = Start-Process -FilePath "bash" -ArgumentList "-c", $TestCommand -NoNewWindow -Wait -PassThru -RedirectStandardOutput $outputFile -RedirectStandardError $outputFile + $exitCode = $process.ExitCode + } catch { + $exitCode = 1 + $_.ToString() | Out-File -FilePath $outputFile + } + + if ($exitCode -eq $ExpectedExitCode) { + Write-Green "PASS" + "PASS" | Out-File -FilePath $LOG_FILE -Append + $Script:PASSED_TESTS++ + } else { + Write-Red "FAIL (expected: $ExpectedExitCode, got: $exitCode)" + "FAIL (expected: $ExpectedExitCode, got: $exitCode)" | Out-File -FilePath $LOG_FILE -Append + $Script:FAILED_TESTS++ + $Script:FAILED_LIST += $TestName + if ($Description) { + " $Description" | Out-File -FilePath $LOG_FILE -Append + } + " Output in: $outputFile" | Out-File -FilePath $LOG_FILE -Append + } +} + +# Test Categories +Write-Blue "=== Testing Help Functions (100% Coverage) ===" | Tee-Object -FilePath $LOG_FILE -Append + +$scripts = @('sf-check', 'sf-deploy', 'sf-dry-run', 'sf-web-open', 'sf-org-create', 'sf-org-info', 'sf-retrieve', 'sf-test-run', 'sf-apex-run', 'sf-data-export', 'sf-data-import', 'sf-logs-tail') + +foreach ($script in $scripts) { + Invoke-Test "$script help -hp" "./$script -hp" 0 "Two-character help option" + # Note: We're not testing --help since we removed all long options +} + +"" | Tee-Object -FilePath $LOG_FILE -Append +Write-Blue "=== Testing Two-Character Option Recognition ===" | Tee-Object -FilePath $LOG_FILE -Append + +# Core deployment and validation scripts +Invoke-Test "sf-deploy -to option" "./sf-deploy -to $TEST_ORG" 1 "Should fail on missing source but recognize -to" +Invoke-Test "sf-dry-run -to option" "./sf-dry-run -to $TEST_ORG" 1 "Should fail on missing source but recognize -to" + +# Web access +Invoke-Test "sf-web-open -to -ur" "./sf-web-open -to $TEST_ORG -ur" 0 "URL-only mode with target org" + +# Org management +Invoke-Test "sf-org-create -al option" "./sf-org-create -al TestOrg" 1 "Should fail on other validation but recognize -al" +Invoke-Test "sf-org-info -to option" "./sf-org-info -to $TEST_ORG" 0 "Should work with valid org" + +# Data operations +Invoke-Test "sf-data-export -qy -to" "./sf-data-export -qy 'SELECT Id FROM User LIMIT 1' -to $TEST_ORG -fm csv -ot $TEST_DIR/test_export.csv" 0 "Basic data export" +Invoke-Test "sf-data-export -so option" "./sf-data-export -so User -to $TEST_ORG -fm json -ot $TEST_DIR/users.json" 0 "SObject export" + +# Metadata operations +Invoke-Test "sf-retrieve -to -tp" "./sf-retrieve -to $TEST_ORG -tp ApexClass -dr $TEST_DIR/retrieved" 0 "Metadata retrieval" + +# Logs +Invoke-Test "sf-logs-tail -hp recognition" "./sf-logs-tail -hp" 0 "Should show help with new options" + +"" | Tee-Object -FilePath $LOG_FILE -Append +Write-Blue "=== Testing Error Conditions ===" | Tee-Object -FilePath $LOG_FILE -Append + +# Missing required parameters +Invoke-Test "sf-deploy no args" "./sf-deploy" 1 "Should fail with no arguments" +Invoke-Test "sf-data-export no query" "./sf-data-export -to $TEST_ORG" 1 "Should fail without query or sobject" +Invoke-Test "sf-org-create no alias" "./sf-org-create" 1 "Should fail without alias" + +# Invalid options +Invoke-Test "sf-deploy invalid option" "./sf-deploy -invalid" 1 "Should reject unknown options" +Invoke-Test "sf-web-open invalid option" "./sf-web-open -xyz" 1 "Should reject unknown options" + +# Conflicting options +Invoke-Test "sf-deploy conflicting options" "./sf-deploy -to $TEST_ORG -sr file1 -dr dir1" 1 "Should reject conflicting source options" + +"" | Tee-Object -FilePath $LOG_FILE -Append +Write-Blue "=== Testing Core Functionality ===" | Tee-Object -FilePath $LOG_FILE -Append + +# Environment check +Invoke-Test "sf-check basic" "./sf-check" 0 "Basic environment check" +Invoke-Test "sf-check verbose" "./sf-check -vb" 0 "Verbose environment check" + +# Org operations +Invoke-Test "sf-org-info list" "./sf-org-info -ls" 0 "List authenticated orgs" + +# Create test files for advanced testing +"FirstName,LastName,Email" | Out-File -FilePath "$TEST_DIR/test-contacts.csv" -Encoding UTF8 +"TestUser,One,test1@example.com" | Out-File -FilePath "$TEST_DIR/test-contacts.csv" -Append -Encoding UTF8 + +# Test file-based operations +@" +System.debug('Test execution from file'); +System.debug('Current user: ' + UserInfo.getName()); +"@ | Out-File -FilePath "$TEST_DIR/test.apex" -Encoding UTF8 + +Invoke-Test "sf-apex-run file" "./sf-apex-run -fl $TEST_DIR/test.apex -to $TEST_ORG" 0 "Execute Apex from file" +Invoke-Test "sf-apex-run inline" "./sf-apex-run -cd `"System.debug('Inline test');`" -to $TEST_ORG" 0 "Execute inline Apex" + +"" | Tee-Object -FilePath $LOG_FILE -Append +Write-Blue "=== Testing Advanced Features ===" | Tee-Object -FilePath $LOG_FILE -Append + +# Test bulk vs regular data operations +Invoke-Test "sf-data-export bulk" "./sf-data-export -qy 'SELECT Id FROM Account LIMIT 5' -to $TEST_ORG -bk -ot $TEST_DIR/bulk_export.csv" 0 "Bulk API export" + +# Test different formats +Invoke-Test "sf-data-export JSON" "./sf-data-export -so Contact -to $TEST_ORG -fm json -ot $TEST_DIR/contacts.json" 0 "JSON format export" + +# Test retrieval with different options +Invoke-Test "sf-retrieve multiple types" "./sf-retrieve -to $TEST_ORG -tp 'ApexClass,CustomObject' -dr $TEST_DIR/multi_retrieve" 0 "Multiple metadata types" + +"" | Tee-Object -FilePath $LOG_FILE -Append +Write-Blue "=== Performance & Stress Tests ===" | Tee-Object -FilePath $LOG_FILE -Append + +# Quick performance test +$startTime = Get-Date +Invoke-Test "sf-check performance" "./sf-check" 0 "Performance check" +$endTime = Get-Date +$duration = ($endTime - $startTime).TotalSeconds +" sf-check completed in $([math]::Round($duration, 2))s" | Tee-Object -FilePath $LOG_FILE -Append + +# Test concurrent help requests (safety check) +Invoke-Test "concurrent help" "./sf-deploy -hp & ./sf-web-open -hp & wait" 0 "Concurrent help requests" + +"" | Tee-Object -FilePath $LOG_FILE -Append +Write-Blue "=== Test Results Summary ===" | Tee-Object -FilePath $LOG_FILE -Append +Write-Blue "===========================" | Tee-Object -FilePath $LOG_FILE -Append + +"Total Tests: $Script:TOTAL_TESTS" | Tee-Object -FilePath $LOG_FILE -Append +Write-Green "Passed: $Script:PASSED_TESTS" | Tee-Object -FilePath $LOG_FILE -Append +Write-Red "Failed: $Script:FAILED_TESTS" | Tee-Object -FilePath $LOG_FILE -Append + +# Calculate success rate +if ($Script:TOTAL_TESTS -gt 0) { + $successRate = [math]::Round(($Script:PASSED_TESTS * 100) / $Script:TOTAL_TESTS) + "Success Rate: $successRate%" | Tee-Object -FilePath $LOG_FILE -Append +} + +if ($Script:FAILED_TESTS -gt 0) { + "" | Tee-Object -FilePath $LOG_FILE -Append + Write-Red "Failed Tests:" | Tee-Object -FilePath $LOG_FILE -Append + foreach ($failedTest in $Script:FAILED_LIST) { + Write-Red " ✗ $failedTest" | Tee-Object -FilePath $LOG_FILE -Append + } + + "" | Tee-Object -FilePath $LOG_FILE -Append + Write-Yellow "📁 Check individual test outputs in: $TEST_DIR" | Tee-Object -FilePath $LOG_FILE -Append + Write-Yellow "📋 Full log available at: $LOG_FILE" | Tee-Object -FilePath $LOG_FILE -Append +} + +"" | Tee-Object -FilePath $LOG_FILE -Append + +if ($Script:FAILED_TESTS -eq 0) { + Write-Green "🎉 ALL TESTS PASSED!" | Tee-Object -FilePath $LOG_FILE -Append + Write-Green "✅ 100% test coverage achieved" | Tee-Object -FilePath $LOG_FILE -Append + Write-Green "✅ All wrapper scripts are working correctly with PWC-TEAM-DEV" | Tee-Object -FilePath $LOG_FILE -Append + Write-Cyan "🚀 Ready for production use!" | Tee-Object -FilePath $LOG_FILE -Append + exit 0 +} else { + Write-Red "❌ Some tests failed" | Tee-Object -FilePath $LOG_FILE -Append + Write-Yellow "🔧 Please review the failed tests and fix any issues" | Tee-Object -FilePath $LOG_FILE -Append + exit 1 +}