feat(cli): add support for JUnit reporter (#4189)

This commit is contained in:
James George
2024-07-26 10:26:58 -07:00
committed by GitHub
parent ecf0901491
commit 5f96cda5e2
15 changed files with 1200 additions and 67 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "@hoppscotch/cli", "name": "@hoppscotch/cli",
"version": "0.9.1", "version": "0.10.0",
"description": "A CLI to run Hoppscotch test scripts in CI environments.", "description": "A CLI to run Hoppscotch test scripts in CI environments.",
"homepage": "https://hoppscotch.io", "homepage": "https://hoppscotch.io",
"type": "module", "type": "module",
@@ -20,9 +20,11 @@
"debugger": "node debugger.js 9999", "debugger": "node debugger.js 9999",
"prepublish": "pnpm exec tsup", "prepublish": "pnpm exec tsup",
"prettier-format": "prettier --config .prettierrc 'src/**/*.ts' --write", "prettier-format": "prettier --config .prettierrc 'src/**/*.ts' --write",
"test": "pnpm run build && vitest run && rm -rf dist", "pretest": "pnpm run build",
"test": "vitest run",
"do-typecheck": "pnpm exec tsc --noEmit", "do-typecheck": "pnpm exec tsc --noEmit",
"do-test": "pnpm test" "do-test": "pnpm run test",
"postinstall": "pnpm run build"
}, },
"keywords": [ "keywords": [
"cli", "cli",
@@ -48,6 +50,7 @@
"lodash-es": "4.17.21", "lodash-es": "4.17.21",
"qs": "6.11.2", "qs": "6.11.2",
"verzod": "0.2.2", "verzod": "0.2.2",
"xmlbuilder2": "3.1.1",
"zod": "3.22.4" "zod": "3.22.4"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -0,0 +1,529 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`hopp test [options] <file_path_or_id> > Test\`hopp test <file_path_or_id> --env <file_path_or_id> --reporter-junit [path] > Generates a JUnit report at the default path 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<testsuites tests=\\"76\\" failures=\\"2\\" errors=\\"66\\" time=\\"time\\">
<testsuite name=\\"test-junit-report-export/request-level-errors/invalid-url\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"22\\" failures=\\"0\\" errors=\\"22\\">
<system-err><![CDATA[
REQUEST_ERROR - TypeError: Invalid URL]]></system-err>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be null\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toInclude should not be null\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be undefined\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toInclude should not be undefined\\"/>
</testcase>
</testsuite>
<testsuite name=\\"test-junit-report-export/request-level-errors/test-script-reference-error\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"0\\" failures=\\"0\\" errors=\\"0\\">
<system-err><![CDATA[
REQUEST_ERROR - TypeError: Invalid URL
TEST_SCRIPT_ERROR - Script execution failed: ReferenceError: status is not defined]]></system-err>
</testsuite>
<testsuite name=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"22\\" failures=\\"0\\" errors=\\"22\\">
<system-err><![CDATA[
PARSING_ERROR - {
\\"key\\": \\"<<key>>\\"
} (ENV_EXPAND_LOOP)]]></system-err>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be null\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toInclude should not be null\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be undefined\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toInclude should not be undefined\\"/>
</testcase>
</testsuite>
<testsuite name=\\"test-junit-report-export/assertions/error\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"22\\" failures=\\"0\\" errors=\\"22\\">
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be null\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toInclude should not be null\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be undefined\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toInclude should not be undefined\\"/>
</testcase>
</testsuite>
<testsuite name=\\"test-junit-report-export/assertions/success\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"5\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Status code is 200 - Expected '200' to be '200'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Check headers - Expected 'application/json, text/plain, */*,image/webp' to be 'application/json, text/plain, */*,image/webp'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Check headers - Expected 'echo.hoppscotch.io' to be 'echo.hoppscotch.io'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Check headers - Expected 'undefined' to be 'undefined'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Status code is 2xx - Expected '200' to be 200-level status\\" classname=\\"test-junit-report-export/assertions/success\\"/>
</testsuite>
<testsuite name=\\"test-junit-report-export/assertions/failure\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"5\\" failures=\\"2\\" errors=\\"0\\">
<testcase name=\\"Simulating failure - Status code is 200 - Expected '200' to not be '200'\\" classname=\\"test-junit-report-export/assertions/failure\\">
<failure type=\\"AssertionFailure\\" message=\\"Expected '200' to not be '200'\\"/>
</testcase>
<testcase name=\\"Simulating failure - Check headers - Expected 'application/json, text/plain, */*,image/webp' to not be 'application/json, text/plain, */*'\\" classname=\\"test-junit-report-export/assertions/failure\\"/>
<testcase name=\\"Simulating failure - Check headers - Expected 'echo.hoppscotch.io' to not be 'httpbin.org'\\" classname=\\"test-junit-report-export/assertions/failure\\"/>
<testcase name=\\"Simulating failure - Check headers - Expected 'undefined' to not be 'value'\\" classname=\\"test-junit-report-export/assertions/failure\\"/>
<testcase name=\\"Simulating failure - Status code is 2xx - Expected '200' to not be 200-level status\\" classname=\\"test-junit-report-export/assertions/failure\\">
<failure type=\\"AssertionFailure\\" message=\\"Expected '200' to not be 200-level status\\"/>
</testcase>
</testsuite>
</testsuites>"
`;
exports[`hopp test [options] <file_path_or_id> > Test\`hopp test <file_path_or_id> --env <file_path_or_id> --reporter-junit [path] > Generates a JUnit report at the specified path 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<testsuites tests=\\"76\\" failures=\\"2\\" errors=\\"66\\" time=\\"time\\">
<testsuite name=\\"test-junit-report-export/request-level-errors/invalid-url\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"22\\" failures=\\"0\\" errors=\\"22\\">
<system-err><![CDATA[
REQUEST_ERROR - TypeError: Invalid URL]]></system-err>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be null\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toInclude should not be null\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be undefined\\" classname=\\"test-junit-report-export/request-level-errors/invalid-url\\">
<error message=\\"Argument for toInclude should not be undefined\\"/>
</testcase>
</testsuite>
<testsuite name=\\"test-junit-report-export/request-level-errors/test-script-reference-error\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"0\\" failures=\\"0\\" errors=\\"0\\">
<system-err><![CDATA[
REQUEST_ERROR - TypeError: Invalid URL
TEST_SCRIPT_ERROR - Script execution failed: ReferenceError: status is not defined]]></system-err>
</testsuite>
<testsuite name=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"22\\" failures=\\"0\\" errors=\\"22\\">
<system-err><![CDATA[
PARSING_ERROR - {
\\"key\\": \\"<<key>>\\"
} (ENV_EXPAND_LOOP)]]></system-err>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be null\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toInclude should not be null\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be undefined\\" classname=\\"test-junit-report-export/request-level-errors/non-existent-env-var\\">
<error message=\\"Argument for toInclude should not be undefined\\"/>
</testcase>
</testsuite>
<testsuite name=\\"test-junit-report-export/assertions/error\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"22\\" failures=\\"0\\" errors=\\"22\\">
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeLevelxxx()\` error scenarios - Expected 200-level status but could not parse value 'foo'\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected 200-level status but could not parse value 'foo'\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toBeType()\` error scenarios - Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toBeType should be &quot;string&quot;, &quot;boolean&quot;, &quot;number&quot;, &quot;object&quot;, &quot;undefined&quot;, &quot;bigint&quot;, &quot;symbol&quot; or &quot;function&quot;\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Expected toHaveLength to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toHaveLength to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toHaveLength()\` error scenarios - Argument for toHaveLength should be a number\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toHaveLength should be a number\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Expected toInclude to be called for an array or string\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Expected toInclude to be called for an array or string\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be null\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toInclude should not be null\\"/>
</testcase>
<testcase name=\\"\`toInclude() error scenarios\` - Argument for toInclude should not be undefined\\" classname=\\"test-junit-report-export/assertions/error\\">
<error message=\\"Argument for toInclude should not be undefined\\"/>
</testcase>
</testsuite>
<testsuite name=\\"test-junit-report-export/assertions/success\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"5\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Status code is 200 - Expected '200' to be '200'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Check headers - Expected 'application/json, text/plain, */*,image/webp' to be 'application/json, text/plain, */*,image/webp'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Check headers - Expected 'echo.hoppscotch.io' to be 'echo.hoppscotch.io'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Check headers - Expected 'undefined' to be 'undefined'\\" classname=\\"test-junit-report-export/assertions/success\\"/>
<testcase name=\\"Status code is 2xx - Expected '200' to be 200-level status\\" classname=\\"test-junit-report-export/assertions/success\\"/>
</testsuite>
<testsuite name=\\"test-junit-report-export/assertions/failure\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"5\\" failures=\\"2\\" errors=\\"0\\">
<testcase name=\\"Simulating failure - Status code is 200 - Expected '200' to not be '200'\\" classname=\\"test-junit-report-export/assertions/failure\\">
<failure type=\\"AssertionFailure\\" message=\\"Expected '200' to not be '200'\\"/>
</testcase>
<testcase name=\\"Simulating failure - Check headers - Expected 'application/json, text/plain, */*,image/webp' to not be 'application/json, text/plain, */*'\\" classname=\\"test-junit-report-export/assertions/failure\\"/>
<testcase name=\\"Simulating failure - Check headers - Expected 'echo.hoppscotch.io' to not be 'httpbin.org'\\" classname=\\"test-junit-report-export/assertions/failure\\"/>
<testcase name=\\"Simulating failure - Check headers - Expected 'undefined' to not be 'value'\\" classname=\\"test-junit-report-export/assertions/failure\\"/>
<testcase name=\\"Simulating failure - Status code is 2xx - Expected '200' to not be 200-level status\\" classname=\\"test-junit-report-export/assertions/failure\\">
<failure type=\\"AssertionFailure\\" message=\\"Expected '200' to not be 200-level status\\"/>
</testcase>
</testsuite>
</testsuites>"
`;
exports[`hopp test [options] <file_path_or_id> > Test\`hopp test <file_path_or_id> --env <file_path_or_id> --reporter-junit [path] > Generates a JUnit report for a collection referring to environment variables 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<testsuites tests=\\"12\\" failures=\\"0\\" errors=\\"0\\" time=\\"time\\">
<testsuite name=\\"Test environment variables in request body/test-request\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"12\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Status code is 200 - Expected '200' to be '200'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments recursively - Expected 'Hello' to be 'Hello'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments recursively - Expected 'Hello' to be 'Hello'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments recursively - Expected 'Hello' to be 'Hello'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected 'Hello' to be 'Hello'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected 'Hello' to be 'Hello'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected 'Hello' to be 'Hello'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected '7' to be '7'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected 'John' to be 'John'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected 'Doe' to be 'Doe'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected 'John Doe' to be 'John Doe'\\" classname=\\"Test environment variables in request body/test-request\\"/>
<testcase name=\\"Successfully resolves environments referenced in the request body - Expected 'Hello, John Doe' to be 'Hello, John Doe'\\" classname=\\"Test environment variables in request body/test-request\\"/>
</testsuite>
</testsuites>"
`;
exports[`hopp test [options] <file_path_or_id> > Test\`hopp test <file_path_or_id> --env <file_path_or_id> --reporter-junit [path] > Generates a JUnit report for a collection with authorization/headers set at the collection level 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<testsuites tests=\\"12\\" failures=\\"0\\" errors=\\"0\\" time=\\"time\\">
<testsuite name=\\"CollectionB/RequestA\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"2\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Correctly inherits auth and headers from the root collection - Expected 'Set at root collection' to be 'Set at root collection'\\" classname=\\"CollectionB/RequestA\\"/>
<testcase name=\\"Correctly inherits auth and headers from the root collection - Expected 'Bearer BearerToken' to be 'Bearer BearerToken'\\" classname=\\"CollectionB/RequestA\\"/>
</testsuite>
<testsuite name=\\"CollectionB/FolderA/RequestB\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"2\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Correctly inherits auth and headers from the parent folder - Expected 'Set at root collection' to be 'Set at root collection'\\" classname=\\"CollectionB/FolderA/RequestB\\"/>
<testcase name=\\"Correctly inherits auth and headers from the parent folder - Expected 'Bearer BearerToken' to be 'Bearer BearerToken'\\" classname=\\"CollectionB/FolderA/RequestB\\"/>
</testsuite>
<testsuite name=\\"CollectionA/RequestA\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"2\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Correctly inherits auth and headers from the root collection - Expected 'Set at root collection' to be 'Set at root collection'\\" classname=\\"CollectionA/RequestA\\"/>
<testcase name=\\"Correctly inherits auth and headers from the root collection - Expected 'Bearer BearerToken' to be 'Bearer BearerToken'\\" classname=\\"CollectionA/RequestA\\"/>
</testsuite>
<testsuite name=\\"CollectionA/FolderA/RequestB\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"2\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Correctly inherits auth and headers from the parent folder - Expected 'Set at root collection' to be 'Set at root collection'\\" classname=\\"CollectionA/FolderA/RequestB\\"/>
<testcase name=\\"Correctly inherits auth and headers from the parent folder - Expected 'Bearer BearerToken' to be 'Bearer BearerToken'\\" classname=\\"CollectionA/FolderA/RequestB\\"/>
</testsuite>
<testsuite name=\\"CollectionA/FolderA/FolderB/RequestC\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"2\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Correctly inherits auth and headers from the parent folder - Expected 'Overriden at FolderB' to be 'Overriden at FolderB'\\" classname=\\"CollectionA/FolderA/FolderB/RequestC\\"/>
<testcase name=\\"Correctly inherits auth and headers from the parent folder - Expected 'test-key' to be 'test-key'\\" classname=\\"CollectionA/FolderA/FolderB/RequestC\\"/>
</testsuite>
<testsuite name=\\"CollectionA/FolderA/FolderB/FolderC/RequestD\\" time=\\"time\\" timestamp=\\"timestamp\\" tests=\\"2\\" failures=\\"0\\" errors=\\"0\\">
<testcase name=\\"Overrides auth and headers set at the parent folder - Expected 'Overriden at RequestD' to be 'Overriden at RequestD'\\" classname=\\"CollectionA/FolderA/FolderB/FolderC/RequestD\\"/>
<testcase name=\\"Overrides auth and headers set at the parent folder - Expected 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=' to be 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='\\" classname=\\"CollectionA/FolderA/FolderB/FolderC/RequestD\\"/>
</testsuite>
</testsuites>"
`;

View File

@@ -1,5 +1,7 @@
import { ExecException } from "child_process"; import { ExecException } from "child_process";
import { describe, expect, test } from "vitest"; import { afterAll, beforeAll, describe, expect, test } from "vitest";
import fs from "fs";
import path from "path";
import { HoppErrorCode } from "../../../types/errors"; import { HoppErrorCode } from "../../../types/errors";
import { getErrorCode, getTestJsonFilePath, runCLI } from "../../utils"; import { getErrorCode, getTestJsonFilePath, runCLI } from "../../utils";
@@ -229,7 +231,7 @@ describe("hopp test [options] <file_path_or_id>", () => {
expect(error).toBeNull(); expect(error).toBeNull();
}); });
test("Works with shorth `-e` flag", async () => { test("Works with short `-e` flag", async () => {
const TESTS_PATH = getTestJsonFilePath( const TESTS_PATH = getTestJsonFilePath(
"env-flag-tests-coll.json", "env-flag-tests-coll.json",
"collection" "collection"
@@ -506,4 +508,163 @@ describe("hopp test [options] <file_path_or_id>", () => {
expect(error).toBeNull(); expect(error).toBeNull();
}); });
}); });
describe("Test`hopp test <file_path_or_id> --env <file_path_or_id> --reporter-junit [path]", () => {
const genPath = path.resolve("hopp-cli-test");
// Helper function to replace dynamic values before generating test snapshots
// Currently scoped to JUnit report generation
const replaceDynamicValuesInStr = (input: string): string =>
input.replace(
/(time|timestamp)="[^"]+"/g,
(_, attr) => `${attr}="${attr}"`
);
beforeAll(() => {
fs.mkdirSync(genPath);
});
afterAll(() => {
fs.rmdirSync(genPath, { recursive: true });
});
test("Report export fails with the code `REPORT_EXPORT_FAILED` while encountering an error during path creation", async () => {
const exportPath = "hopp-junit-report.xml";
const COLL_PATH = getTestJsonFilePath("passes-coll.json", "collection");
const args = `test ${COLL_PATH} --reporter-junit /non-existent-path/report.xml`;
const { stdout, stderr } = await runCLI(args, {
cwd: path.resolve("hopp-cli-test"),
});
const out = getErrorCode(stderr);
expect(out).toBe<HoppErrorCode>("REPORT_EXPORT_FAILED");
expect(stdout).not.toContain(
`Successfully exported the JUnit report to: ${exportPath}`
);
});
test("Generates a JUnit report at the default path", async () => {
const exportPath = "hopp-junit-report.xml";
const COLL_PATH = getTestJsonFilePath(
"test-junit-report-export-coll.json",
"collection"
);
const args = `test ${COLL_PATH} --reporter-junit`;
const { stdout } = await runCLI(args, {
cwd: path.resolve("hopp-cli-test"),
});
expect(stdout).not.toContain(
`Overwriting the pre-existing path: ${exportPath}`
);
expect(stdout).toContain(
`Successfully exported the JUnit report to: ${exportPath}`
);
const fileContents = fs
.readFileSync(path.resolve(genPath, exportPath))
.toString();
expect(replaceDynamicValuesInStr(fileContents)).toMatchSnapshot();
});
test("Generates a JUnit report at the specified path", async () => {
const exportPath = "outer-dir/inner-dir/report.xml";
const COLL_PATH = getTestJsonFilePath(
"test-junit-report-export-coll.json",
"collection"
);
const args = `test ${COLL_PATH} --reporter-junit ${exportPath}`;
const { stdout } = await runCLI(args, {
cwd: path.resolve("hopp-cli-test"),
});
expect(stdout).not.toContain(
`Overwriting the pre-existing path: ${exportPath}`
);
expect(stdout).toContain(
`Successfully exported the JUnit report to: ${exportPath}`
);
const fileContents = fs
.readFileSync(path.resolve(genPath, exportPath))
.toString();
expect(replaceDynamicValuesInStr(fileContents)).toMatchSnapshot();
});
test("Generates a JUnit report for a collection with authorization/headers set at the collection level", async () => {
const exportPath = "hopp-junit-report.xml";
const COLL_PATH = getTestJsonFilePath(
"collection-level-auth-headers-coll.json",
"collection"
);
const args = `test ${COLL_PATH} --reporter-junit`;
const { stdout } = await runCLI(args, {
cwd: path.resolve("hopp-cli-test"),
});
expect(stdout).toContain(
`Overwriting the pre-existing path: ${exportPath}`
);
expect(stdout).toContain(
`Successfully exported the JUnit report to: ${exportPath}`
);
const fileContents = fs
.readFileSync(path.resolve(genPath, exportPath))
.toString();
expect(replaceDynamicValuesInStr(fileContents)).toMatchSnapshot();
});
test("Generates a JUnit report for a collection referring to environment variables", async () => {
const exportPath = "hopp-junit-report.xml";
const COLL_PATH = getTestJsonFilePath(
"req-body-env-vars-coll.json",
"collection"
);
const ENV_PATH = getTestJsonFilePath(
"req-body-env-vars-envs.json",
"environment"
);
const args = `test ${COLL_PATH} --env ${ENV_PATH} --reporter-junit`;
const { stdout } = await runCLI(args, {
cwd: path.resolve("hopp-cli-test"),
});
expect(stdout).toContain(
`Overwriting the pre-existing path: ${exportPath}`
);
expect(stdout).toContain(
`Successfully exported the JUnit report to: ${exportPath}`
);
const fileContents = fs
.readFileSync(path.resolve(genPath, exportPath))
.toString();
expect(replaceDynamicValuesInStr(fileContents)).toMatchSnapshot();
});
});
}); });

View File

@@ -0,0 +1,150 @@
{
"v": 2,
"name": "test-junit-report-export",
"folders": [
{
"v": 2,
"name": "assertions",
"folders": [],
"requests": [
{
"v": "5",
"auth": {
"authType": "inherit",
"authActive": true
},
"body": {
"body": null,
"contentType": null
},
"name": "error",
"method": "GET",
"params": [],
"headers": [],
"endpoint": "https://echo.hoppscotch.io",
"testScript": "pw.test(\"`toBeLevelxxx()` error scenarios\", ()=> {\n pw.expect(\"foo\").toBeLevel2xx();\n pw.expect(\"foo\").not.toBeLevel2xx();\n});\n\npw.test(\"`toBeType()` error scenarios\", () => {\n pw.expect(2).toBeType(\"foo\")\n pw.expect(\"2\").toBeType(\"bar\")\n pw.expect(true).toBeType(\"baz\")\n pw.expect({}).toBeType(\"qux\")\n pw.expect(undefined).toBeType(\"quux\")\n \n pw.expect(2).not.toBeType(\"foo\")\n pw.expect(\"2\").not.toBeType(\"bar\")\n pw.expect(true).not.toBeType(\"baz\")\n pw.expect({}).not.toBeType(\"qux\")\n pw.expect(undefined).not.toBeType(\"quux\")\n})\n\npw.test(\"`toHaveLength()` error scenarios\", () => {\n pw.expect(5).toHaveLength(0)\n pw.expect(true).toHaveLength(0)\n\n pw.expect(5).not.toHaveLength(0)\n pw.expect(true).not.toHaveLength(0)\n\n pw.expect([1, 2, 3, 4]).toHaveLength(\"a\")\n\n pw.expect([1, 2, 3, 4]).not.toHaveLength(\"a\")\n})\n\npw.test(\"`toInclude() error scenarios`\", () => {\n pw.expect(5).not.toInclude(0)\n pw.expect(true).not.toInclude(0)\n\n pw.expect([1, 2, 3, 4]).not.toInclude(null)\n\n pw.expect([1, 2, 3, 4]).not.toInclude(undefined)\n})",
"preRequestScript": "",
"requestVariables": []
},
{
"v": "5",
"auth": {
"authType": "inherit",
"authActive": true
},
"body": {
"body": null,
"contentType": null
},
"name": "success",
"method": "GET",
"params": [],
"headers": [],
"endpoint": "https://echo.hoppscotch.io",
"testScript": "\n\n// Check status code is 200\npw.test(\"Status code is 200\", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\n// Check headers\npw.test(\"Check headers\", ()=> {\n pw.expect(pw.response.body.headers[\"accept\"]).toBe(\"application/json, text/plain, */*,image/webp\");\n pw.expect(pw.response.body.headers[\"host\"]).toBe(\"echo.hoppscotch.io\")\n pw.expect(pw.response.body.headers[\"custom-header\"]).toBe(undefined)\n});\n\n// Check status code is 2xx\npw.test(\"Status code is 2xx\", ()=> {\n pw.expect(pw.response.status).toBeLevel2xx();\n});",
"preRequestScript": "",
"requestVariables": []
},
{
"v": "5",
"auth": {
"authType": "inherit",
"authActive": true
},
"body": {
"body": null,
"contentType": null
},
"name": "failure",
"method": "GET",
"params": [],
"headers": [],
"endpoint": "https://echo.hoppscotch.io",
"testScript": "\n\n// Check status code is 200\npw.test(\"Simulating failure - Status code is 200\", ()=> {\n pw.expect(pw.response.status).not.toBe(200);\n});\n\n// Check JSON response property\npw.test(\"Simulating failure - Check headers\", ()=> {\n pw.expect(pw.response.body.headers[\"accept\"]).not.toBe(\"application/json, text/plain, */*\");\n pw.expect(pw.response.body.headers[\"host\"]).not.toBe(\"httpbin.org\")\n pw.expect(pw.response.body.headers[\"custom-header\"]).not.toBe(\"value\")\n});\n\n// Check status code is 2xx\npw.test(\"Simulating failure - Status code is 2xx\", ()=> {\n pw.expect(pw.response.status).not.toBeLevel2xx();\n});",
"preRequestScript": "",
"requestVariables": []
}
],
"auth": {
"authType": "inherit",
"authActive": true
},
"headers": []
},
{
"v": 2,
"name": "request-level-errors",
"folders": [],
"requests": [
{
"v": "5",
"auth": {
"authType": "inherit",
"authActive": true
},
"body": {
"body": null,
"contentType": null
},
"name": "invalid-url",
"method": "GET",
"params": [],
"headers": [],
"endpoint": "invalid-url",
"testScript": "pw.test(\"`toBeLevelxxx()` error scenarios\", ()=> {\n pw.expect(\"foo\").toBeLevel2xx();\n pw.expect(\"foo\").not.toBeLevel2xx();\n});\n\npw.test(\"`toBeType()` error scenarios\", () => {\n pw.expect(2).toBeType(\"foo\")\n pw.expect(\"2\").toBeType(\"bar\")\n pw.expect(true).toBeType(\"baz\")\n pw.expect({}).toBeType(\"qux\")\n pw.expect(undefined).toBeType(\"quux\")\n \n pw.expect(2).not.toBeType(\"foo\")\n pw.expect(\"2\").not.toBeType(\"bar\")\n pw.expect(true).not.toBeType(\"baz\")\n pw.expect({}).not.toBeType(\"qux\")\n pw.expect(undefined).not.toBeType(\"quux\")\n})\n\npw.test(\"`toHaveLength()` error scenarios\", () => {\n pw.expect(5).toHaveLength(0)\n pw.expect(true).toHaveLength(0)\n\n pw.expect(5).not.toHaveLength(0)\n pw.expect(true).not.toHaveLength(0)\n\n pw.expect([1, 2, 3, 4]).toHaveLength(\"a\")\n\n pw.expect([1, 2, 3, 4]).not.toHaveLength(\"a\")\n})\n\npw.test(\"`toInclude() error scenarios`\", () => {\n pw.expect(5).not.toInclude(0)\n pw.expect(true).not.toInclude(0)\n\n pw.expect([1, 2, 3, 4]).not.toInclude(null)\n\n pw.expect([1, 2, 3, 4]).not.toInclude(undefined)\n})",
"preRequestScript": "",
"requestVariables": []
},
{
"v": "5",
"auth": {
"authType": "inherit",
"authActive": true
},
"body": {
"body": null,
"contentType": null
},
"name": "test-script-reference-error",
"method": "GET",
"params": [],
"headers": [],
"endpoint": "invalid-url",
"testScript": "pw.test(\"Reference error\", () => {\n pw.expect(status).toBe(200);\n})",
"preRequestScript": "",
"requestVariables": []
},
{
"v": "5",
"auth": {
"authType": "inherit",
"authActive": true
},
"body": {
"body": "{\n \"key\": \"<<key>>\"\n}",
"contentType": "application/json"
},
"name": "non-existent-env-var",
"method": "POST",
"params": [],
"headers": [],
"endpoint": "https://echo.hoppscotch.io",
"testScript": "pw.test(\"`toBeLevelxxx()` error scenarios\", ()=> {\n pw.expect(\"foo\").toBeLevel2xx();\n pw.expect(\"foo\").not.toBeLevel2xx();\n});\n\npw.test(\"`toBeType()` error scenarios\", () => {\n pw.expect(2).toBeType(\"foo\")\n pw.expect(\"2\").toBeType(\"bar\")\n pw.expect(true).toBeType(\"baz\")\n pw.expect({}).toBeType(\"qux\")\n pw.expect(undefined).toBeType(\"quux\")\n \n pw.expect(2).not.toBeType(\"foo\")\n pw.expect(\"2\").not.toBeType(\"bar\")\n pw.expect(true).not.toBeType(\"baz\")\n pw.expect({}).not.toBeType(\"qux\")\n pw.expect(undefined).not.toBeType(\"quux\")\n})\n\npw.test(\"`toHaveLength()` error scenarios\", () => {\n pw.expect(5).toHaveLength(0)\n pw.expect(true).toHaveLength(0)\n\n pw.expect(5).not.toHaveLength(0)\n pw.expect(true).not.toHaveLength(0)\n\n pw.expect([1, 2, 3, 4]).toHaveLength(\"a\")\n\n pw.expect([1, 2, 3, 4]).not.toHaveLength(\"a\")\n})\n\npw.test(\"`toInclude() error scenarios`\", () => {\n pw.expect(5).not.toInclude(0)\n pw.expect(true).not.toInclude(0)\n\n pw.expect([1, 2, 3, 4]).not.toInclude(null)\n\n pw.expect([1, 2, 3, 4]).not.toInclude(undefined)\n})",
"preRequestScript": "",
"requestVariables": []
}
],
"auth": {
"authType": "inherit",
"authActive": true
},
"headers": []
}
],
"requests": [],
"auth": {
"authType": "inherit",
"authActive": true
},
"headers": []
}

View File

@@ -1,7 +1,7 @@
import { handleError } from "../handlers/error"; import { handleError } from "../handlers/error";
import { parseDelayOption } from "../options/test/delay"; import { parseDelayOption } from "../options/test/delay";
import { parseEnvsData } from "../options/test/env"; import { parseEnvsData } from "../options/test/env";
import { TestCmdOptions, TestCmdEnvironmentOptions } from "../types/commands"; import { TestCmdEnvironmentOptions, TestCmdOptions } from "../types/commands";
import { HoppEnvs } from "../types/request"; import { HoppEnvs } from "../types/request";
import { isHoppCLIError } from "../utils/checks"; import { isHoppCLIError } from "../utils/checks";
import { import {
@@ -22,7 +22,7 @@ export const test = (pathOrId: string, options: TestCmdOptions) => async () => {
const collections = await parseCollectionData(pathOrId, options); const collections = await parseCollectionData(pathOrId, options);
const report = await collectionsRunner({ collections, envs, delay }); const report = await collectionsRunner({ collections, envs, delay });
const hasSucceeded = collectionsRunnerResult(report); const hasSucceeded = collectionsRunnerResult(report, options.reporterJunit);
collectionsRunnerExit(hasSucceeded); collectionsRunnerExit(hasSucceeded);
} catch (e) { } catch (e) {

View File

@@ -97,6 +97,10 @@ export const handleError = <T extends HoppErrorCode>(error: HoppError<T>) => {
case "SERVER_CONNECTION_REFUSED": case "SERVER_CONNECTION_REFUSED":
ERROR_MSG = `Unable to connect to the server. Please check your network connection or server instance URL and try again: ${error.data}`; ERROR_MSG = `Unable to connect to the server. Please check your network connection or server instance URL and try again: ${error.data}`;
break; break;
case "REPORT_EXPORT_FAILED":
const moreInfo = error.data ? `: ${error.data}` : S.empty;
ERROR_MSG = `Failed to export the report at ${error.path}${moreInfo}`;
break;
} }
if (!S.isEmpty(ERROR_MSG)) { if (!S.isEmpty(ERROR_MSG)) {

View File

@@ -65,6 +65,10 @@ program
"personal access token to access collections/environments from a workspace" "personal access token to access collections/environments from a workspace"
) )
.option("--server <server_url>", "server URL for SH instance") .option("--server <server_url>", "server URL for SH instance")
.option(
"--reporter-junit [path]",
"generate JUnit report optionally specifying the path"
)
.allowExcessArguments(false) .allowExcessArguments(false)
.allowUnknownOption(false) .allowUnknownOption(false)
.description("running hoppscotch collection.json file") .description("running hoppscotch collection.json file")
@@ -74,7 +78,18 @@ program
"https://docs.hoppscotch.io/documentation/clients/cli/overview#commands" "https://docs.hoppscotch.io/documentation/clients/cli/overview#commands"
)}` )}`
) )
.action(async (pathOrId, options) => await test(pathOrId, options)()); .action(async (pathOrId, options) => {
const overrides: Record<string, unknown> = {};
// Choose `hopp-junit-report.xml` as the default value if `reporter-junit` flag is supplied without a value
if (options.reporterJunit === true) {
overrides.reporterJunit = "hopp-junit-report.xml";
}
const effectiveOptions = { ...options, ...overrides };
await test(pathOrId, effectiveOptions)();
});
export const cli = async (args: string[]) => { export const cli = async (args: string[]) => {
try { try {

View File

@@ -3,6 +3,7 @@ export type TestCmdOptions = {
delay?: string; delay?: string;
token?: string; token?: string;
server?: string; server?: string;
reporterJunit?: string;
}; };
// Consumed in the collection `file_path_or_id` argument action handler // Consumed in the collection `file_path_or_id` argument action handler

View File

@@ -31,6 +31,7 @@ type HoppErrors = {
INVALID_ID: HoppErrorData; INVALID_ID: HoppErrorData;
INVALID_SERVER_URL: HoppErrorData; INVALID_SERVER_URL: HoppErrorData;
SERVER_CONNECTION_REFUSED: HoppErrorData; SERVER_CONNECTION_REFUSED: HoppErrorData;
REPORT_EXPORT_FAILED: HoppErrorPath & HoppErrorData;
}; };
export type HoppErrorCode = keyof HoppErrors; export type HoppErrorCode = keyof HoppErrors;

View File

@@ -27,6 +27,7 @@ import {
} from "./display"; } from "./display";
import { exceptionColors } from "./getters"; import { exceptionColors } from "./getters";
import { getPreRequestMetrics } from "./pre-request"; import { getPreRequestMetrics } from "./pre-request";
import { buildJUnitReport, generateJUnitReportExport } from "./reporters/junit";
import { import {
getRequestMetrics, getRequestMetrics,
preProcessRequest, preProcessRequest,
@@ -56,19 +57,22 @@ export const collectionsRunner = async (
// Pop out top-most collection from stack to be processed. // Pop out top-most collection from stack to be processed.
const { collection, path } = <CollectionStack>collectionStack.pop(); const { collection, path } = <CollectionStack>collectionStack.pop();
// Processing each request in collection // Processing each request in collection
for (const request of collection.requests) { for (const request of collection.requests) {
const _request = preProcessRequest(request as HoppRESTRequest, collection); const _request = preProcessRequest(
const requestPath = `${path}/${_request.name}`; request as HoppRESTRequest,
const processRequestParams: ProcessRequestParams = { collection
path: requestPath, );
request: _request, const requestPath = `${path}/${_request.name}`;
envs, const processRequestParams: ProcessRequestParams = {
delay, path: requestPath,
}; request: _request,
envs,
delay,
};
// Request processing initiated message. // Request processing initiated message.
log(WARN(`\nRunning: ${chalk.bold(requestPath)}`)); log(WARN(`\nRunning: ${chalk.bold(requestPath)}`));
// Processing current request. // Processing current request.
const result = await processRequest(processRequestParams)(); const result = await processRequest(processRequestParams)();
@@ -78,35 +82,40 @@ export const collectionsRunner = async (
envs.global = global; envs.global = global;
envs.selected = selected; envs.selected = selected;
// Storing current request's report. // Storing current request's report.
const requestReport = result.report; const requestReport = result.report;
requestsReport.push(requestReport); requestsReport.push(requestReport);
}
// 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,
});
}
} }
// 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; return requestsReport;
}; };
@@ -134,7 +143,8 @@ const getCollectionStack = (collections: HoppCollection[]): CollectionStack[] =>
* False, if errors occurred or test-cases failed. * False, if errors occurred or test-cases failed.
*/ */
export const collectionsRunnerResult = ( export const collectionsRunnerResult = (
requestsReport: RequestReport[] requestsReport: RequestReport[],
reporterJUnitExportPath?: string
): boolean => { ): boolean => {
const overallTestMetrics = <TestMetrics>{ const overallTestMetrics = <TestMetrics>{
tests: { failed: 0, passed: 0 }, tests: { failed: 0, passed: 0 },
@@ -152,6 +162,9 @@ export const collectionsRunnerResult = (
}; };
let finalResult = true; let finalResult = true;
let totalErroredTestCases = 0;
let totalFailedTestCases = 0;
// 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, duration } = requestReport; const { path, tests, errors, result, duration } = requestReport;
@@ -165,6 +178,19 @@ export const collectionsRunnerResult = (
printErrorsReport(path, errors); printErrorsReport(path, errors);
if (reporterJUnitExportPath) {
const { failedRequestTestCases, erroredRequestTestCases } =
buildJUnitReport({
path,
tests,
errors,
duration: duration.test,
});
totalFailedTestCases += failedRequestTestCases;
totalErroredTestCases += erroredRequestTestCases;
}
/** /**
* Extracting current request report's test-metrics and updating * Extracting current request report's test-metrics and updating
* overall test-metrics. * overall test-metrics.
@@ -216,6 +242,19 @@ export const collectionsRunnerResult = (
printRequestsMetrics(overallRequestMetrics); printRequestsMetrics(overallRequestMetrics);
printPreRequestMetrics(overallPreRequestMetrics); printPreRequestMetrics(overallPreRequestMetrics);
if (reporterJUnitExportPath) {
const totalTestCases =
overallTestMetrics.tests.failed + overallTestMetrics.tests.passed;
generateJUnitReportExport({
totalTestCases,
totalFailedTestCases,
totalErroredTestCases,
testDuration: overallTestMetrics.duration,
reporterJUnitExportPath,
});
}
return finalResult; return finalResult;
}; };

View File

@@ -47,7 +47,10 @@ export const preRequestScriptRunner = (
), ),
TE.map( TE.map(
({ selected, global }) => ({ selected, global }) =>
<Environment>{ name: "Env", variables: [...selected, ...global] } <Environment>{
name: "Env",
variables: [...(selected ?? []), ...(global ?? [])],
}
), ),
TE.chainEitherKW((env) => getEffectiveRESTRequest(request, env)), TE.chainEitherKW((env) => getEffectiveRESTRequest(request, env)),
TE.mapLeft((reason) => TE.mapLeft((reason) =>

View File

@@ -0,0 +1,178 @@
import { info, log } from "console";
import fs from "fs";
import path from "path";
import { create } from "xmlbuilder2";
import { XMLBuilder } from "xmlbuilder2/lib/interfaces";
import { TestReport } from "../../interfaces/response";
import { error, HoppCLIError } from "../../types/errors";
import { RequestReport } from "../../types/request";
import { exceptionColors } from "../getters";
type BuildJUnitReportArgs = Omit<RequestReport, "result" | "duration"> & {
duration: RequestReport["duration"]["test"];
};
type BuildJUnitReportResult = {
failedRequestTestCases: number;
erroredRequestTestCases: number;
};
type GenerateJUnitReportExportArgs = {
totalTestCases: number;
totalFailedTestCases: number;
totalErroredTestCases: number;
testDuration: number;
reporterJUnitExportPath: string;
};
const { INFO, SUCCESS } = exceptionColors;
// Create the root XML element
const rootEl = create({ version: "1.0", encoding: "UTF-8" }).ele("testsuites");
/**
* Builds a JUnit report based on the provided request report.
* Creates a test suite at the request level populating the XML document structure.
*
* @param {BuildJUnitReportArgs} options - The options to build the JUnit report.
* @param {string} options.path - The path of the request.
* @param {TestReport[]} options.tests - The test suites for the request.
* @param {HoppCLIError[]} options.errors - The errors encountered during the request.
* @param {number} options.duration - Time taken to execute the test suite.
* @returns {BuildJUnitReportResult} An object containing the number of failed and errored test cases.
*/
export const buildJUnitReport = ({
path,
tests: testSuites,
errors: requestTestSuiteErrors,
duration: testSuiteDuration,
}: BuildJUnitReportArgs): BuildJUnitReportResult => {
let requestTestSuiteError: XMLBuilder | null = null;
// Create a test suite at the request level
const requestTestSuite = rootEl.ele("testsuite", {
name: path,
time: testSuiteDuration,
timestamp: new Date().toISOString(),
});
if (requestTestSuiteErrors.length > 0) {
requestTestSuiteError = requestTestSuite.ele("system-err");
}
let systemErrContent = "";
requestTestSuiteErrors.forEach((error) => {
let compiledError = error.code;
if ("data" in error) {
compiledError += ` - ${error.data}`;
}
// Append each error message with a newline for separation
systemErrContent += `\n${" ".repeat(6)}${compiledError}`;
});
// There'll be a single `CDATA` element compiling all the error messages
if (requestTestSuiteError) {
requestTestSuiteError.dat(systemErrContent);
}
let requestTestCases = 0;
let erroredRequestTestCases = 0;
let failedRequestTestCases = 0;
// Test suites correspond to `pw.test()` invocations
testSuites.forEach(({ descriptor, expectResults }) => {
requestTestCases += expectResults.length;
expectResults.forEach(({ status, message }) => {
const testCase = requestTestSuite
.ele("testcase", {
name: `${descriptor} - ${message}`,
})
.att("classname", path);
if (status === "fail") {
failedRequestTestCases += 1;
testCase
.ele("failure")
.att("type", "AssertionFailure")
.att("message", message);
} else if (status === "error") {
erroredRequestTestCases += 1;
testCase.ele("error").att("message", message);
}
});
});
requestTestSuite.att("tests", requestTestCases.toString());
requestTestSuite.att("failures", failedRequestTestCases.toString());
requestTestSuite.att("errors", erroredRequestTestCases.toString());
return {
failedRequestTestCases,
erroredRequestTestCases,
};
};
/**
* Generates the built JUnit report export at the specified path.
*
* @param {GenerateJUnitReportExportArgs} options - The options to generate the JUnit report export.
* @param {number} options.totalTestCases - The total number of test cases.
* @param {number} options.totalFailedTestCases - The total number of failed test cases.
* @param {number} options.totalErroredTestCases - The total number of errored test cases.
* @param {number} options.testDuration - The total duration of test cases.
* @param {string} options.reporterJUnitExportPath - The path to export the JUnit report.
* @returns {void}
*/
export const generateJUnitReportExport = ({
totalTestCases,
totalFailedTestCases,
totalErroredTestCases,
testDuration,
reporterJUnitExportPath,
}: GenerateJUnitReportExportArgs) => {
rootEl
.att("tests", totalTestCases.toString())
.att("failures", totalFailedTestCases.toString())
.att("errors", totalErroredTestCases.toString())
.att("time", testDuration.toString());
// Convert the XML structure to a string
const xmlDocString = rootEl.end({ prettyPrint: true });
// Write the XML string to the specified path
try {
const resolvedExportPath = path.resolve(reporterJUnitExportPath);
if (fs.existsSync(resolvedExportPath)) {
info(
INFO(`\nOverwriting the pre-existing path: ${reporterJUnitExportPath}.`)
);
}
fs.mkdirSync(path.dirname(resolvedExportPath), {
recursive: true,
});
fs.writeFileSync(resolvedExportPath, xmlDocString);
log(
SUCCESS(
`\nSuccessfully exported the JUnit report to: ${reporterJUnitExportPath}.`
)
);
} catch (err) {
const data = err instanceof Error ? err.message : null;
throw error({
code: "REPORT_EXPORT_FAILED",
data,
path: reporterJUnitExportPath,
});
}
};

View File

@@ -52,10 +52,11 @@ const processVariables = (variable: Environment["variables"][number]) => {
* @param envs Global + selected envs used by requests with in collection * @param envs Global + selected envs used by requests with in collection
* @returns Processed envs with each variable processed * @returns Processed envs with each variable processed
*/ */
const processEnvs = (envs: HoppEnvs) => { const processEnvs = (envs: Partial<HoppEnvs>) => {
// This can take the shape `{ global: undefined, selected: undefined }` when no environment is supplied
const processedEnvs = { const processedEnvs = {
global: envs.global.map(processVariables), global: envs.global?.map(processVariables),
selected: envs.selected.map(processVariables), selected: envs.selected?.map(processVariables),
}; };
return processedEnvs; return processedEnvs;
@@ -270,7 +271,7 @@ export const processRequest =
// Updating report for errors & current result // Updating report for errors & current result
report.errors.push(preRequestRes.left); report.errors.push(preRequestRes.left);
report.result = report.result && false; report.result = report.result;
} else { } else {
// Updating effective-request and consuming updated envs after pre-request script execution // Updating effective-request and consuming updated envs after pre-request script execution
({ effectiveRequest, updatedEnvs } = preRequestRes.right); ({ effectiveRequest, updatedEnvs } = preRequestRes.right);
@@ -298,7 +299,7 @@ export const processRequest =
if (E.isLeft(requestRunnerRes)) { if (E.isLeft(requestRunnerRes)) {
// Updating report for errors & current result // Updating report for errors & current result
report.errors.push(requestRunnerRes.left); report.errors.push(requestRunnerRes.left);
report.result = report.result && false; report.result = report.result;
printRequestRunner.fail(); printRequestRunner.fail();
} else { } else {
@@ -321,7 +322,7 @@ export const processRequest =
// Updating report with current errors & result. // Updating report with current errors & result.
report.errors.push(testRunnerRes.left); report.errors.push(testRunnerRes.left);
report.result = report.result && false; report.result = report.result;
} else { } else {
const { envs, testsReport, duration } = testRunnerRes.right; const { envs, testsReport, duration } = testRunnerRes.right;
const _hasFailedTestCases = hasFailedTestCases(testsReport); const _hasFailedTestCases = hasFailedTestCases(testsReport);

View File

@@ -10,7 +10,8 @@
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"composite": true "composite": true,
"lib": ["ESNext", "DOM"],
}, },
"files": ["package.json"] "files": ["package.json"]
} }

69
pnpm-lock.yaml generated
View File

@@ -324,6 +324,9 @@ importers:
verzod: verzod:
specifier: 0.2.2 specifier: 0.2.2
version: 0.2.2(zod@3.22.4) version: 0.2.2(zod@3.22.4)
xmlbuilder2:
specifier: 3.1.1
version: 3.1.1
zod: zod:
specifier: 3.22.4 specifier: 3.22.4
version: 3.22.4 version: 3.22.4
@@ -3513,8 +3516,8 @@ packages:
resolution: {integrity: sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==} resolution: {integrity: sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
'@intlify/message-compiler@10.0.0-beta.2': '@intlify/message-compiler@10.0.0-beta.5':
resolution: {integrity: sha512-2yl340oNiCDjdpPIfo49a7o56ZTc+35iN7mxdQvXOLxJ6Pdh9p0GkB0duV44hfHaAxsD1cGQ4naLDRokKUdyvQ==} resolution: {integrity: sha512-hLLchnM1dmtSEruerkzvU9vePsLqBXz3RU85SCx/Vd12fFQiymP+/5Rn9MJ8MyfLmIOLDEx4PRh+/GkIQP6oog==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
'@intlify/message-compiler@9.13.1': '@intlify/message-compiler@9.13.1':
@@ -3533,8 +3536,8 @@ packages:
resolution: {integrity: sha512-McnYWhcoYmDJvssVu6QGR0shqlkJuL1HHdi5lK7fNqvQqRYaQ4lSLjYmZxwc8tRNMdIe9/KUKfyPxU9M6yCtNQ==} resolution: {integrity: sha512-McnYWhcoYmDJvssVu6QGR0shqlkJuL1HHdi5lK7fNqvQqRYaQ4lSLjYmZxwc8tRNMdIe9/KUKfyPxU9M6yCtNQ==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
'@intlify/shared@10.0.0-beta.2': '@intlify/shared@10.0.0-beta.5':
resolution: {integrity: sha512-u3ey3jn7VZl8SfuBH1nZC1xvdu59/PYkjR6UjXMWiDoowmr/PuPzmIRmOD8jZvRfCbKnKWYRK33HN4uTWLr/Yw==} resolution: {integrity: sha512-g9bq5Y1bOcC9qxtNk4UWtF3sXm6Wh0fGISb7vD5aLyF7yQv7ZFjxQjJzBP2GqG/9+PAGYutqjP1GGadNqFtyAQ==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
'@intlify/shared@9.13.1': '@intlify/shared@9.13.1':
@@ -3994,6 +3997,22 @@ packages:
'@one-ini/wasm@0.1.1': '@one-ini/wasm@0.1.1':
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
'@oozcitak/dom@1.15.10':
resolution: {integrity: sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==}
engines: {node: '>=8.0'}
'@oozcitak/infra@1.0.8':
resolution: {integrity: sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==}
engines: {node: '>=6.0'}
'@oozcitak/url@1.0.4':
resolution: {integrity: sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==}
engines: {node: '>=8.0'}
'@oozcitak/util@8.3.8':
resolution: {integrity: sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==}
engines: {node: '>=8.0'}
'@peculiar/asn1-schema@2.3.8': '@peculiar/asn1-schema@2.3.8':
resolution: {integrity: sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==} resolution: {integrity: sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==}
@@ -12304,6 +12323,10 @@ packages:
resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==}
engines: {node: '>=4.0.0'} engines: {node: '>=4.0.0'}
xmlbuilder2@3.1.1:
resolution: {integrity: sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==}
engines: {node: '>=12.0'}
xmlbuilder@11.0.1: xmlbuilder@11.0.1:
resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==}
engines: {node: '>=4.0'} engines: {node: '>=4.0'}
@@ -15479,8 +15502,8 @@ snapshots:
'@intlify/bundle-utils@3.4.0(vue-i18n@9.8.0(vue@3.3.9(typescript@5.3.2)))': '@intlify/bundle-utils@3.4.0(vue-i18n@9.8.0(vue@3.3.9(typescript@5.3.2)))':
dependencies: dependencies:
'@intlify/message-compiler': 10.0.0-beta.2 '@intlify/message-compiler': 10.0.0-beta.5
'@intlify/shared': 10.0.0-beta.2 '@intlify/shared': 10.0.0-beta.5
jsonc-eslint-parser: 1.4.1 jsonc-eslint-parser: 1.4.1
source-map: 0.6.1 source-map: 0.6.1
yaml-eslint-parser: 0.3.2 yaml-eslint-parser: 0.3.2
@@ -15533,9 +15556,9 @@ snapshots:
dependencies: dependencies:
'@intlify/shared': 9.2.2 '@intlify/shared': 9.2.2
'@intlify/message-compiler@10.0.0-beta.2': '@intlify/message-compiler@10.0.0-beta.5':
dependencies: dependencies:
'@intlify/shared': 10.0.0-beta.2 '@intlify/shared': 10.0.0-beta.5
source-map-js: 1.2.0 source-map-js: 1.2.0
'@intlify/message-compiler@9.13.1': '@intlify/message-compiler@9.13.1':
@@ -15558,7 +15581,7 @@ snapshots:
'@intlify/shared': 9.8.0 '@intlify/shared': 9.8.0
source-map-js: 1.2.0 source-map-js: 1.2.0
'@intlify/shared@10.0.0-beta.2': {} '@intlify/shared@10.0.0-beta.5': {}
'@intlify/shared@9.13.1': {} '@intlify/shared@9.13.1': {}
@@ -15591,7 +15614,7 @@ snapshots:
'@intlify/vite-plugin-vue-i18n@6.0.1(vite@4.5.0(@types/node@18.18.8)(sass@1.69.5)(terser@5.31.0))(vue-i18n@9.8.0(vue@3.3.9(typescript@4.9.5)))': '@intlify/vite-plugin-vue-i18n@6.0.1(vite@4.5.0(@types/node@18.18.8)(sass@1.69.5)(terser@5.31.0))(vue-i18n@9.8.0(vue@3.3.9(typescript@4.9.5)))':
dependencies: dependencies:
'@intlify/bundle-utils': 7.0.0(vue-i18n@9.8.0(vue@3.3.9(typescript@4.9.5))) '@intlify/bundle-utils': 7.0.0(vue-i18n@9.8.0(vue@3.3.9(typescript@4.9.5)))
'@intlify/shared': 10.0.0-beta.2 '@intlify/shared': 10.0.0-beta.5
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.4.0) debug: 4.3.4(supports-color@9.4.0)
fast-glob: 3.3.2 fast-glob: 3.3.2
@@ -15605,7 +15628,7 @@ snapshots:
'@intlify/vite-plugin-vue-i18n@7.0.0(vite@4.5.0(@types/node@18.18.8)(sass@1.69.5)(terser@5.31.0))(vue-i18n@9.8.0(vue@3.3.9(typescript@5.3.2)))': '@intlify/vite-plugin-vue-i18n@7.0.0(vite@4.5.0(@types/node@18.18.8)(sass@1.69.5)(terser@5.31.0))(vue-i18n@9.8.0(vue@3.3.9(typescript@5.3.2)))':
dependencies: dependencies:
'@intlify/bundle-utils': 3.4.0(vue-i18n@9.8.0(vue@3.3.9(typescript@5.3.2))) '@intlify/bundle-utils': 3.4.0(vue-i18n@9.8.0(vue@3.3.9(typescript@5.3.2)))
'@intlify/shared': 10.0.0-beta.2 '@intlify/shared': 10.0.0-beta.5
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.4.0) debug: 4.3.4(supports-color@9.4.0)
fast-glob: 3.3.2 fast-glob: 3.3.2
@@ -16177,6 +16200,23 @@ snapshots:
'@one-ini/wasm@0.1.1': {} '@one-ini/wasm@0.1.1': {}
'@oozcitak/dom@1.15.10':
dependencies:
'@oozcitak/infra': 1.0.8
'@oozcitak/url': 1.0.4
'@oozcitak/util': 8.3.8
'@oozcitak/infra@1.0.8':
dependencies:
'@oozcitak/util': 8.3.8
'@oozcitak/url@1.0.4':
dependencies:
'@oozcitak/infra': 1.0.8
'@oozcitak/util': 8.3.8
'@oozcitak/util@8.3.8': {}
'@peculiar/asn1-schema@2.3.8': '@peculiar/asn1-schema@2.3.8':
dependencies: dependencies:
asn1js: 3.0.5 asn1js: 3.0.5
@@ -26967,6 +27007,13 @@ snapshots:
sax: 1.3.0 sax: 1.3.0
xmlbuilder: 11.0.1 xmlbuilder: 11.0.1
xmlbuilder2@3.1.1:
dependencies:
'@oozcitak/dom': 1.15.10
'@oozcitak/infra': 1.0.8
'@oozcitak/util': 8.3.8
js-yaml: 3.14.1
xmlbuilder@11.0.1: {} xmlbuilder@11.0.1: {}
xmlchars@2.2.0: xmlchars@2.2.0: