feat: added execution duration and updated collection-metrics (#2257)
This commit is contained in:
@@ -29,6 +29,7 @@ export interface RequestRunnerResponse extends TestResponse {
|
|||||||
endpoint: string;
|
endpoint: string;
|
||||||
method: Method;
|
method: Method;
|
||||||
statusText: string;
|
statusText: string;
|
||||||
|
duration: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,14 +50,14 @@ export interface TestScriptParams {
|
|||||||
* @property {string} descriptor Test description.
|
* @property {string} descriptor Test description.
|
||||||
* @property {ExpectResult[]} expectResults Expected results for each
|
* @property {ExpectResult[]} expectResults Expected results for each
|
||||||
* test-case.
|
* test-case.
|
||||||
* @property {number} failing Total failing test-cases.
|
* @property {number} failed Total failed test-cases.
|
||||||
* @property {number} passing Total passing test-cases;
|
* @property {number} passed Total passed test-cases;
|
||||||
*/
|
*/
|
||||||
export interface TestReport {
|
export interface TestReport {
|
||||||
descriptor: string;
|
descriptor: string;
|
||||||
expectResults: ExpectResult[];
|
expectResults: ExpectResult[];
|
||||||
failing: number;
|
failed: number;
|
||||||
passing: number;
|
passed: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,4 +28,5 @@ export type RequestReport = {
|
|||||||
tests: TestReport[];
|
tests: TestReport[];
|
||||||
errors: HoppCLIError[];
|
errors: HoppCLIError[];
|
||||||
result: boolean;
|
result: boolean;
|
||||||
|
duration: { test: number; request: number; preRequest: number };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,20 +9,74 @@ export type ExpectResult = {
|
|||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TestMetrics = {
|
/**
|
||||||
/**
|
* Stats describing number of failed and passed for test-cases/test-suites/
|
||||||
* Total passed and failed test-cases.
|
* test-scripts/pre-request-scripts/request.
|
||||||
*/
|
*/
|
||||||
tests: { failing: number; passing: number };
|
export type Stats = {
|
||||||
|
failed: number;
|
||||||
|
passed: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PreRequestMetrics = {
|
||||||
|
/**
|
||||||
|
* Pre-request-script(s) failed and passed stats.
|
||||||
|
*/
|
||||||
|
scripts: Stats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Total test-blocks/test-suites passed & failed, calculated
|
* Time taken (in seconds) to execute pre-request-script(s).
|
||||||
* based on test-cases failed/passed with in each test-block.
|
|
||||||
*/
|
*/
|
||||||
testSuites: { failing: number; passing: number };
|
duration: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RequestMetrics = {
|
||||||
|
/**
|
||||||
|
* Request(s) failed and passed stats.
|
||||||
|
*/
|
||||||
|
requests: Stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time taken (in seconds) to execute request(s).
|
||||||
|
*/
|
||||||
|
duration: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TestMetrics = {
|
||||||
|
/**
|
||||||
|
* Test-cases failed and passed stats.
|
||||||
|
*/
|
||||||
|
tests: Stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test-block(s)/test-suite(s) failed and passed stats.
|
||||||
|
*/
|
||||||
|
testSuites: Stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test script(s) execution failed and passed stats.
|
||||||
|
*/
|
||||||
|
scripts: Stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time taken (in seconds) to execute test-script(s).
|
||||||
|
*/
|
||||||
|
duration: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TestRunnerRes = {
|
export type TestRunnerRes = {
|
||||||
|
/**
|
||||||
|
* Updated envs after running test-script.
|
||||||
|
*/
|
||||||
envs: HoppEnvs;
|
envs: HoppEnvs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes expected details for each test-suite.
|
||||||
|
*/
|
||||||
testsReport: TestReport[];
|
testsReport: TestReport[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time taken (in seconds) to execute the test-script.
|
||||||
|
*/
|
||||||
|
duration: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,16 +3,31 @@ import * as A from "fp-ts/Array";
|
|||||||
import { pipe } from "fp-ts/function";
|
import { pipe } from "fp-ts/function";
|
||||||
import { bold } from "chalk";
|
import { bold } from "chalk";
|
||||||
import { log } from "console";
|
import { log } from "console";
|
||||||
|
import round from "lodash/round";
|
||||||
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
|
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
|
||||||
import { HoppEnvs, CollectionStack, RequestReport } from "../types/request";
|
import { HoppEnvs, CollectionStack, RequestReport } from "../types/request";
|
||||||
import { preProcessRequest, processRequest } from "./request";
|
import {
|
||||||
|
getRequestMetrics,
|
||||||
|
preProcessRequest,
|
||||||
|
processRequest,
|
||||||
|
} from "./request";
|
||||||
import { exceptionColors } from "./getters";
|
import { exceptionColors } from "./getters";
|
||||||
import { TestReport } from "../interfaces/response";
|
|
||||||
import {
|
import {
|
||||||
printErrorsReport,
|
printErrorsReport,
|
||||||
printFailedTestsReport,
|
printFailedTestsReport,
|
||||||
|
printPreRequestMetrics,
|
||||||
|
printRequestsMetrics,
|
||||||
printTestsMetrics,
|
printTestsMetrics,
|
||||||
} from "./display";
|
} from "./display";
|
||||||
|
import {
|
||||||
|
PreRequestMetrics,
|
||||||
|
RequestMetrics,
|
||||||
|
TestMetrics,
|
||||||
|
} from "../types/response";
|
||||||
|
import { getTestMetrics } from "./test";
|
||||||
|
import { DEFAULT_DURATION_PRECISION } from "./constants";
|
||||||
|
import { getPreRequestMetrics } from "./pre-request";
|
||||||
|
|
||||||
const { WARN, FAIL } = exceptionColors;
|
const { WARN, FAIL } = exceptionColors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,21 +97,39 @@ const getCollectionStack = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints collection-runner-report using test-metrics data in table format.
|
* Prints collection-runner-report using test-metrics, request-metrics and
|
||||||
|
* pre-request-metrics data in pretty-format.
|
||||||
* @param requestsReport Provides data for each request-report which includes
|
* @param requestsReport Provides data for each request-report which includes
|
||||||
* failed-tests-report, errors
|
* path of each request within collection-json file, failed-tests-report, errors,
|
||||||
|
* total execution duration for requests, pre-request-scripts, test-scripts.
|
||||||
* @returns True, if collection runner executed without any errors or failed test-cases.
|
* @returns True, if collection runner executed without any errors or failed test-cases.
|
||||||
* False, if errors occured or test-cases failed.
|
* False, if errors occured or test-cases failed.
|
||||||
*/
|
*/
|
||||||
export const collectionsRunnerResult = (
|
export const collectionsRunnerResult = (
|
||||||
requestsReport: RequestReport[]
|
requestsReport: RequestReport[]
|
||||||
): boolean => {
|
): boolean => {
|
||||||
const testsReport: TestReport[] = [];
|
const overallTestMetrics = <TestMetrics>{
|
||||||
|
tests: { failed: 0, passed: 0 },
|
||||||
|
testSuites: { failed: 0, passed: 0 },
|
||||||
|
duration: 0,
|
||||||
|
scripts: { failed: 0, passed: 0 },
|
||||||
|
};
|
||||||
|
const overallRequestMetrics = <RequestMetrics>{
|
||||||
|
requests: { failed: 0, passed: 0 },
|
||||||
|
duration: 0,
|
||||||
|
};
|
||||||
|
const overallPreRequestMetrics = <PreRequestMetrics>{
|
||||||
|
scripts: { failed: 0, passed: 0 },
|
||||||
|
duration: 0,
|
||||||
|
};
|
||||||
let finalResult = true;
|
let finalResult = true;
|
||||||
|
|
||||||
// Printing requests-report details of failed-tests and errors
|
// Printing requests-report details of failed-tests and errors
|
||||||
for (const requestReport of requestsReport) {
|
for (const requestReport of requestsReport) {
|
||||||
const { path, tests, errors, result } = requestReport;
|
const { path, tests, errors, result, duration } = requestReport;
|
||||||
|
const requestDuration = duration.request;
|
||||||
|
const testsDuration = duration.test;
|
||||||
|
const preRequestDuration = duration.preRequest;
|
||||||
|
|
||||||
finalResult = finalResult && result;
|
finalResult = finalResult && result;
|
||||||
|
|
||||||
@@ -104,10 +137,56 @@ export const collectionsRunnerResult = (
|
|||||||
|
|
||||||
printErrorsReport(path, errors);
|
printErrorsReport(path, errors);
|
||||||
|
|
||||||
testsReport.push.apply(testsReport, tests);
|
/**
|
||||||
|
* Extracting current request report's test-metrics and updating
|
||||||
|
* overall test-metrics.
|
||||||
|
*/
|
||||||
|
const testMetrics = getTestMetrics(tests, testsDuration, errors);
|
||||||
|
overallTestMetrics.duration += testMetrics.duration;
|
||||||
|
overallTestMetrics.testSuites.failed += testMetrics.testSuites.failed;
|
||||||
|
overallTestMetrics.testSuites.passed += testMetrics.testSuites.passed;
|
||||||
|
overallTestMetrics.tests.failed += testMetrics.tests.failed;
|
||||||
|
overallTestMetrics.tests.passed += testMetrics.tests.passed;
|
||||||
|
overallTestMetrics.scripts.failed += testMetrics.scripts.failed;
|
||||||
|
overallTestMetrics.scripts.passed += testMetrics.scripts.passed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracting current request report's request-metrics and updating
|
||||||
|
* overall request-metrics.
|
||||||
|
*/
|
||||||
|
const requestMetrics = getRequestMetrics(errors, requestDuration);
|
||||||
|
overallRequestMetrics.duration += requestMetrics.duration;
|
||||||
|
overallRequestMetrics.requests.failed += requestMetrics.requests.failed;
|
||||||
|
overallRequestMetrics.requests.passed += requestMetrics.requests.passed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracting current request report's pre-request-metrics and updating
|
||||||
|
* overall pre-request-metrics.
|
||||||
|
*/
|
||||||
|
const preRequestMetrics = getPreRequestMetrics(errors, preRequestDuration);
|
||||||
|
overallPreRequestMetrics.duration += preRequestMetrics.duration;
|
||||||
|
overallPreRequestMetrics.scripts.failed += preRequestMetrics.scripts.failed;
|
||||||
|
overallPreRequestMetrics.scripts.passed += preRequestMetrics.scripts.passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
printTestsMetrics(testsReport);
|
const testMetricsDuration = overallTestMetrics.duration;
|
||||||
|
const requestMetricsDuration = overallRequestMetrics.duration;
|
||||||
|
|
||||||
|
// Rounding-off overall test-metrics duration upto DEFAULT_DURATION_PRECISION.
|
||||||
|
overallTestMetrics.duration = round(
|
||||||
|
testMetricsDuration,
|
||||||
|
DEFAULT_DURATION_PRECISION
|
||||||
|
);
|
||||||
|
|
||||||
|
// Rounding-off overall request-metrics duration upto DEFAULT_DURATION_PRECISION.
|
||||||
|
overallRequestMetrics.duration = round(
|
||||||
|
requestMetricsDuration,
|
||||||
|
DEFAULT_DURATION_PRECISION
|
||||||
|
);
|
||||||
|
|
||||||
|
printTestsMetrics(overallTestMetrics);
|
||||||
|
printRequestsMetrics(overallRequestMetrics);
|
||||||
|
printPreRequestMetrics(overallPreRequestMetrics);
|
||||||
|
|
||||||
return finalResult;
|
return finalResult;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,3 +5,8 @@ export const responseErrors: ResponseErrorPair = {
|
|||||||
408: "NETWORK TIMEOUT",
|
408: "NETWORK TIMEOUT",
|
||||||
400: "BAD REQUEST",
|
400: "BAD REQUEST",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default decimal precision to round-off calculated HRTime time in seconds.
|
||||||
|
*/
|
||||||
|
export const DEFAULT_DURATION_PRECISION: number = 3;
|
||||||
|
|||||||
@@ -4,49 +4,109 @@ import { handleError } from "../handlers/error";
|
|||||||
import { RequestConfig } from "../interfaces/request";
|
import { RequestConfig } from "../interfaces/request";
|
||||||
import { RequestRunnerResponse, TestReport } from "../interfaces/response";
|
import { RequestRunnerResponse, TestReport } from "../interfaces/response";
|
||||||
import { HoppCLIError } from "../types/errors";
|
import { HoppCLIError } from "../types/errors";
|
||||||
import { exceptionColors, getColorStatusCode } from "./getters";
|
|
||||||
import {
|
import {
|
||||||
getFailedExpectedResults,
|
PreRequestMetrics,
|
||||||
getFailedTestsReport,
|
RequestMetrics,
|
||||||
getTestMetrics,
|
TestMetrics,
|
||||||
} from "./test";
|
} from "../types/response";
|
||||||
const { FAIL, SUCCESS, BG_INFO } = exceptionColors;
|
import { exceptionColors, getColorStatusCode } from "./getters";
|
||||||
|
import { getFailedExpectedResults, getFailedTestsReport } from "./test";
|
||||||
|
|
||||||
|
const { FAIL, SUCCESS, BG_INFO, INFO_BRIGHT } = exceptionColors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints total failed and passed stats of executed pre-request-scripts.
|
||||||
|
* @param preRequestMetrics Provides data for total failed and passed
|
||||||
|
* stats of all executed pre-request-scripts.
|
||||||
|
*/
|
||||||
|
export const printPreRequestMetrics = (
|
||||||
|
preRequestMetrics: PreRequestMetrics
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
scripts: { failed, passed },
|
||||||
|
} = preRequestMetrics;
|
||||||
|
|
||||||
|
const failedPreRequestsOut = FAIL(`${failed} failed`);
|
||||||
|
const passedPreRequestsOut = SUCCESS(`${passed} passed`);
|
||||||
|
const preRequestsOut = `Pre-Request Scripts: ${failedPreRequestsOut} ${passedPreRequestsOut}\n`;
|
||||||
|
|
||||||
|
const message = `\n${preRequestsOut}`;
|
||||||
|
process.stdout.write(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints total failed and passed stats, duration of executed request.
|
||||||
|
* @param requestsMetrics Provides data for total duration and total failed and
|
||||||
|
* passed stats of all executed requests.
|
||||||
|
*/
|
||||||
|
export const printRequestsMetrics = (requestsMetrics: RequestMetrics) => {
|
||||||
|
const {
|
||||||
|
requests: { failed, passed },
|
||||||
|
duration,
|
||||||
|
} = requestsMetrics;
|
||||||
|
|
||||||
|
const failedRequestsOut = FAIL(`${failed} failed`);
|
||||||
|
const passedRequestsOut = SUCCESS(`${passed} passed`);
|
||||||
|
const requestsOut = `Requests: ${failedRequestsOut} ${passedRequestsOut}\n`;
|
||||||
|
const requestsDurationOut =
|
||||||
|
duration > 0 ? `Requests Duration: ${INFO_BRIGHT(`${duration} s`)}\n` : "";
|
||||||
|
|
||||||
|
const message = `\n${requestsOut}${requestsDurationOut}`;
|
||||||
|
process.stdout.write(message);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints test-suites in pretty-way describing each test-suites failed/passed
|
* Prints test-suites in pretty-way describing each test-suites failed/passed
|
||||||
* status.
|
* status and duration to execute the test-script.
|
||||||
* @param testsReport Providing details of each test-suites with tests-report.
|
* @param testsReport Providing details of each test-suites with tests-report.
|
||||||
|
* @param duration Time taken (in seconds) to execute the test-script.
|
||||||
*/
|
*/
|
||||||
export const printTestSuitesReport = (testsReport: TestReport[]) => {
|
export const printTestSuitesReport = (
|
||||||
|
testsReport: TestReport[],
|
||||||
|
duration: number
|
||||||
|
) => {
|
||||||
|
const durationMsg =
|
||||||
|
duration > 0 ? INFO_BRIGHT(`Ran tests in ${duration} s`) : "";
|
||||||
|
|
||||||
group();
|
group();
|
||||||
for (const testReport of testsReport) {
|
for (const testReport of testsReport) {
|
||||||
const { failing, descriptor } = testReport;
|
const { failed, descriptor } = testReport;
|
||||||
|
|
||||||
if (failing > 0) {
|
if (failed > 0) {
|
||||||
log(`${FAIL("✖")} ${descriptor}`);
|
log(`${FAIL("✖")} ${descriptor}`);
|
||||||
} else {
|
} else {
|
||||||
log(`${SUCCESS("✔")} ${descriptor}`);
|
log(`${SUCCESS("✔")} ${descriptor}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log(durationMsg);
|
||||||
groupEnd();
|
groupEnd();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints total number of test-cases and test-suites passed/failed.
|
* Prints total failed and passed stats for test-suites, test-cases, test-scripts,
|
||||||
* @param testsReport Provides testSuites and testCases metrics.
|
* and total duration of executed test-scripts.
|
||||||
|
* @param testsMetrics Provides testSuites, testCases metrics, test-script
|
||||||
|
* execution duration and test-script passed/failed stats.
|
||||||
*/
|
*/
|
||||||
export const printTestsMetrics = (testsReport: TestReport[]) => {
|
export const printTestsMetrics = (testsMetrics: TestMetrics) => {
|
||||||
const { testSuites, tests } = getTestMetrics(testsReport);
|
const { testSuites, tests, duration, scripts } = testsMetrics;
|
||||||
|
|
||||||
const failedTestCasesOut = FAIL(`${tests.failing} failing`);
|
const failedTestCasesOut = FAIL(`${tests.failed} failed`);
|
||||||
const passedTestCasesOut = SUCCESS(`${tests.passing} passing`);
|
const passedTestCasesOut = SUCCESS(`${tests.passed} passed`);
|
||||||
const testCasesOut = `Test Cases: ${failedTestCasesOut} ${passedTestCasesOut}\n`;
|
const testCasesOut = `Test Cases: ${failedTestCasesOut} ${passedTestCasesOut}\n`;
|
||||||
|
|
||||||
const failedTestSuitesOut = FAIL(`${testSuites.failing} failing`);
|
const failedTestSuitesOut = FAIL(`${testSuites.failed} failed`);
|
||||||
const passedTestSuitesOut = SUCCESS(`${testSuites.passing} passing`);
|
const passedTestSuitesOut = SUCCESS(`${testSuites.passed} passed`);
|
||||||
const testSuitesOut = `Test Suites: ${failedTestSuitesOut} ${passedTestSuitesOut}\n`;
|
const testSuitesOut = `Test Suites: ${failedTestSuitesOut} ${passedTestSuitesOut}\n`;
|
||||||
|
|
||||||
const message = `\n${testCasesOut}${testSuitesOut}`;
|
const failedTestScriptsOut = FAIL(`${scripts.failed} failed`);
|
||||||
|
const passedTestScriptsOut = SUCCESS(`${scripts.passed} passed`);
|
||||||
|
const testScriptsOut = `Test Scripts: ${failedTestScriptsOut} ${passedTestScriptsOut}\n`;
|
||||||
|
|
||||||
|
const testsDurationOut =
|
||||||
|
duration > 0 ? `Tests Duration: ${INFO_BRIGHT(`${duration} s`)}\n` : "";
|
||||||
|
|
||||||
|
const message = `\n${testCasesOut}${testSuitesOut}${testScriptsOut}${testsDurationOut}`;
|
||||||
process.stdout.write(message);
|
process.stdout.write(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,7 +141,7 @@ export const printFailedTestsReport = (
|
|||||||
) => {
|
) => {
|
||||||
const failedTestsReport = getFailedTestsReport(testsReport);
|
const failedTestsReport = getFailedTestsReport(testsReport);
|
||||||
|
|
||||||
// Only printing test-reports with failing test-cases.
|
// Only printing test-reports with failed test-cases.
|
||||||
if (failedTestsReport.length > 0) {
|
if (failedTestsReport.length > 0) {
|
||||||
const FAILED_TESTS_PATH = FAIL(`\n${bold(path)} failed tests:`);
|
const FAILED_TESTS_PATH = FAIL(`\n${bold(path)} failed tests:`);
|
||||||
group(FAILED_TESTS_PATH);
|
group(FAILED_TESTS_PATH);
|
||||||
@@ -110,7 +170,10 @@ export const printFailedTestsReport = (
|
|||||||
* Provides methods for printing request-runner's state messages.
|
* Provides methods for printing request-runner's state messages.
|
||||||
*/
|
*/
|
||||||
export const printRequestRunner = {
|
export const printRequestRunner = {
|
||||||
// Request-runner starting message.
|
/**
|
||||||
|
* Request-runner starting message.
|
||||||
|
* @param requestConfig Provides request's method and url.
|
||||||
|
*/
|
||||||
start: (requestConfig: RequestConfig) => {
|
start: (requestConfig: RequestConfig) => {
|
||||||
const METHOD = BG_INFO(` ${requestConfig.method} `);
|
const METHOD = BG_INFO(` ${requestConfig.method} `);
|
||||||
const ENDPOINT = requestConfig.url;
|
const ENDPOINT = requestConfig.url;
|
||||||
@@ -118,15 +181,21 @@ export const printRequestRunner = {
|
|||||||
process.stdout.write(`${METHOD} ${ENDPOINT}`);
|
process.stdout.write(`${METHOD} ${ENDPOINT}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Prints response's status, when request-runner executes successfully.
|
/**
|
||||||
|
* Prints response's status, when request-runner executes successfully.
|
||||||
|
* @param requestResponse Provides request's status and execution duration.
|
||||||
|
*/
|
||||||
success: (requestResponse: RequestRunnerResponse) => {
|
success: (requestResponse: RequestRunnerResponse) => {
|
||||||
const { status, statusText } = requestResponse;
|
const { status, statusText, duration } = requestResponse;
|
||||||
const statusMsg = getColorStatusCode(status, statusText);
|
const statusMsg = getColorStatusCode(status, statusText);
|
||||||
|
const durationMsg = duration > 0 ? INFO_BRIGHT(`(${duration} s)`) : "";
|
||||||
|
|
||||||
process.stdout.write(` ${statusMsg}\n`);
|
process.stdout.write(` ${statusMsg} ${durationMsg}\n`);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Prints error message, when request-runner fails to execute.
|
/**
|
||||||
|
* Prints error message, when request-runner fails to execute.
|
||||||
|
*/
|
||||||
fail: () => log(FAIL(" ERROR\n⚠ Error running request.")),
|
fail: () => log(FAIL(" ERROR\n⚠ Error running request.")),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,12 +203,27 @@ export const printRequestRunner = {
|
|||||||
* Provides methods for printing test-runner's state messages.
|
* Provides methods for printing test-runner's state messages.
|
||||||
*/
|
*/
|
||||||
export const printTestRunner = {
|
export const printTestRunner = {
|
||||||
|
/**
|
||||||
|
* Prints test-runner failed message.
|
||||||
|
*/
|
||||||
fail: () => log(FAIL("⚠ Error running test-script.")),
|
fail: () => log(FAIL("⚠ Error running test-script.")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints test-runner success message including tests-report.
|
||||||
|
* @param testsReport List of expected result(s) and metrics for the executed
|
||||||
|
* test-script.
|
||||||
|
* @param duration Time taken to execute a test-script.
|
||||||
|
*/
|
||||||
|
success: (testsReport: TestReport[], duration: number) =>
|
||||||
|
printTestSuitesReport(testsReport, duration),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides methods for printing pre-request-runner's state messages.
|
* Provides methods for printing pre-request-runner's state messages.
|
||||||
*/
|
*/
|
||||||
export const printPreRequestRunner = {
|
export const printPreRequestRunner = {
|
||||||
|
/**
|
||||||
|
* Prints pre-request-runner failed message.
|
||||||
|
*/
|
||||||
fail: () => log(FAIL("⚠ Error running pre-request-script.")),
|
fail: () => log(FAIL("⚠ Error running pre-request-script.")),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import * as E from "fp-ts/Either";
|
|||||||
import * as S from "fp-ts/string";
|
import * as S from "fp-ts/string";
|
||||||
import * as O from "fp-ts/Option";
|
import * as O from "fp-ts/Option";
|
||||||
import { error } from "../types/errors";
|
import { error } from "../types/errors";
|
||||||
|
import round from "lodash/round";
|
||||||
|
import { DEFAULT_DURATION_PRECISION } from "./constants";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates template string (status + statusText) with specific color unicodes
|
* Generates template string (status + statusText) with specific color unicodes
|
||||||
@@ -106,8 +108,24 @@ export const exceptionColors = {
|
|||||||
INFO: chalk.blue,
|
INFO: chalk.blue,
|
||||||
FAIL: chalk.red,
|
FAIL: chalk.red,
|
||||||
SUCCESS: chalk.green,
|
SUCCESS: chalk.green,
|
||||||
|
INFO_BRIGHT: chalk.blueBright,
|
||||||
BG_WARN: chalk.bgYellow,
|
BG_WARN: chalk.bgYellow,
|
||||||
BG_FAIL: chalk.bgRed,
|
BG_FAIL: chalk.bgRed,
|
||||||
BG_INFO: chalk.bgBlue,
|
BG_INFO: chalk.bgBlue,
|
||||||
BG_SUCCESS: chalk.bgGreen,
|
BG_SUCCESS: chalk.bgGreen,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates duration in seconds for given end-HRTime of format [seconds, nanoseconds],
|
||||||
|
* which is rounded-off upto given decimal value.
|
||||||
|
* @param end Providing end-HRTime of format [seconds, nanoseconds].
|
||||||
|
* @param precision Decimal precision to round-off float duration value (DEFAULT = 3).
|
||||||
|
* @returns Rounded duration in seconds for given decimal precision.
|
||||||
|
*/
|
||||||
|
export const getDurationInSeconds = (
|
||||||
|
end: [number, number],
|
||||||
|
precision: number = DEFAULT_DURATION_PRECISION
|
||||||
|
) => {
|
||||||
|
const durationInSeconds = (end[0] * 1e9 + end[1]) / 1e9;
|
||||||
|
return round(durationInSeconds, precision);
|
||||||
|
};
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { isHoppCLIError } from "./checks";
|
|||||||
import { tupleToRecord, arraySort, arrayFlatMap } from "./functions/array";
|
import { tupleToRecord, arraySort, arrayFlatMap } from "./functions/array";
|
||||||
import { toFormData } from "./mutators";
|
import { toFormData } from "./mutators";
|
||||||
import { getEffectiveFinalMetaData } from "./getters";
|
import { getEffectiveFinalMetaData } from "./getters";
|
||||||
|
import { PreRequestMetrics } from "../types/response";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs pre-request-script runner over given request which extracts set ENVs and
|
* Runs pre-request-script runner over given request which extracts set ENVs and
|
||||||
@@ -266,3 +267,23 @@ function getFinalBodyFromRequest(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pre-request-metrics (stats + duration) object based on existence of
|
||||||
|
* PRE_REQUEST_ERROR code in given hopp-error list.
|
||||||
|
* @param errors List of errors to check for PRE_REQUEST_ERROR code.
|
||||||
|
* @param duration Time taken (in seconds) to execute the pre-request-script.
|
||||||
|
* @returns Object containing details of pre-request-script's execution stats
|
||||||
|
* i.e., failed/passed data and duration.
|
||||||
|
*/
|
||||||
|
export const getPreRequestMetrics = (
|
||||||
|
errors: HoppCLIError[],
|
||||||
|
duration: number
|
||||||
|
): PreRequestMetrics =>
|
||||||
|
pipe(
|
||||||
|
errors,
|
||||||
|
A.some(({ code }) => code === "PRE_REQUEST_SCRIPT_ERROR"),
|
||||||
|
(hasPreReqErrors) =>
|
||||||
|
hasPreReqErrors ? { failed: 1, passed: 0 } : { failed: 0, passed: 1 },
|
||||||
|
(scripts) => <PreRequestMetrics>{ scripts, duration }
|
||||||
|
);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import * as E from "fp-ts/Either";
|
|||||||
import * as TE from "fp-ts/TaskEither";
|
import * as TE from "fp-ts/TaskEither";
|
||||||
import { HoppRESTRequest } from "@hoppscotch/data";
|
import { HoppRESTRequest } from "@hoppscotch/data";
|
||||||
import { responseErrors } from "./constants";
|
import { responseErrors } from "./constants";
|
||||||
import { getMetaDataPairs } from "./getters";
|
import { getDurationInSeconds, getMetaDataPairs } from "./getters";
|
||||||
import { testRunner, getTestScriptParams, hasFailedTestCases } from "./test";
|
import { testRunner, getTestScriptParams, hasFailedTestCases } from "./test";
|
||||||
import { RequestConfig, EffectiveHoppRESTRequest } from "../interfaces/request";
|
import { RequestConfig, EffectiveHoppRESTRequest } from "../interfaces/request";
|
||||||
import { RequestRunnerResponse } from "../interfaces/response";
|
import { RequestRunnerResponse } from "../interfaces/response";
|
||||||
@@ -17,9 +17,11 @@ import {
|
|||||||
printPreRequestRunner,
|
printPreRequestRunner,
|
||||||
printRequestRunner,
|
printRequestRunner,
|
||||||
printTestRunner,
|
printTestRunner,
|
||||||
printTestSuitesReport,
|
|
||||||
} from "./display";
|
} from "./display";
|
||||||
import { error, HoppCLIError } from "../types/errors";
|
import { error, HoppCLIError } from "../types/errors";
|
||||||
|
import { hrtime } from "process";
|
||||||
|
import { RequestMetrics } from "../types/response";
|
||||||
|
import { pipe } from "fp-ts/function";
|
||||||
|
|
||||||
// !NOTE: The `config.supported` checks are temporary until OAuth2 and Multipart Forms are supported
|
// !NOTE: The `config.supported` checks are temporary until OAuth2 and Multipart Forms are supported
|
||||||
|
|
||||||
@@ -83,6 +85,8 @@ export const requestRunner =
|
|||||||
requestConfig: RequestConfig
|
requestConfig: RequestConfig
|
||||||
): TE.TaskEither<HoppCLIError, RequestRunnerResponse> =>
|
): TE.TaskEither<HoppCLIError, RequestRunnerResponse> =>
|
||||||
async () => {
|
async () => {
|
||||||
|
const start = hrtime();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// NOTE: Temporary parsing check for request endpoint.
|
// NOTE: Temporary parsing check for request endpoint.
|
||||||
requestConfig.url = new URL(requestConfig.url ?? "").toString();
|
requestConfig.url = new URL(requestConfig.url ?? "").toString();
|
||||||
@@ -95,6 +99,7 @@ export const requestRunner =
|
|||||||
endpoint: getRequest.endpoint(config.url),
|
endpoint: getRequest.endpoint(config.url),
|
||||||
method: getRequest.method(config.method),
|
method: getRequest.method(config.method),
|
||||||
body: baseResponse.data,
|
body: baseResponse.data,
|
||||||
|
duration: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// !NOTE: Temporary `config.supported` check
|
// !NOTE: Temporary `config.supported` check
|
||||||
@@ -104,6 +109,10 @@ export const requestRunner =
|
|||||||
runnerResponse.statusText = responseErrors[status];
|
runnerResponse.statusText = responseErrors[status];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const end = hrtime(start);
|
||||||
|
const duration = getDurationInSeconds(end);
|
||||||
|
runnerResponse.duration = duration;
|
||||||
|
|
||||||
return E.right(runnerResponse);
|
return E.right(runnerResponse);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let status: number;
|
let status: number;
|
||||||
@@ -114,6 +123,7 @@ export const requestRunner =
|
|||||||
statusText: responseErrors[400],
|
statusText: responseErrors[400],
|
||||||
status: 400,
|
status: 400,
|
||||||
headers: [],
|
headers: [],
|
||||||
|
duration: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (axios.isAxiosError(e)) {
|
if (axios.isAxiosError(e)) {
|
||||||
@@ -133,6 +143,10 @@ export const requestRunner =
|
|||||||
return E.left(error({ code: "REQUEST_ERROR", data: E.toError(e) }));
|
return E.left(error({ code: "REQUEST_ERROR", data: E.toError(e) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const end = hrtime(start);
|
||||||
|
const duration = getDurationInSeconds(end);
|
||||||
|
runnerResponse.duration = duration;
|
||||||
|
|
||||||
return E.right(runnerResponse);
|
return E.right(runnerResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +206,7 @@ export const processRequest =
|
|||||||
tests: [],
|
tests: [],
|
||||||
errors: [],
|
errors: [],
|
||||||
result: true,
|
result: true,
|
||||||
|
duration: { test: 0, request: 0, preRequest: 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initial value for effective-request with default values for properties.
|
// Initial value for effective-request with default values for properties.
|
||||||
@@ -229,6 +244,7 @@ export const processRequest =
|
|||||||
status: 400,
|
status: 400,
|
||||||
statusText: "",
|
statusText: "",
|
||||||
body: Object(null),
|
body: Object(null),
|
||||||
|
duration: 0,
|
||||||
};
|
};
|
||||||
// Executing request-runner.
|
// Executing request-runner.
|
||||||
const requestRunnerRes = await requestRunner(requestConfig)();
|
const requestRunnerRes = await requestRunner(requestConfig)();
|
||||||
@@ -240,6 +256,7 @@ export const processRequest =
|
|||||||
printRequestRunner.fail();
|
printRequestRunner.fail();
|
||||||
} else {
|
} else {
|
||||||
_requestRunnerRes = requestRunnerRes.right;
|
_requestRunnerRes = requestRunnerRes.right;
|
||||||
|
report.duration.request = _requestRunnerRes.duration;
|
||||||
printRequestRunner.success(_requestRunnerRes);
|
printRequestRunner.success(_requestRunnerRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,17 +276,19 @@ export const processRequest =
|
|||||||
report.errors.push(testRunnerRes.left);
|
report.errors.push(testRunnerRes.left);
|
||||||
report.result = report.result && false;
|
report.result = report.result && false;
|
||||||
} else {
|
} else {
|
||||||
const { envs, testsReport } = testRunnerRes.right;
|
const { envs, testsReport, duration } = testRunnerRes.right;
|
||||||
const _hasFailedTestCases = hasFailedTestCases(testsReport);
|
const _hasFailedTestCases = hasFailedTestCases(testsReport);
|
||||||
|
|
||||||
// Updating report with current tests & result.
|
// Updating report with current tests, result and duration.
|
||||||
report.tests = testsReport;
|
report.tests = testsReport;
|
||||||
report.result = report.result && _hasFailedTestCases;
|
report.result = report.result && _hasFailedTestCases;
|
||||||
|
report.duration.test = duration;
|
||||||
|
|
||||||
// Updating resulting envs from test-runner.
|
// Updating resulting envs from test-runner.
|
||||||
result.envs = envs;
|
result.envs = envs;
|
||||||
|
|
||||||
printTestSuitesReport(testsReport);
|
// Printing tests-report, when test-runner executes successfully.
|
||||||
|
printTestRunner.success(testsReport, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.report = report;
|
result.report = report;
|
||||||
@@ -319,3 +338,23 @@ export const preProcessRequest = (
|
|||||||
}
|
}
|
||||||
return tempRequest;
|
return tempRequest;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get request-metrics object (stats+duration) based on existence of REQUEST_ERROR code
|
||||||
|
* in hopp-errors list.
|
||||||
|
* @param errors List of errors to check for REQUEST_ERROR.
|
||||||
|
* @param duration Time taken (in seconds) to execute the request.
|
||||||
|
* @returns Object containing details of request's execution stats i.e., failed/passed
|
||||||
|
* data and duration.
|
||||||
|
*/
|
||||||
|
export const getRequestMetrics = (
|
||||||
|
errors: HoppCLIError[],
|
||||||
|
duration: number
|
||||||
|
): RequestMetrics =>
|
||||||
|
pipe(
|
||||||
|
errors,
|
||||||
|
A.some(({ code }) => code === "REQUEST_ERROR"),
|
||||||
|
(hasReqErrors) =>
|
||||||
|
hasReqErrors ? { failed: 1, passed: 0 } : { failed: 0, passed: 1 },
|
||||||
|
(requests) => <RequestMetrics>{ requests, duration }
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { HoppRESTRequest } from "@hoppscotch/data";
|
import { HoppRESTRequest } from "@hoppscotch/data";
|
||||||
import { execTestScript, TestDescriptor } from "@hoppscotch/js-sandbox";
|
import { execTestScript, TestDescriptor } from "@hoppscotch/js-sandbox";
|
||||||
|
import { hrtime } from "process";
|
||||||
import { flow, pipe } from "fp-ts/function";
|
import { flow, pipe } from "fp-ts/function";
|
||||||
import * as RA from "fp-ts/ReadonlyArray";
|
import * as RA from "fp-ts/ReadonlyArray";
|
||||||
import * as A from "fp-ts/Array";
|
import * as A from "fp-ts/Array";
|
||||||
@@ -13,12 +14,13 @@ import {
|
|||||||
import { error, HoppCLIError } from "../types/errors";
|
import { error, HoppCLIError } from "../types/errors";
|
||||||
import { HoppEnvs } from "../types/request";
|
import { HoppEnvs } from "../types/request";
|
||||||
import { ExpectResult, TestMetrics, TestRunnerRes } from "../types/response";
|
import { ExpectResult, TestMetrics, TestRunnerRes } from "../types/response";
|
||||||
|
import { getDurationInSeconds } from "./getters";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes test script and runs testDescriptorParser to generate test-report using
|
* Executes test script and runs testDescriptorParser to generate test-report using
|
||||||
* expected-results, test-status & test-descriptor.
|
* expected-results, test-status & test-descriptor.
|
||||||
* @param testScriptData Parameters related to test-script function.
|
* @param testScriptData Parameters related to test-script function.
|
||||||
* @returns If executes successfully, we get TestRunnerRes(updated ENVs + test-reports).
|
* @returns If executes successfully, we get TestRunnerRes(updated ENVs, test-reports, duration).
|
||||||
* Else, HoppCLIError with appropriate code & data.
|
* Else, HoppCLIError with appropriate code & data.
|
||||||
*/
|
*/
|
||||||
export const testRunner = (
|
export const testRunner = (
|
||||||
@@ -28,16 +30,22 @@ export const testRunner = (
|
|||||||
/**
|
/**
|
||||||
* Executing test-script.
|
* Executing test-script.
|
||||||
*/
|
*/
|
||||||
|
TE.Do,
|
||||||
|
TE.bind("start", () => TE.of(hrtime())),
|
||||||
|
TE.bind("test_response", () =>
|
||||||
|
pipe(
|
||||||
TE.of(testScriptData),
|
TE.of(testScriptData),
|
||||||
TE.chain(({ testScript, response, envs }) =>
|
TE.chain(({ testScript, response, envs }) =>
|
||||||
execTestScript(testScript, envs, response)
|
execTestScript(testScript, envs, response)
|
||||||
|
)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively parsing test-results using test-descriptor-parser
|
* Recursively parsing test-results using test-descriptor-parser
|
||||||
* to generate test-reports.
|
* to generate test-reports.
|
||||||
*/
|
*/
|
||||||
TE.chainTaskK(({ envs, tests }) =>
|
TE.chainTaskK(({ test_response: { tests, envs }, start }) =>
|
||||||
pipe(
|
pipe(
|
||||||
tests,
|
tests,
|
||||||
A.map(testDescriptorParser),
|
A.map(testDescriptorParser),
|
||||||
@@ -46,7 +54,12 @@ export const testRunner = (
|
|||||||
flow(
|
flow(
|
||||||
RA.flatten,
|
RA.flatten,
|
||||||
RA.toArray,
|
RA.toArray,
|
||||||
(testsReport) => <TestRunnerRes>{ envs, testsReport }
|
(testsReport) =>
|
||||||
|
<TestRunnerRes>{
|
||||||
|
envs,
|
||||||
|
testsReport,
|
||||||
|
duration: pipe(start, hrtime, getDurationInSeconds),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -58,7 +71,6 @@ export const testRunner = (
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursive function to parse test-descriptor from nested-children and
|
* Recursive function to parse test-descriptor from nested-children and
|
||||||
* generate tests-report.
|
* generate tests-report.
|
||||||
@@ -77,19 +89,19 @@ export const testDescriptorParser = (
|
|||||||
A.isNonEmpty(expectResults)
|
A.isNonEmpty(expectResults)
|
||||||
? pipe(
|
? pipe(
|
||||||
expectResults,
|
expectResults,
|
||||||
A.reduce({ failing: 0, passing: 0 }, (prev, { status }) =>
|
A.reduce({ failed: 0, passed: 0 }, (prev, { status }) =>
|
||||||
/**
|
/**
|
||||||
* Incrementing number of passed test-cases if status is "pass",
|
* Incrementing number of passed test-cases if status is "pass",
|
||||||
* else, incrementing number of failed test-cases.
|
* else, incrementing number of failed test-cases.
|
||||||
*/
|
*/
|
||||||
status === "pass"
|
status === "pass"
|
||||||
? { failing: prev.failing, passing: prev.passing + 1 }
|
? { failed: prev.failed, passed: prev.passed + 1 }
|
||||||
: { failing: prev.failing + 1, passing: prev.passing }
|
: { failed: prev.failed + 1, passed: prev.passed }
|
||||||
),
|
),
|
||||||
({ failing, passing }) =>
|
({ failed, passed }) =>
|
||||||
<TestReport>{
|
<TestReport>{
|
||||||
failing,
|
failed,
|
||||||
passing,
|
passed,
|
||||||
descriptor,
|
descriptor,
|
||||||
expectResults,
|
expectResults,
|
||||||
},
|
},
|
||||||
@@ -141,36 +153,48 @@ export const getTestScriptParams = (
|
|||||||
* Combines quantitative details (test-cases passed/failed) of each test-report
|
* Combines quantitative details (test-cases passed/failed) of each test-report
|
||||||
* to generate TestMetrics object with total test-cases & total test-suites.
|
* to generate TestMetrics object with total test-cases & total test-suites.
|
||||||
* @param testsReport Contains details of each test-report (failed/passed test-cases).
|
* @param testsReport Contains details of each test-report (failed/passed test-cases).
|
||||||
|
* @param testDuration Time taken (in seconds) to execute the test-script.
|
||||||
|
* @param errors List of HoppCLIErrors to check for TEST_SCRIPT_ERROR code.
|
||||||
* @returns Object containing details of total test-cases passed/failed and
|
* @returns Object containing details of total test-cases passed/failed and
|
||||||
* total test-suites passed/failed.
|
* total test-suites passed/failed.
|
||||||
*/
|
*/
|
||||||
export const getTestMetrics = (testsReport: TestReport[]): TestMetrics =>
|
export const getTestMetrics = (
|
||||||
|
testsReport: TestReport[],
|
||||||
|
testDuration: number,
|
||||||
|
errors: HoppCLIError[]
|
||||||
|
): TestMetrics =>
|
||||||
testsReport.reduce(
|
testsReport.reduce(
|
||||||
({ testSuites, tests }, testReport) => ({
|
({ testSuites, tests, duration, scripts }, testReport) => ({
|
||||||
tests: {
|
tests: {
|
||||||
failing: tests.failing + testReport.failing,
|
failed: tests.failed + testReport.failed,
|
||||||
passing: tests.passing + testReport.passing,
|
passed: tests.passed + testReport.passed,
|
||||||
},
|
},
|
||||||
testSuites: {
|
testSuites: {
|
||||||
failing: testSuites.failing + (testReport.failing > 0 ? 1 : 0),
|
failed: testSuites.failed + (testReport.failed > 0 ? 1 : 0),
|
||||||
passing: testSuites.passing + (testReport.failing === 0 ? 1 : 0),
|
passed: testSuites.passed + (testReport.failed === 0 ? 1 : 0),
|
||||||
},
|
},
|
||||||
|
scripts: scripts,
|
||||||
|
duration: duration,
|
||||||
}),
|
}),
|
||||||
<TestMetrics>{
|
<TestMetrics>{
|
||||||
tests: { failing: 0, passing: 0 },
|
tests: { failed: 0, passed: 0 },
|
||||||
testSuites: { failing: 0, passing: 0 },
|
testSuites: { failed: 0, passed: 0 },
|
||||||
|
duration: testDuration,
|
||||||
|
scripts: errors.some(({ code }) => code === "TEST_SCRIPT_ERROR")
|
||||||
|
? { failed: 1, passed: 0 }
|
||||||
|
: { failed: 0, passed: 1 },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters tests-report containing atleast one or more failed test-cases.
|
* Filters tests-report containing atleast one or more failed test-cases.
|
||||||
* @param testsReport Provides "failing" test-cases data.
|
* @param testsReport Provides "failed" test-cases data.
|
||||||
* @returns Tests report with one or more test-cases failing.
|
* @returns Tests report with one or more test-cases failed.
|
||||||
*/
|
*/
|
||||||
export const getFailedTestsReport = (testsReport: TestReport[]) =>
|
export const getFailedTestsReport = (testsReport: TestReport[]) =>
|
||||||
pipe(
|
pipe(
|
||||||
testsReport,
|
testsReport,
|
||||||
A.filter(({ failing }) => failing > 0)
|
A.filter(({ failed }) => failed > 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -186,12 +210,12 @@ export const getFailedExpectedResults = (expectResults: ExpectResult[]) =>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if any of the tests-report have failed test-cases.
|
* Checks if any of the tests-report have failed test-cases.
|
||||||
* @param testsReport Provides "failing" test-cases data.
|
* @param testsReport Provides "failed" test-cases data.
|
||||||
* @returns True, if one or more failed test-cases found.
|
* @returns True, if one or more failed test-cases found.
|
||||||
* False, if all test-cases passed.
|
* False, if all test-cases passed.
|
||||||
*/
|
*/
|
||||||
export const hasFailedTestCases = (testsReport: TestReport[]) =>
|
export const hasFailedTestCases = (testsReport: TestReport[]) =>
|
||||||
pipe(
|
pipe(
|
||||||
testsReport,
|
testsReport,
|
||||||
A.every(({ failing }) => failing === 0)
|
A.every(({ failed }) => failed === 0)
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user