qualyx 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +523 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +124 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +3 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +122 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/run.d.ts +12 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +160 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/schedule.d.ts +19 -0
- package/dist/cli/commands/schedule.d.ts.map +1 -0
- package/dist/cli/commands/schedule.js +240 -0
- package/dist/cli/commands/schedule.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +3 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +47 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +194 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/claude-runner.d.ts +23 -0
- package/dist/core/claude-runner.d.ts.map +1 -0
- package/dist/core/claude-runner.js +196 -0
- package/dist/core/claude-runner.js.map +1 -0
- package/dist/core/config-loader.d.ts +137 -0
- package/dist/core/config-loader.d.ts.map +1 -0
- package/dist/core/config-loader.js +239 -0
- package/dist/core/config-loader.js.map +1 -0
- package/dist/core/executor.d.ts +75 -0
- package/dist/core/executor.d.ts.map +1 -0
- package/dist/core/executor.js +337 -0
- package/dist/core/executor.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +7 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/prompt-builder.d.ts +24 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +145 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/retry-handler.d.ts +42 -0
- package/dist/core/retry-handler.d.ts.map +1 -0
- package/dist/core/retry-handler.js +126 -0
- package/dist/core/retry-handler.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/email.d.ts +38 -0
- package/dist/integrations/email.d.ts.map +1 -0
- package/dist/integrations/email.js +216 -0
- package/dist/integrations/email.js.map +1 -0
- package/dist/integrations/index.d.ts +5 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +5 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/jira.d.ts +68 -0
- package/dist/integrations/jira.d.ts.map +1 -0
- package/dist/integrations/jira.js +288 -0
- package/dist/integrations/jira.js.map +1 -0
- package/dist/integrations/slack.d.ts +66 -0
- package/dist/integrations/slack.d.ts.map +1 -0
- package/dist/integrations/slack.js +192 -0
- package/dist/integrations/slack.js.map +1 -0
- package/dist/integrations/teams.d.ts +72 -0
- package/dist/integrations/teams.d.ts.map +1 -0
- package/dist/integrations/teams.js +197 -0
- package/dist/integrations/teams.js.map +1 -0
- package/dist/reporters/console.d.ts +83 -0
- package/dist/reporters/console.d.ts.map +1 -0
- package/dist/reporters/console.js +299 -0
- package/dist/reporters/console.js.map +1 -0
- package/dist/reporters/html.d.ts +29 -0
- package/dist/reporters/html.d.ts.map +1 -0
- package/dist/reporters/html.js +105 -0
- package/dist/reporters/html.js.map +1 -0
- package/dist/storage/results.d.ts +61 -0
- package/dist/storage/results.d.ts.map +1 -0
- package/dist/storage/results.js +111 -0
- package/dist/storage/results.js.map +1 -0
- package/dist/storage/sqlite.d.ts +70 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +240 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/types/index.d.ts +1239 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +105 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +75 -0
- package/templates/crontab.hbs +24 -0
- package/templates/github-schedule.yml.hbs +153 -0
- package/templates/prompt.md.hbs +147 -0
- package/templates/report.html.hbs +423 -0
- package/templates/slack-message.json.hbs +93 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,SAAS,IAAI,OAAO,CAmNnC"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { runInit } from './commands/init.js';
|
|
3
|
+
import { runValidate } from './commands/validate.js';
|
|
4
|
+
import { runList } from './commands/list.js';
|
|
5
|
+
import { runRun } from './commands/run.js';
|
|
6
|
+
import { runScheduleList, runScheduleCron, runScheduleGithub } from './commands/schedule.js';
|
|
7
|
+
const VERSION = '0.3.0';
|
|
8
|
+
export function createCli() {
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name('qualyx')
|
|
12
|
+
.description('AI-powered QA automation platform using Claude Code CLI and Playwright')
|
|
13
|
+
.version(VERSION);
|
|
14
|
+
// Init command
|
|
15
|
+
program
|
|
16
|
+
.command('init')
|
|
17
|
+
.description('Create a starter qualyx.yml configuration file')
|
|
18
|
+
.option('-f, --force', 'Overwrite existing configuration file')
|
|
19
|
+
.option('-p, --path <path>', 'Path for the configuration file', 'qualyx.yml')
|
|
20
|
+
.action(async (options) => {
|
|
21
|
+
await runInit(options);
|
|
22
|
+
});
|
|
23
|
+
// Validate command
|
|
24
|
+
program
|
|
25
|
+
.command('validate')
|
|
26
|
+
.description('Validate the configuration file')
|
|
27
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
28
|
+
.option('-s, --strict', 'Treat warnings as errors')
|
|
29
|
+
.action(async (options) => {
|
|
30
|
+
await runValidate(options.config, { strict: options.strict });
|
|
31
|
+
});
|
|
32
|
+
// List command
|
|
33
|
+
program
|
|
34
|
+
.command('list [resource]')
|
|
35
|
+
.description('List apps and rules from configuration')
|
|
36
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
37
|
+
.option('-f, --format <format>', 'Output format: table or json', 'table')
|
|
38
|
+
.action(async (resource, options) => {
|
|
39
|
+
await runList(resource, options.config, { format: options.format });
|
|
40
|
+
});
|
|
41
|
+
// Run command
|
|
42
|
+
program
|
|
43
|
+
.command('run')
|
|
44
|
+
.description('Execute tests')
|
|
45
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
46
|
+
.option('-a, --app <name>', 'Run tests only for specified app')
|
|
47
|
+
.option('-r, --rule <id>', 'Run only specified rule')
|
|
48
|
+
.option('-e, --environment <name>', 'Environment to run against')
|
|
49
|
+
.option('--dry-run', 'Preview tests without executing')
|
|
50
|
+
.option('--headed', 'Run browser in headed mode (visible)')
|
|
51
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
52
|
+
.option('--retries <number>', 'Number of retries on failure', parseInt)
|
|
53
|
+
.option('--timeout <ms>', 'Timeout per test in milliseconds', parseInt)
|
|
54
|
+
.option('--parallel', 'Run tests in parallel')
|
|
55
|
+
.option('--max-parallel <number>', 'Maximum number of parallel tests', parseInt)
|
|
56
|
+
.option('--collect-metrics', 'Collect performance metrics during tests')
|
|
57
|
+
.option('--report', 'Generate HTML report')
|
|
58
|
+
.option('--report-dir <path>', 'Directory for HTML reports', './qualyx-reports')
|
|
59
|
+
.option('--no-save', 'Do not save results to history')
|
|
60
|
+
.action(async (options) => {
|
|
61
|
+
await runRun({
|
|
62
|
+
config: options.config,
|
|
63
|
+
app: options.app,
|
|
64
|
+
rule: options.rule,
|
|
65
|
+
environment: options.environment,
|
|
66
|
+
dryRun: options.dryRun,
|
|
67
|
+
headed: options.headed,
|
|
68
|
+
verbose: options.verbose,
|
|
69
|
+
retries: options.retries,
|
|
70
|
+
timeout: options.timeout,
|
|
71
|
+
parallel: options.parallel,
|
|
72
|
+
maxParallel: options.maxParallel,
|
|
73
|
+
collectMetrics: options.collectMetrics,
|
|
74
|
+
report: options.report,
|
|
75
|
+
reportDir: options.reportDir,
|
|
76
|
+
save: options.save,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
// Schedule command
|
|
80
|
+
const scheduleCmd = program
|
|
81
|
+
.command('schedule')
|
|
82
|
+
.description('Manage scheduled test rules');
|
|
83
|
+
scheduleCmd
|
|
84
|
+
.command('list')
|
|
85
|
+
.description('List all scheduled rules')
|
|
86
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
87
|
+
.option('-f, --format <format>', 'Output format: table or json', 'table')
|
|
88
|
+
.action(async (options) => {
|
|
89
|
+
await runScheduleList({
|
|
90
|
+
config: options.config,
|
|
91
|
+
format: options.format,
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
scheduleCmd
|
|
95
|
+
.command('cron')
|
|
96
|
+
.description('Generate crontab entries for scheduled rules')
|
|
97
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
98
|
+
.option('-o, --output <path>', 'Output file path')
|
|
99
|
+
.option('-p, --project-path <path>', 'Project path for cron commands')
|
|
100
|
+
.action(async (options) => {
|
|
101
|
+
await runScheduleCron({
|
|
102
|
+
config: options.config,
|
|
103
|
+
output: options.output,
|
|
104
|
+
projectPath: options.projectPath,
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
scheduleCmd
|
|
108
|
+
.command('github')
|
|
109
|
+
.description('Generate GitHub Actions workflow for scheduled rules')
|
|
110
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
111
|
+
.option('-o, --output <path>', 'Output file path')
|
|
112
|
+
.action(async (options) => {
|
|
113
|
+
await runScheduleGithub({
|
|
114
|
+
config: options.config,
|
|
115
|
+
output: options.output,
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
// Report command (view last report)
|
|
119
|
+
program
|
|
120
|
+
.command('report')
|
|
121
|
+
.description('View or regenerate the last test report')
|
|
122
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
123
|
+
.option('-o, --output <path>', 'Output path for HTML report')
|
|
124
|
+
.option('--run-id <id>', 'Generate report for specific run ID')
|
|
125
|
+
.action(async (options) => {
|
|
126
|
+
const { getLatestRunResult, getRunResult } = await import('../storage/results.js');
|
|
127
|
+
const { generateHtmlReport } = await import('../reporters/html.js');
|
|
128
|
+
const { loadConfig } = await import('../core/config-loader.js');
|
|
129
|
+
const chalk = (await import('chalk')).default;
|
|
130
|
+
// Get the run result
|
|
131
|
+
const runResult = options.runId ? getRunResult(options.runId) : getLatestRunResult();
|
|
132
|
+
if (!runResult) {
|
|
133
|
+
console.log();
|
|
134
|
+
console.log(chalk.yellow(' No test runs found in history'));
|
|
135
|
+
console.log(chalk.gray(' Run tests first with: qualyx run'));
|
|
136
|
+
console.log();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Load config to get organization name
|
|
140
|
+
let orgName = 'Qualyx';
|
|
141
|
+
try {
|
|
142
|
+
const configResult = loadConfig(options.config);
|
|
143
|
+
orgName = configResult.config.organization.name;
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Use default org name
|
|
147
|
+
}
|
|
148
|
+
// Generate the report
|
|
149
|
+
const reportPath = generateHtmlReport(runResult, { outputDir: options.output || './qualyx-reports' }, orgName);
|
|
150
|
+
console.log();
|
|
151
|
+
console.log(chalk.green(` Report generated: ${reportPath}`));
|
|
152
|
+
console.log(chalk.gray(` Run ID: ${runResult.runId}`));
|
|
153
|
+
console.log(chalk.gray(` Date: ${new Date(runResult.startedAt).toLocaleString()}`));
|
|
154
|
+
console.log(chalk.gray(` Results: ${runResult.passed}/${runResult.totalTests} passed`));
|
|
155
|
+
console.log();
|
|
156
|
+
});
|
|
157
|
+
// History command
|
|
158
|
+
program
|
|
159
|
+
.command('history')
|
|
160
|
+
.description('View test run history')
|
|
161
|
+
.option('-l, --limit <number>', 'Number of runs to show', '10')
|
|
162
|
+
.option('--failed', 'Show only failed runs')
|
|
163
|
+
.option('-f, --format <format>', 'Output format: table or json', 'table')
|
|
164
|
+
.action(async (options) => {
|
|
165
|
+
const { getRecentRunResults, getFailedRunResults } = await import('../storage/results.js');
|
|
166
|
+
const chalk = (await import('chalk')).default;
|
|
167
|
+
const limit = parseInt(options.limit, 10);
|
|
168
|
+
const runs = options.failed ? getFailedRunResults(limit) : getRecentRunResults(limit);
|
|
169
|
+
if (runs.length === 0) {
|
|
170
|
+
console.log();
|
|
171
|
+
console.log(chalk.yellow(' No test runs found in history'));
|
|
172
|
+
console.log();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (options.format === 'json') {
|
|
176
|
+
console.log(JSON.stringify(runs, null, 2));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
console.log();
|
|
180
|
+
console.log(chalk.bold.cyan(' Test Run History'));
|
|
181
|
+
console.log();
|
|
182
|
+
for (const run of runs) {
|
|
183
|
+
const date = new Date(run.startedAt).toLocaleString();
|
|
184
|
+
const status = run.failed > 0 ? chalk.red('FAILED') : chalk.green('PASSED');
|
|
185
|
+
const stats = `${run.passed}/${run.totalTests} passed`;
|
|
186
|
+
console.log(` ${status} ${chalk.gray(date)} - ${stats}`);
|
|
187
|
+
console.log(chalk.gray(` ID: ${run.runId.slice(0, 8)}...`));
|
|
188
|
+
console.log(chalk.gray(` Environment: ${run.environment}`));
|
|
189
|
+
console.log();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return program;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ClaudeRunnerOptions, ClaudeResponse, TestStatus, StepResult, ValidationResult } from '../types/index.js';
|
|
2
|
+
export declare class ClaudeRunnerError extends Error {
|
|
3
|
+
readonly exitCode?: number | undefined;
|
|
4
|
+
readonly stderr?: string | undefined;
|
|
5
|
+
constructor(message: string, exitCode?: number | undefined, stderr?: string | undefined);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Run Claude Code CLI with the given prompt.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runClaude(prompt: string, options?: Partial<ClaudeRunnerOptions>): Promise<ClaudeResponse>;
|
|
11
|
+
/**
|
|
12
|
+
* Check if Claude Code CLI is available.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isClaudeAvailable(): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Get Claude Code CLI version.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getClaudeVersion(): Promise<string | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Create a mock response for testing purposes.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createMockResponse(status: TestStatus, steps?: StepResult[], validations?: ValidationResult[], error?: string): ClaudeResponse;
|
|
23
|
+
//# sourceMappingURL=claude-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-runner.d.ts","sourceRoot":"","sources":["../../src/core/claude-runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,UAAU,EACV,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,iBAAkB,SAAQ,KAAK;aAGxB,QAAQ,CAAC,EAAE,MAAM;aACjB,MAAM,CAAC,EAAE,MAAM;gBAF/B,OAAO,EAAE,MAAM,EACC,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,MAAM,CAAC,EAAE,MAAM,YAAA;CAKlC;AA6DD;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAM,GACzC,OAAO,CAAC,cAAc,CAAC,CAgBzB;AAiFD;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAc1D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwB/D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,KAAK,GAAE,UAAU,EAAO,EACxB,WAAW,GAAE,gBAAgB,EAAO,EACpC,KAAK,CAAC,EAAE,MAAM,GACb,cAAc,CAOhB"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
export class ClaudeRunnerError extends Error {
|
|
3
|
+
exitCode;
|
|
4
|
+
stderr;
|
|
5
|
+
constructor(message, exitCode, stderr) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.exitCode = exitCode;
|
|
8
|
+
this.stderr = stderr;
|
|
9
|
+
this.name = 'ClaudeRunnerError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const DEFAULT_OPTIONS = {
|
|
13
|
+
timeout: 60000,
|
|
14
|
+
headless: true,
|
|
15
|
+
retries: 2,
|
|
16
|
+
dryRun: false,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Parse JSON response from Claude output.
|
|
20
|
+
* Claude may output additional text before/after the JSON, so we need to extract it.
|
|
21
|
+
*/
|
|
22
|
+
function parseClaudeResponse(output) {
|
|
23
|
+
// Try to find JSON in the output
|
|
24
|
+
const jsonMatch = output.match(/\{[\s\S]*"status"[\s\S]*\}/);
|
|
25
|
+
if (!jsonMatch) {
|
|
26
|
+
// If no valid JSON found, treat it as a failure
|
|
27
|
+
return {
|
|
28
|
+
status: 'failed',
|
|
29
|
+
steps: [],
|
|
30
|
+
validations: [],
|
|
31
|
+
error: `Could not parse Claude response. Raw output: ${output.slice(0, 500)}...`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
36
|
+
// Validate the response structure
|
|
37
|
+
const response = {
|
|
38
|
+
status: parsed.status === 'passed' ? 'passed' : 'failed',
|
|
39
|
+
steps: Array.isArray(parsed.steps) ? parsed.steps : [],
|
|
40
|
+
validations: Array.isArray(parsed.validations) ? parsed.validations : [],
|
|
41
|
+
error: parsed.error,
|
|
42
|
+
screenshot: parsed.screenshot,
|
|
43
|
+
};
|
|
44
|
+
return response;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return {
|
|
48
|
+
status: 'failed',
|
|
49
|
+
steps: [],
|
|
50
|
+
validations: [],
|
|
51
|
+
error: `Failed to parse JSON response: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the Claude Code CLI command arguments.
|
|
57
|
+
*/
|
|
58
|
+
function buildClaudeArgs() {
|
|
59
|
+
return [
|
|
60
|
+
'--print', // Non-interactive mode
|
|
61
|
+
'--output-format', 'text', // Use text format (we'll parse JSON from output)
|
|
62
|
+
'--dangerously-skip-permissions', // Skip permission prompts for automation
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Run Claude Code CLI with the given prompt.
|
|
67
|
+
*/
|
|
68
|
+
export async function runClaude(prompt, options = {}) {
|
|
69
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
70
|
+
if (opts.dryRun) {
|
|
71
|
+
// In dry-run mode, return a mock response
|
|
72
|
+
return {
|
|
73
|
+
status: 'skipped',
|
|
74
|
+
steps: [],
|
|
75
|
+
validations: [],
|
|
76
|
+
error: 'Dry run - no execution performed',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const args = buildClaudeArgs();
|
|
80
|
+
const output = await executeClaudeProcess(args, prompt, opts.timeout);
|
|
81
|
+
return parseClaudeResponse(output);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Execute the Claude Code CLI process and capture output.
|
|
85
|
+
* Uses stdin to pass the prompt for better handling of long prompts.
|
|
86
|
+
*/
|
|
87
|
+
async function executeClaudeProcess(args, prompt, timeout) {
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
let stdout = '';
|
|
90
|
+
let stderr = '';
|
|
91
|
+
let isResolved = false;
|
|
92
|
+
const claude = spawn('claude', args, {
|
|
93
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
94
|
+
env: {
|
|
95
|
+
...process.env,
|
|
96
|
+
// Ensure Claude uses the right settings
|
|
97
|
+
NO_COLOR: '1', // Disable color output for easier parsing
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const timeoutId = setTimeout(() => {
|
|
101
|
+
if (!isResolved) {
|
|
102
|
+
isResolved = true;
|
|
103
|
+
claude.kill('SIGTERM');
|
|
104
|
+
reject(new ClaudeRunnerError(`Claude execution timed out after ${timeout}ms`));
|
|
105
|
+
}
|
|
106
|
+
}, timeout);
|
|
107
|
+
// Write prompt to stdin and close it
|
|
108
|
+
claude.stdin.write(prompt);
|
|
109
|
+
claude.stdin.end();
|
|
110
|
+
claude.stdout.on('data', (data) => {
|
|
111
|
+
stdout += data.toString();
|
|
112
|
+
});
|
|
113
|
+
claude.stderr.on('data', (data) => {
|
|
114
|
+
stderr += data.toString();
|
|
115
|
+
});
|
|
116
|
+
claude.on('error', (error) => {
|
|
117
|
+
if (!isResolved) {
|
|
118
|
+
isResolved = true;
|
|
119
|
+
clearTimeout(timeoutId);
|
|
120
|
+
if (error.code === 'ENOENT') {
|
|
121
|
+
reject(new ClaudeRunnerError('Claude Code CLI not found. Please install it with: npm install -g @anthropic-ai/claude-code'));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
reject(new ClaudeRunnerError(`Failed to spawn Claude process: ${error.message}`));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
claude.on('close', (code) => {
|
|
129
|
+
if (!isResolved) {
|
|
130
|
+
isResolved = true;
|
|
131
|
+
clearTimeout(timeoutId);
|
|
132
|
+
if (code !== 0 && !stdout) {
|
|
133
|
+
// Process failed without output
|
|
134
|
+
reject(new ClaudeRunnerError(`Claude exited with code ${code}`, code ?? undefined, stderr));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// Process completed (may have non-zero exit but still produced output)
|
|
138
|
+
resolve(stdout);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Check if Claude Code CLI is available.
|
|
146
|
+
*/
|
|
147
|
+
export async function isClaudeAvailable() {
|
|
148
|
+
return new Promise((resolve) => {
|
|
149
|
+
const claude = spawn('claude', ['--version'], {
|
|
150
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
151
|
+
});
|
|
152
|
+
claude.on('error', () => {
|
|
153
|
+
resolve(false);
|
|
154
|
+
});
|
|
155
|
+
claude.on('close', (code) => {
|
|
156
|
+
resolve(code === 0);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get Claude Code CLI version.
|
|
162
|
+
*/
|
|
163
|
+
export async function getClaudeVersion() {
|
|
164
|
+
return new Promise((resolve) => {
|
|
165
|
+
let stdout = '';
|
|
166
|
+
const claude = spawn('claude', ['--version'], {
|
|
167
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
168
|
+
});
|
|
169
|
+
claude.stdout.on('data', (data) => {
|
|
170
|
+
stdout += data.toString();
|
|
171
|
+
});
|
|
172
|
+
claude.on('error', () => {
|
|
173
|
+
resolve(null);
|
|
174
|
+
});
|
|
175
|
+
claude.on('close', (code) => {
|
|
176
|
+
if (code === 0) {
|
|
177
|
+
resolve(stdout.trim());
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
resolve(null);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Create a mock response for testing purposes.
|
|
187
|
+
*/
|
|
188
|
+
export function createMockResponse(status, steps = [], validations = [], error) {
|
|
189
|
+
return {
|
|
190
|
+
status,
|
|
191
|
+
steps,
|
|
192
|
+
validations,
|
|
193
|
+
error,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=claude-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-runner.js","sourceRoot":"","sources":["../../src/core/claude-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { ZodError } from 'zod';
|
|
2
|
+
import { type QualyxConfig } from '../types/index.js';
|
|
3
|
+
export declare class ConfigLoadError extends Error {
|
|
4
|
+
readonly filePath?: string | undefined;
|
|
5
|
+
readonly validationErrors?: ZodError | undefined;
|
|
6
|
+
constructor(message: string, filePath?: string | undefined, validationErrors?: ZodError | undefined);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Find the configuration file path.
|
|
10
|
+
* Searches for default config file names if no path is specified.
|
|
11
|
+
*/
|
|
12
|
+
export declare function findConfigFile(configPath?: string): string;
|
|
13
|
+
export interface LoadConfigResult {
|
|
14
|
+
config: QualyxConfig;
|
|
15
|
+
filePath: string;
|
|
16
|
+
warnings: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Load, parse, and validate the Qualyx configuration file.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadConfig(configPath?: string): LoadConfigResult;
|
|
22
|
+
/**
|
|
23
|
+
* Get a specific app from the configuration by name.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getApp(config: QualyxConfig, appName: string): {
|
|
26
|
+
name: string;
|
|
27
|
+
url: string;
|
|
28
|
+
rules: {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
32
|
+
steps: (string | {
|
|
33
|
+
action: string;
|
|
34
|
+
hint?: string | undefined;
|
|
35
|
+
caution?: string | undefined;
|
|
36
|
+
})[];
|
|
37
|
+
timeout?: number | undefined;
|
|
38
|
+
validations?: string[] | undefined;
|
|
39
|
+
on_failure?: string[] | undefined;
|
|
40
|
+
test_data?: Record<string, unknown> | undefined;
|
|
41
|
+
schedule?: string | undefined;
|
|
42
|
+
skip_setup?: boolean | undefined;
|
|
43
|
+
}[];
|
|
44
|
+
environments?: Record<string, string> | undefined;
|
|
45
|
+
auth?: {
|
|
46
|
+
type: "form-login" | "basic" | "bearer" | "cookie" | "none";
|
|
47
|
+
credentials?: Record<string, string> | undefined;
|
|
48
|
+
login_url?: string | undefined;
|
|
49
|
+
} | undefined;
|
|
50
|
+
screenshots?: {
|
|
51
|
+
on_failure: boolean;
|
|
52
|
+
on_success: boolean;
|
|
53
|
+
each_step: boolean;
|
|
54
|
+
} | undefined;
|
|
55
|
+
setup?: string[] | undefined;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Get a specific rule from an app by ID.
|
|
59
|
+
*/
|
|
60
|
+
export declare function getRule(config: QualyxConfig, appName: string, ruleId: string): {
|
|
61
|
+
app: {
|
|
62
|
+
name: string;
|
|
63
|
+
url: string;
|
|
64
|
+
rules: {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
68
|
+
steps: (string | {
|
|
69
|
+
action: string;
|
|
70
|
+
hint?: string | undefined;
|
|
71
|
+
caution?: string | undefined;
|
|
72
|
+
})[];
|
|
73
|
+
timeout?: number | undefined;
|
|
74
|
+
validations?: string[] | undefined;
|
|
75
|
+
on_failure?: string[] | undefined;
|
|
76
|
+
test_data?: Record<string, unknown> | undefined;
|
|
77
|
+
schedule?: string | undefined;
|
|
78
|
+
skip_setup?: boolean | undefined;
|
|
79
|
+
}[];
|
|
80
|
+
environments?: Record<string, string> | undefined;
|
|
81
|
+
auth?: {
|
|
82
|
+
type: "form-login" | "basic" | "bearer" | "cookie" | "none";
|
|
83
|
+
credentials?: Record<string, string> | undefined;
|
|
84
|
+
login_url?: string | undefined;
|
|
85
|
+
} | undefined;
|
|
86
|
+
screenshots?: {
|
|
87
|
+
on_failure: boolean;
|
|
88
|
+
on_success: boolean;
|
|
89
|
+
each_step: boolean;
|
|
90
|
+
} | undefined;
|
|
91
|
+
setup?: string[] | undefined;
|
|
92
|
+
};
|
|
93
|
+
rule: {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
97
|
+
steps: (string | {
|
|
98
|
+
action: string;
|
|
99
|
+
hint?: string | undefined;
|
|
100
|
+
caution?: string | undefined;
|
|
101
|
+
})[];
|
|
102
|
+
timeout?: number | undefined;
|
|
103
|
+
validations?: string[] | undefined;
|
|
104
|
+
on_failure?: string[] | undefined;
|
|
105
|
+
test_data?: Record<string, unknown> | undefined;
|
|
106
|
+
schedule?: string | undefined;
|
|
107
|
+
skip_setup?: boolean | undefined;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Get the URL for a specific environment, with fallback to the default URL.
|
|
112
|
+
*/
|
|
113
|
+
export declare function getEnvironmentUrl(app: {
|
|
114
|
+
url: string;
|
|
115
|
+
environments?: Record<string, string>;
|
|
116
|
+
}, environment?: string): string;
|
|
117
|
+
/**
|
|
118
|
+
* Get the directory containing the configuration file.
|
|
119
|
+
*/
|
|
120
|
+
export declare function getConfigDir(filePath: string): string;
|
|
121
|
+
/**
|
|
122
|
+
* Get all scheduled rules from the configuration.
|
|
123
|
+
*/
|
|
124
|
+
export declare function getScheduledRules(config: QualyxConfig): Array<{
|
|
125
|
+
appName: string;
|
|
126
|
+
ruleId: string;
|
|
127
|
+
ruleName: string;
|
|
128
|
+
schedule: string;
|
|
129
|
+
severity: string;
|
|
130
|
+
}>;
|
|
131
|
+
/**
|
|
132
|
+
* Get setup steps for an app.
|
|
133
|
+
*/
|
|
134
|
+
export declare function getAppSetup(app: {
|
|
135
|
+
setup?: string[];
|
|
136
|
+
}): string[];
|
|
137
|
+
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC/B,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAI1E,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,QAAQ,CAAC,EAAE,MAAM;aACjB,gBAAgB,CAAC,EAAE,QAAQ;gBAF3C,OAAO,EAAE,MAAM,EACC,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,gBAAgB,CAAC,EAAE,QAAQ,YAAA;CAK9C;AAyCD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAqB1D;AA+FD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAyBhE;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAM3D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAO5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAW3H;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAwBD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,MAAM,EAAE,CAE/D"}
|