SuperCharge Claude Code v1.0.0 - Complete Customization Package
Features: - 30+ Custom Skills (cognitive, development, UI/UX, autonomous agents) - RalphLoop autonomous agent integration - Multi-AI consultation (Qwen) - Agent management system with sync capabilities - Custom hooks for session management - MCP servers integration - Plugin marketplace setup - Comprehensive installation script Components: - Skills: always-use-superpowers, ralph, brainstorming, ui-ux-pro-max, etc. - Agents: 100+ agents across engineering, marketing, product, etc. - Hooks: session-start-superpowers, qwen-consult, ralph-auto-trigger - Commands: /brainstorm, /write-plan, /execute-plan - MCP Servers: zai-mcp-server, web-search-prime, web-reader, zread - Binaries: ralphloop wrapper Installation: ./supercharge.sh
This commit is contained in:
362
plugins/claude-code-safety-net/tests/verify-config.test.ts
Normal file
362
plugins/claude-code-safety-net/tests/verify-config.test.ts
Normal file
@@ -0,0 +1,362 @@
|
||||
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
||||
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { verifyConfig as main, type VerifyConfigOptions } from '../src/bin/verify-config.ts';
|
||||
|
||||
describe('verify-config', () => {
|
||||
let tempDir: string;
|
||||
let userConfigPath: string;
|
||||
let projectConfigPath: string;
|
||||
let capturedStdout: string[];
|
||||
let capturedStderr: string[];
|
||||
let originalConsoleLog: typeof console.log;
|
||||
let originalConsoleError: typeof console.error;
|
||||
|
||||
beforeEach(() => {
|
||||
// Create unique temp directory
|
||||
tempDir = join(
|
||||
tmpdir(),
|
||||
`verify-config-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
);
|
||||
mkdirSync(tempDir, { recursive: true });
|
||||
|
||||
// Set up paths
|
||||
userConfigPath = join(tempDir, '.cc-safety-net', 'config.json');
|
||||
projectConfigPath = join(tempDir, '.safety-net.json');
|
||||
|
||||
// Capture console output
|
||||
capturedStdout = [];
|
||||
capturedStderr = [];
|
||||
originalConsoleLog = console.log;
|
||||
originalConsoleError = console.error;
|
||||
console.log = (...args: unknown[]) => {
|
||||
capturedStdout.push(args.map(String).join(' '));
|
||||
};
|
||||
console.error = (...args: unknown[]) => {
|
||||
capturedStderr.push(args.map(String).join(' '));
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Restore console
|
||||
console.log = originalConsoleLog;
|
||||
console.error = originalConsoleError;
|
||||
|
||||
// Clean up temp directory
|
||||
if (existsSync(tempDir)) {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
function writeUserConfig(content: string): void {
|
||||
const dir = join(tempDir, '.cc-safety-net');
|
||||
mkdirSync(dir, { recursive: true });
|
||||
writeFileSync(userConfigPath, content, 'utf-8');
|
||||
}
|
||||
|
||||
function writeProjectConfig(content: string): void {
|
||||
writeFileSync(projectConfigPath, content, 'utf-8');
|
||||
}
|
||||
|
||||
function runMain(): number {
|
||||
const options: VerifyConfigOptions = {
|
||||
userConfigPath,
|
||||
projectConfigPath,
|
||||
};
|
||||
return main(options);
|
||||
}
|
||||
|
||||
function getStdout(): string {
|
||||
return capturedStdout.join('\n');
|
||||
}
|
||||
|
||||
function getStderr(): string {
|
||||
return capturedStderr.join('\n');
|
||||
}
|
||||
|
||||
describe('no configs', () => {
|
||||
test('returns zero when no configs exist', () => {
|
||||
const result = runMain();
|
||||
expect(result).toBe(0);
|
||||
});
|
||||
|
||||
test('prints header', () => {
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('Safety Net Config');
|
||||
expect(output).toContain('═');
|
||||
});
|
||||
|
||||
test('prints no configs message', () => {
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('No config files found');
|
||||
expect(output).toContain('Using built-in rules only');
|
||||
});
|
||||
});
|
||||
|
||||
describe('valid configs', () => {
|
||||
test('user config only returns zero', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(0);
|
||||
});
|
||||
|
||||
test('user config prints checkmark', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('✓ User config:');
|
||||
});
|
||||
|
||||
test('user config shows rules none', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('Rules: (none)');
|
||||
});
|
||||
|
||||
test('user config with rules shows numbered list', () => {
|
||||
writeUserConfig(
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
rules: [
|
||||
{
|
||||
name: 'block-foo',
|
||||
command: 'foo',
|
||||
block_args: ['-x'],
|
||||
reason: 'Blocked',
|
||||
},
|
||||
{
|
||||
name: 'block-bar',
|
||||
command: 'bar',
|
||||
block_args: ['-y'],
|
||||
reason: 'Blocked',
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('Rules:');
|
||||
expect(output).toContain('1. block-foo');
|
||||
expect(output).toContain('2. block-bar');
|
||||
});
|
||||
|
||||
test('project config only returns zero', () => {
|
||||
writeProjectConfig('{"version": 1}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(0);
|
||||
});
|
||||
|
||||
test('project config prints checkmark', () => {
|
||||
writeProjectConfig('{"version": 1}');
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('✓ Project config:');
|
||||
});
|
||||
|
||||
test('both configs returns zero', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
writeProjectConfig('{"version": 1}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(0);
|
||||
});
|
||||
|
||||
test('both configs prints both checkmarks', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
writeProjectConfig('{"version": 1}');
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('✓ User config:');
|
||||
expect(output).toContain('✓ Project config:');
|
||||
});
|
||||
|
||||
test('valid config prints success message', () => {
|
||||
writeProjectConfig('{"version": 1}');
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('All configs valid.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('invalid configs', () => {
|
||||
test('invalid user config returns one', () => {
|
||||
writeUserConfig('{"version": 2}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(1);
|
||||
});
|
||||
|
||||
test('invalid user config prints x mark', () => {
|
||||
writeUserConfig('{"version": 2}');
|
||||
runMain();
|
||||
const output = getStderr();
|
||||
expect(output).toContain('✗ User config:');
|
||||
});
|
||||
|
||||
test('invalid config shows numbered errors', () => {
|
||||
writeUserConfig('{"version": 2}');
|
||||
runMain();
|
||||
const output = getStderr();
|
||||
expect(output).toContain('Errors:');
|
||||
expect(output).toContain('1.');
|
||||
expect(output).toContain('version');
|
||||
});
|
||||
|
||||
test('invalid project config returns one', () => {
|
||||
writeProjectConfig('{"rules": []}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(1);
|
||||
});
|
||||
|
||||
test('invalid project config prints x mark', () => {
|
||||
writeProjectConfig('{"rules": []}');
|
||||
runMain();
|
||||
const output = getStderr();
|
||||
expect(output).toContain('✗ Project config:');
|
||||
});
|
||||
|
||||
test('both invalid returns one', () => {
|
||||
writeUserConfig('{"version": 2}');
|
||||
writeProjectConfig('{"rules": []}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(1);
|
||||
});
|
||||
|
||||
test('both invalid prints both errors', () => {
|
||||
writeUserConfig('{"version": 2}');
|
||||
writeProjectConfig('{"rules": []}');
|
||||
runMain();
|
||||
const output = getStderr();
|
||||
expect(output).toContain('✗ User config:');
|
||||
expect(output).toContain('✗ Project config:');
|
||||
});
|
||||
|
||||
test('invalid json prints error', () => {
|
||||
writeProjectConfig('{ not valid json }');
|
||||
runMain();
|
||||
const output = getStderr();
|
||||
expect(output).toContain('✗ Project config:');
|
||||
});
|
||||
|
||||
test('validation failed message', () => {
|
||||
writeProjectConfig('{"version": 2}');
|
||||
runMain();
|
||||
const output = getStderr();
|
||||
expect(output).toContain('Config validation failed.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('mixed validity', () => {
|
||||
test('valid user invalid project returns one', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
writeProjectConfig('{"version": 2}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(1);
|
||||
});
|
||||
|
||||
test('valid user invalid project shows both', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
writeProjectConfig('{"version": 2}');
|
||||
runMain();
|
||||
const stdout = getStdout();
|
||||
const stderr = getStderr();
|
||||
expect(stdout).toContain('✓ User config:');
|
||||
expect(stderr).toContain('✗ Project config:');
|
||||
});
|
||||
|
||||
test('invalid user valid project returns one', () => {
|
||||
writeUserConfig('{"version": 2}');
|
||||
writeProjectConfig('{"version": 1}');
|
||||
const result = runMain();
|
||||
expect(result).toBe(1);
|
||||
});
|
||||
|
||||
test('invalid user valid project shows both', () => {
|
||||
writeUserConfig('{"version": 2}');
|
||||
writeProjectConfig('{"version": 1}');
|
||||
runMain();
|
||||
const stdout = getStdout();
|
||||
const stderr = getStderr();
|
||||
expect(stderr).toContain('✗ User config:');
|
||||
expect(stdout).toContain('✓ Project config:');
|
||||
});
|
||||
});
|
||||
|
||||
describe('schema auto-add', () => {
|
||||
function readProjectConfig(): Record<string, unknown> {
|
||||
return JSON.parse(readFileSync(projectConfigPath, 'utf-8'));
|
||||
}
|
||||
|
||||
function readUserConfig(): Record<string, unknown> {
|
||||
return JSON.parse(readFileSync(userConfigPath, 'utf-8'));
|
||||
}
|
||||
|
||||
test('adds $schema to valid project config missing it', () => {
|
||||
writeProjectConfig('{"version": 1}');
|
||||
runMain();
|
||||
const config = readProjectConfig();
|
||||
expect(config.$schema).toBe(
|
||||
'https://raw.githubusercontent.com/kenryu42/claude-code-safety-net/main/assets/cc-safety-net.schema.json',
|
||||
);
|
||||
});
|
||||
|
||||
test('adds $schema to valid user config missing it', () => {
|
||||
writeUserConfig('{"version": 1}');
|
||||
runMain();
|
||||
const config = readUserConfig();
|
||||
expect(config.$schema).toBe(
|
||||
'https://raw.githubusercontent.com/kenryu42/claude-code-safety-net/main/assets/cc-safety-net.schema.json',
|
||||
);
|
||||
});
|
||||
|
||||
test('does not modify config that already has $schema', () => {
|
||||
const originalConfig = {
|
||||
$schema:
|
||||
'https://raw.githubusercontent.com/kenryu42/claude-code-safety-net/main/assets/cc-safety-net.schema.json',
|
||||
version: 1,
|
||||
};
|
||||
writeProjectConfig(JSON.stringify(originalConfig, null, 2));
|
||||
runMain();
|
||||
const config = readProjectConfig();
|
||||
expect(config).toEqual(originalConfig);
|
||||
});
|
||||
|
||||
test('preserves existing rules when adding $schema', () => {
|
||||
const originalConfig = {
|
||||
version: 1,
|
||||
rules: [
|
||||
{
|
||||
name: 'block-foo',
|
||||
command: 'foo',
|
||||
block_args: ['-x'],
|
||||
reason: 'Blocked',
|
||||
},
|
||||
],
|
||||
};
|
||||
writeProjectConfig(JSON.stringify(originalConfig));
|
||||
runMain();
|
||||
const config = readProjectConfig();
|
||||
expect(config.$schema).toBe(
|
||||
'https://raw.githubusercontent.com/kenryu42/claude-code-safety-net/main/assets/cc-safety-net.schema.json',
|
||||
);
|
||||
expect(config.version).toBe(1);
|
||||
expect(config.rules).toEqual(originalConfig.rules);
|
||||
});
|
||||
|
||||
test('does not add $schema to invalid config', () => {
|
||||
writeProjectConfig('{"version": 2}');
|
||||
runMain();
|
||||
const config = readProjectConfig();
|
||||
expect(config.$schema).toBeUndefined();
|
||||
});
|
||||
|
||||
test('prints message when $schema is added', () => {
|
||||
writeProjectConfig('{"version": 1}');
|
||||
runMain();
|
||||
const output = getStdout();
|
||||
expect(output).toContain('Added $schema');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user