Files
gh-vanman2024-cli-builder-p…/skills/cli-testing-patterns/templates/jest-config-test.ts
2025-11-30 09:04:14 +08:00

199 lines
5.9 KiB
TypeScript

/**
* Jest Configuration Testing Template
*
* Test CLI configuration file handling, validation, and persistence
*/
import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';
import os from 'os';
describe('CLI Configuration Tests', () => {
const CLI_PATH = path.join(__dirname, '../bin/mycli');
const TEST_CONFIG_DIR = path.join(os.tmpdir(), 'cli-test-config');
const TEST_CONFIG_FILE = path.join(TEST_CONFIG_DIR, '.myclirc');
function runCLI(args: string, env: Record<string, string> = {}): {
stdout: string;
stderr: string;
code: number;
} {
try {
const stdout = execSync(`${CLI_PATH} ${args}`, {
encoding: 'utf8',
stdio: 'pipe',
env: {
...process.env,
HOME: TEST_CONFIG_DIR,
...env,
},
});
return { stdout, stderr: '', code: 0 };
} catch (error: any) {
return {
stdout: error.stdout || '',
stderr: error.stderr || '',
code: error.status || 1,
};
}
}
beforeEach(() => {
// Create temporary config directory
if (!fs.existsSync(TEST_CONFIG_DIR)) {
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
}
});
afterEach(() => {
// Clean up test config directory
if (fs.existsSync(TEST_CONFIG_DIR)) {
fs.rmSync(TEST_CONFIG_DIR, { recursive: true, force: true });
}
});
describe('config initialization', () => {
test('should create config file on first run', () => {
runCLI('config init');
expect(fs.existsSync(TEST_CONFIG_FILE)).toBe(true);
});
test('should not overwrite existing config', () => {
fs.writeFileSync(TEST_CONFIG_FILE, 'existing: data\n');
const { stderr, code } = runCLI('config init');
expect(code).toBe(1);
expect(stderr).toContain('Config file already exists');
});
test('should create config with default values', () => {
runCLI('config init');
const config = fs.readFileSync(TEST_CONFIG_FILE, 'utf8');
expect(config).toContain('api_key: your_api_key_here');
expect(config).toContain('environment: development');
});
});
describe('config set operations', () => {
beforeEach(() => {
runCLI('config init');
});
test('should set string value', () => {
const { code } = runCLI('config set api_key test_key_123');
expect(code).toBe(0);
const config = fs.readFileSync(TEST_CONFIG_FILE, 'utf8');
expect(config).toContain('api_key: test_key_123');
});
test('should set boolean value', () => {
const { code } = runCLI('config set verbose true');
expect(code).toBe(0);
const config = fs.readFileSync(TEST_CONFIG_FILE, 'utf8');
expect(config).toContain('verbose: true');
});
test('should set nested value', () => {
const { code } = runCLI('config set logging.level debug');
expect(code).toBe(0);
const config = fs.readFileSync(TEST_CONFIG_FILE, 'utf8');
expect(config).toContain('level: debug');
});
test('should handle invalid key names', () => {
const { stderr, code } = runCLI('config set invalid..key value');
expect(code).toBe(1);
expect(stderr).toContain('Invalid key name');
});
});
describe('config get operations', () => {
beforeEach(() => {
runCLI('config init');
runCLI('config set api_key test_key_123');
runCLI('config set environment production');
});
test('should get existing value', () => {
const { stdout, code } = runCLI('config get api_key');
expect(code).toBe(0);
expect(stdout).toContain('test_key_123');
});
test('should handle non-existent key', () => {
const { stderr, code } = runCLI('config get nonexistent');
expect(code).toBe(1);
expect(stderr).toContain('Key not found');
});
test('should get nested value', () => {
runCLI('config set database.host localhost');
const { stdout, code } = runCLI('config get database.host');
expect(code).toBe(0);
expect(stdout).toContain('localhost');
});
});
describe('config list operations', () => {
beforeEach(() => {
runCLI('config init');
runCLI('config set api_key test_key_123');
runCLI('config set verbose true');
});
test('should list all configuration', () => {
const { stdout, code } = runCLI('config list');
expect(code).toBe(0);
expect(stdout).toContain('api_key');
expect(stdout).toContain('verbose');
});
test('should format list output', () => {
const { stdout, code } = runCLI('config list --format json');
expect(code).toBe(0);
const config = JSON.parse(stdout);
expect(config.api_key).toBe('test_key_123');
expect(config.verbose).toBe(true);
});
});
describe('config validation', () => {
test('should validate config file on load', () => {
fs.writeFileSync(TEST_CONFIG_FILE, 'invalid yaml: [}');
const { stderr, code } = runCLI('config list');
expect(code).toBe(1);
expect(stderr).toContain('Invalid configuration file');
});
test('should validate required fields', () => {
runCLI('config init');
fs.writeFileSync(TEST_CONFIG_FILE, 'optional: value\n');
const { stderr, code } = runCLI('deploy production');
expect(code).toBe(1);
expect(stderr).toContain('api_key is required');
});
});
describe('environment variable overrides', () => {
beforeEach(() => {
runCLI('config init');
runCLI('config set api_key file_key_123');
});
test('should override with environment variable', () => {
const { stdout } = runCLI('config get api_key', {
MYCLI_API_KEY: 'env_key_123',
});
expect(stdout).toContain('env_key_123');
});
test('should use file value when env var not set', () => {
const { stdout } = runCLI('config get api_key');
expect(stdout).toContain('file_key_123');
});
});
});