mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-11-09 14:04:06 +09:00
- Implemented a validation script to check the installation of Claude optimized templates. - The script verifies the presence of required files, directory structure, and file content. - Added tests for command structure, version consistency, and installation timestamp. docs: Create comprehensive init command analysis report - Added an analysis report detailing the structure and functionality of the `claude-flow init` command. - Included sections on command flow, file structure, key functions, and SPARC integration. - Provided recommendations for optimization and next steps for further development. chore: Introduce init command file map for better organization - Created a JSON file mapping the structure and key components of the init command. - Included details on file locations, generated files, and key functions for easier reference. test: Develop extensive test suite for init command functionality - Established a comprehensive test suite covering unit, integration, and performance tests for the init command. - Included tests for batch initialization features, error handling, and environment configurations. - Ensured high test coverage and validation of all command functionalities. test: Add batch initialization tests for various scenarios - Implemented tests for batch initialization, including validation of options, project templates, and environment configurations. - Covered error handling and multi-environment initialization scenarios.
302 lines
8.3 KiB
TypeScript
Executable File
302 lines
8.3 KiB
TypeScript
Executable File
#!/usr/bin/env -S deno run --allow-all
|
|
|
|
/**
|
|
* Test runner specifically for the init command tests
|
|
* Runs all unit, integration, and performance tests for the init command
|
|
*/
|
|
|
|
import { parseArgs } from "https://deno.land/std@0.224.0/cli/parse_args.ts";
|
|
import { join } from "@std/path/mod.ts";
|
|
import { exists } from "@std/fs/mod.ts";
|
|
|
|
interface TestSuite {
|
|
name: string;
|
|
path: string;
|
|
type: "unit" | "integration" | "performance";
|
|
description: string;
|
|
}
|
|
|
|
const TEST_SUITES: TestSuite[] = [
|
|
{
|
|
name: "init-command",
|
|
path: "tests/unit/cli/commands/init/init-command.test.ts",
|
|
type: "unit",
|
|
description: "Core init command functionality"
|
|
},
|
|
{
|
|
name: "templates",
|
|
path: "tests/unit/cli/commands/init/templates.test.ts",
|
|
type: "unit",
|
|
description: "Template generation and content validation"
|
|
},
|
|
{
|
|
name: "sparc-structure",
|
|
path: "tests/unit/cli/commands/init/sparc-structure.test.ts",
|
|
type: "unit",
|
|
description: "SPARC structure creation and validation"
|
|
},
|
|
{
|
|
name: "validation",
|
|
path: "tests/unit/cli/commands/init/validation.test.ts",
|
|
type: "unit",
|
|
description: "File integrity and configuration validation"
|
|
},
|
|
{
|
|
name: "rollback",
|
|
path: "tests/unit/cli/commands/init/rollback.test.ts",
|
|
type: "unit",
|
|
description: "Error handling and rollback functionality"
|
|
},
|
|
{
|
|
name: "full-init-flow",
|
|
path: "tests/integration/cli/init/full-init-flow.test.ts",
|
|
type: "integration",
|
|
description: "Complete initialization flow integration"
|
|
},
|
|
{
|
|
name: "selective-modes",
|
|
path: "tests/integration/cli/init/selective-modes.test.ts",
|
|
type: "integration",
|
|
description: "Selective mode initialization (minimal, SPARC, etc.)"
|
|
},
|
|
{
|
|
name: "e2e-workflow",
|
|
path: "tests/integration/cli/init/e2e-workflow.test.ts",
|
|
type: "integration",
|
|
description: "End-to-end workflow and real-world scenarios"
|
|
},
|
|
{
|
|
name: "init-performance",
|
|
path: "tests/performance/cli/init/init-performance.test.ts",
|
|
type: "performance",
|
|
description: "Performance and resource usage validation"
|
|
}
|
|
];
|
|
|
|
async function runTests(
|
|
suites: TestSuite[],
|
|
options: {
|
|
verbose?: boolean;
|
|
coverage?: boolean;
|
|
failFast?: boolean;
|
|
parallel?: boolean;
|
|
} = {}
|
|
): Promise<boolean> {
|
|
console.log(`🧪 Running ${suites.length} test suite(s) for init command\n`);
|
|
|
|
const results: Array<{ suite: TestSuite; success: boolean; duration: number; output: string }> = [];
|
|
|
|
for (const suite of suites) {
|
|
console.log(`📋 Running ${suite.name} (${suite.type}): ${suite.description}`);
|
|
|
|
// Check if test file exists
|
|
if (!await exists(suite.path)) {
|
|
console.log(` ❌ Test file not found: ${suite.path}`);
|
|
results.push({ suite, success: false, duration: 0, output: "Test file not found" });
|
|
if (options.failFast) break;
|
|
continue;
|
|
}
|
|
|
|
const startTime = performance.now();
|
|
|
|
const denoArgs = [
|
|
"test",
|
|
"--allow-all",
|
|
"--no-check",
|
|
suite.path
|
|
];
|
|
|
|
if (options.coverage) {
|
|
denoArgs.push("--coverage=coverage");
|
|
}
|
|
|
|
if (options.failFast) {
|
|
denoArgs.push("--fail-fast");
|
|
}
|
|
|
|
const command = new Deno.Command("deno", {
|
|
args: denoArgs,
|
|
stdout: options.verbose ? "inherit" : "piped",
|
|
stderr: options.verbose ? "inherit" : "piped"
|
|
});
|
|
|
|
try {
|
|
const result = await command.output();
|
|
const endTime = performance.now();
|
|
const duration = endTime - startTime;
|
|
|
|
const output = options.verbose ? "" :
|
|
new TextDecoder().decode(result.stdout) + new TextDecoder().decode(result.stderr);
|
|
|
|
if (result.success) {
|
|
console.log(` ✅ Passed in ${duration.toFixed(2)}ms`);
|
|
} else {
|
|
console.log(` ❌ Failed in ${duration.toFixed(2)}ms`);
|
|
if (!options.verbose) {
|
|
console.log(` Error output:\n${output}`);
|
|
}
|
|
}
|
|
|
|
results.push({ suite, success: result.success, duration, output });
|
|
|
|
if (!result.success && options.failFast) {
|
|
break;
|
|
}
|
|
} catch (error) {
|
|
const endTime = performance.now();
|
|
const duration = endTime - startTime;
|
|
|
|
console.log(` ❌ Error running test: ${error.message}`);
|
|
results.push({
|
|
suite,
|
|
success: false,
|
|
duration,
|
|
output: `Error: ${error.message}`
|
|
});
|
|
|
|
if (options.failFast) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Summary
|
|
console.log("\n📊 Test Results Summary:");
|
|
console.log("=" .repeat(60));
|
|
|
|
const passed = results.filter(r => r.success).length;
|
|
const failed = results.filter(r => r.success === false).length;
|
|
const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
|
|
|
|
console.log(`Total suites: ${results.length}`);
|
|
console.log(`Passed: ${passed}`);
|
|
console.log(`Failed: ${failed}`);
|
|
console.log(`Total time: ${(totalDuration / 1000).toFixed(2)}s`);
|
|
|
|
if (failed > 0) {
|
|
console.log("\n❌ Failed test suites:");
|
|
for (const result of results) {
|
|
if (!result.success) {
|
|
console.log(` - ${result.suite.name}: ${result.suite.description}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generate coverage report if requested
|
|
if (options.coverage && passed > 0) {
|
|
console.log("\n📈 Generating coverage report...");
|
|
try {
|
|
const coverageCommand = new Deno.Command("deno", {
|
|
args: ["coverage", "coverage", "--html"],
|
|
stdout: "inherit",
|
|
stderr: "inherit"
|
|
});
|
|
await coverageCommand.output();
|
|
console.log("Coverage report generated in coverage/ directory");
|
|
} catch (error) {
|
|
console.log(`Error generating coverage: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
return failed === 0;
|
|
}
|
|
|
|
async function main() {
|
|
const args = parseArgs(Deno.args, {
|
|
boolean: ["help", "verbose", "coverage", "fail-fast", "unit", "integration", "performance", "list"],
|
|
string: ["suite"],
|
|
alias: {
|
|
h: "help",
|
|
v: "verbose",
|
|
c: "coverage",
|
|
f: "fail-fast",
|
|
s: "suite",
|
|
l: "list"
|
|
}
|
|
});
|
|
|
|
if (args.help) {
|
|
console.log(`
|
|
🧪 Init Command Test Runner
|
|
|
|
Usage: deno run --allow-all scripts/test-init-command.ts [options]
|
|
|
|
Options:
|
|
-h, --help Show this help message
|
|
-v, --verbose Show detailed test output
|
|
-c, --coverage Generate coverage report
|
|
-f, --fail-fast Stop on first failure
|
|
-s, --suite <name> Run specific test suite
|
|
-l, --list List available test suites
|
|
--unit Run only unit tests
|
|
--integration Run only integration tests
|
|
--performance Run only performance tests
|
|
|
|
Examples:
|
|
./scripts/test-init-command.ts # Run all tests
|
|
./scripts/test-init-command.ts --unit # Run only unit tests
|
|
./scripts/test-init-command.ts --suite templates # Run specific suite
|
|
./scripts/test-init-command.ts --coverage # Run with coverage
|
|
`);
|
|
return;
|
|
}
|
|
|
|
if (args.list) {
|
|
console.log("📋 Available test suites:\n");
|
|
for (const suite of TEST_SUITES) {
|
|
console.log(` ${suite.name.padEnd(20)} (${suite.type.padEnd(11)}) - ${suite.description}`);
|
|
}
|
|
return;
|
|
}
|
|
|
|
let suitesToRun = TEST_SUITES;
|
|
|
|
// Filter by type
|
|
if (args.unit) {
|
|
suitesToRun = suitesToRun.filter(suite => suite.type === "unit");
|
|
} else if (args.integration) {
|
|
suitesToRun = suitesToRun.filter(suite => suite.type === "integration");
|
|
} else if (args.performance) {
|
|
suitesToRun = suitesToRun.filter(suite => suite.type === "performance");
|
|
}
|
|
|
|
// Filter by specific suite
|
|
if (args.suite) {
|
|
const requestedSuite = suitesToRun.find(suite => suite.name === args.suite);
|
|
if (!requestedSuite) {
|
|
console.error(`❌ Test suite '${args.suite}' not found.`);
|
|
console.log("\nAvailable suites:");
|
|
for (const suite of TEST_SUITES) {
|
|
console.log(` - ${suite.name}`);
|
|
}
|
|
Deno.exit(1);
|
|
}
|
|
suitesToRun = [requestedSuite];
|
|
}
|
|
|
|
if (suitesToRun.length === 0) {
|
|
console.error("❌ No test suites to run");
|
|
Deno.exit(1);
|
|
}
|
|
|
|
console.log(`🚀 Claude Flow Init Command Test Suite`);
|
|
console.log(`Running ${suitesToRun.length} test suite(s)\n`);
|
|
|
|
const success = await runTests(suitesToRun, {
|
|
verbose: args.verbose,
|
|
coverage: args.coverage,
|
|
failFast: args["fail-fast"]
|
|
});
|
|
|
|
if (success) {
|
|
console.log("\n✅ All tests passed!");
|
|
Deno.exit(0);
|
|
} else {
|
|
console.log("\n❌ Some tests failed!");
|
|
Deno.exit(1);
|
|
}
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
await main();
|
|
} |