From 9104c25323826c64740a9459d0725f93f3d92a49 Mon Sep 17 00:00:00 2001 From: mihai Date: Tue, 13 Jun 2023 15:20:12 +0300 Subject: [PATCH 01/18] Test summary output --- .gitignore | 2 ++ action.yml | 2 ++ dist/index.js | 26 ++++++++++++++++++++++++++ index.js | 26 ++++++++++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/.gitignore b/.gitignore index f6b3f6a65..5a46d1ebd 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ examples/**/.yarn/* !examples/**/.yarn/releases !examples/**/.yarn/sdks !examples/**/.yarn/versions + +.idea diff --git a/action.yml b/action.yml index ba3d3983b..cd7c2e081 100644 --- a/action.yml +++ b/action.yml @@ -96,6 +96,8 @@ outputs: description: 'Cypress Cloud URL if the run was recorded (deprecated)' resultsUrl: description: 'Cypress Cloud URL if the run was recorded' + testResultsObject: + description: 'Cypress test results stringifyed JSON object' runs: using: 'node16' main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js index 9c46b946e..108b245d7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -75139,6 +75139,7 @@ const runTests = async () => { process.chdir(workingDirectory) return cypress .run(cypressOptions) + .then(generateOutputTestResultsObject) .then(generateSummary) .then(onTestsFinished, onTestsError) } @@ -75150,10 +75151,16 @@ const isSummaryEnabled = () => { } const generateSummary = async (testResults) => { + console.log( + 'Generating summary: %s', + isSummaryEnabled() ? 'yes' : 'no' + ) if (!isSummaryEnabled()) { return testResults } + console.log('after generating summary') + const headers = [ { data: 'Result', header: true }, { data: 'Passed :white_check_mark:', header: true }, @@ -75189,6 +75196,25 @@ const generateSummary = async (testResults) => { return testResults } +const generateOutputTestResultsObject = (testResults) => { + console.log('Generating output test results object') + console.log(JSON.stringify(outputObject)) + console.log(testResults) + + const outputObject = { + success: testResults.totalFailed === 0, + totalPassed: testResults.totalPassed, + totalFailed: testResults.totalFailed, + totalPending: testResults.totalPending, + totalSkipped: testResults.totalSkipped, + totalDuration: testResults.totalDuration / 1000 + 's' || 0 + } + + core.setOutput('testResultsObject', JSON.stringify(outputObject)) + + return testResults +} + const installMaybe = () => { const installParameter = getInputBool('install', true) if (!installParameter) { diff --git a/index.js b/index.js index 81311a294..6599b29f1 100644 --- a/index.js +++ b/index.js @@ -788,6 +788,7 @@ const runTests = async () => { process.chdir(workingDirectory) return cypress .run(cypressOptions) + .then(generateOutputTestResultsObject) .then(generateSummary) .then(onTestsFinished, onTestsError) } @@ -799,10 +800,16 @@ const isSummaryEnabled = () => { } const generateSummary = async (testResults) => { + console.log( + 'Generating summary: %s', + isSummaryEnabled() ? 'yes' : 'no' + ) if (!isSummaryEnabled()) { return testResults } + console.log('after generating summary') + const headers = [ { data: 'Result', header: true }, { data: 'Passed :white_check_mark:', header: true }, @@ -838,6 +845,25 @@ const generateSummary = async (testResults) => { return testResults } +const generateOutputTestResultsObject = (testResults) => { + console.log('Generating output test results object') + console.log(JSON.stringify(outputObject)) + console.log(testResults) + + const outputObject = { + success: testResults.totalFailed === 0, + totalPassed: testResults.totalPassed, + totalFailed: testResults.totalFailed, + totalPending: testResults.totalPending, + totalSkipped: testResults.totalSkipped, + totalDuration: testResults.totalDuration / 1000 + 's' || '' + } + + core.setOutput('testResultsObject', JSON.stringify(outputObject)) + + return testResults +} + const installMaybe = () => { const installParameter = getInputBool('install', true) if (!installParameter) { From 86ba246f3c8e02df783b8267ac45ad91c12f1ac1 Mon Sep 17 00:00:00 2001 From: mihai Date: Thu, 15 Jun 2023 10:42:48 +0300 Subject: [PATCH 02/18] Removed debug logs --- dist/index.js | 10 ---------- index.js | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/dist/index.js b/dist/index.js index 108b245d7..66805c568 100644 --- a/dist/index.js +++ b/dist/index.js @@ -75151,16 +75151,10 @@ const isSummaryEnabled = () => { } const generateSummary = async (testResults) => { - console.log( - 'Generating summary: %s', - isSummaryEnabled() ? 'yes' : 'no' - ) if (!isSummaryEnabled()) { return testResults } - console.log('after generating summary') - const headers = [ { data: 'Result', header: true }, { data: 'Passed :white_check_mark:', header: true }, @@ -75197,10 +75191,6 @@ const generateSummary = async (testResults) => { } const generateOutputTestResultsObject = (testResults) => { - console.log('Generating output test results object') - console.log(JSON.stringify(outputObject)) - console.log(testResults) - const outputObject = { success: testResults.totalFailed === 0, totalPassed: testResults.totalPassed, diff --git a/index.js b/index.js index 6599b29f1..6daa2f6d0 100644 --- a/index.js +++ b/index.js @@ -800,16 +800,10 @@ const isSummaryEnabled = () => { } const generateSummary = async (testResults) => { - console.log( - 'Generating summary: %s', - isSummaryEnabled() ? 'yes' : 'no' - ) if (!isSummaryEnabled()) { return testResults } - console.log('after generating summary') - const headers = [ { data: 'Result', header: true }, { data: 'Passed :white_check_mark:', header: true }, @@ -846,10 +840,6 @@ const generateSummary = async (testResults) => { } const generateOutputTestResultsObject = (testResults) => { - console.log('Generating output test results object') - console.log(JSON.stringify(outputObject)) - console.log(testResults) - const outputObject = { success: testResults.totalFailed === 0, totalPassed: testResults.totalPassed, From 212e2ffb1f78d37104b24f6216076418c438e8c7 Mon Sep 17 00:00:00 2001 From: mihai Date: Thu, 15 Jun 2023 11:00:41 +0300 Subject: [PATCH 03/18] Added some documentation for the testResultsObject output --- README.md | 28 ++++++++++++++++++++++++++++ dist/index.js | 2 +- index.js | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e350e15e1..8eed1ad21 100644 --- a/README.md +++ b/README.md @@ -1386,6 +1386,34 @@ The GitHub step output `dashboardUrl` is deprecated. Cypress Dashboard is now [C **Note:** every GitHub workflow step can have `outcome` and `conclusion` properties. See the GitHub [Contexts](https://docs.github.com/en/actions/learn-github-actions/contexts) documentation section [steps context](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#steps-context). In particular, the `outcome` or `conclusion` value can be `success`, `failure`, `cancelled`, or `skipped` which you can use in any following steps. +It also sets a step output `testResultsObject` which contains a stringified test results JSON object. +In order to use it you should parse the string into an object. +Ex: +```yaml +... + steps: + - name: Parse results + uses: actions/github-script@v6.4.1 + with: + script: | + const testResults = JSON.parse('${{ steps.cypress-run.outputs.testResultsObject }}') + console.log(testResults.success) + console.log(testResults.totalPassed) + ... +``` +Example structure of the JSON object: +```json +{ + "success": true, + "totalPassed": 5, + "totalFailed": 2, + "totalPending": 0, + "totalSkipped": 1, + "totalDuration": 25 +} +``` +**Note:** `totalDuration` is expressed in seconds. + ### Print Cypress info Sometimes you might want to print Cypress and OS information, like the list of detected browsers. You can use the [`cypress info`](https://on.cypress.io/command-line#cypress-info) command for this. diff --git a/dist/index.js b/dist/index.js index 66805c568..8f58c0cdf 100644 --- a/dist/index.js +++ b/dist/index.js @@ -75197,7 +75197,7 @@ const generateOutputTestResultsObject = (testResults) => { totalFailed: testResults.totalFailed, totalPending: testResults.totalPending, totalSkipped: testResults.totalSkipped, - totalDuration: testResults.totalDuration / 1000 + 's' || 0 + totalDuration: testResults.totalDuration / 1000 || '' } core.setOutput('testResultsObject', JSON.stringify(outputObject)) diff --git a/index.js b/index.js index 6daa2f6d0..2f33312c0 100644 --- a/index.js +++ b/index.js @@ -846,7 +846,7 @@ const generateOutputTestResultsObject = (testResults) => { totalFailed: testResults.totalFailed, totalPending: testResults.totalPending, totalSkipped: testResults.totalSkipped, - totalDuration: testResults.totalDuration / 1000 + 's' || '' + totalDuration: testResults.totalDuration / 1000 || '' } core.setOutput('testResultsObject', JSON.stringify(outputObject)) From 1e424a043500860f0e34a4e11b8af2ad7c48630e Mon Sep 17 00:00:00 2001 From: mihai Date: Thu, 15 Jun 2023 17:21:15 +0300 Subject: [PATCH 04/18] Test cypress testResultsObject output in example-recording.yml --- .github/workflows/example-recording.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index 28003aa1d..90988684b 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -133,6 +133,24 @@ jobs: echo Cypress finished with: ${{ steps.cypress.outcome }} echo See results at ${{ steps.cypress.outputs.resultsUrl }} + # print the `testResultsObject` output directly as string + - name: Print Cypress test results output + run: | + echo Cypress test results: ${{ steps.cypress.outputs.testResultsObject }} + + # parse the `testResultsObject` output as JSON + - name: Parse the Cypress test results output + uses: actions/github-script@v6.4.1 + with: + script: | + const testResults = JSON.parse('${{ steps.cypress.outputs.testResultsObject }}') + console.log("Success: " + testResults.success) + console.log("TotalPassed: " + testResults.totalPassed) + console.log("TotalFailed: " + testResults.totalFailed) + console.log("TotalPending: " + testResults.totalPending) + console.log("TotalSkipped: " + testResults.totalSkipped) + console.log("TotalDuration: " + testResults.totalDuration) + group: runs-on: ubuntu-22.04 needs: [check-record-key] From 8188a63c84fa0e2e24fb170e8a3e91eb03908e81 Mon Sep 17 00:00:00 2001 From: mihai Date: Thu, 15 Jun 2023 17:37:21 +0300 Subject: [PATCH 05/18] Test cypress testResultsObject output in example-recording.yml --- .github/workflows/example-recording.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index 90988684b..1e85b71d8 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -103,7 +103,7 @@ jobs: matrix: # run copies of the current job in parallel containers: [1, 2] - if: needs.check-record-key.outputs.record-key-exists == 'true' + if: always() # needs.check-record-key.outputs.record-key-exists == 'true' steps: - name: Checkout uses: actions/checkout@v3 From 63fc3804ab7ed44b67ab43a21a7f1ad1225b8510 Mon Sep 17 00:00:00 2001 From: mihai Date: Fri, 16 Jun 2023 16:43:38 +0300 Subject: [PATCH 06/18] Skip parsing testResultsObject if empty --- .github/workflows/example-recording.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index 1e85b71d8..56d3d63a1 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -138,18 +138,24 @@ jobs: run: | echo Cypress test results: ${{ steps.cypress.outputs.testResultsObject }} - # parse the `testResultsObject` output as JSON + # parse the `testResultsObject` output as JSON. + # Note that the output is a string and empty if there is a custom command passed to the action and the command runs through CLI - name: Parse the Cypress test results output uses: actions/github-script@v6.4.1 with: script: | + if (${{ steps.cypress.outputs.testResultsObject }} == "") { + console.log('No test results found') + return + } + const testResults = JSON.parse('${{ steps.cypress.outputs.testResultsObject }}') console.log("Success: " + testResults.success) console.log("TotalPassed: " + testResults.totalPassed) console.log("TotalFailed: " + testResults.totalFailed) console.log("TotalPending: " + testResults.totalPending) console.log("TotalSkipped: " + testResults.totalSkipped) - console.log("TotalDuration: " + testResults.totalDuration) + console.log("TotalDuration: " + testResults.totalDuration) group: runs-on: ubuntu-22.04 From 3c0abeb7dfe6c00646dc8d2384959dab868f3cf5 Mon Sep 17 00:00:00 2001 From: Mihai Gogu Date: Wed, 21 Jun 2023 17:36:36 +0300 Subject: [PATCH 07/18] Update example-recording.yml Revert back to needs.check-record-key.outputs.record-key-exists == 'true' --- .github/workflows/example-recording.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index 56d3d63a1..23ad023fe 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -103,7 +103,7 @@ jobs: matrix: # run copies of the current job in parallel containers: [1, 2] - if: always() # needs.check-record-key.outputs.record-key-exists == 'true' + if: needs.check-record-key.outputs.record-key-exists == 'true' steps: - name: Checkout uses: actions/checkout@v3 From f9794b0ece2b610178fda41e7517c65015693871 Mon Sep 17 00:00:00 2001 From: Mihai Gogu Date: Mon, 26 Jun 2023 11:36:28 +0300 Subject: [PATCH 08/18] Update .gitignore - remove .idea excluded directory --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5a46d1ebd..f6b3f6a65 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,3 @@ examples/**/.yarn/* !examples/**/.yarn/releases !examples/**/.yarn/sdks !examples/**/.yarn/versions - -.idea From ab2c53e07f43c69705d55d6925aaf14b11166067 Mon Sep 17 00:00:00 2001 From: mihai Date: Thu, 5 Oct 2023 17:41:14 +0300 Subject: [PATCH 09/18] Removed the calculated success status from testResultsObject --- .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/github-action.iml | 9 ++ .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 ++ .idea/workspace.xml | 56 +++++++++++ dist/index.js | 144 +++++++++------------------ index.js | 1 - 7 files changed, 133 insertions(+), 96 deletions(-) create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/github-action.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 000000000..a55e7a179 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/github-action.iml b/.idea/github-action.iml new file mode 100644 index 000000000..5e764c4f0 --- /dev/null +++ b/.idea/github-action.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..e4d4358c3 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 000000000..d3fb4b5c0 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + { + "keyToString": { + "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.go.formatter.settings.were.checked": "true", + "RunOnceActivity.go.migrated.go.modules.settings": "true", + "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true", + "WebServerToolWindowFactoryState": "false", + "full.screen.before.presentation.mode": "true", + "git-widget-placeholder": "feat/add-test-reults-output", + "go.import.settings.migrated": "true", + "go.sdk.automatically.set": "true", + "last_opened_file_path": "/Users/mihai/workspace/github-action", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "ts.external.directory.path": "/Applications/GoLand.app/Contents/plugins/javascript-impl/jsLanguageServicesImpl/external" + } +} + + + + + true + + \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index fe392014b..1a5c228b5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -6964,7 +6964,7 @@ const Constants = { /** * The core-http version */ - coreHttpVersion: "3.0.2", + coreHttpVersion: "3.0.0", /** * Specifies HTTP. */ @@ -7042,6 +7042,13 @@ const XML_CHARKEY = "_"; // Copyright (c) Microsoft Corporation. const validUuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/i; +/** + * A constant that indicates whether the environment is node.js or browser based. + */ +const isNode = typeof process !== "undefined" && + !!process.version && + !!process.versions && + !!process.versions.node; /** * Encodes an URI. * @@ -11722,7 +11729,7 @@ function createDefaultRequestPolicyFactories(authPolicyFactory, options) { factories.push(throttlingRetryPolicy()); } factories.push(deserializationPolicy(options.deserializationContentTypes)); - if (coreUtil.isNode) { + if (isNode) { factories.push(proxyPolicy(options.proxySettings)); } factories.push(logPolicy({ logger: logger.info })); @@ -11754,7 +11761,7 @@ function createPipelineFromOptions(pipelineOptions, authPolicyFactory) { const keepAliveOptions = Object.assign(Object.assign({}, DefaultKeepAliveOptions), pipelineOptions.keepAliveOptions); const retryOptions = Object.assign(Object.assign({}, DefaultRetryOptions), pipelineOptions.retryOptions); const redirectOptions = Object.assign(Object.assign({}, DefaultRedirectOptions), pipelineOptions.redirectOptions); - if (coreUtil.isNode) { + if (isNode) { requestPolicyFactories.push(proxyPolicy(pipelineOptions.proxyOptions)); } const deserializationOptions = Object.assign(Object.assign({}, DefaultDeserializationOptions), pipelineOptions.deserializationOptions); @@ -11767,7 +11774,7 @@ function createPipelineFromOptions(pipelineOptions, authPolicyFactory) { requestPolicyFactories.push(authPolicyFactory); } requestPolicyFactories.push(logPolicy(loggingOptions)); - if (coreUtil.isNode && pipelineOptions.decompressResponse === false) { + if (isNode && pipelineOptions.decompressResponse === false) { requestPolicyFactories.push(disableResponseDecompressionPolicy()); } return { @@ -11898,7 +11905,10 @@ function flattenResponse(_response, responseSpec) { } function getCredentialScopes(options, baseUri) { if (options === null || options === void 0 ? void 0 : options.credentialScopes) { - return options.credentialScopes; + const scopes = options.credentialScopes; + return Array.isArray(scopes) + ? scopes.map((scope) => new URL(scope).toString()) + : new URL(scopes).toString(); } if (baseUri) { return `${baseUri}/.default`; @@ -12131,10 +12141,6 @@ Object.defineProperty(exports, "delay", ({ enumerable: true, get: function () { return coreUtil.delay; } })); -Object.defineProperty(exports, "isNode", ({ - enumerable: true, - get: function () { return coreUtil.isNode; } -})); Object.defineProperty(exports, "isTokenCredential", ({ enumerable: true, get: function () { return coreAuth.isTokenCredential; } @@ -12174,6 +12180,7 @@ exports.generateUuid = generateUuid; exports.getDefaultProxySettings = getDefaultProxySettings; exports.getDefaultUserAgentValue = getDefaultUserAgentValue; exports.isDuration = isDuration; +exports.isNode = isNode; exports.isValidUuid = isValidUuid; exports.keepAlivePolicy = keepAlivePolicy; exports.logPolicy = logPolicy; @@ -53177,7 +53184,6 @@ const statusCodeCacheableByDefault = new Set([ 206, 300, 301, - 308, 404, 405, 410, @@ -53250,10 +53256,10 @@ function parseCacheControl(header) { // TODO: When there is more than one value present for a given directive (e.g., two Expires header fields, multiple Cache-Control: max-age directives), // the directive's value is considered invalid. Caches are encouraged to consider responses that have invalid freshness information to be stale - const parts = header.trim().split(/,/); + const parts = header.trim().split(/\s*,\s*/); // TODO: lame parsing for (const part of parts) { - const [k, v] = part.split(/=/, 2); - cc[k.trim()] = v === undefined ? true : v.trim().replace(/^"|"$/g, ''); + const [k, v] = part.split(/\s*=\s*/, 2); + cc[k] = v === undefined ? true : v.replace(/^"|"$/g, ''); // TODO: lame unquoting } return cc; @@ -63855,11 +63861,8 @@ var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || // Max safe segment length for coercion. var MAX_SAFE_COMPONENT_LENGTH = 16 -var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6 - // The actual regexps go on exports.re var re = exports.re = [] -var safeRe = exports.safeRe = [] var src = exports.src = [] var t = exports.tokens = {} var R = 0 @@ -63868,31 +63871,6 @@ function tok (n) { t[n] = R++ } -var LETTERDASHNUMBER = '[a-zA-Z0-9-]' - -// Replace some greedy regex tokens to prevent regex dos issues. These regex are -// used internally via the safeRe object since all inputs in this library get -// normalized first to trim and collapse all extra whitespace. The original -// regexes are exported for userland consumption and lower level usage. A -// future breaking change could export the safer regex only with a note that -// all input should have extra whitespace removed. -var safeRegexReplacements = [ - ['\\s', 1], - ['\\d', MAX_LENGTH], - [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH], -] - -function makeSafeRe (value) { - for (var i = 0; i < safeRegexReplacements.length; i++) { - var token = safeRegexReplacements[i][0] - var max = safeRegexReplacements[i][1] - value = value - .split(token + '*').join(token + '{0,' + max + '}') - .split(token + '+').join(token + '{1,' + max + '}') - } - return value -} - // The following Regular Expressions can be used for tokenizing, // validating, and parsing SemVer version strings. @@ -63902,14 +63880,14 @@ function makeSafeRe (value) { tok('NUMERICIDENTIFIER') src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*' tok('NUMERICIDENTIFIERLOOSE') -src[t.NUMERICIDENTIFIERLOOSE] = '\\d+' +src[t.NUMERICIDENTIFIERLOOSE] = '[0-9]+' // ## Non-numeric Identifier // Zero or more digits, followed by a letter or hyphen, and then zero or // more letters, digits, or hyphens. tok('NONNUMERICIDENTIFIER') -src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-]' + LETTERDASHNUMBER + '*' +src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' // ## Main Version // Three dot-separated numeric identifiers. @@ -63951,7 +63929,7 @@ src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] + // Any combination of digits, letters, or hyphens. tok('BUILDIDENTIFIER') -src[t.BUILDIDENTIFIER] = LETTERDASHNUMBER + '+' +src[t.BUILDIDENTIFIER] = '[0-9A-Za-z-]+' // ## Build Metadata // Plus sign, followed by one or more period-separated build metadata @@ -64031,7 +64009,6 @@ src[t.COERCE] = '(^|[^\\d])' + '(?:$|[^\\d])' tok('COERCERTL') re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g') -safeRe[t.COERCERTL] = new RegExp(makeSafeRe(src[t.COERCE]), 'g') // Tilde ranges. // Meaning is "reasonably at or greater than" @@ -64041,7 +64018,6 @@ src[t.LONETILDE] = '(?:~>?)' tok('TILDETRIM') src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+' re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g') -safeRe[t.TILDETRIM] = new RegExp(makeSafeRe(src[t.TILDETRIM]), 'g') var tildeTrimReplace = '$1~' tok('TILDE') @@ -64057,7 +64033,6 @@ src[t.LONECARET] = '(?:\\^)' tok('CARETTRIM') src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+' re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g') -safeRe[t.CARETTRIM] = new RegExp(makeSafeRe(src[t.CARETTRIM]), 'g') var caretTrimReplace = '$1^' tok('CARET') @@ -64079,7 +64054,6 @@ src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] + // this one has to use the /g flag re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g') -safeRe[t.COMPARATORTRIM] = new RegExp(makeSafeRe(src[t.COMPARATORTRIM]), 'g') var comparatorTrimReplace = '$1$2$3' // Something like `1.2.3 - 1.2.4` @@ -64108,14 +64082,6 @@ for (var i = 0; i < R; i++) { debug(i, src[i]) if (!re[i]) { re[i] = new RegExp(src[i]) - - // Replace all greedy whitespace to prevent regex dos issues. These regex are - // used internally via the safeRe object since all inputs in this library get - // normalized first to trim and collapse all extra whitespace. The original - // regexes are exported for userland consumption and lower level usage. A - // future breaking change could export the safer regex only with a note that - // all input should have extra whitespace removed. - safeRe[i] = new RegExp(makeSafeRe(src[i])) } } @@ -64140,7 +64106,7 @@ function parse (version, options) { return null } - var r = options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL] + var r = options.loose ? re[t.LOOSE] : re[t.FULL] if (!r.test(version)) { return null } @@ -64195,7 +64161,7 @@ function SemVer (version, options) { this.options = options this.loose = !!options.loose - var m = version.trim().match(options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL]) + var m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) if (!m) { throw new TypeError('Invalid Version: ' + version) @@ -64640,7 +64606,6 @@ function Comparator (comp, options) { return new Comparator(comp, options) } - comp = comp.trim().split(/\s+/).join(' ') debug('comparator', comp, options) this.options = options this.loose = !!options.loose @@ -64657,7 +64622,7 @@ function Comparator (comp, options) { var ANY = {} Comparator.prototype.parse = function (comp) { - var r = this.options.loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] + var r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] var m = comp.match(r) if (!m) { @@ -64781,16 +64746,9 @@ function Range (range, options) { this.loose = !!options.loose this.includePrerelease = !!options.includePrerelease - // First reduce all whitespace as much as possible so we do not have to rely - // on potentially slow regexes like \s*. This is then stored and used for - // future error messages as well. - this.raw = range - .trim() - .split(/\s+/) - .join(' ') - // First, split based on boolean or || - this.set = this.raw.split('||').map(function (range) { + this.raw = range + this.set = range.split(/\s*\|\|\s*/).map(function (range) { return this.parseRange(range.trim()) }, this).filter(function (c) { // throw out any that are not relevant for whatever reason @@ -64798,7 +64756,7 @@ function Range (range, options) { }) if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + this.raw) + throw new TypeError('Invalid SemVer Range: ' + range) } this.format() @@ -64817,19 +64775,20 @@ Range.prototype.toString = function () { Range.prototype.parseRange = function (range) { var loose = this.options.loose + range = range.trim() // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? safeRe[t.HYPHENRANGELOOSE] : safeRe[t.HYPHENRANGE] + var hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] range = range.replace(hr, hyphenReplace) debug('hyphen replace', range) // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(safeRe[t.COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range, safeRe[t.COMPARATORTRIM]) + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[t.COMPARATORTRIM]) // `~ 1.2.3` => `~1.2.3` - range = range.replace(safeRe[t.TILDETRIM], tildeTrimReplace) + range = range.replace(re[t.TILDETRIM], tildeTrimReplace) // `^ 1.2.3` => `^1.2.3` - range = range.replace(safeRe[t.CARETTRIM], caretTrimReplace) + range = range.replace(re[t.CARETTRIM], caretTrimReplace) // normalize spaces range = range.split(/\s+/).join(' ') @@ -64837,7 +64796,7 @@ Range.prototype.parseRange = function (range) { // At this point, the range is completely trimmed and // ready to be split into comparators. - var compRe = loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] + var compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] var set = range.split(' ').map(function (comp) { return parseComparator(comp, this.options) }, this).join(' ').split(/\s+/) @@ -64937,7 +64896,7 @@ function replaceTildes (comp, options) { } function replaceTilde (comp, options) { - var r = options.loose ? safeRe[t.TILDELOOSE] : safeRe[t.TILDE] + var r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] return comp.replace(r, function (_, M, m, p, pr) { debug('tilde', comp, _, M, m, p, pr) var ret @@ -64978,7 +64937,7 @@ function replaceCarets (comp, options) { function replaceCaret (comp, options) { debug('caret', comp, options) - var r = options.loose ? safeRe[t.CARETLOOSE] : safeRe[t.CARET] + var r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] return comp.replace(r, function (_, M, m, p, pr) { debug('caret', comp, _, M, m, p, pr) var ret @@ -65037,7 +64996,7 @@ function replaceXRanges (comp, options) { function replaceXRange (comp, options) { comp = comp.trim() - var r = options.loose ? safeRe[t.XRANGELOOSE] : safeRe[t.XRANGE] + var r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] return comp.replace(r, function (ret, gtlt, M, m, p, pr) { debug('xRange', comp, ret, gtlt, M, m, p, pr) var xM = isX(M) @@ -65112,7 +65071,7 @@ function replaceXRange (comp, options) { function replaceStars (comp, options) { debug('replaceStars', comp, options) // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(safeRe[t.STAR], '') + return comp.trim().replace(re[t.STAR], '') } // This function is passed to string.replace(re[t.HYPHENRANGE]) @@ -65438,7 +65397,7 @@ function coerce (version, options) { var match = null if (!options.rtl) { - match = version.match(safeRe[t.COERCE]) + match = version.match(re[t.COERCE]) } else { // Find the right-most coercible string that does not share // a terminus with a more left-ward coercible string. @@ -65449,17 +65408,17 @@ function coerce (version, options) { // Stop when we get a match that ends at the string end, since no // coercible string can be more right-ward without the same terminus. var next - while ((next = safeRe[t.COERCERTL].exec(version)) && + while ((next = re[t.COERCERTL].exec(version)) && (!match || match.index + match[0].length !== version.length) ) { if (!match || next.index + next[0].length !== match.index + match[0].length) { match = next } - safeRe[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length + re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length } // leave it in a clean state - safeRe[t.COERCERTL].lastIndex = -1 + re[t.COERCERTL].lastIndex = -1 } if (match === null) { @@ -69195,14 +69154,14 @@ function wrappy (fn, cb) { this.saxParser.onopentag = (function(_this) { return function(node) { var key, newValue, obj, processedKey, ref; - obj = Object.create(null); + obj = {}; obj[charkey] = ""; if (!_this.options.ignoreAttrs) { ref = node.attributes; for (key in ref) { if (!hasProp.call(ref, key)) continue; if (!(attrkey in obj) && !_this.options.mergeAttrs) { - obj[attrkey] = Object.create(null); + obj[attrkey] = {}; } newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key]; processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key; @@ -69252,11 +69211,7 @@ function wrappy (fn, cb) { } } if (isEmpty(obj)) { - if (typeof _this.options.emptyTag === 'function') { - obj = _this.options.emptyTag(); - } else { - obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr; - } + obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr; } if (_this.options.validator != null) { xpath = "/" + ((function() { @@ -69280,7 +69235,7 @@ function wrappy (fn, cb) { } if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') { if (!_this.options.preserveChildrenOrder) { - node = Object.create(null); + node = {}; if (_this.options.attrkey in obj) { node[_this.options.attrkey] = obj[_this.options.attrkey]; delete obj[_this.options.attrkey]; @@ -69295,7 +69250,7 @@ function wrappy (fn, cb) { obj = node; } else if (s) { s[_this.options.childkey] = s[_this.options.childkey] || []; - objClone = Object.create(null); + objClone = {}; for (key in obj) { if (!hasProp.call(obj, key)) continue; objClone[key] = obj[key]; @@ -69312,7 +69267,7 @@ function wrappy (fn, cb) { } else { if (_this.options.explicitRoot) { old = obj; - obj = Object.create(null); + obj = {}; obj[nodeName] = old; } _this.resultObject = obj; @@ -75313,7 +75268,6 @@ const generateSummary = async (testResults) => { const generateOutputTestResultsObject = (testResults) => { const outputObject = { - success: testResults.totalFailed === 0, totalPassed: testResults.totalPassed, totalFailed: testResults.totalFailed, totalPending: testResults.totalPending, diff --git a/index.js b/index.js index 209a28b7a..1557ba3fc 100644 --- a/index.js +++ b/index.js @@ -917,7 +917,6 @@ const generateSummary = async (testResults) => { const generateOutputTestResultsObject = (testResults) => { const outputObject = { - success: testResults.totalFailed === 0, totalPassed: testResults.totalPassed, totalFailed: testResults.totalFailed, totalPending: testResults.totalPending, From 087d18b266e2eb2acc2a671b116d69a3f269d8d8 Mon Sep 17 00:00:00 2001 From: mihai Date: Thu, 5 Oct 2023 17:48:27 +0300 Subject: [PATCH 10/18] Update docs and workflow to reflect removal of success property from testResultsObject --- .github/workflows/example-recording.yml | 1 - .idea/codeStyles/codeStyleConfig.xml | 5 --- .idea/github-action.iml | 9 ---- .idea/modules.xml | 8 ---- .idea/vcs.xml | 6 --- .idea/workspace.xml | 56 ------------------------- README.md | 2 - 7 files changed, 87 deletions(-) delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/github-action.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index 9ca767dfa..10042c513 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -90,7 +90,6 @@ jobs: } const testResults = JSON.parse('${{ steps.cypress.outputs.testResultsObject }}') - console.log("Success: " + testResults.success) console.log("TotalPassed: " + testResults.totalPassed) console.log("TotalFailed: " + testResults.totalFailed) console.log("TotalPending: " + testResults.totalPending) diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index a55e7a179..000000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/github-action.iml b/.idea/github-action.iml deleted file mode 100644 index 5e764c4f0..000000000 --- a/.idea/github-action.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index e4d4358c3..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddfb..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index d3fb4b5c0..000000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - { - "keyToString": { - "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.go.formatter.settings.were.checked": "true", - "RunOnceActivity.go.migrated.go.modules.settings": "true", - "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true", - "WebServerToolWindowFactoryState": "false", - "full.screen.before.presentation.mode": "true", - "git-widget-placeholder": "feat/add-test-reults-output", - "go.import.settings.migrated": "true", - "go.sdk.automatically.set": "true", - "last_opened_file_path": "/Users/mihai/workspace/github-action", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "ts.external.directory.path": "/Applications/GoLand.app/Contents/plugins/javascript-impl/jsLanguageServicesImpl/external" - } -} - - - - - true - - \ No newline at end of file diff --git a/README.md b/README.md index 5a73378b9..144e8c44f 100644 --- a/README.md +++ b/README.md @@ -1383,14 +1383,12 @@ Ex: with: script: | const testResults = JSON.parse('${{ steps.cypress-run.outputs.testResultsObject }}') - console.log(testResults.success) console.log(testResults.totalPassed) ... ``` Example structure of the JSON object: ```json { - "success": true, "totalPassed": 5, "totalFailed": 2, "totalPending": 0, From 3a8d64551e423952f06b31d4802270efdc4d28a7 Mon Sep 17 00:00:00 2001 From: mihai Date: Wed, 11 Oct 2023 09:24:57 +0300 Subject: [PATCH 11/18] Updated testResultsObject to testResults default --- README.md | 16 +++------------- action.yml | 2 +- dist/index.js | 17 ++--------------- index.js | 17 ++--------------- 4 files changed, 8 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 144e8c44f..0b9587731 100644 --- a/README.md +++ b/README.md @@ -1372,7 +1372,7 @@ The GitHub step output `dashboardUrl` is deprecated. Cypress Dashboard is now [C **Note:** every GitHub workflow step can have `outcome` and `conclusion` properties. See the GitHub [Contexts](https://docs.github.com/en/actions/learn-github-actions/contexts) documentation section [steps context](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#steps-context). In particular, the `outcome` or `conclusion` value can be `success`, `failure`, `cancelled`, or `skipped` which you can use in any following steps. -It also sets a step output `testResultsObject` which contains a stringified test results JSON object. +It also sets a step output `testResults` which contains a stringified test results JSON object. In order to use it you should parse the string into an object. Ex: ```yaml @@ -1382,21 +1382,11 @@ Ex: uses: actions/github-script@v6.4.1 with: script: | - const testResults = JSON.parse('${{ steps.cypress-run.outputs.testResultsObject }}') + const testResults = JSON.parse('${{ steps.cypress-run.outputs.testResults }}') console.log(testResults.totalPassed) ... ``` -Example structure of the JSON object: -```json -{ - "totalPassed": 5, - "totalFailed": 2, - "totalPending": 0, - "totalSkipped": 1, - "totalDuration": 25 -} -``` -**Note:** `totalDuration` is expressed in seconds. +Structure of the test results object can be found [here](https://docs.cypress.io/guides/guides/module-api#Results). ### Print Cypress info diff --git a/action.yml b/action.yml index 7b000f6b8..99a7771ea 100644 --- a/action.yml +++ b/action.yml @@ -96,7 +96,7 @@ outputs: description: 'Cypress Cloud URL if the run was recorded (deprecated)' resultsUrl: description: 'Cypress Cloud URL if the run was recorded' - testResultsObject: + testResults: description: 'Cypress test results stringifyed JSON object' runs: using: 'node20' diff --git a/dist/index.js b/dist/index.js index 1a5c228b5..d64c214fd 100644 --- a/dist/index.js +++ b/dist/index.js @@ -75167,6 +75167,8 @@ const runTests = async () => { debug(`Cypress options ${JSON.stringify(cypressOptions)}`) const onTestsFinished = (testResults) => { + core.setOutput('testResults', testResults) + const resultsUrl = testResults.runUrl process.chdir(startWorkingDirectory) @@ -75215,7 +75217,6 @@ const runTests = async () => { process.chdir(workingDirectory) return cypress .run(cypressOptions) - .then(generateOutputTestResultsObject) .then(generateSummary) .then(onTestsFinished, onTestsError) } @@ -75266,20 +75267,6 @@ const generateSummary = async (testResults) => { return testResults } -const generateOutputTestResultsObject = (testResults) => { - const outputObject = { - totalPassed: testResults.totalPassed, - totalFailed: testResults.totalFailed, - totalPending: testResults.totalPending, - totalSkipped: testResults.totalSkipped, - totalDuration: testResults.totalDuration / 1000 || '' - } - - core.setOutput('testResultsObject', JSON.stringify(outputObject)) - - return testResults -} - const installMaybe = () => { const installParameter = getInputBool('install', true) if (!installParameter) { diff --git a/index.js b/index.js index 1557ba3fc..df90f9f27 100644 --- a/index.js +++ b/index.js @@ -816,6 +816,8 @@ const runTests = async () => { debug(`Cypress options ${JSON.stringify(cypressOptions)}`) const onTestsFinished = (testResults) => { + core.setOutput('testResults', testResults) + const resultsUrl = testResults.runUrl process.chdir(startWorkingDirectory) @@ -864,7 +866,6 @@ const runTests = async () => { process.chdir(workingDirectory) return cypress .run(cypressOptions) - .then(generateOutputTestResultsObject) .then(generateSummary) .then(onTestsFinished, onTestsError) } @@ -915,20 +916,6 @@ const generateSummary = async (testResults) => { return testResults } -const generateOutputTestResultsObject = (testResults) => { - const outputObject = { - totalPassed: testResults.totalPassed, - totalFailed: testResults.totalFailed, - totalPending: testResults.totalPending, - totalSkipped: testResults.totalSkipped, - totalDuration: testResults.totalDuration / 1000 || '' - } - - core.setOutput('testResultsObject', JSON.stringify(outputObject)) - - return testResults -} - const installMaybe = () => { const installParameter = getInputBool('install', true) if (!installParameter) { From 4d4750139f1aa68c398c9fbf345a7a028dcbb447 Mon Sep 17 00:00:00 2001 From: mihai Date: Wed, 11 Oct 2023 10:04:45 +0300 Subject: [PATCH 12/18] Updated testResultsObject to testResults default - update workflow --- .github/workflows/example-recording.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index 10042c513..fe1849688 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -78,18 +78,18 @@ jobs: run: | echo Cypress test results: ${{ steps.cypress.outputs.testResultsObject }} - # parse the `testResultsObject` output as JSON. + # parse the `testResults` output as JSON. # Note that the output is a string and empty if there is a custom command passed to the action and the command runs through CLI - name: Parse the Cypress test results output uses: actions/github-script@v6.4.1 with: script: | - if (${{ steps.cypress.outputs.testResultsObject }} == "") { + if (${{ steps.cypress.outputs.testResults }} == "") { console.log('No test results found') return } - const testResults = JSON.parse('${{ steps.cypress.outputs.testResultsObject }}') + const testResults = JSON.parse('${{ steps.cypress.outputs.testResults }}') console.log("TotalPassed: " + testResults.totalPassed) console.log("TotalFailed: " + testResults.totalFailed) console.log("TotalPending: " + testResults.totalPending) From 7421400557c3a0813fcdf02019e1c495b166eef2 Mon Sep 17 00:00:00 2001 From: mihai Date: Wed, 11 Oct 2023 10:05:31 +0300 Subject: [PATCH 13/18] Updated testResultsObject to testResults default - update workflow --- .github/workflows/example-recording.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index fe1849688..b9ab6cec0 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -73,10 +73,10 @@ jobs: echo Cypress finished with: ${{ steps.cypress.outcome }} echo See results at ${{ steps.cypress.outputs.resultsUrl }} - # print the `testResultsObject` output directly as string + # print the `testResults` output directly as string - name: Print Cypress test results output run: | - echo Cypress test results: ${{ steps.cypress.outputs.testResultsObject }} + echo Cypress test results: ${{ steps.cypress.outputs.testResults }} # parse the `testResults` output as JSON. # Note that the output is a string and empty if there is a custom command passed to the action and the command runs through CLI From 84f0d2a154ae075280df4b4a396682c880a6750e Mon Sep 17 00:00:00 2001 From: Mihai Gogu Date: Thu, 12 Oct 2023 08:31:32 +0300 Subject: [PATCH 14/18] Update .github/workflows/example-recording.yml Co-authored-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> --- .github/workflows/example-recording.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index b9ab6cec0..9d81731d6 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -81,7 +81,7 @@ jobs: # parse the `testResults` output as JSON. # Note that the output is a string and empty if there is a custom command passed to the action and the command runs through CLI - name: Parse the Cypress test results output - uses: actions/github-script@v6.4.1 + uses: actions/github-script@v6 with: script: | if (${{ steps.cypress.outputs.testResults }} == "") { From 185d2ef3060c4036f95204d1aff253a0bdbd2733 Mon Sep 17 00:00:00 2001 From: Mihai Gogu Date: Thu, 12 Oct 2023 08:33:18 +0300 Subject: [PATCH 15/18] Update README.md Co-authored-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 907b3b266..a4c66657f 100644 --- a/README.md +++ b/README.md @@ -1381,7 +1381,7 @@ Ex: ... steps: - name: Parse results - uses: actions/github-script@v6.4.1 + uses: actions/github-script@v6 with: script: | const testResults = JSON.parse('${{ steps.cypress-run.outputs.testResults }}') From 4f33b71529e4b0b1a971817c1c20e20dc537bf04 Mon Sep 17 00:00:00 2001 From: Mihai Gogu Date: Fri, 20 Oct 2023 11:05:35 +0300 Subject: [PATCH 16/18] Update action.yml update testResults description Co-authored-by: Matt Schile --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 99a7771ea..dd0612d52 100644 --- a/action.yml +++ b/action.yml @@ -97,7 +97,7 @@ outputs: resultsUrl: description: 'Cypress Cloud URL if the run was recorded' testResults: - description: 'Cypress test results stringifyed JSON object' + description: 'Cypress run results (stringified JSON object)' runs: using: 'node20' main: 'dist/index.js' From d144906067290d0c3e804bfd8c5dcc78546672fc Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Mon, 23 Oct 2023 11:49:20 -0600 Subject: [PATCH 17/18] updating to runResults --- .github/workflows/example-recording.yml | 26 ++--- README.md | 19 ++-- action.yml | 2 +- dist/index.js | 143 ++++++++++++++++-------- 4 files changed, 118 insertions(+), 72 deletions(-) diff --git a/.github/workflows/example-recording.yml b/.github/workflows/example-recording.yml index 9d81731d6..1d315ffba 100644 --- a/.github/workflows/example-recording.yml +++ b/.github/workflows/example-recording.yml @@ -73,28 +73,28 @@ jobs: echo Cypress finished with: ${{ steps.cypress.outcome }} echo See results at ${{ steps.cypress.outputs.resultsUrl }} - # print the `testResults` output directly as string - - name: Print Cypress test results output + # print the `runResults` output directly as string + - name: Print Cypress run results output run: | - echo Cypress test results: ${{ steps.cypress.outputs.testResults }} + echo Cypress run results: ${{ steps.cypress.outputs.runResults }} - # parse the `testResults` output as JSON. + # parse the `runResults` output as JSON. # Note that the output is a string and empty if there is a custom command passed to the action and the command runs through CLI - - name: Parse the Cypress test results output + - name: Parse the Cypress run results output uses: actions/github-script@v6 with: script: | - if (${{ steps.cypress.outputs.testResults }} == "") { - console.log('No test results found') + if (${{ steps.cypress.outputs.runResults }} == "") { + console.log('No run results found') return } - const testResults = JSON.parse('${{ steps.cypress.outputs.testResults }}') - console.log("TotalPassed: " + testResults.totalPassed) - console.log("TotalFailed: " + testResults.totalFailed) - console.log("TotalPending: " + testResults.totalPending) - console.log("TotalSkipped: " + testResults.totalSkipped) - console.log("TotalDuration: " + testResults.totalDuration) + const runResults = JSON.parse('${{ steps.cypress.outputs.runResults }}') + console.log("TotalPassed: " + runResults.totalPassed) + console.log("TotalFailed: " + runResults.totalFailed) + console.log("TotalPending: " + runResults.totalPending) + console.log("TotalSkipped: " + runResults.totalSkipped) + console.log("TotalDuration: " + runResults.totalDuration) group: runs-on: ubuntu-22.04 diff --git a/README.md b/README.md index a4c66657f..e2f578fc5 100644 --- a/README.md +++ b/README.md @@ -1370,25 +1370,26 @@ This is an example of using the step output `resultsUrl`: The GitHub step output `dashboardUrl` is deprecated. Cypress Dashboard is now [Cypress Cloud](https://on.cypress.io/cloud-introduction). -[![recording example](https://github.com/cypress-io/github-action/workflows/example-recording/badge.svg?branch=master)](.github/workflows/example-recording.yml) +This action also sets a GitHub step output `runResults` which contains a stringified JSON object. -**Note:** every GitHub workflow step can have `outcome` and `conclusion` properties. See the GitHub [Contexts](https://docs.github.com/en/actions/learn-github-actions/contexts) documentation section [steps context](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#steps-context). In particular, the `outcome` or `conclusion` value can be `success`, `failure`, `cancelled`, or `skipped` which you can use in any following steps. +This is an example of parsing the `runResults`. -It also sets a step output `testResults` which contains a stringified test results JSON object. -In order to use it you should parse the string into an object. -Ex: ```yaml ... steps: - - name: Parse results + - name: Parse run results uses: actions/github-script@v6 with: script: | - const testResults = JSON.parse('${{ steps.cypress-run.outputs.testResults }}') - console.log(testResults.totalPassed) + const runResults = JSON.parse('${{ steps.cypress-run.outputs.runResults }}') + console.log(runResults.totalPassed) ... ``` -Structure of the test results object can be found [here](https://docs.cypress.io/guides/guides/module-api#Results). +Structure of the run results object can be found [here](https://docs.cypress.io/guides/guides/module-api#Results). + +[![recording example](https://github.com/cypress-io/github-action/workflows/example-recording/badge.svg?branch=master)](.github/workflows/example-recording.yml) + +**Note:** every GitHub workflow step can have `outcome` and `conclusion` properties. See the GitHub [Contexts](https://docs.github.com/en/actions/learn-github-actions/contexts) documentation section [steps context](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#steps-context). In particular, the `outcome` or `conclusion` value can be `success`, `failure`, `cancelled`, or `skipped` which you can use in any following steps. ### Print Cypress info diff --git a/action.yml b/action.yml index dd0612d52..f19250c86 100644 --- a/action.yml +++ b/action.yml @@ -96,7 +96,7 @@ outputs: description: 'Cypress Cloud URL if the run was recorded (deprecated)' resultsUrl: description: 'Cypress Cloud URL if the run was recorded' - testResults: + runResults: description: 'Cypress run results (stringified JSON object)' runs: using: 'node20' diff --git a/dist/index.js b/dist/index.js index d64c214fd..faf997fa2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -6964,7 +6964,7 @@ const Constants = { /** * The core-http version */ - coreHttpVersion: "3.0.0", + coreHttpVersion: "3.0.2", /** * Specifies HTTP. */ @@ -7042,13 +7042,6 @@ const XML_CHARKEY = "_"; // Copyright (c) Microsoft Corporation. const validUuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/i; -/** - * A constant that indicates whether the environment is node.js or browser based. - */ -const isNode = typeof process !== "undefined" && - !!process.version && - !!process.versions && - !!process.versions.node; /** * Encodes an URI. * @@ -11729,7 +11722,7 @@ function createDefaultRequestPolicyFactories(authPolicyFactory, options) { factories.push(throttlingRetryPolicy()); } factories.push(deserializationPolicy(options.deserializationContentTypes)); - if (isNode) { + if (coreUtil.isNode) { factories.push(proxyPolicy(options.proxySettings)); } factories.push(logPolicy({ logger: logger.info })); @@ -11761,7 +11754,7 @@ function createPipelineFromOptions(pipelineOptions, authPolicyFactory) { const keepAliveOptions = Object.assign(Object.assign({}, DefaultKeepAliveOptions), pipelineOptions.keepAliveOptions); const retryOptions = Object.assign(Object.assign({}, DefaultRetryOptions), pipelineOptions.retryOptions); const redirectOptions = Object.assign(Object.assign({}, DefaultRedirectOptions), pipelineOptions.redirectOptions); - if (isNode) { + if (coreUtil.isNode) { requestPolicyFactories.push(proxyPolicy(pipelineOptions.proxyOptions)); } const deserializationOptions = Object.assign(Object.assign({}, DefaultDeserializationOptions), pipelineOptions.deserializationOptions); @@ -11774,7 +11767,7 @@ function createPipelineFromOptions(pipelineOptions, authPolicyFactory) { requestPolicyFactories.push(authPolicyFactory); } requestPolicyFactories.push(logPolicy(loggingOptions)); - if (isNode && pipelineOptions.decompressResponse === false) { + if (coreUtil.isNode && pipelineOptions.decompressResponse === false) { requestPolicyFactories.push(disableResponseDecompressionPolicy()); } return { @@ -11905,10 +11898,7 @@ function flattenResponse(_response, responseSpec) { } function getCredentialScopes(options, baseUri) { if (options === null || options === void 0 ? void 0 : options.credentialScopes) { - const scopes = options.credentialScopes; - return Array.isArray(scopes) - ? scopes.map((scope) => new URL(scope).toString()) - : new URL(scopes).toString(); + return options.credentialScopes; } if (baseUri) { return `${baseUri}/.default`; @@ -12141,6 +12131,10 @@ Object.defineProperty(exports, "delay", ({ enumerable: true, get: function () { return coreUtil.delay; } })); +Object.defineProperty(exports, "isNode", ({ + enumerable: true, + get: function () { return coreUtil.isNode; } +})); Object.defineProperty(exports, "isTokenCredential", ({ enumerable: true, get: function () { return coreAuth.isTokenCredential; } @@ -12180,7 +12174,6 @@ exports.generateUuid = generateUuid; exports.getDefaultProxySettings = getDefaultProxySettings; exports.getDefaultUserAgentValue = getDefaultUserAgentValue; exports.isDuration = isDuration; -exports.isNode = isNode; exports.isValidUuid = isValidUuid; exports.keepAlivePolicy = keepAlivePolicy; exports.logPolicy = logPolicy; @@ -53184,6 +53177,7 @@ const statusCodeCacheableByDefault = new Set([ 206, 300, 301, + 308, 404, 405, 410, @@ -53256,10 +53250,10 @@ function parseCacheControl(header) { // TODO: When there is more than one value present for a given directive (e.g., two Expires header fields, multiple Cache-Control: max-age directives), // the directive's value is considered invalid. Caches are encouraged to consider responses that have invalid freshness information to be stale - const parts = header.trim().split(/\s*,\s*/); // TODO: lame parsing + const parts = header.trim().split(/,/); for (const part of parts) { - const [k, v] = part.split(/\s*=\s*/, 2); - cc[k] = v === undefined ? true : v.replace(/^"|"$/g, ''); // TODO: lame unquoting + const [k, v] = part.split(/=/, 2); + cc[k.trim()] = v === undefined ? true : v.trim().replace(/^"|"$/g, ''); } return cc; @@ -63861,8 +63855,11 @@ var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || // Max safe segment length for coercion. var MAX_SAFE_COMPONENT_LENGTH = 16 +var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6 + // The actual regexps go on exports.re var re = exports.re = [] +var safeRe = exports.safeRe = [] var src = exports.src = [] var t = exports.tokens = {} var R = 0 @@ -63871,6 +63868,31 @@ function tok (n) { t[n] = R++ } +var LETTERDASHNUMBER = '[a-zA-Z0-9-]' + +// Replace some greedy regex tokens to prevent regex dos issues. These regex are +// used internally via the safeRe object since all inputs in this library get +// normalized first to trim and collapse all extra whitespace. The original +// regexes are exported for userland consumption and lower level usage. A +// future breaking change could export the safer regex only with a note that +// all input should have extra whitespace removed. +var safeRegexReplacements = [ + ['\\s', 1], + ['\\d', MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH], +] + +function makeSafeRe (value) { + for (var i = 0; i < safeRegexReplacements.length; i++) { + var token = safeRegexReplacements[i][0] + var max = safeRegexReplacements[i][1] + value = value + .split(token + '*').join(token + '{0,' + max + '}') + .split(token + '+').join(token + '{1,' + max + '}') + } + return value +} + // The following Regular Expressions can be used for tokenizing, // validating, and parsing SemVer version strings. @@ -63880,14 +63902,14 @@ function tok (n) { tok('NUMERICIDENTIFIER') src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*' tok('NUMERICIDENTIFIERLOOSE') -src[t.NUMERICIDENTIFIERLOOSE] = '[0-9]+' +src[t.NUMERICIDENTIFIERLOOSE] = '\\d+' // ## Non-numeric Identifier // Zero or more digits, followed by a letter or hyphen, and then zero or // more letters, digits, or hyphens. tok('NONNUMERICIDENTIFIER') -src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' +src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-]' + LETTERDASHNUMBER + '*' // ## Main Version // Three dot-separated numeric identifiers. @@ -63929,7 +63951,7 @@ src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] + // Any combination of digits, letters, or hyphens. tok('BUILDIDENTIFIER') -src[t.BUILDIDENTIFIER] = '[0-9A-Za-z-]+' +src[t.BUILDIDENTIFIER] = LETTERDASHNUMBER + '+' // ## Build Metadata // Plus sign, followed by one or more period-separated build metadata @@ -64009,6 +64031,7 @@ src[t.COERCE] = '(^|[^\\d])' + '(?:$|[^\\d])' tok('COERCERTL') re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g') +safeRe[t.COERCERTL] = new RegExp(makeSafeRe(src[t.COERCE]), 'g') // Tilde ranges. // Meaning is "reasonably at or greater than" @@ -64018,6 +64041,7 @@ src[t.LONETILDE] = '(?:~>?)' tok('TILDETRIM') src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+' re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g') +safeRe[t.TILDETRIM] = new RegExp(makeSafeRe(src[t.TILDETRIM]), 'g') var tildeTrimReplace = '$1~' tok('TILDE') @@ -64033,6 +64057,7 @@ src[t.LONECARET] = '(?:\\^)' tok('CARETTRIM') src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+' re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g') +safeRe[t.CARETTRIM] = new RegExp(makeSafeRe(src[t.CARETTRIM]), 'g') var caretTrimReplace = '$1^' tok('CARET') @@ -64054,6 +64079,7 @@ src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] + // this one has to use the /g flag re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g') +safeRe[t.COMPARATORTRIM] = new RegExp(makeSafeRe(src[t.COMPARATORTRIM]), 'g') var comparatorTrimReplace = '$1$2$3' // Something like `1.2.3 - 1.2.4` @@ -64082,6 +64108,14 @@ for (var i = 0; i < R; i++) { debug(i, src[i]) if (!re[i]) { re[i] = new RegExp(src[i]) + + // Replace all greedy whitespace to prevent regex dos issues. These regex are + // used internally via the safeRe object since all inputs in this library get + // normalized first to trim and collapse all extra whitespace. The original + // regexes are exported for userland consumption and lower level usage. A + // future breaking change could export the safer regex only with a note that + // all input should have extra whitespace removed. + safeRe[i] = new RegExp(makeSafeRe(src[i])) } } @@ -64106,7 +64140,7 @@ function parse (version, options) { return null } - var r = options.loose ? re[t.LOOSE] : re[t.FULL] + var r = options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL] if (!r.test(version)) { return null } @@ -64161,7 +64195,7 @@ function SemVer (version, options) { this.options = options this.loose = !!options.loose - var m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) + var m = version.trim().match(options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL]) if (!m) { throw new TypeError('Invalid Version: ' + version) @@ -64606,6 +64640,7 @@ function Comparator (comp, options) { return new Comparator(comp, options) } + comp = comp.trim().split(/\s+/).join(' ') debug('comparator', comp, options) this.options = options this.loose = !!options.loose @@ -64622,7 +64657,7 @@ function Comparator (comp, options) { var ANY = {} Comparator.prototype.parse = function (comp) { - var r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] + var r = this.options.loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] var m = comp.match(r) if (!m) { @@ -64746,9 +64781,16 @@ function Range (range, options) { this.loose = !!options.loose this.includePrerelease = !!options.includePrerelease - // First, split based on boolean or || + // First reduce all whitespace as much as possible so we do not have to rely + // on potentially slow regexes like \s*. This is then stored and used for + // future error messages as well. this.raw = range - this.set = range.split(/\s*\|\|\s*/).map(function (range) { + .trim() + .split(/\s+/) + .join(' ') + + // First, split based on boolean or || + this.set = this.raw.split('||').map(function (range) { return this.parseRange(range.trim()) }, this).filter(function (c) { // throw out any that are not relevant for whatever reason @@ -64756,7 +64798,7 @@ function Range (range, options) { }) if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range) + throw new TypeError('Invalid SemVer Range: ' + this.raw) } this.format() @@ -64775,20 +64817,19 @@ Range.prototype.toString = function () { Range.prototype.parseRange = function (range) { var loose = this.options.loose - range = range.trim() // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] + var hr = loose ? safeRe[t.HYPHENRANGELOOSE] : safeRe[t.HYPHENRANGE] range = range.replace(hr, hyphenReplace) debug('hyphen replace', range) // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range, re[t.COMPARATORTRIM]) + range = range.replace(safeRe[t.COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, safeRe[t.COMPARATORTRIM]) // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[t.TILDETRIM], tildeTrimReplace) + range = range.replace(safeRe[t.TILDETRIM], tildeTrimReplace) // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[t.CARETTRIM], caretTrimReplace) + range = range.replace(safeRe[t.CARETTRIM], caretTrimReplace) // normalize spaces range = range.split(/\s+/).join(' ') @@ -64796,7 +64837,7 @@ Range.prototype.parseRange = function (range) { // At this point, the range is completely trimmed and // ready to be split into comparators. - var compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] + var compRe = loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] var set = range.split(' ').map(function (comp) { return parseComparator(comp, this.options) }, this).join(' ').split(/\s+/) @@ -64896,7 +64937,7 @@ function replaceTildes (comp, options) { } function replaceTilde (comp, options) { - var r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] + var r = options.loose ? safeRe[t.TILDELOOSE] : safeRe[t.TILDE] return comp.replace(r, function (_, M, m, p, pr) { debug('tilde', comp, _, M, m, p, pr) var ret @@ -64937,7 +64978,7 @@ function replaceCarets (comp, options) { function replaceCaret (comp, options) { debug('caret', comp, options) - var r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] + var r = options.loose ? safeRe[t.CARETLOOSE] : safeRe[t.CARET] return comp.replace(r, function (_, M, m, p, pr) { debug('caret', comp, _, M, m, p, pr) var ret @@ -64996,7 +65037,7 @@ function replaceXRanges (comp, options) { function replaceXRange (comp, options) { comp = comp.trim() - var r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] + var r = options.loose ? safeRe[t.XRANGELOOSE] : safeRe[t.XRANGE] return comp.replace(r, function (ret, gtlt, M, m, p, pr) { debug('xRange', comp, ret, gtlt, M, m, p, pr) var xM = isX(M) @@ -65071,7 +65112,7 @@ function replaceXRange (comp, options) { function replaceStars (comp, options) { debug('replaceStars', comp, options) // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[t.STAR], '') + return comp.trim().replace(safeRe[t.STAR], '') } // This function is passed to string.replace(re[t.HYPHENRANGE]) @@ -65397,7 +65438,7 @@ function coerce (version, options) { var match = null if (!options.rtl) { - match = version.match(re[t.COERCE]) + match = version.match(safeRe[t.COERCE]) } else { // Find the right-most coercible string that does not share // a terminus with a more left-ward coercible string. @@ -65408,17 +65449,17 @@ function coerce (version, options) { // Stop when we get a match that ends at the string end, since no // coercible string can be more right-ward without the same terminus. var next - while ((next = re[t.COERCERTL].exec(version)) && + while ((next = safeRe[t.COERCERTL].exec(version)) && (!match || match.index + match[0].length !== version.length) ) { if (!match || next.index + next[0].length !== match.index + match[0].length) { match = next } - re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length + safeRe[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length } // leave it in a clean state - re[t.COERCERTL].lastIndex = -1 + safeRe[t.COERCERTL].lastIndex = -1 } if (match === null) { @@ -69154,14 +69195,14 @@ function wrappy (fn, cb) { this.saxParser.onopentag = (function(_this) { return function(node) { var key, newValue, obj, processedKey, ref; - obj = {}; + obj = Object.create(null); obj[charkey] = ""; if (!_this.options.ignoreAttrs) { ref = node.attributes; for (key in ref) { if (!hasProp.call(ref, key)) continue; if (!(attrkey in obj) && !_this.options.mergeAttrs) { - obj[attrkey] = {}; + obj[attrkey] = Object.create(null); } newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key]; processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key; @@ -69211,7 +69252,11 @@ function wrappy (fn, cb) { } } if (isEmpty(obj)) { - obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr; + if (typeof _this.options.emptyTag === 'function') { + obj = _this.options.emptyTag(); + } else { + obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr; + } } if (_this.options.validator != null) { xpath = "/" + ((function() { @@ -69235,7 +69280,7 @@ function wrappy (fn, cb) { } if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') { if (!_this.options.preserveChildrenOrder) { - node = {}; + node = Object.create(null); if (_this.options.attrkey in obj) { node[_this.options.attrkey] = obj[_this.options.attrkey]; delete obj[_this.options.attrkey]; @@ -69250,7 +69295,7 @@ function wrappy (fn, cb) { obj = node; } else if (s) { s[_this.options.childkey] = s[_this.options.childkey] || []; - objClone = {}; + objClone = Object.create(null); for (key in obj) { if (!hasProp.call(obj, key)) continue; objClone[key] = obj[key]; @@ -69267,7 +69312,7 @@ function wrappy (fn, cb) { } else { if (_this.options.explicitRoot) { old = obj; - obj = {}; + obj = Object.create(null); obj[nodeName] = old; } _this.resultObject = obj; From 6f3e59ee0b719215db174b87b246e54f2f8074c4 Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Mon, 23 Oct 2023 11:51:04 -0600 Subject: [PATCH 18/18] updating to runResults --- dist/index.js | 2 +- index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index faf997fa2..dd3201984 100644 --- a/dist/index.js +++ b/dist/index.js @@ -75212,7 +75212,7 @@ const runTests = async () => { debug(`Cypress options ${JSON.stringify(cypressOptions)}`) const onTestsFinished = (testResults) => { - core.setOutput('testResults', testResults) + core.setOutput('runResults', testResults) const resultsUrl = testResults.runUrl process.chdir(startWorkingDirectory) diff --git a/index.js b/index.js index df90f9f27..869dbfc6e 100644 --- a/index.js +++ b/index.js @@ -816,7 +816,7 @@ const runTests = async () => { debug(`Cypress options ${JSON.stringify(cypressOptions)}`) const onTestsFinished = (testResults) => { - core.setOutput('testResults', testResults) + core.setOutput('runResults', testResults) const resultsUrl = testResults.runUrl process.chdir(startWorkingDirectory)