diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index eafbf584fd..da64a41760 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -7,6 +7,10 @@ _Released 02/08/2026 (PENDING)_ - Fixed an issue on Windows where extracting the Studio or Prompt bundle could fail with `EPERM: operation not permitted` when renaming extracted files. The extract step now retries on EPERM/EACCES with a short delay to handle transient file locks. Addressed in [#33330](https://github.com/cypress-io/cypress/pull/33330). +**Misc:** + +- The Node.js path is now displayed correctly in run log headers for typical GitHub Actions paths. ANSI escape sequences are no longer incorrectly displayed for longer Node.js paths. Addresses [#32736](https://github.com/cypress-io/cypress/issues/32736). + **Dependency Updates:** - Upgraded `rimraf` to `6.1.1` to address [CVE-2026-25547](https://github.com/isaacs/brace-expansion/security/advisories/GHSA-7h2j-956f-4vf2) vulnerability reported in security scans. Addressed in [#33336](https://github.com/cypress-io/cypress/pull/33336). diff --git a/packages/server/lib/util/newlines.js b/packages/server/lib/util/newlines.js index 960d31c73f..b2c1c18c62 100644 --- a/packages/server/lib/util/newlines.js +++ b/packages/server/lib/util/newlines.js @@ -1,3 +1,5 @@ +const util = require('util') + const addNewlineAtEveryNChar = (str, n) => { if (!str) { return str @@ -6,6 +8,16 @@ const addNewlineAtEveryNChar = (str, n) => { let result = [] let idx = 0 + let printableString = util.stripVTControlCharacters(str) + + if (printableString.length !== str.length) { + if (printableString.length <= n) { + return str + } else { + str = printableString + } + } + while (idx < str.length) { result.push(str.slice(idx, idx += n)) } diff --git a/packages/server/test/unit/util/newlines_spec.ts b/packages/server/test/unit/util/newlines_spec.ts index a5f06ca4aa..c1987e5ee0 100644 --- a/packages/server/test/unit/util/newlines_spec.ts +++ b/packages/server/test/unit/util/newlines_spec.ts @@ -3,13 +3,31 @@ import '../../spec_helper' import newlines from '../../../lib/util/newlines' describe('lib/util/newlines', function () { - it('inserts newline at each n char', function () { - expect(newlines.addNewlineAtEveryNChar('123456789', 3)).to.eq('123\n456\n789') + context('regular strings', function () { + it('inserts newline at each n char', function () { + expect(newlines.addNewlineAtEveryNChar('123456789', 3)).to.eq('123\n456\n789') + }) + + it('does not insert newline if str length <= n', function () { + expect(newlines.addNewlineAtEveryNChar('123', 3)).to.eq('123') + }) + + it('returns undefined if str not defined', function () { + expect(newlines.addNewlineAtEveryNChar(undefined, 3)).to.eq(undefined) + }) }) -}) -describe('lib/util/newlines', function () { - it('returns undefined if str not defined', function () { - expect(newlines.addNewlineAtEveryNChar(undefined, 3)).to.eq(undefined) + context('strings with ANSI codes', function () { + it('returns str unchanged if ANSI stripped length <= n', function () { + const shortAnsiString = '\u001B[31m123\u001B[39m' // "123" in red + + expect(newlines.addNewlineAtEveryNChar(shortAnsiString, 3)).to.eq(shortAnsiString) + }) + + it('returns str with ANSI stripped if printing length > n', function () { + const longAnsiString = '\u001B[31m123456789\u001B[39m' // "123456789" in red + + expect(newlines.addNewlineAtEveryNChar(longAnsiString, 3)).to.eq('123\n456\n789') + }) }) })