Initial commit
This commit is contained in:
235
skills/cli-testing-patterns/scripts/setup-jest-testing.sh
Executable file
235
skills/cli-testing-patterns/scripts/setup-jest-testing.sh
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user