这个技能负责检测和集成 test-generator 插件,让 dev-tools 能够调用专业的测试生成功能。
自动检测并集成 test-generator 插件,为测试生成调用专业工具或提供基础降级方案
/plugin marketplace add Protagonistss/claude-plugins/plugin install dev-tools@claude-plugins-protagonisthsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
这个技能负责检测和集成 test-generator 插件,让 dev-tools 能够调用专业的测试生成功能。
// 检查测试插件是否可用
const hasTestPlugin = await checkUnitTestGeneratorPlugin();
if (hasTestPlugin) {
// 使用专业模式
return await callTestPlugin(target, options);
} else {
// 使用基础模式
return generateBasicTest(target, options);
}
// 代理调用测试插件
async function callTestPlugin(target: string, options: TestOptions) {
const skillArgs = {
plugin: 'test-generator',
skill: 'unit-test-generation',
params: {
target,
framework: options.framework || 'jest',
outputDir: options.outputDir,
includeMocks: options.mock || false,
coverage: options.coverage || false
}
};
return await callPluginSkill(skillArgs);
}
async function checkUnitTestGeneratorPlugin(): Promise<boolean> {
try {
// 检查插件目录是否存在
const pluginPath = path.join(process.cwd(), 'plugins', 'test-generator');
const exists = await fs.pathExists(pluginPath);
if (!exists) {
return false;
}
// 检查插件配置
const configPath = path.join(pluginPath, '.claude-plugin', 'plugin.json');
const config = await fs.readJson(configPath);
// 验证插件名称和版本
return config.name === 'test-generator' &&
semver.gte(config.version, '1.0.0');
} catch (error) {
console.error('Failed to check test-generator plugin:', error);
return false;
}
}
async function promptUserForTestMode(): Promise<boolean> {
const response = await promptUser({
type: 'confirm',
message: '检测到 test-generator 插件,是否使用专业测试生成模式?',
default: true,
choices: [
{ name: '是 - 使用专业测试插件', value: true },
{ name: '否 - 使用基础测试生成', value: false }
]
});
// 记录用户选择
await setUserPreference('use-professional-test', response);
return response;
}
function convertGenOptionsToTestOptions(genOptions: GenOptions): TestOptions {
return {
target: genOptions.target,
framework: genOptions.framework || detectFrameworkFromProject(),
outputDir: genOptions.output || getDefaultTestDir(),
includeMocks: genOptions.mock || false,
coverage: genOptions.coverage || false,
update: genOptions.update || false,
skipSetup: genOptions.skipSetup || false
};
}
function detectFrameworkFromProject(): string {
// 检测项目使用的测试框架
if (hasPackage('vitest')) return 'vitest';
if (hasPackage('jest')) return 'jest';
if (hasPackage('pytest')) return 'pytest';
if (hasPackage('junit')) return 'junit';
return 'vitest'; // 默认框架
}
async function generateBasicTest(target: string, options: GenOptions): Promise<TestResult> {
const testTemplate = await loadTestTemplate(options.framework || 'jest');
// 基础代码分析
const codeInfo = await analyzeCode(target);
// 生成基础测试
const testCode = await fillTemplate(testTemplate, {
target: codeInfo.name,
functions: codeInfo.functions,
className: codeInfo.className,
imports: codeInfo.imports
});
// 写入测试文件
const testPath = getTestPath(target);
await writeFile(testPath, testCode);
return {
success: true,
testPath,
message: `基础测试已生成: ${testPath}\n提示:安装 test-generator 插件以获得更强大的测试生成功能`
};
}
function generateInstallPrompt(): string {
return `
⚡ 提升您的测试体验!
安装 test-generator 插件以获得:
✨ 支持更多测试框架 (Jest, Vitest, Pytest, JUnit等)
🎭 自动生成Mock数据和Stub函数
🎯 智能边界值和错误场景测试
📊 测试覆盖率分析和优化建议
🤖 测试专家代理 (@test-expert)
安装方法:
1. 下载插件: https://github.com/Protagonisths/claude-plugins
2. 复制到插件目录
3. 重启 Claude Code
或者使用 dev-tools 安装:
/install-plugin test-generator
`;
}
// 处理 /gen test 命令
if (command === 'test') {
const target = args[0];
const options = parseOptions(args.slice(1));
// 检测专业插件
const hasPlugin = await checkUnitTestGeneratorPlugin();
if (hasPlugin) {
// 检查用户偏好或提示选择
const useProfessional = await getUserPreference('use-professional-test') ??
await promptUserForTestMode();
if (useProfessional) {
return await callTestPlugin(target, options);
}
}
// 使用基础测试生成
const result = await generateBasicTest(target, options);
// 显示安装提示
if (!hasPlugin) {
console.log(generateInstallPrompt());
}
return result;
}
// 调用测试插件技能的标准接口
interface TestPluginSkillCall {
plugin: 'test-generator';
skill: string;
params: {
target: string;
framework?: string;
outputDir?: string;
includeMocks?: boolean;
coverage?: boolean;
update?: boolean;
[key: string]: any;
};
}
// 执行调用
async function executeTestPluginSkill(skillCall: TestPluginSkillCall): Promise<any> {
try {
// 通过 Claude Code 的技能调用机制执行
const result = await callSkill(skillCall.plugin, skillCall.skill, skillCall.params);
// 处理返回结果
if (result.success) {
// 触发钩子事件
await triggerHook('onTestGenerated', {
target: skillCall.params.target,
outputPath: result.testPath,
framework: skillCall.params.framework
});
}
return result;
} catch (error) {
console.error('Failed to execute test plugin skill:', error);
throw error;
}
}
// 用户偏好存储
interface UserPreferences {
useProfessionalTest?: boolean;
defaultTestFramework?: string;
autoGenerateMocks?: boolean;
promptForPluginInstall?: boolean;
}
// 获取用户偏好
async function getUserPreference(key: keyof UserPreferences): Promise<any> {
const prefs = await loadUserPreferences();
return prefs[key];
}
// 设置用户偏好
async function setUserPreference(key: keyof UserPreferences, value: any): Promise<void> {
const prefs = await loadUserPreferences();
prefs[key] = value;
await saveUserPreferences(prefs);
}
// 项目配置 (test-integration.config.json)
interface ProjectConfig {
testPlugin?: {
enabled: boolean;
framework?: string;
outputDir?: string;
autoMock?: boolean;
coverageThreshold?: number;
};
fallback?: {
framework?: string;
template?: string;
};
}
// 读取项目配置
async function loadProjectConfig(): Promise<ProjectConfig> {
const configPath = path.join(process.cwd(), 'test-integration.config.json');
if (await fs.pathExists(configPath)) {
return await fs.readJson(configPath);
}
return {};
}
This skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.