Skip to content

Commit 73af777

Browse files
authored
Add interactive mode with verbose checking (#23)
* add back interactive mode, todo: print instructions for running w/ command and fix optional error message on command * add verbose checking
1 parent 091a95d commit 73af777

3 files changed

Lines changed: 44 additions & 8 deletions

File tree

src/index.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
printClientResults,
88
runServerConformanceTest,
99
printServerResults,
10-
printServerSummary
10+
printServerSummary,
11+
runInteractiveMode
1112
} from './runner';
1213
import { listScenarios, listClientScenarios } from './scenarios';
1314
import { ConformanceCheck } from './types';
@@ -24,8 +25,10 @@ program
2425
// Client command - tests a client implementation against scenarios
2526
program
2627
.command('client')
27-
.description('Run conformance tests against a client implementation')
28-
.requiredOption('--command <command>', 'Command to run the client')
28+
.description(
29+
'Run conformance tests against a client implementation or start interactive mode'
30+
)
31+
.option('--command <command>', 'Command to run the client')
2932
.requiredOption('--scenario <scenario>', 'Scenario to test')
3033
.option('--timeout <ms>', 'Timeout in milliseconds', '30000')
3134
.option('--verbose', 'Show verbose output')
@@ -34,10 +37,20 @@ program
3437
// Validate options with Zod
3538
const validated = ClientOptionsSchema.parse(options);
3639

40+
// If no command provided, run in interactive mode
41+
if (!validated.command) {
42+
await runInteractiveMode(
43+
validated.scenario,
44+
validated.verbose ?? false
45+
);
46+
process.exit(0);
47+
}
48+
49+
// Otherwise run conformance test
3750
const result = await runConformanceTest(
3851
validated.command,
3952
validated.scenario,
40-
validated.timeout
53+
validated.timeout ?? 30000
4154
);
4255

4356
const { failed } = printClientResults(

src/runner/client.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ export function printClientResults(
170170
return { passed, failed, denominator };
171171
}
172172

173-
export async function runInteractiveMode(scenarioName: string): Promise<void> {
173+
export async function runInteractiveMode(
174+
scenarioName: string,
175+
verbose: boolean = false
176+
): Promise<void> {
174177
await ensureResultsDir();
175178
const resultDir = createResultDir(scenarioName);
176179
await fs.mkdir(resultDir, { recursive: true });
@@ -193,7 +196,11 @@ export async function runInteractiveMode(scenarioName: string): Promise<void> {
193196
JSON.stringify(checks, null, 2)
194197
);
195198

196-
console.log(`\nChecks:\n${JSON.stringify(checks, null, 2)}`);
199+
if (verbose) {
200+
console.log(`\nChecks:\n${JSON.stringify(checks, null, 2)}`);
201+
} else {
202+
console.log(`\nChecks:\n${formatPrettyChecks(checks)}`);
203+
}
197204
console.log(`\nChecks saved to ${resultDir}/checks.json`);
198205

199206
await scenario.stop();

src/schemas.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { getScenario, getClientScenario } from './scenarios';
33

44
// Client command options schema
55
export const ClientOptionsSchema = z.object({
6-
command: z.string().min(1, 'Command cannot be empty'),
6+
command: z.string().min(1, 'Command cannot be empty').optional(),
77
scenario: z
88
.string()
99
.min(1, 'Scenario cannot be empty')
@@ -21,7 +21,8 @@ export const ClientOptionsSchema = z.object({
2121
.number()
2222
.positive('Timeout must be a positive number')
2323
.int('Timeout must be an integer')
24-
),
24+
)
25+
.optional(),
2526
verbose: z.boolean().optional()
2627
});
2728

@@ -42,3 +43,18 @@ export const ServerOptionsSchema = z.object({
4243
});
4344

4445
export type ServerOptions = z.infer<typeof ServerOptionsSchema>;
46+
47+
// Interactive command options schema
48+
export const InteractiveOptionsSchema = z.object({
49+
scenario: z
50+
.string()
51+
.min(1, 'Scenario cannot be empty')
52+
.refine(
53+
(scenario) => getScenario(scenario) !== undefined,
54+
(scenario) => ({
55+
message: `Unknown scenario '${scenario}'`
56+
})
57+
)
58+
});
59+
60+
export type InteractiveOptions = z.infer<typeof InteractiveOptionsSchema>;

0 commit comments

Comments
 (0)