@requesto/cli 1.13.0 → 1.14.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/dist/index.mjs +185 -33
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -82169,9 +82169,15 @@ var require_environment_service = __commonJS({
|
|
|
82169
82169
|
const overrides = this.localRepo.getForEnvironment(env2.id);
|
|
82170
82170
|
if (Object.keys(overrides).length === 0)
|
|
82171
82171
|
return env2;
|
|
82172
|
+
const variables = env2.variables.map((v) => Object.prototype.hasOwnProperty.call(overrides, v.key) ? { ...v, currentValue: overrides[v.key] } : v);
|
|
82173
|
+
for (const [key, currentValue] of Object.entries(overrides)) {
|
|
82174
|
+
if (!variables.some((v) => v.key === key)) {
|
|
82175
|
+
variables.push({ key, value: "", currentValue, enabled: true });
|
|
82176
|
+
}
|
|
82177
|
+
}
|
|
82172
82178
|
return {
|
|
82173
82179
|
...env2,
|
|
82174
|
-
variables
|
|
82180
|
+
variables
|
|
82175
82181
|
};
|
|
82176
82182
|
}
|
|
82177
82183
|
getAll() {
|
|
@@ -106612,6 +106618,7 @@ var require_proxy_service = __commonJS({
|
|
|
106612
106618
|
validateStatus: () => true,
|
|
106613
106619
|
timeout: opts.timeout ?? 3e4,
|
|
106614
106620
|
responseType: "arraybuffer",
|
|
106621
|
+
...opts.signal && { signal: opts.signal },
|
|
106615
106622
|
...httpsAgent && { httpsAgent }
|
|
106616
106623
|
};
|
|
106617
106624
|
const axiosAuth = (0, auth_1.getAxiosAuthConfig)(substitutedAuth);
|
|
@@ -134526,6 +134533,9 @@ function escapeXml(text) {
|
|
|
134526
134533
|
function seconds(ms) {
|
|
134527
134534
|
return ((ms ?? 0) / 1e3).toFixed(3);
|
|
134528
134535
|
}
|
|
134536
|
+
function skippedTestcaseCount(results) {
|
|
134537
|
+
return results.filter((r2) => r2.status === "skipped" || r2.status === "warned").length;
|
|
134538
|
+
}
|
|
134529
134539
|
function testcase(result, indent2) {
|
|
134530
134540
|
const classname = escapeXml(result.collectionName);
|
|
134531
134541
|
const lines = [];
|
|
@@ -134547,6 +134557,15 @@ function testcase(result, indent2) {
|
|
|
134547
134557
|
);
|
|
134548
134558
|
return lines;
|
|
134549
134559
|
}
|
|
134560
|
+
if (result.status === "warned") {
|
|
134561
|
+
const message = result.warning ?? "Warning";
|
|
134562
|
+
lines.push(
|
|
134563
|
+
`${indent2}<testcase name="${escapeXml(`Request: ${result.request.name}`)}" classname="${classname}" time="${seconds(result.duration)}">`,
|
|
134564
|
+
`${indent2} <skipped message="${escapeXml(message)}"/>`,
|
|
134565
|
+
`${indent2}</testcase>`
|
|
134566
|
+
);
|
|
134567
|
+
return lines;
|
|
134568
|
+
}
|
|
134550
134569
|
if (result.testResults.length === 0) {
|
|
134551
134570
|
lines.push(
|
|
134552
134571
|
`${indent2}<testcase name="Request: ${escapeXml(result.request.name)}" classname="${classname}" time="${seconds(result.duration)}"/>`
|
|
@@ -134588,7 +134607,7 @@ function buildJunitReport(summary) {
|
|
|
134588
134607
|
const time = seconds(results.reduce((acc, r2) => acc + (r2.duration ?? 0), 0));
|
|
134589
134608
|
suites.push(
|
|
134590
134609
|
[
|
|
134591
|
-
` <testsuite name="${escapeXml(collectionName)}" tests="${tests}" failures="${failures}" errors="${errors}" time="${time}">`,
|
|
134610
|
+
` <testsuite name="${escapeXml(collectionName)}" tests="${tests}" failures="${failures}" errors="${errors}" skipped="${skippedTestcaseCount(results)}" time="${time}">`,
|
|
134592
134611
|
...results.flatMap((r2) => testcase(r2, " ")),
|
|
134593
134612
|
` </testsuite>`
|
|
134594
134613
|
].join("\n")
|
|
@@ -134605,7 +134624,7 @@ function buildJunitReport(summary) {
|
|
|
134605
134624
|
const totalErrors = summary.results.filter((r2) => r2.status === "error").length;
|
|
134606
134625
|
return [
|
|
134607
134626
|
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
134608
|
-
`<testsuites name="requesto" tests="${totalTests}" failures="${totalFailures}" errors="${totalErrors}" time="${seconds(summary.totalDuration)}">`,
|
|
134627
|
+
`<testsuites name="requesto" tests="${totalTests}" failures="${totalFailures}" errors="${totalErrors}" skipped="${skippedTestcaseCount(summary.results)}" time="${seconds(summary.totalDuration)}">`,
|
|
134609
134628
|
...suites,
|
|
134610
134629
|
`</testsuites>`,
|
|
134611
134630
|
``
|
|
@@ -134621,6 +134640,7 @@ function buildJsonReport(summary) {
|
|
|
134621
134640
|
passed: summary.passed,
|
|
134622
134641
|
failed: summary.failed,
|
|
134623
134642
|
errored: summary.errored,
|
|
134643
|
+
warned: summary.warned,
|
|
134624
134644
|
skipped: summary.skipped
|
|
134625
134645
|
},
|
|
134626
134646
|
tests: {
|
|
@@ -134642,6 +134662,8 @@ function buildJsonReport(summary) {
|
|
|
134642
134662
|
httpStatus: result.response?.status ?? null,
|
|
134643
134663
|
durationMs: result.duration ?? null,
|
|
134644
134664
|
error: result.error ?? null,
|
|
134665
|
+
warning: result.warning ?? null,
|
|
134666
|
+
warningKind: result.warningKind ?? null,
|
|
134645
134667
|
tests: result.testResults.map((test) => ({
|
|
134646
134668
|
name: test.name,
|
|
134647
134669
|
passed: test.passed,
|
|
@@ -134670,6 +134692,8 @@ function statusIcon(result, paint) {
|
|
|
134670
134692
|
return paint.green("\u2713");
|
|
134671
134693
|
case "failed":
|
|
134672
134694
|
return paint.red("\u2717");
|
|
134695
|
+
case "warned":
|
|
134696
|
+
return paint.yellow("\u26A0");
|
|
134673
134697
|
case "error":
|
|
134674
134698
|
return paint.yellow("\u2717");
|
|
134675
134699
|
case "skipped":
|
|
@@ -134682,6 +134706,8 @@ function dotChar(result, paint) {
|
|
|
134682
134706
|
return paint.green("\xB7");
|
|
134683
134707
|
case "failed":
|
|
134684
134708
|
return paint.red("\xD7");
|
|
134709
|
+
case "warned":
|
|
134710
|
+
return paint.yellow("!");
|
|
134685
134711
|
case "error":
|
|
134686
134712
|
return paint.yellow("\xD7");
|
|
134687
134713
|
case "skipped":
|
|
@@ -134726,6 +134752,10 @@ function createConsoleReporter(mode, stream = process.stdout) {
|
|
|
134726
134752
|
const writeRequestLine = (result) => {
|
|
134727
134753
|
stream.write(` ${statusIcon(result, paint)} ${result.request.name}${paint.dim(durationTail(result))}
|
|
134728
134754
|
`);
|
|
134755
|
+
if (result.status === "warned" && result.warning) {
|
|
134756
|
+
stream.write(paint.yellow(` \u26A0 ${result.warning}
|
|
134757
|
+
`));
|
|
134758
|
+
}
|
|
134729
134759
|
};
|
|
134730
134760
|
const failureEntries = (summary) => summary.results.filter((r2) => r2.status === "failed" || r2.status === "error").map((r2) => ({
|
|
134731
134761
|
label: `${r2.collectionName} > ${r2.request.name}`,
|
|
@@ -134747,10 +134777,11 @@ function createConsoleReporter(mode, stream = process.stdout) {
|
|
|
134747
134777
|
}
|
|
134748
134778
|
};
|
|
134749
134779
|
const writeSummary = (summary, meta) => {
|
|
134750
|
-
const failed = summary.failed + summary.errored;
|
|
134751
134780
|
const counts = [
|
|
134752
134781
|
summary.passed > 0 ? paint.green(`${summary.passed} passed`) : null,
|
|
134753
|
-
failed > 0 ? paint.red(`${failed} failed`) : null,
|
|
134782
|
+
summary.failed > 0 ? paint.red(`${summary.failed} failed`) : null,
|
|
134783
|
+
summary.errored > 0 ? paint.yellow(`${summary.errored} errored`) : null,
|
|
134784
|
+
summary.warned > 0 ? paint.yellow(`${summary.warned} warnings`) : null,
|
|
134754
134785
|
summary.skipped > 0 ? paint.dim(`${summary.skipped} skipped`) : null
|
|
134755
134786
|
].filter(Boolean);
|
|
134756
134787
|
stream.write("\n");
|
|
@@ -134888,11 +134919,12 @@ function buildSavedGraphQLRequest(req) {
|
|
|
134888
134919
|
if (operation.operation !== "query") {
|
|
134889
134920
|
throw new Error("GraphQL GET requests can only execute query operations");
|
|
134890
134921
|
}
|
|
134891
|
-
|
|
134892
|
-
|
|
134893
|
-
|
|
134894
|
-
|
|
134895
|
-
|
|
134922
|
+
return {
|
|
134923
|
+
method: "GET",
|
|
134924
|
+
url: encodeGraphQLGetUrl(req.url, document2, variables),
|
|
134925
|
+
headers,
|
|
134926
|
+
auth: req.auth
|
|
134927
|
+
};
|
|
134896
134928
|
}
|
|
134897
134929
|
setDefaultHeader(headers, "Content-Type", "application/json");
|
|
134898
134930
|
const body = {
|
|
@@ -134908,6 +134940,18 @@ function buildSavedGraphQLRequest(req) {
|
|
|
134908
134940
|
auth: req.auth
|
|
134909
134941
|
};
|
|
134910
134942
|
}
|
|
134943
|
+
function encodeGraphQLGetUrl(base, document2, variables) {
|
|
134944
|
+
const hashIndex = base.indexOf("#");
|
|
134945
|
+
const withoutHash = hashIndex < 0 ? base : base.slice(0, hashIndex);
|
|
134946
|
+
const hash = hashIndex < 0 ? "" : base.slice(hashIndex);
|
|
134947
|
+
const queryIndex = withoutHash.indexOf("?");
|
|
134948
|
+
const path6 = queryIndex < 0 ? withoutHash : withoutHash.slice(0, queryIndex);
|
|
134949
|
+
const params = new URLSearchParams(queryIndex < 0 ? "" : withoutHash.slice(queryIndex + 1));
|
|
134950
|
+
params.set("query", document2);
|
|
134951
|
+
if (variables)
|
|
134952
|
+
params.set("variables", JSON.stringify(variables));
|
|
134953
|
+
return `${path6}?${params}${hash}`;
|
|
134954
|
+
}
|
|
134911
134955
|
function buildProxyRequest(req, insecureTls) {
|
|
134912
134956
|
if (req.requestType === "graphql") {
|
|
134913
134957
|
return { ...buildSavedGraphQLRequest(req), insecureTls };
|
|
@@ -134924,6 +134968,31 @@ function buildProxyRequest(req, insecureTls) {
|
|
|
134924
134968
|
};
|
|
134925
134969
|
}
|
|
134926
134970
|
|
|
134971
|
+
// ../../packages/engine/dist/request/graphql-envelope.js
|
|
134972
|
+
function getGraphQLResponseInfo(response) {
|
|
134973
|
+
if (response.bodyEncoding !== "utf8")
|
|
134974
|
+
return null;
|
|
134975
|
+
try {
|
|
134976
|
+
const payload = JSON.parse(response.body);
|
|
134977
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload))
|
|
134978
|
+
return null;
|
|
134979
|
+
const envelope = payload;
|
|
134980
|
+
if (!Array.isArray(envelope.errors))
|
|
134981
|
+
return null;
|
|
134982
|
+
const errors = envelope.errors.filter((error) => typeof error === "object" && error !== null).map((error) => ({
|
|
134983
|
+
message: typeof error.message === "string" ? error.message : "Unknown GraphQL error",
|
|
134984
|
+
...Array.isArray(error.path) && { path: error.path },
|
|
134985
|
+
...Array.isArray(error.locations) && {
|
|
134986
|
+
locations: error.locations.filter((location2) => typeof location2 === "object" && location2 !== null && typeof location2.line === "number" && typeof location2.column === "number")
|
|
134987
|
+
}
|
|
134988
|
+
}));
|
|
134989
|
+
const hasData = Object.prototype.hasOwnProperty.call(envelope, "data") && envelope.data !== null;
|
|
134990
|
+
return { errors, hasData, isPartial: hasData && errors.length > 0 };
|
|
134991
|
+
} catch {
|
|
134992
|
+
return null;
|
|
134993
|
+
}
|
|
134994
|
+
}
|
|
134995
|
+
|
|
134927
134996
|
// ../../packages/engine/dist/runner/display.js
|
|
134928
134997
|
function buildCollectionItems(collection, folderIds) {
|
|
134929
134998
|
const items = [];
|
|
@@ -134991,6 +135060,31 @@ function applyEnvOverrides(env2, overrides) {
|
|
|
134991
135060
|
}
|
|
134992
135061
|
return { ...env2, variables };
|
|
134993
135062
|
}
|
|
135063
|
+
function resolveStatus(allTestsPassed, testCount, response, warnings) {
|
|
135064
|
+
if (!allTestsPassed)
|
|
135065
|
+
return { status: "failed" };
|
|
135066
|
+
const warningsEnabled = warnings?.httpErrorStatuses !== false;
|
|
135067
|
+
const hasTests = testCount > 0;
|
|
135068
|
+
if (warningsEnabled && !hasTests) {
|
|
135069
|
+
if (response.status >= 400) {
|
|
135070
|
+
const statusText = response.statusText?.trim();
|
|
135071
|
+
return {
|
|
135072
|
+
status: "warned",
|
|
135073
|
+
warning: statusText ? `HTTP ${response.status} ${statusText}` : `HTTP ${response.status}`,
|
|
135074
|
+
warningKind: "http-status"
|
|
135075
|
+
};
|
|
135076
|
+
}
|
|
135077
|
+
const graphqlInfo = getGraphQLResponseInfo(response);
|
|
135078
|
+
if (graphqlInfo && graphqlInfo.errors.length > 0) {
|
|
135079
|
+
return {
|
|
135080
|
+
status: "warned",
|
|
135081
|
+
warning: graphqlInfo.errors[0].message,
|
|
135082
|
+
warningKind: "graphql-errors"
|
|
135083
|
+
};
|
|
135084
|
+
}
|
|
135085
|
+
}
|
|
135086
|
+
return { status: "passed" };
|
|
135087
|
+
}
|
|
134994
135088
|
async function runCollections(opts) {
|
|
134995
135089
|
const results = [];
|
|
134996
135090
|
const started = Date.now();
|
|
@@ -135074,8 +135168,16 @@ async function runCollections(opts) {
|
|
|
135074
135168
|
liveEnv = applyEnvOverrides(liveEnv, outcome);
|
|
135075
135169
|
}
|
|
135076
135170
|
const allPassed = testResults.every((t2) => t2.passed);
|
|
135077
|
-
const status = allPassed
|
|
135078
|
-
const result = {
|
|
135171
|
+
const { status, warning, warningKind } = resolveStatus(allPassed, testResults.length, response, opts.warnings);
|
|
135172
|
+
const result = {
|
|
135173
|
+
...base,
|
|
135174
|
+
status,
|
|
135175
|
+
response,
|
|
135176
|
+
testResults,
|
|
135177
|
+
...warning !== void 0 && { warning },
|
|
135178
|
+
...warningKind !== void 0 && { warningKind },
|
|
135179
|
+
duration: response.duration
|
|
135180
|
+
};
|
|
135079
135181
|
results.push(result);
|
|
135080
135182
|
opts.onEvent?.({ type: "request-end", result });
|
|
135081
135183
|
if (!allPassed && opts.bail)
|
|
@@ -135102,6 +135204,7 @@ async function runCollections(opts) {
|
|
|
135102
135204
|
passed: results.filter((r2) => r2.status === "passed").length,
|
|
135103
135205
|
failed: results.filter((r2) => r2.status === "failed").length,
|
|
135104
135206
|
errored: results.filter((r2) => r2.status === "error").length,
|
|
135207
|
+
warned: results.filter((r2) => r2.status === "warned").length,
|
|
135105
135208
|
skipped: results.filter((r2) => r2.status === "skipped").length,
|
|
135106
135209
|
totalTests: results.reduce((acc, r2) => acc + r2.testResults.length, 0),
|
|
135107
135210
|
passedTests: results.reduce((acc, r2) => acc + r2.testResults.filter((t2) => t2.passed).length, 0),
|
|
@@ -135562,7 +135665,11 @@ var CliWorkspace = class {
|
|
|
135562
135665
|
available ? `Environment "${selector}" not found. Available: ${available} (or "none").` : `Environment "${selector}" not found: this workspace has no environments (use "none" or define one).`
|
|
135563
135666
|
);
|
|
135564
135667
|
}
|
|
135565
|
-
/**
|
|
135668
|
+
/**
|
|
135669
|
+
* Send a request through the backend engine with the given per-run options.
|
|
135670
|
+
* The runner-provided abort signal is forwarded so an interrupted run can
|
|
135671
|
+
* cancel the in-flight HTTP request instead of waiting for its timeout.
|
|
135672
|
+
*/
|
|
135566
135673
|
sendRequest(request, opts) {
|
|
135567
135674
|
return this.proxyService.executeRequest(request, {
|
|
135568
135675
|
// The CLI substitutes variables itself against the live environment,
|
|
@@ -135570,6 +135677,7 @@ var CliWorkspace = class {
|
|
|
135570
135677
|
environment: null,
|
|
135571
135678
|
oauthResolver: opts.oauthResolver,
|
|
135572
135679
|
timeout: opts.timeout,
|
|
135680
|
+
signal: opts.signal,
|
|
135573
135681
|
saveHistory: false
|
|
135574
135682
|
});
|
|
135575
135683
|
}
|
|
@@ -135596,6 +135704,34 @@ function resolveWorkspacePath(input) {
|
|
|
135596
135704
|
|
|
135597
135705
|
// src/commands/run.ts
|
|
135598
135706
|
var BUILTIN_SERVER_VAR = "requestoServerUrl";
|
|
135707
|
+
function wireAbortSignal(opts) {
|
|
135708
|
+
const controller = new AbortController();
|
|
135709
|
+
const externalSignal = opts.signal ?? null;
|
|
135710
|
+
let interrupts = 0;
|
|
135711
|
+
const handleInterrupt = () => {
|
|
135712
|
+
interrupts += 1;
|
|
135713
|
+
if (interrupts > 1) {
|
|
135714
|
+
process.stderr.write("\nForcing exit (second interrupt).\n");
|
|
135715
|
+
process.exit(130);
|
|
135716
|
+
}
|
|
135717
|
+
controller.abort();
|
|
135718
|
+
process.stderr.write(
|
|
135719
|
+
"\nInterrupted: cancelling the in-flight request and skipping the rest of the run. Press Ctrl-C again to force exit.\n"
|
|
135720
|
+
);
|
|
135721
|
+
};
|
|
135722
|
+
const handleExternalAbort = () => {
|
|
135723
|
+
controller.abort(externalSignal?.reason);
|
|
135724
|
+
};
|
|
135725
|
+
process.on("SIGINT", handleInterrupt);
|
|
135726
|
+
externalSignal?.addEventListener("abort", handleExternalAbort);
|
|
135727
|
+
return {
|
|
135728
|
+
signal: controller.signal,
|
|
135729
|
+
dispose: () => {
|
|
135730
|
+
process.off("SIGINT", handleInterrupt);
|
|
135731
|
+
externalSignal?.removeEventListener("abort", handleExternalAbort);
|
|
135732
|
+
}
|
|
135733
|
+
};
|
|
135734
|
+
}
|
|
135599
135735
|
async function runCommand(opts) {
|
|
135600
135736
|
const started = Date.now();
|
|
135601
135737
|
const workspacePath = resolveWorkspacePath(opts.path);
|
|
@@ -135647,6 +135783,7 @@ async function runCommand(opts) {
|
|
|
135647
135783
|
serverUrl = embedded.url;
|
|
135648
135784
|
}
|
|
135649
135785
|
const runEnv = withBuiltinServerVar(effectiveEnv, serverUrl);
|
|
135786
|
+
const abort = wireAbortSignal(opts);
|
|
135650
135787
|
try {
|
|
135651
135788
|
const summary = await runCollections({
|
|
135652
135789
|
collections,
|
|
@@ -135659,6 +135796,8 @@ async function runCommand(opts) {
|
|
|
135659
135796
|
bail: opts.bail,
|
|
135660
135797
|
insecure: opts.insecure,
|
|
135661
135798
|
timeout: opts.timeout,
|
|
135799
|
+
signal: abort.signal,
|
|
135800
|
+
warnings: { httpErrorStatuses: !opts.noWarnHttpErrors },
|
|
135662
135801
|
onEvent: opts.onEvent
|
|
135663
135802
|
});
|
|
135664
135803
|
return {
|
|
@@ -135668,6 +135807,7 @@ async function runCommand(opts) {
|
|
|
135668
135807
|
serverUrl
|
|
135669
135808
|
};
|
|
135670
135809
|
} finally {
|
|
135810
|
+
abort.dispose();
|
|
135671
135811
|
if (embedded) {
|
|
135672
135812
|
try {
|
|
135673
135813
|
await embedded.stop();
|
|
@@ -135686,8 +135826,9 @@ async function runCommand(opts) {
|
|
|
135686
135826
|
}
|
|
135687
135827
|
}
|
|
135688
135828
|
}
|
|
135689
|
-
function computeExitCode(summary) {
|
|
135690
|
-
|
|
135829
|
+
function computeExitCode(summary, opts = {}) {
|
|
135830
|
+
const failing = summary.failed + summary.errored + (opts.failOnWarn ? summary.warned : 0);
|
|
135831
|
+
return failing > 0 ? 1 : 0;
|
|
135691
135832
|
}
|
|
135692
135833
|
function referencesBuiltin(env2) {
|
|
135693
135834
|
if (!env2) return false;
|
|
@@ -135769,6 +135910,26 @@ function writeFileReports(specs, result) {
|
|
|
135769
135910
|
`);
|
|
135770
135911
|
}
|
|
135771
135912
|
}
|
|
135913
|
+
function collectRunOptions(pathArg, opts) {
|
|
135914
|
+
return {
|
|
135915
|
+
path: pathArg,
|
|
135916
|
+
collections: opts.collection,
|
|
135917
|
+
excludeCollections: opts.excludeCollection,
|
|
135918
|
+
folders: opts.folder,
|
|
135919
|
+
environment: opts.environment,
|
|
135920
|
+
vars: opts.var,
|
|
135921
|
+
varFile: opts.varFile,
|
|
135922
|
+
tokens: opts.token,
|
|
135923
|
+
oauthSecrets: opts.oauthSecret,
|
|
135924
|
+
refreshTokens: opts.refreshToken,
|
|
135925
|
+
bail: opts.bail,
|
|
135926
|
+
insecure: opts.insecure,
|
|
135927
|
+
timeout: opts.timeout,
|
|
135928
|
+
persist: opts.persist,
|
|
135929
|
+
server: opts.server,
|
|
135930
|
+
noWarnHttpErrors: opts.warnHttpErrors === false
|
|
135931
|
+
};
|
|
135932
|
+
}
|
|
135772
135933
|
async function runCli(argv) {
|
|
135773
135934
|
const program2 = new Command();
|
|
135774
135935
|
program2.exitOverride();
|
|
@@ -135784,31 +135945,22 @@ The run never touches your workspace or any server data: collections targeting t
|
|
|
135784
135945
|
{{${BUILTIN_SERVER_VAR}}} variable run against an ephemeral scratch server that the CLI
|
|
135785
135946
|
boots and tears down itself. Use --server to test a deployed server instead.
|
|
135786
135947
|
|
|
135787
|
-
Exit codes: 0 = all passed, 1 = failures/errors, 2 = configuration error
|
|
135948
|
+
Exit codes: 0 = all passed, 1 = failures/errors, 2 = configuration error.
|
|
135949
|
+
|
|
135950
|
+
4xx/5xx responses with no test assertions land as warnings: they print as \u26A0 and
|
|
135951
|
+
never affect the exit code unless --fail-on-warn is given. Ctrl-C cancels the
|
|
135952
|
+
in-flight request and skips the rest; press again to exit immediately.`
|
|
135788
135953
|
).argument("[path]", "repository or .requesto directory", process.cwd()).option("-c, --collection <name>", "collection to run (name or id, repeatable; default: all)", collect, []).option("-C, --exclude-collection <name>", "collection to skip (name or id, repeatable; subtracts from the selection)", collect, []).option("-f, --folder <name>", "folder to run within the selected collections (name or id, repeatable)", collect, []).option("-e, --environment <name>", 'environment (name or id, or "none"; default: active environment)').option("--var <key=value>", "variable override (repeatable; highest precedence)", collect, []).option("--var-file <path>", ".env file providing variable overrides").option("--token <configId=accessToken>", "access token for an OAuth config, e.g. --token my-entra=eyJ... (repeatable; REQUESTO_TOKEN_* env vars work too)", collect, []).option("--oauth-secret <configId=secret>", "client secret for a non-interactive OAuth config (repeatable; REQUESTO_OAUTH_SECRET_* env vars work too)", collect, []).option("--refresh-token <configId=token>", "refresh token to seed for an OAuth config (repeatable; REQUESTO_REFRESH_TOKEN_* env vars work too)", collect, []).option("-x, --bail", "stop the run after the first failed or errored request", false).option("--insecure", "skip TLS certificate verification (self-signed certs)", false).option("--timeout <ms>", "per-request timeout in ms (default 30000)", (v) => {
|
|
135789
135954
|
const n = Number(v);
|
|
135790
135955
|
if (!Number.isFinite(n) || n <= 0) throw new CliError(`Invalid --timeout value "${v}"`);
|
|
135791
135956
|
return n;
|
|
135792
|
-
}).option("--persist", "persist OAuth tokens acquired during the run to .requesto/local/ (default: memory only)", false).option("--server <url>", "test a deployed Requesto server instead of the embedded scratch server (its active workspace is protected by a scratch workspace)").option("--reporter <spec>", "reporter: console, verbose, dot, junit:<path> or json:<path> (repeatable; default: console)", collect, []).action(async (pathArg, opts) => {
|
|
135957
|
+
}).option("--persist", "persist OAuth tokens acquired during the run to .requesto/local/ (default: memory only)", false).option("--server <url>", "test a deployed Requesto server instead of the embedded scratch server (its active workspace is protected by a scratch workspace)").option("--no-warn-http-errors", "disable warn-tier results for 4xx/5xx responses with no test assertions (default: warns are on)").option("--fail-on-warn", "exit 1 when any request is warned (default: warns never affect the exit code)", false).option("--reporter <spec>", "reporter: console, verbose, dot, junit:<path> or json:<path> (repeatable; default: console)", collect, []).action(async (pathArg, opts) => {
|
|
135793
135958
|
const specs = opts.reporter.map(parseReporterSpec);
|
|
135794
135959
|
const consoleMode = findConsoleMode(specs);
|
|
135795
135960
|
const consoleReporter = createConsoleReporter(consoleMode);
|
|
135961
|
+
const runOptions = collectRunOptions(pathArg, opts);
|
|
135796
135962
|
const result = await runCommand({
|
|
135797
|
-
|
|
135798
|
-
collections: opts.collection,
|
|
135799
|
-
excludeCollections: opts.excludeCollection,
|
|
135800
|
-
folders: opts.folder,
|
|
135801
|
-
environment: opts.environment,
|
|
135802
|
-
vars: opts.var,
|
|
135803
|
-
varFile: opts.varFile,
|
|
135804
|
-
tokens: opts.token,
|
|
135805
|
-
oauthSecrets: opts.oauthSecret,
|
|
135806
|
-
refreshTokens: opts.refreshToken,
|
|
135807
|
-
bail: opts.bail,
|
|
135808
|
-
insecure: opts.insecure,
|
|
135809
|
-
timeout: opts.timeout,
|
|
135810
|
-
persist: opts.persist,
|
|
135811
|
-
server: opts.server,
|
|
135963
|
+
...runOptions,
|
|
135812
135964
|
onEvent: (event) => consoleReporter.onEvent(event)
|
|
135813
135965
|
});
|
|
135814
135966
|
consoleReporter.finish(result.summary, {
|
|
@@ -135817,7 +135969,7 @@ Exit codes: 0 = all passed, 1 = failures/errors, 2 = configuration error.`
|
|
|
135817
135969
|
serverUrl: result.serverUrl
|
|
135818
135970
|
});
|
|
135819
135971
|
writeFileReports(specs, result);
|
|
135820
|
-
exitCode = computeExitCode(result.summary);
|
|
135972
|
+
exitCode = computeExitCode(result.summary, { failOnWarn: opts.failOnWarn });
|
|
135821
135973
|
});
|
|
135822
135974
|
await program2.parseAsync(argv, { from: "user" });
|
|
135823
135975
|
return exitCode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@requesto/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Run your Requesto collections from the terminal and CI pipelines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^26.6.4",
|
|
28
28
|
"esbuild": "^0.28.2",
|
|
29
|
-
"requesto-backend": "1.
|
|
30
|
-
"requesto-engine": "1.
|
|
29
|
+
"requesto-backend": "1.14.0",
|
|
30
|
+
"requesto-engine": "1.14.0",
|
|
31
31
|
"tsx": "^4.23.15",
|
|
32
32
|
"typescript": "^7.0.2",
|
|
33
33
|
"vitest": "^5.0.3"
|