feat(cli): support collection level authorization and headers (#3636)
This commit is contained in:
@@ -1,63 +1,64 @@
|
||||
import { ExecException } from "child_process";
|
||||
|
||||
import { HoppErrorCode } from "../../types/errors";
|
||||
import { execAsync, getErrorCode, getTestJsonFilePath } from "../utils";
|
||||
import { runCLI, getErrorCode, getTestJsonFilePath } from "../utils";
|
||||
|
||||
describe("Test 'hopp test <file>' command:", () => {
|
||||
test("No collection file path provided.", async () => {
|
||||
const cmd = `node ./bin/hopp test`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = "test";
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("INVALID_ARGUMENT");
|
||||
});
|
||||
|
||||
test("Collection file not found.", async () => {
|
||||
const cmd = `node ./bin/hopp test notfound.json`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = "test notfound.json";
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("FILE_NOT_FOUND");
|
||||
});
|
||||
|
||||
test("Collection file is invalid JSON.", async () => {
|
||||
const cmd = `node ./bin/hopp test ${getTestJsonFilePath(
|
||||
const args = `test ${getTestJsonFilePath(
|
||||
"malformed-collection.json"
|
||||
)}`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("UNKNOWN_ERROR");
|
||||
});
|
||||
|
||||
test("Malformed collection file.", async () => {
|
||||
const cmd = `node ./bin/hopp test ${getTestJsonFilePath(
|
||||
const args = `test ${getTestJsonFilePath(
|
||||
"malformed-collection2.json"
|
||||
)}`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("MALFORMED_COLLECTION");
|
||||
});
|
||||
|
||||
test("Invalid arguement.", async () => {
|
||||
const cmd = `node ./bin/hopp invalid-arg`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = "invalid-arg";
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("INVALID_ARGUMENT");
|
||||
});
|
||||
|
||||
test("Collection file not JSON type.", async () => {
|
||||
const cmd = `node ./bin/hopp test ${getTestJsonFilePath("notjson.txt")}`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = `test ${getTestJsonFilePath("notjson.txt")}`;
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("INVALID_FILE_TYPE");
|
||||
});
|
||||
|
||||
test("Some errors occured (exit code 1).", async () => {
|
||||
const cmd = `node ./bin/hopp test ${getTestJsonFilePath("fails.json")}`;
|
||||
const { error } = await execAsync(cmd);
|
||||
const args = `test ${getTestJsonFilePath("fails.json")}`;
|
||||
const { error } = await runCLI(args);
|
||||
|
||||
expect(error).not.toBeNull();
|
||||
expect(error).toMatchObject(<ExecException>{
|
||||
@@ -66,75 +67,83 @@ describe("Test 'hopp test <file>' command:", () => {
|
||||
});
|
||||
|
||||
test("No errors occured (exit code 0).", async () => {
|
||||
const cmd = `node ./bin/hopp test ${getTestJsonFilePath("passes.json")}`;
|
||||
const { error } = await execAsync(cmd);
|
||||
const args = `test ${getTestJsonFilePath("passes.json")}`;
|
||||
const { error } = await runCLI(args);
|
||||
|
||||
expect(error).toBeNull();
|
||||
});
|
||||
|
||||
test("Supports inheriting headers and authorization set at the root collection", async () => {
|
||||
const args = `test ${getTestJsonFilePath("collection-level-headers-auth.json")}`;
|
||||
const { error } = await runCLI(args);
|
||||
|
||||
expect(error).toBeNull();
|
||||
})
|
||||
});
|
||||
|
||||
describe("Test 'hopp test <file> --env <file>' command:", () => {
|
||||
const VALID_TEST_CMD = `node ./bin/hopp test ${getTestJsonFilePath(
|
||||
const VALID_TEST_ARGS = `test ${getTestJsonFilePath(
|
||||
"passes.json"
|
||||
)}`;
|
||||
|
||||
test("No env file path provided.", async () => {
|
||||
const cmd = `${VALID_TEST_CMD} --env`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = `${VALID_TEST_ARGS} --env`;
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("INVALID_ARGUMENT");
|
||||
});
|
||||
|
||||
test("ENV file not JSON type.", async () => {
|
||||
const cmd = `${VALID_TEST_CMD} --env ${getTestJsonFilePath("notjson.txt")}`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = `${VALID_TEST_ARGS} --env ${getTestJsonFilePath("notjson.txt")}`;
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("INVALID_FILE_TYPE");
|
||||
});
|
||||
|
||||
test("ENV file not found.", async () => {
|
||||
const cmd = `${VALID_TEST_CMD} --env notfound.json`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = `${VALID_TEST_ARGS} --env notfound.json`;
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("FILE_NOT_FOUND");
|
||||
});
|
||||
|
||||
test("No errors occured (exit code 0).", async () => {
|
||||
const TESTS_PATH = getTestJsonFilePath("env-flag-tests.json");
|
||||
const ENV_PATH = getTestJsonFilePath("env-flag-envs.json");
|
||||
const cmd = `node ./bin/hopp test ${TESTS_PATH} --env ${ENV_PATH}`;
|
||||
const { error, stdout } = await execAsync(cmd);
|
||||
const args = `test ${TESTS_PATH} --env ${ENV_PATH}`;
|
||||
|
||||
const { error } = await runCLI(args);
|
||||
expect(error).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Test 'hopp test <file> --delay <delay_in_ms>' command:", () => {
|
||||
const VALID_TEST_CMD = `node ./bin/hopp test ${getTestJsonFilePath(
|
||||
const VALID_TEST_ARGS = `test ${getTestJsonFilePath(
|
||||
"passes.json"
|
||||
)}`;
|
||||
|
||||
test("No value passed to delay flag.", async () => {
|
||||
const cmd = `${VALID_TEST_CMD} --delay`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const out = getErrorCode(stderr);
|
||||
const args = `${VALID_TEST_ARGS} --delay`;
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("INVALID_ARGUMENT");
|
||||
});
|
||||
|
||||
test("Invalid value passed to delay flag.", async () => {
|
||||
const cmd = `${VALID_TEST_CMD} --delay 'NaN'`;
|
||||
const { stderr } = await execAsync(cmd);
|
||||
const args = `${VALID_TEST_ARGS} --delay 'NaN'`;
|
||||
const { stderr } = await runCLI(args);
|
||||
|
||||
const out = getErrorCode(stderr);
|
||||
expect(out).toBe<HoppErrorCode>("INVALID_ARGUMENT");
|
||||
});
|
||||
|
||||
test("Valid value passed to delay flag.", async () => {
|
||||
const cmd = `${VALID_TEST_CMD} --delay 1`;
|
||||
const { error } = await execAsync(cmd);
|
||||
const args = `${VALID_TEST_ARGS} --delay 1`;
|
||||
const { error } = await runCLI(args);
|
||||
|
||||
expect(error).toBeNull();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
[
|
||||
{
|
||||
"v": 1,
|
||||
"name": "CollectionA",
|
||||
"folders": [
|
||||
{
|
||||
"v": 1,
|
||||
"name": "FolderA",
|
||||
"folders": [
|
||||
{
|
||||
"v": 1,
|
||||
"name": "FolderB",
|
||||
"folders": [
|
||||
{
|
||||
"v": 1,
|
||||
"name": "FolderC",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"name": "RequestD",
|
||||
"params": [],
|
||||
"headers": [
|
||||
{
|
||||
"active": true,
|
||||
"key": "X-Test-Header",
|
||||
"value": "Overriden at RequestD"
|
||||
}
|
||||
],
|
||||
"method": "GET",
|
||||
"auth": {
|
||||
"authType": "basic",
|
||||
"authActive": true,
|
||||
"username": "username",
|
||||
"password": "password"
|
||||
},
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Overrides auth and headers set at the parent folder\", ()=> {\n pw.expect(pw.response.body.headers[\"x-test-header\"]).toBe(\"Overriden at RequestD\");\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Basic dXNlcm5hbWU6cGFzc3dvcmQ=\");\n});",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"headers": []
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"name": "RequestC",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"method": "GET",
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Correctly inherits auth and headers from the parent folder\", ()=> {\n pw.expect(pw.response.body.headers[\"x-test-header\"]).toBe(\"Overriden at FolderB\");\n pw.expect(pw.response.body.headers[\"key\"]).toBe(\"test-key\");\n});",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "api-key",
|
||||
"authActive": true,
|
||||
"addTo": "Headers",
|
||||
"key": "key",
|
||||
"value": "test-key"
|
||||
},
|
||||
"headers": [
|
||||
{
|
||||
"active": true,
|
||||
"key": "X-Test-Header",
|
||||
"value": "Overriden at FolderB"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"name": "RequestB",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"method": "GET",
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Correctly inherits auth and headers from the parent folder\", ()=> {\n pw.expect(pw.response.body.headers[\"x-test-header\"]).toBe(\"Set at root collection\");\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer BearerToken\");\n});",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
},
|
||||
"id": "clpttpdq00003qp16kut6doqv"
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"headers": []
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"name": "RequestA",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"method": "GET",
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Correctly inherits auth and headers from the root collection\", ()=> {\n pw.expect(pw.response.body.headers[\"x-test-header\"]).toBe(\"Set at root collection\");\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer BearerToken\");\n});",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
},
|
||||
"id": "clpttpdq00003qp16kut6doqv"
|
||||
}
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"active": true,
|
||||
"key": "X-Test-Header",
|
||||
"value": "Set at root collection"
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "bearer",
|
||||
"authActive": true,
|
||||
"token": "BearerToken"
|
||||
}
|
||||
},
|
||||
{
|
||||
"v": 1,
|
||||
"name": "CollectionB",
|
||||
"folders": [
|
||||
{
|
||||
"v": 1,
|
||||
"name": "FolderA",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"name": "RequestB",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"method": "GET",
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Correctly inherits auth and headers from the parent folder\", ()=> {\n pw.expect(pw.response.body.headers[\"x-test-header\"]).toBe(\"Set at root collection\");\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer BearerToken\");\n});",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
},
|
||||
"id": "clpttpdq00003qp16kut6doqv"
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"headers": []
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"name": "RequestA",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"method": "GET",
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Correctly inherits auth and headers from the root collection\", ()=> {\n pw.expect(pw.response.body.headers[\"x-test-header\"]).toBe(\"Set at root collection\");\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer BearerToken\");\n});",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
},
|
||||
"id": "clpttpdq00003qp16kut6doqv"
|
||||
}
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"active": true,
|
||||
"key": "X-Test-Header",
|
||||
"value": "Set at root collection"
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "bearer",
|
||||
"authActive": true,
|
||||
"token": "BearerToken"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,10 +1,17 @@
|
||||
import { exec } from "child_process";
|
||||
import { resolve } from "path";
|
||||
|
||||
import { ExecResponse } from "./types";
|
||||
|
||||
export const execAsync = (command: string): Promise<ExecResponse> =>
|
||||
new Promise((resolve) =>
|
||||
exec(command, (error, stdout, stderr) => resolve({ error, stdout, stderr }))
|
||||
);
|
||||
export const runCLI = (args: string): Promise<ExecResponse> =>
|
||||
{
|
||||
const CLI_PATH = resolve(__dirname, "../../bin/hopp");
|
||||
const command = `node ${CLI_PATH} ${args}`
|
||||
|
||||
return new Promise((resolve) =>
|
||||
exec(command, (error, stdout, stderr) => resolve({ error, stdout, stderr }))
|
||||
);
|
||||
}
|
||||
|
||||
export const trimAnsi = (target: string) => {
|
||||
const ansiRegex =
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import * as A from "fp-ts/Array";
|
||||
import { pipe } from "fp-ts/function";
|
||||
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
|
||||
import { bold } from "chalk";
|
||||
import { log } from "console";
|
||||
import * as A from "fp-ts/Array";
|
||||
import { pipe } from "fp-ts/function";
|
||||
import round from "lodash/round";
|
||||
import { HoppCollection } from "@hoppscotch/data";
|
||||
|
||||
import { CollectionRunnerParam } from "../types/collections";
|
||||
import {
|
||||
HoppEnvs,
|
||||
CollectionStack,
|
||||
RequestReport,
|
||||
HoppEnvs,
|
||||
ProcessRequestParams,
|
||||
RequestReport,
|
||||
} from "../types/request";
|
||||
import {
|
||||
getRequestMetrics,
|
||||
preProcessRequest,
|
||||
processRequest,
|
||||
} from "./request";
|
||||
import { exceptionColors } from "./getters";
|
||||
PreRequestMetrics,
|
||||
RequestMetrics,
|
||||
TestMetrics,
|
||||
} from "../types/response";
|
||||
import { DEFAULT_DURATION_PRECISION } from "./constants";
|
||||
import {
|
||||
printErrorsReport,
|
||||
printFailedTestsReport,
|
||||
@@ -23,15 +25,14 @@ import {
|
||||
printRequestsMetrics,
|
||||
printTestsMetrics,
|
||||
} from "./display";
|
||||
import {
|
||||
PreRequestMetrics,
|
||||
RequestMetrics,
|
||||
TestMetrics,
|
||||
} from "../types/response";
|
||||
import { getTestMetrics } from "./test";
|
||||
import { DEFAULT_DURATION_PRECISION } from "./constants";
|
||||
import { exceptionColors } from "./getters";
|
||||
import { getPreRequestMetrics } from "./pre-request";
|
||||
import { CollectionRunnerParam } from "../types/collections";
|
||||
import {
|
||||
getRequestMetrics,
|
||||
preProcessRequest,
|
||||
processRequest,
|
||||
} from "./request";
|
||||
import { getTestMetrics } from "./test";
|
||||
|
||||
const { WARN, FAIL } = exceptionColors;
|
||||
|
||||
@@ -55,19 +56,19 @@ export const collectionsRunner = async (
|
||||
// Pop out top-most collection from stack to be processed.
|
||||
const { collection, path } = <CollectionStack>collectionStack.pop();
|
||||
|
||||
// Processing each request in collection
|
||||
for (const request of collection.requests) {
|
||||
const _request = preProcessRequest(request);
|
||||
const requestPath = `${path}/${_request.name}`;
|
||||
const processRequestParams: ProcessRequestParams = {
|
||||
path: requestPath,
|
||||
request: _request,
|
||||
envs,
|
||||
delay,
|
||||
};
|
||||
// Processing each request in collection
|
||||
for (const request of collection.requests) {
|
||||
const _request = preProcessRequest(request as HoppRESTRequest, collection);
|
||||
const requestPath = `${path}/${_request.name}`;
|
||||
const processRequestParams: ProcessRequestParams = {
|
||||
path: requestPath,
|
||||
request: _request,
|
||||
envs,
|
||||
delay,
|
||||
};
|
||||
|
||||
// Request processing initiated message.
|
||||
log(WARN(`\nRunning: ${bold(requestPath)}`));
|
||||
// Request processing initiated message.
|
||||
log(WARN(`\nRunning: ${bold(requestPath)}`));
|
||||
|
||||
// Processing current request.
|
||||
const result = await processRequest(processRequestParams)();
|
||||
@@ -77,19 +78,34 @@ export const collectionsRunner = async (
|
||||
envs.global = global;
|
||||
envs.selected = selected;
|
||||
|
||||
// Storing current request's report.
|
||||
const requestReport = result.report;
|
||||
requestsReport.push(requestReport);
|
||||
}
|
||||
// Storing current request's report.
|
||||
const requestReport = result.report;
|
||||
requestsReport.push(requestReport);
|
||||
}
|
||||
|
||||
// Pushing remaining folders realted collection to stack.
|
||||
for (const folder of collection.folders) {
|
||||
collectionStack.push({
|
||||
path: `${path}/${folder.name}`,
|
||||
collection: folder,
|
||||
});
|
||||
// Pushing remaining folders realted collection to stack.
|
||||
for (const folder of collection.folders) {
|
||||
const updatedFolder: HoppCollection = { ...folder }
|
||||
|
||||
if (updatedFolder.auth?.authType === "inherit") {
|
||||
updatedFolder.auth = collection.auth;
|
||||
}
|
||||
|
||||
if (collection.headers?.length) {
|
||||
// Filter out header entries present in the parent collection under the same name
|
||||
// This ensures the folder headers take precedence over the collection headers
|
||||
const filteredHeaders = collection.headers.filter((collectionHeaderEntries) => {
|
||||
return !updatedFolder.headers.some((folderHeaderEntries) => folderHeaderEntries.key === collectionHeaderEntries.key)
|
||||
})
|
||||
updatedFolder.headers.push(...filteredHeaders);
|
||||
}
|
||||
|
||||
collectionStack.push({
|
||||
path: `${path}/${updatedFolder.name}`,
|
||||
collection: updatedFolder,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestsReport;
|
||||
};
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
|
||||
import axios, { Method } from "axios";
|
||||
import { URL } from "url";
|
||||
import * as S from "fp-ts/string";
|
||||
import * as A from "fp-ts/Array";
|
||||
import * as T from "fp-ts/Task";
|
||||
import * as E from "fp-ts/Either";
|
||||
import * as T from "fp-ts/Task";
|
||||
import * as TE from "fp-ts/TaskEither";
|
||||
import { HoppRESTRequest } from "@hoppscotch/data";
|
||||
import { responseErrors } from "./constants";
|
||||
import { getDurationInSeconds, getMetaDataPairs } from "./getters";
|
||||
import { testRunner, getTestScriptParams, hasFailedTestCases } from "./test";
|
||||
import { RequestConfig, EffectiveHoppRESTRequest } from "../interfaces/request";
|
||||
import { pipe } from "fp-ts/function";
|
||||
import * as S from "fp-ts/string";
|
||||
import { hrtime } from "process";
|
||||
import { URL } from "url";
|
||||
import { EffectiveHoppRESTRequest, RequestConfig } from "../interfaces/request";
|
||||
import { RequestRunnerResponse } from "../interfaces/response";
|
||||
import { preRequestScriptRunner } from "./pre-request";
|
||||
import { HoppCLIError, error } from "../types/errors";
|
||||
import {
|
||||
HoppEnvs,
|
||||
ProcessRequestParams,
|
||||
RequestReport,
|
||||
} from "../types/request";
|
||||
import { RequestMetrics } from "../types/response";
|
||||
import { responseErrors } from "./constants";
|
||||
import {
|
||||
printPreRequestRunner,
|
||||
printRequestRunner,
|
||||
printTestRunner,
|
||||
} from "./display";
|
||||
import { error, HoppCLIError } from "../types/errors";
|
||||
import { hrtime } from "process";
|
||||
import { RequestMetrics } from "../types/response";
|
||||
import { pipe } from "fp-ts/function";
|
||||
import { getDurationInSeconds, getMetaDataPairs } from "./getters";
|
||||
import { preRequestScriptRunner } from "./pre-request";
|
||||
import { getTestScriptParams, hasFailedTestCases, testRunner } from "./test";
|
||||
|
||||
// !NOTE: The `config.supported` checks are temporary until OAuth2 and Multipart Forms are supported
|
||||
|
||||
@@ -309,9 +309,12 @@ export const processRequest =
|
||||
* @returns Updated request object free of invalid/missing data.
|
||||
*/
|
||||
export const preProcessRequest = (
|
||||
request: HoppRESTRequest
|
||||
request: HoppRESTRequest,
|
||||
collection: HoppCollection,
|
||||
): HoppRESTRequest => {
|
||||
const tempRequest = Object.assign({}, request);
|
||||
const { headers: parentHeaders, auth: parentAuth } = collection;
|
||||
|
||||
if (!tempRequest.v) {
|
||||
tempRequest.v = "1";
|
||||
}
|
||||
@@ -327,18 +330,31 @@ export const preProcessRequest = (
|
||||
if (!tempRequest.params) {
|
||||
tempRequest.params = [];
|
||||
}
|
||||
if (!tempRequest.headers) {
|
||||
|
||||
if (parentHeaders?.length) {
|
||||
// Filter out header entries present in the parent (folder/collection) under the same name
|
||||
// This ensures the child headers take precedence over the parent headers
|
||||
const filteredEntries = parentHeaders.filter((parentHeaderEntries) => {
|
||||
return !tempRequest.headers.some((reqHeaderEntries) => reqHeaderEntries.key === parentHeaderEntries.key)
|
||||
})
|
||||
tempRequest.headers.push(...filteredEntries);
|
||||
} else if (!tempRequest.headers) {
|
||||
tempRequest.headers = [];
|
||||
}
|
||||
|
||||
if (!tempRequest.preRequestScript) {
|
||||
tempRequest.preRequestScript = "";
|
||||
}
|
||||
if (!tempRequest.testScript) {
|
||||
tempRequest.testScript = "";
|
||||
}
|
||||
if (!tempRequest.auth) {
|
||||
|
||||
if (tempRequest.auth?.authType === "inherit") {
|
||||
tempRequest.auth = parentAuth;
|
||||
} else if (!tempRequest.auth) {
|
||||
tempRequest.auth = { authActive: false, authType: "none" };
|
||||
}
|
||||
|
||||
if (!tempRequest.body) {
|
||||
tempRequest.body = { contentType: null, body: null };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user