Files
2025-11-30 09:04:14 +08:00

236 lines
5.6 KiB
Bash
Executable File

#!/bin/bash
#
# Setup Jest for CLI Testing (Node.js/TypeScript)
#
# This script installs and configures Jest for testing CLI applications
# Includes TypeScript support, coverage reporting, and CLI testing utilities
set -e
echo "🔧 Setting up Jest for CLI testing..."
# Check if npm is available
if ! command -v npm &> /dev/null; then
echo "❌ Error: npm is not installed"
exit 1
fi
# Install Jest and related dependencies
echo "📦 Installing Jest and dependencies..."
npm install --save-dev \
jest \
@types/jest \
ts-jest \
@types/node
# Create Jest configuration
echo "⚙️ Creating Jest configuration..."
cat > jest.config.js << 'EOF'
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/tests'],
testMatch: [
'**/__tests__/**/*.ts',
'**/?(*.)+(spec|test).ts'
],
collectCoverageFrom: [
'src/**/*.{ts,js}',
'!src/**/*.d.ts',
'!src/**/*.test.ts',
'!src/**/__tests__/**'
],
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov', 'html'],
coverageThresholds: {
global: {
branches: 70,
functions: 70,
lines: 70,
statements: 70
}
},
verbose: true,
testTimeout: 10000
};
EOF
# Create tests directory structure
echo "📁 Creating test directory structure..."
mkdir -p tests/{unit,integration,helpers}
# Create test helper file
echo "📝 Creating test helpers..."
cat > tests/helpers/cli-helpers.ts << 'EOF'
import { execSync } from 'child_process';
import path from 'path';
export interface CLIResult {
stdout: string;
stderr: string;
code: number;
}
export const CLI_PATH = path.join(__dirname, '../../bin/cli');
export function runCLI(args: string): CLIResult {
try {
const stdout = execSync(`${CLI_PATH} ${args}`, {
encoding: 'utf8',
stdio: 'pipe',
});
return { stdout, stderr: '', code: 0 };
} catch (error: any) {
return {
stdout: error.stdout || '',
stderr: error.stderr || '',
code: error.status || 1,
};
}
}
EOF
# Create sample test file
echo "📝 Creating sample test file..."
cat > tests/unit/cli.test.ts << 'EOF'
import { runCLI } from '../helpers/cli-helpers';
describe('CLI Tests', () => {
test('should display version', () => {
const { stdout, code } = runCLI('--version');
expect(code).toBe(0);
expect(stdout).toMatch(/\d+\.\d+\.\d+/);
});
test('should display help', () => {
const { stdout, code } = runCLI('--help');
expect(code).toBe(0);
expect(stdout).toContain('Usage:');
});
});
EOF
# Create TypeScript configuration for tests
echo "⚙️ Creating TypeScript configuration..."
if [ ! -f tsconfig.json ]; then
cat > tsconfig.json << 'EOF'
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "tests"]
}
EOF
fi
# Update package.json scripts
echo "⚙️ Updating package.json scripts..."
if [ -f package.json ]; then
# Check if jq is available for JSON manipulation
if command -v jq &> /dev/null; then
# Add test scripts using jq
tmp=$(mktemp)
jq '.scripts.test = "jest" |
.scripts["test:watch"] = "jest --watch" |
.scripts["test:coverage"] = "jest --coverage" |
.scripts["test:ci"] = "jest --ci --coverage --maxWorkers=2"' \
package.json > "$tmp"
mv "$tmp" package.json
else
echo "⚠️ jq not found. Please manually add test scripts to package.json:"
echo ' "test": "jest"'
echo ' "test:watch": "jest --watch"'
echo ' "test:coverage": "jest --coverage"'
echo ' "test:ci": "jest --ci --coverage --maxWorkers=2"'
fi
fi
# Create .gitignore entries
echo "📝 Updating .gitignore..."
if [ -f .gitignore ]; then
grep -qxF 'coverage/' .gitignore || echo 'coverage/' >> .gitignore
grep -qxF '*.log' .gitignore || echo '*.log' >> .gitignore
else
cat > .gitignore << 'EOF'
node_modules/
dist/
coverage/
*.log
.env
.env.local
EOF
fi
# Create README for tests
echo "📝 Creating test documentation..."
cat > tests/README.md << 'EOF'
# CLI Tests
## Running Tests
```bash
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Run tests in CI mode
npm run test:ci
```
## Test Structure
- `unit/` - Unit tests for individual functions
- `integration/` - Integration tests for complete workflows
- `helpers/` - Test helper functions and utilities
## Writing Tests
Use the `runCLI` helper to execute CLI commands:
```typescript
import { runCLI } from '../helpers/cli-helpers';
test('should execute command', () => {
const { stdout, stderr, code } = runCLI('command --flag');
expect(code).toBe(0);
expect(stdout).toContain('expected output');
});
```
## Coverage
Coverage reports are generated in the `coverage/` directory.
Target: 70% coverage for branches, functions, lines, and statements.
EOF
echo "✅ Jest setup complete!"
echo ""
echo "Next steps:"
echo " 1. Run 'npm test' to execute tests"
echo " 2. Add more tests in tests/unit/ and tests/integration/"
echo " 3. Run 'npm run test:coverage' to see coverage report"
echo ""
echo "📚 Test files created:"
echo " - jest.config.js"
echo " - tests/helpers/cli-helpers.ts"
echo " - tests/unit/cli.test.ts"
echo " - tests/README.md"