@boolesai/tspec-cli 1.3.0 → 1.3.1
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/dist/index.js +300 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/types/commands/parse.d.ts +3 -0
- package/types/commands/run.d.ts +2 -0
- package/types/commands/validate.d.ts +3 -0
package/dist/index.js
CHANGED
|
@@ -3,10 +3,10 @@ import { existsSync, statSync, readFileSync, mkdirSync, writeFileSync } from "fs
|
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { isAbsolute, resolve as resolve$1, basename, relative, dirname, join } from "path";
|
|
5
5
|
import ora from "ora";
|
|
6
|
-
import { getTypeFromFilePath, isSuiteFile, getSuiteProtocolType, validateTestCase, clearTemplateCache, getPluginManager, version as version$1, registry as registry$1, executeSuite, parseTestCases, scheduler, PluginManager } from "@boolesai/tspec";
|
|
7
|
-
import { glob } from "glob";
|
|
8
6
|
import chalk from "chalk";
|
|
7
|
+
import { getTypeFromFilePath, isSuiteFile, getSuiteProtocolType, loadConfig, isProxyEnabled, getProxyConfig, validateTestCase, readTestFiles, ProxyClient, clearTemplateCache, getPluginManager, version as version$1, registry as registry$1, executeSuite, parseTestCases, scheduler, PluginManager } from "@boolesai/tspec";
|
|
9
8
|
import { findConfigFile, findLocalConfigFile, findGlobalConfigFile, PLUGINS_DIR, isPluginInstalled, installPlugin, GLOBAL_CONFIG_PATH } from "@boolesai/tspec/plugin";
|
|
9
|
+
import { glob } from "glob";
|
|
10
10
|
import process$2 from "node:process";
|
|
11
11
|
async function discoverTSpecFiles(patterns, cwd) {
|
|
12
12
|
const workingDir = process.cwd();
|
|
@@ -233,7 +233,7 @@ function error(message, ...args) {
|
|
|
233
233
|
console.error(chalk.red(`[error] ${message}`), ...args);
|
|
234
234
|
}
|
|
235
235
|
function log(message, ...args) {
|
|
236
|
-
console.
|
|
236
|
+
console.log(message, ...args);
|
|
237
237
|
}
|
|
238
238
|
function newline() {
|
|
239
239
|
if (!globalOptions.quiet) {
|
|
@@ -250,8 +250,77 @@ const logger = {
|
|
|
250
250
|
newline,
|
|
251
251
|
setOptions: setLoggerOptions
|
|
252
252
|
};
|
|
253
|
+
async function executeValidateViaProxy(params, proxyConfig) {
|
|
254
|
+
const output = params.output ?? "text";
|
|
255
|
+
const { files: fileDescriptors } = await discoverTSpecFiles(params.files);
|
|
256
|
+
const allFiles = fileDescriptors.map((f) => f.path);
|
|
257
|
+
if (allFiles.length === 0) {
|
|
258
|
+
return {
|
|
259
|
+
success: false,
|
|
260
|
+
output: "No .tcase files found",
|
|
261
|
+
data: { results: [] }
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const fileResult = readTestFiles(allFiles);
|
|
265
|
+
if (fileResult.errors.length > 0 && Object.keys(fileResult.fileContents).length === 0) {
|
|
266
|
+
return {
|
|
267
|
+
success: false,
|
|
268
|
+
output: `Failed to read test files: ${fileResult.errors.map((e) => e.error).join(", ")}`,
|
|
269
|
+
data: { results: [] }
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
const client = new ProxyClient({
|
|
273
|
+
url: proxyConfig.url,
|
|
274
|
+
timeout: proxyConfig.timeout,
|
|
275
|
+
headers: proxyConfig.headers
|
|
276
|
+
});
|
|
277
|
+
const result = await client.executeValidate(allFiles, fileResult.fileContents);
|
|
278
|
+
if (!result.success || !result.data) {
|
|
279
|
+
const errorMsg = result.error ? `${result.error.code}: ${result.error.message}${result.error.details ? ` (${result.error.details})` : ""}` : "Unknown proxy error";
|
|
280
|
+
return {
|
|
281
|
+
success: false,
|
|
282
|
+
output: output === "json" ? formatJson({ error: errorMsg, results: [] }) : `Proxy error: ${errorMsg}`,
|
|
283
|
+
data: { results: [] }
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
const proxyResponse = result.data;
|
|
287
|
+
const results = (proxyResponse.results || []).map((r) => ({
|
|
288
|
+
file: r.file,
|
|
289
|
+
valid: r.valid,
|
|
290
|
+
errors: r.errors
|
|
291
|
+
}));
|
|
292
|
+
const hasErrors = results.some((r) => !r.valid);
|
|
293
|
+
let outputStr;
|
|
294
|
+
if (output === "json") {
|
|
295
|
+
outputStr = formatJson({ results });
|
|
296
|
+
} else {
|
|
297
|
+
const parts = [];
|
|
298
|
+
parts.push(chalk.cyan(`[Proxy: ${proxyConfig.url}]`));
|
|
299
|
+
parts.push(formatValidationResults(
|
|
300
|
+
results.map((r) => ({ file: r.file, result: { valid: r.valid, errors: r.errors } })),
|
|
301
|
+
{ format: output }
|
|
302
|
+
));
|
|
303
|
+
outputStr = parts.join("\n");
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
success: !hasErrors,
|
|
307
|
+
output: outputStr,
|
|
308
|
+
data: { results }
|
|
309
|
+
};
|
|
310
|
+
}
|
|
253
311
|
async function executeValidate(params) {
|
|
254
312
|
const output = params.output ?? "text";
|
|
313
|
+
if (!params.noProxy) {
|
|
314
|
+
const configPath = params.config || findConfigFile() || void 0;
|
|
315
|
+
const config2 = await loadConfig(configPath);
|
|
316
|
+
const proxyUrl = params.proxyUrl;
|
|
317
|
+
if (proxyUrl || isProxyEnabled(config2, "validate")) {
|
|
318
|
+
const proxyConfig = proxyUrl ? { url: proxyUrl, timeout: 3e4, headers: {} } : getProxyConfig(config2);
|
|
319
|
+
if (proxyConfig) {
|
|
320
|
+
return executeValidateViaProxy(params, proxyConfig);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
255
324
|
const { files: fileDescriptors } = await discoverTSpecFiles(params.files);
|
|
256
325
|
if (fileDescriptors.length === 0) {
|
|
257
326
|
return {
|
|
@@ -279,13 +348,16 @@ async function executeValidate(params) {
|
|
|
279
348
|
data: { results }
|
|
280
349
|
};
|
|
281
350
|
}
|
|
282
|
-
const validateCommand = new Command("validate").description("Validate .tcase files for schema correctness").argument("<files...>", "Files or glob patterns to validate").option("-o, --output <format>", "Output format: json, text", "text").option("-q, --quiet", "Only output errors").action(async (files, options) => {
|
|
351
|
+
const validateCommand = new Command("validate").description("Validate .tcase files for schema correctness").argument("<files...>", "Files or glob patterns to validate").option("-o, --output <format>", "Output format: json, text", "text").option("-q, --quiet", "Only output errors").option("--config <path>", "Path to tspec.config.json").option("--no-proxy", "Disable proxy for this execution").option("--proxy-url <url>", "Override proxy URL for this execution").action(async (files, options) => {
|
|
283
352
|
setLoggerOptions({ quiet: options.quiet });
|
|
284
353
|
const spinner = options.quiet ? null : ora("Validating...").start();
|
|
285
354
|
try {
|
|
286
355
|
const result = await executeValidate({
|
|
287
356
|
files,
|
|
288
|
-
output: options.output
|
|
357
|
+
output: options.output,
|
|
358
|
+
noProxy: options.noProxy,
|
|
359
|
+
proxyUrl: options.proxyUrl,
|
|
360
|
+
config: options.config
|
|
289
361
|
});
|
|
290
362
|
spinner?.stop();
|
|
291
363
|
logger.log(result.output);
|
|
@@ -355,6 +427,23 @@ async function runFileTestCasesInternal(descriptor, env, params, concurrency, fa
|
|
|
355
427
|
async function executeRun(params) {
|
|
356
428
|
clearTemplateCache();
|
|
357
429
|
const configPath = params.config || findConfigFile();
|
|
430
|
+
if (!params.noProxy) {
|
|
431
|
+
const config2 = await loadConfig(configPath || void 0);
|
|
432
|
+
const proxyUrl = params.proxyUrl;
|
|
433
|
+
if (proxyUrl || isProxyEnabled(config2, "run")) {
|
|
434
|
+
const proxyConfig = proxyUrl ? { url: proxyUrl, timeout: 3e4, headers: {} } : getProxyConfig(config2);
|
|
435
|
+
if (proxyConfig) {
|
|
436
|
+
return executeRunViaProxy(params, proxyConfig);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (configPath) {
|
|
441
|
+
const pluginManager = getPluginManager(version$1);
|
|
442
|
+
await pluginManager.initialize(configPath, {
|
|
443
|
+
skipAutoInstall: params.noAutoInstall
|
|
444
|
+
});
|
|
445
|
+
registry$1.enablePluginManager();
|
|
446
|
+
}
|
|
358
447
|
if (configPath) {
|
|
359
448
|
const pluginManager = getPluginManager(version$1);
|
|
360
449
|
await pluginManager.initialize(configPath, {
|
|
@@ -474,6 +563,7 @@ ${parseErrors.length} file(s) failed to parse:`);
|
|
|
474
563
|
}
|
|
475
564
|
async function executeSuiteRun(suiteFiles, additionalTspecFiles, options) {
|
|
476
565
|
const { env, params: paramValues, failFast, output, verbose, quiet } = options;
|
|
566
|
+
const isJsonOutput = output === "json";
|
|
477
567
|
const allResults = [];
|
|
478
568
|
const parseErrors = [];
|
|
479
569
|
let totalTests = 0;
|
|
@@ -487,14 +577,15 @@ async function executeSuiteRun(suiteFiles, additionalTspecFiles, options) {
|
|
|
487
577
|
const suiteResult = await executeSuite(suiteDescriptor.path, {
|
|
488
578
|
env,
|
|
489
579
|
params: paramValues,
|
|
490
|
-
|
|
580
|
+
silent: isJsonOutput,
|
|
581
|
+
onSuiteStart: isJsonOutput ? void 0 : (name) => {
|
|
491
582
|
if (!quiet) logger.log(chalk.blue(`
|
|
492
583
|
Suite: ${name}`));
|
|
493
584
|
},
|
|
494
|
-
onTestStart: (file) => {
|
|
585
|
+
onTestStart: isJsonOutput ? void 0 : (file) => {
|
|
495
586
|
if (verbose) logger.log(chalk.gray(` Running: ${file}`));
|
|
496
587
|
},
|
|
497
|
-
onTestComplete: (file, result) => {
|
|
588
|
+
onTestComplete: isJsonOutput ? void 0 : (file, result) => {
|
|
498
589
|
const statusIcon = result.status === "passed" ? chalk.green("✓") : chalk.red("✗");
|
|
499
590
|
if (!quiet) logger.log(` ${statusIcon} ${result.name} (${result.duration}ms)`);
|
|
500
591
|
}
|
|
@@ -582,9 +673,105 @@ ${parseErrors.length} file(s) failed to parse:`);
|
|
|
582
673
|
data: { results: allResults, summary, parseErrors }
|
|
583
674
|
};
|
|
584
675
|
}
|
|
585
|
-
|
|
676
|
+
async function executeRunViaProxy(params, proxyConfig) {
|
|
677
|
+
const output = params.output ?? "text";
|
|
678
|
+
const { tspecFiles, suiteFiles } = await discoverAllTestFiles(params.files);
|
|
679
|
+
const allFiles = [...tspecFiles.map((f) => f.path), ...suiteFiles.map((f) => f.path)];
|
|
680
|
+
if (allFiles.length === 0) {
|
|
681
|
+
return {
|
|
682
|
+
success: false,
|
|
683
|
+
output: "No .tcase or .tsuite files found",
|
|
684
|
+
data: {
|
|
685
|
+
results: [],
|
|
686
|
+
summary: { total: 0, passed: 0, failed: 0, passRate: 0, duration: 0 },
|
|
687
|
+
parseErrors: []
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
const fileResult = readTestFiles(allFiles);
|
|
692
|
+
if (fileResult.errors.length > 0 && Object.keys(fileResult.fileContents).length === 0) {
|
|
693
|
+
return {
|
|
694
|
+
success: false,
|
|
695
|
+
output: `Failed to read test files: ${fileResult.errors.map((e) => e.error).join(", ")}`,
|
|
696
|
+
data: {
|
|
697
|
+
results: [],
|
|
698
|
+
summary: { total: 0, passed: 0, failed: 0, passRate: 0, duration: 0 },
|
|
699
|
+
parseErrors: fileResult.errors.map((e) => ({ file: e.file, error: e.error }))
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
const client = new ProxyClient({
|
|
704
|
+
url: proxyConfig.url,
|
|
705
|
+
timeout: proxyConfig.timeout,
|
|
706
|
+
headers: proxyConfig.headers
|
|
707
|
+
});
|
|
708
|
+
const result = await client.executeRun(
|
|
709
|
+
allFiles,
|
|
710
|
+
fileResult.fileContents,
|
|
711
|
+
{
|
|
712
|
+
concurrency: params.concurrency,
|
|
713
|
+
failFast: params.failFast,
|
|
714
|
+
env: params.env,
|
|
715
|
+
params: params.params
|
|
716
|
+
}
|
|
717
|
+
);
|
|
718
|
+
if (!result.success || !result.data) {
|
|
719
|
+
const errorMsg = result.error ? `${result.error.code}: ${result.error.message}${result.error.details ? ` (${result.error.details})` : ""}` : "Unknown proxy error";
|
|
720
|
+
return {
|
|
721
|
+
success: false,
|
|
722
|
+
output: output === "json" ? formatJson({ error: errorMsg, results: [], summary: { total: 0, passed: 0, failed: 0, passRate: 0, duration: 0 }, parseErrors: [] }) : `Proxy error: ${errorMsg}`,
|
|
723
|
+
data: {
|
|
724
|
+
results: [],
|
|
725
|
+
summary: { total: 0, passed: 0, failed: 0, passRate: 0, duration: 0 },
|
|
726
|
+
parseErrors: []
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
const proxyResponse = result.data;
|
|
731
|
+
const formattedResults = (proxyResponse.results || []).map((r) => ({
|
|
732
|
+
testCaseId: r.testCaseId,
|
|
733
|
+
passed: r.passed,
|
|
734
|
+
duration: r.duration,
|
|
735
|
+
assertions: (r.assertions || []).map((a) => ({
|
|
736
|
+
passed: a.passed,
|
|
737
|
+
type: a.type,
|
|
738
|
+
message: a.message || ""
|
|
739
|
+
}))
|
|
740
|
+
}));
|
|
741
|
+
const summary = proxyResponse.summary ? {
|
|
742
|
+
total: proxyResponse.summary.total,
|
|
743
|
+
passed: proxyResponse.summary.passed,
|
|
744
|
+
failed: proxyResponse.summary.failed,
|
|
745
|
+
passRate: proxyResponse.summary.passRate,
|
|
746
|
+
duration: proxyResponse.summary.duration
|
|
747
|
+
} : { total: 0, passed: 0, failed: 0, passRate: 0, duration: 0 };
|
|
748
|
+
const parseErrors = (proxyResponse.parseErrors || []).map((e) => ({
|
|
749
|
+
file: e.file,
|
|
750
|
+
error: e.message
|
|
751
|
+
}));
|
|
752
|
+
let outputStr;
|
|
753
|
+
if (output === "json") {
|
|
754
|
+
outputStr = formatJson({ results: formattedResults, summary, parseErrors });
|
|
755
|
+
} else {
|
|
756
|
+
const parts = [];
|
|
757
|
+
parts.push(chalk.cyan(`[Proxy: ${proxyConfig.url}]`));
|
|
758
|
+
parts.push(formatTestResults(formattedResults, summary, { format: output, verbose: params.verbose }));
|
|
759
|
+
if (parseErrors.length > 0) {
|
|
760
|
+
parts.push(`
|
|
761
|
+
${parseErrors.length} file(s) failed to parse:`);
|
|
762
|
+
parseErrors.forEach(({ file, error: error2 }) => parts.push(` ${file}: ${error2}`));
|
|
763
|
+
}
|
|
764
|
+
outputStr = parts.join("\n");
|
|
765
|
+
}
|
|
766
|
+
return {
|
|
767
|
+
success: summary.failed === 0 && parseErrors.length === 0,
|
|
768
|
+
output: outputStr,
|
|
769
|
+
data: { results: formattedResults, summary, parseErrors }
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
const runCommand = new Command("run").description("Execute test cases and report results").argument("<files...>", "Files or glob patterns to run").option("-o, --output <format>", "Output format: json, text", "text").option("-c, --concurrency <number>", "Max concurrent tests", "5").option("-e, --env <key=value>", "Environment variables", parseKeyValue$1, {}).option("-p, --params <key=value>", "Parameters", parseKeyValue$1, {}).option("-v, --verbose", "Verbose output").option("-q, --quiet", "Only output summary").option("--fail-fast", "Stop on first failure").option("--config <path>", "Path to tspec.config.json for plugin loading").option("--no-auto-install", "Skip automatic plugin installation").option("--no-proxy", "Disable proxy for this execution").option("--proxy-url <url>", "Override proxy URL for this execution").action(async (files, options) => {
|
|
586
773
|
setLoggerOptions({ verbose: options.verbose, quiet: options.quiet });
|
|
587
|
-
const spinner = options.quiet ? null : ora("Running tests...").start();
|
|
774
|
+
const spinner = options.quiet || options.output === "json" ? null : ora("Running tests...").start();
|
|
588
775
|
try {
|
|
589
776
|
const result = await executeRun({
|
|
590
777
|
files,
|
|
@@ -595,6 +782,8 @@ const runCommand = new Command("run").description("Execute test cases and report
|
|
|
595
782
|
failFast: options.failFast,
|
|
596
783
|
config: options.config,
|
|
597
784
|
noAutoInstall: options.noAutoInstall,
|
|
785
|
+
noProxy: options.noProxy,
|
|
786
|
+
proxyUrl: options.proxyUrl,
|
|
598
787
|
env: options.env,
|
|
599
788
|
params: options.params
|
|
600
789
|
});
|
|
@@ -639,12 +828,108 @@ function parseKeyValue(value, previous = {}) {
|
|
|
639
828
|
}
|
|
640
829
|
return previous;
|
|
641
830
|
}
|
|
831
|
+
async function executeParseViaProxy(params, proxyConfig) {
|
|
832
|
+
const output = params.output ?? "text";
|
|
833
|
+
params.verbose ?? false;
|
|
834
|
+
const { files: fileDescriptors } = await discoverTSpecFiles(params.files);
|
|
835
|
+
const allFiles = fileDescriptors.map((f) => f.path);
|
|
836
|
+
if (allFiles.length === 0) {
|
|
837
|
+
return {
|
|
838
|
+
success: false,
|
|
839
|
+
output: "No .tcase files found",
|
|
840
|
+
data: {
|
|
841
|
+
testCases: [],
|
|
842
|
+
parseErrors: [],
|
|
843
|
+
summary: { totalFiles: 0, totalTestCases: 0, parseErrors: 0 }
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
const fileResult = readTestFiles(allFiles);
|
|
848
|
+
if (fileResult.errors.length > 0 && Object.keys(fileResult.fileContents).length === 0) {
|
|
849
|
+
return {
|
|
850
|
+
success: false,
|
|
851
|
+
output: `Failed to read test files: ${fileResult.errors.map((e) => e.error).join(", ")}`,
|
|
852
|
+
data: {
|
|
853
|
+
testCases: [],
|
|
854
|
+
parseErrors: fileResult.errors.map((e) => ({ file: e.file, error: e.error })),
|
|
855
|
+
summary: { totalFiles: 0, totalTestCases: 0, parseErrors: fileResult.errors.length }
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
const client = new ProxyClient({
|
|
860
|
+
url: proxyConfig.url,
|
|
861
|
+
timeout: proxyConfig.timeout,
|
|
862
|
+
headers: proxyConfig.headers
|
|
863
|
+
});
|
|
864
|
+
const result = await client.executeParse(
|
|
865
|
+
allFiles,
|
|
866
|
+
fileResult.fileContents,
|
|
867
|
+
{ env: params.env, params: params.params }
|
|
868
|
+
);
|
|
869
|
+
if (!result.success || !result.data) {
|
|
870
|
+
const errorMsg = result.error ? `${result.error.code}: ${result.error.message}${result.error.details ? ` (${result.error.details})` : ""}` : "Unknown proxy error";
|
|
871
|
+
return {
|
|
872
|
+
success: false,
|
|
873
|
+
output: output === "json" ? formatJson({ error: errorMsg, testCases: [], errors: [], summary: { totalFiles: 0, totalTestCases: 0, parseErrors: 0 } }) : `Proxy error: ${errorMsg}`,
|
|
874
|
+
data: {
|
|
875
|
+
testCases: [],
|
|
876
|
+
parseErrors: [],
|
|
877
|
+
summary: { totalFiles: 0, totalTestCases: 0, parseErrors: 0 }
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
const proxyResponse = result.data;
|
|
882
|
+
const testCases = proxyResponse.testCases || [];
|
|
883
|
+
const parseErrors = (proxyResponse.parseErrors || []).map((e) => ({
|
|
884
|
+
file: e.file,
|
|
885
|
+
error: e.message
|
|
886
|
+
}));
|
|
887
|
+
const summary = proxyResponse.summary || {
|
|
888
|
+
totalFiles: allFiles.length,
|
|
889
|
+
totalTestCases: testCases.length,
|
|
890
|
+
parseErrors: parseErrors.length
|
|
891
|
+
};
|
|
892
|
+
let outputStr;
|
|
893
|
+
if (output === "json") {
|
|
894
|
+
outputStr = formatJson({ testCases, errors: parseErrors, summary });
|
|
895
|
+
} else {
|
|
896
|
+
const parts = [];
|
|
897
|
+
parts.push(chalk.cyan(`[Proxy: ${proxyConfig.url}]`));
|
|
898
|
+
parts.push(`Parsed ${testCases.length} test case(s) from ${summary.totalFiles} file(s)`);
|
|
899
|
+
parts.push("");
|
|
900
|
+
for (const testCase of testCases) {
|
|
901
|
+
parts.push(formatParsedTestCase(testCase, { format: output }));
|
|
902
|
+
parts.push("");
|
|
903
|
+
}
|
|
904
|
+
if (parseErrors.length > 0) {
|
|
905
|
+
parts.push(`${parseErrors.length} file(s) failed to parse:`);
|
|
906
|
+
parseErrors.forEach(({ file, error: error2 }) => parts.push(` ${file}: ${error2}`));
|
|
907
|
+
}
|
|
908
|
+
outputStr = parts.join("\n");
|
|
909
|
+
}
|
|
910
|
+
return {
|
|
911
|
+
success: parseErrors.length === 0,
|
|
912
|
+
output: outputStr,
|
|
913
|
+
data: { testCases, parseErrors, summary }
|
|
914
|
+
};
|
|
915
|
+
}
|
|
642
916
|
async function executeParse(params) {
|
|
643
917
|
clearTemplateCache();
|
|
644
918
|
const output = params.output ?? "text";
|
|
645
919
|
params.verbose ?? false;
|
|
646
920
|
const env = params.env ?? {};
|
|
647
921
|
const paramValues = params.params ?? {};
|
|
922
|
+
if (!params.noProxy) {
|
|
923
|
+
const configPath = params.config || findConfigFile() || void 0;
|
|
924
|
+
const config2 = await loadConfig(configPath);
|
|
925
|
+
const proxyUrl = params.proxyUrl;
|
|
926
|
+
if (proxyUrl || isProxyEnabled(config2, "parse")) {
|
|
927
|
+
const proxyConfig = proxyUrl ? { url: proxyUrl, timeout: 3e4, headers: {} } : getProxyConfig(config2);
|
|
928
|
+
if (proxyConfig) {
|
|
929
|
+
return executeParseViaProxy(params, proxyConfig);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
648
933
|
const { files: fileDescriptors } = await discoverTSpecFiles(params.files);
|
|
649
934
|
if (fileDescriptors.length === 0) {
|
|
650
935
|
return {
|
|
@@ -696,7 +981,7 @@ async function executeParse(params) {
|
|
|
696
981
|
data: { testCases: allTestCases, parseErrors, summary }
|
|
697
982
|
};
|
|
698
983
|
}
|
|
699
|
-
const parseCommand = new Command("parse").description("Parse and display test case information without execution").argument("<files...>", "Files or glob patterns to parse").option("-o, --output <format>", "Output format: json, text", "text").option("-v, --verbose", "Show detailed information").option("-q, --quiet", "Minimal output").option("-e, --env <key=value>", "Environment variables", parseKeyValue, {}).option("-p, --params <key=value>", "Parameters", parseKeyValue, {}).action(async (files, options) => {
|
|
984
|
+
const parseCommand = new Command("parse").description("Parse and display test case information without execution").argument("<files...>", "Files or glob patterns to parse").option("-o, --output <format>", "Output format: json, text", "text").option("-v, --verbose", "Show detailed information").option("-q, --quiet", "Minimal output").option("-e, --env <key=value>", "Environment variables", parseKeyValue, {}).option("-p, --params <key=value>", "Parameters", parseKeyValue, {}).option("--config <path>", "Path to tspec.config.json").option("--no-proxy", "Disable proxy for this execution").option("--proxy-url <url>", "Override proxy URL for this execution").action(async (files, options) => {
|
|
700
985
|
setLoggerOptions({ verbose: options.verbose, quiet: options.quiet });
|
|
701
986
|
const spinner = options.quiet ? null : ora("Parsing...").start();
|
|
702
987
|
try {
|
|
@@ -705,7 +990,10 @@ const parseCommand = new Command("parse").description("Parse and display test ca
|
|
|
705
990
|
output: options.output,
|
|
706
991
|
verbose: options.verbose,
|
|
707
992
|
env: options.env,
|
|
708
|
-
params: options.params
|
|
993
|
+
params: options.params,
|
|
994
|
+
noProxy: options.noProxy,
|
|
995
|
+
proxyUrl: options.proxyUrl,
|
|
996
|
+
config: options.config
|
|
709
997
|
});
|
|
710
998
|
spinner?.stop();
|
|
711
999
|
logger.log(result.output);
|