Skip to content

Commit 418c438

Browse files
authored
fix: stderr tokens are no longer injected when in development mode (#32674)
* do not tag streams when in dev mode, or when electron_enable_logging is true * test negative of ELECTRON_ENABLE_LOGGING * changelog * refactor / better structuring of tag enable/disable * improvement * changelog * flush with an empty buffer if there is nothing left in the decoder * make flush / transform consistent w/ empty output
1 parent e0c001f commit 418c438

File tree

8 files changed

+120
-41
lines changed

8 files changed

+120
-41
lines changed

cli/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ _Released 10/21/2025 (PENDING)_
1010
**Bugfixes:**
1111

1212
- An error is no longer thrown during command execution when the application under test overwrites the `window.$` property with a non-function. Fixes [#1502](https://github.com/cypress-io/cypress/issues/1502). Fixed in [#32682](https://github.com/cypress-io/cypress/pull/32682).
13+
- When running `cypress` in Cypress development environments, or when `ELECTRON_ENABLE_LOGGING` is otherwise set to 1, certain messages written to `stderr` will no longer be bracketed with verbose tags. Addresses [#32569](https://github.com/cypress-io/cypress/issues/32569). Addressed in [#32674](https://github.com/cypress-io/cypress/pull/32674).
1314

1415
**Misc:**
1516

packages/stderr-filtering/lib/Filter.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ import { START_TAG, END_TAG } from './constants'
44
import { FilterPrefixedContent } from './FilterPrefixedContent'
55
import { FilterTaggedContent } from './FilterTaggedContent'
66
import { WriteToDebug } from './WriteToDebug'
7+
import { tagsDisabled } from './tagsDisabled'
78

8-
const DISABLE_TAGS = process.env.ELECTRON_ENABLE_LOGGING === '1'
9-
10-
export function filter (stderr: Writable, debug: Debugger, prefix: RegExp, disableTags: boolean = false): Writable {
9+
export function filter (stderr: Writable, debug: Debugger, prefix: RegExp): Writable {
1110
const prefixTx = new FilterPrefixedContent(prefix, stderr)
12-
const tagTx = new FilterTaggedContent(START_TAG, END_TAG, stderr)
1311
const debugWriter = new WriteToDebug(debug)
1412

15-
if (DISABLE_TAGS || disableTags) {
13+
if (tagsDisabled()) {
1614
prefixTx.pipe(debugWriter)
1715
} else {
16+
const tagTx = new FilterTaggedContent(START_TAG, END_TAG, stderr)
17+
1818
prefixTx.pipe(tagTx).pipe(debugWriter)
1919
}
2020

packages/stderr-filtering/lib/TagStream.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { Transform } from 'stream'
22
import { START_TAG, END_TAG } from './constants'
33
import { StringDecoder } from 'string_decoder'
44
import Debug from 'debug'
5+
import { tagsDisabled } from './tagsDisabled'
56

67
const debug = Debug('cypress:stderr-filtering:TagStream')
8+
const debugVerbose = Debug('cypress-verbose:stderr-filtering:TagStream')
79

810
/**
911
* A Transform stream that wraps input data with start and end tags.
@@ -66,13 +68,13 @@ export class TagStream extends Transform {
6668
const out = chunk instanceof Buffer ?
6769
this.initializedDecoder.write(chunk) :
6870
chunk
69-
const transformed = `${this.startTag}${out}${this.endTag}`
71+
const transformed = out ? this.tag(out) : Buffer.from('')
7072

71-
debug(`transformed: "${transformed.replaceAll('\n', '\\n')}"`)
72-
const canWrite = this.push(out ? Buffer.from(transformed) : '')
73+
debugVerbose(`transformed: "${transformed.toString().replaceAll('\n', '\\n')}"`)
74+
const canWrite = this.push(transformed)
7375

7476
if (!canWrite) {
75-
debug('waiting for drain')
77+
debugVerbose('waiting for drain')
7678
await new Promise((resolve) => this.once('drain', resolve))
7779
}
7880

@@ -95,6 +97,10 @@ export class TagStream extends Transform {
9597
debug('flushing')
9698
const out = this.initializedDecoder.end()
9799

98-
callback(undefined, Buffer.from(`${this.startTag}${out}${this.endTag}`))
100+
callback(undefined, out ? this.tag(out) : Buffer.from(''))
101+
}
102+
103+
private tag (str: string): Buffer {
104+
return tagsDisabled() ? Buffer.from(str) : Buffer.from(`${this.startTag}${str}${this.endTag}`)
99105
}
100106
}

packages/stderr-filtering/lib/__spec__/Filter.spec.ts

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ vi.mock('../FilterPrefixedContent')
1010
vi.mock('../FilterTaggedContent')
1111
vi.mock('../WriteToDebug')
1212

13-
// Mock process.env
14-
const originalEnv = process.env
15-
1613
describe('Filter', () => {
1714
let mockStderr: any
1815
let mockDebug: any
@@ -21,9 +18,6 @@ describe('Filter', () => {
2118
let mockWriteToDebug: any
2219

2320
beforeEach(() => {
24-
// Reset environment
25-
process.env = { ...originalEnv }
26-
2721
// Create mock objects
2822
mockStderr = {
2923
write: vi.fn(),
@@ -54,48 +48,38 @@ describe('Filter', () => {
5448

5549
afterEach(() => {
5650
vi.clearAllMocks()
57-
process.env = originalEnv
51+
vi.unstubAllEnvs()
5852
})
5953

60-
describe('when disableTags is false', () => {
61-
beforeEach(() => {
62-
process.env.ELECTRON_ENABLE_LOGGING = '0'
63-
})
64-
54+
describe('when tags are enabled', () => {
6555
it('pipes prefixTx -> tagTx -> debugWriter', () => {
66-
const result = filter(mockStderr, mockDebug, DEBUG_PREFIX, false)
56+
vi.stubEnv('ELECTRON_ENABLE_LOGGING', '0')
57+
vi.stubEnv('CYPRESS_INTERNAL_ENV', 'production')
58+
59+
const result = filter(mockStderr, mockDebug, DEBUG_PREFIX)
6760

68-
// Verify FilterPrefixedContent was created with correct args
6961
expect(FilterPrefixedContent).toHaveBeenCalledWith(DEBUG_PREFIX, mockStderr)
7062

71-
// Verify FilterTaggedContent was created with correct args
7263
expect(FilterTaggedContent).toHaveBeenCalledWith(START_TAG, END_TAG, mockStderr)
7364

74-
// Verify WriteToDebug was created with correct args
7565
expect(WriteToDebug).toHaveBeenCalledWith(mockDebug)
7666

77-
// Verify the pipe chain: prefixTx -> tagTx -> debugWriter
7867
expect(mockFilterPrefixedContent.pipe).toHaveBeenCalledWith(mockFilterTaggedContent)
7968
expect(mockFilterTaggedContent.pipe).toHaveBeenCalledWith(mockWriteToDebug)
8069

81-
// Verify the result is the prefixTx
8270
expect(result).toBe(mockFilterPrefixedContent)
8371
})
8472
})
8573

86-
describe('when disableTags parameter is true', () => {
87-
beforeEach(() => {
88-
process.env.ELECTRON_ENABLE_LOGGING = '0'
89-
})
90-
91-
it('should pipe prefixTx -> debugWriter (skip tagTx)', () => {
92-
const result = filter(mockStderr, mockDebug, DEBUG_PREFIX, true)
74+
describe('disabling tags', () => {
75+
function expectNoTags () {
76+
const result = filter(mockStderr, mockDebug, DEBUG_PREFIX)
9377

9478
// Verify FilterPrefixedContent was created with correct args
9579
expect(FilterPrefixedContent).toHaveBeenCalledWith(DEBUG_PREFIX, mockStderr)
9680

9781
// Verify FilterTaggedContent was created with correct args
98-
expect(FilterTaggedContent).toHaveBeenCalledWith(START_TAG, END_TAG, mockStderr)
82+
expect(FilterTaggedContent).not.toHaveBeenCalled()
9983

10084
// Verify WriteToDebug was created with correct args
10185
expect(WriteToDebug).toHaveBeenCalledWith(mockDebug)
@@ -106,6 +90,16 @@ describe('Filter', () => {
10690

10791
// Verify the result is the prefixTx
10892
expect(result).toBe(mockFilterPrefixedContent)
93+
}
94+
95+
it('does not add tags when ELECTRON_ENABLE_LOGGING is enabled', () => {
96+
vi.stubEnv('ELECTRON_ENABLE_LOGGING', '1')
97+
expectNoTags()
98+
})
99+
100+
it('does not add tags when CYPRESS_INTERNAL_ENV is development', () => {
101+
vi.stubEnv('CYPRESS_INTERNAL_ENV', 'development')
102+
expectNoTags()
109103
})
110104
})
111105
})

packages/stderr-filtering/lib/__spec__/TagStream.spec.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe('TagStream', () => {
9393
const cb = vi.fn()
9494

9595
await tagStream.transform(bufInput, 'buffer', cb)
96-
expect(tagStream.push).toHaveBeenCalledWith('')
96+
expect(tagStream.push).toHaveBeenCalledWith(Buffer.from(''))
9797
expect(cb).toHaveBeenCalled()
9898
})
9999
})
@@ -115,4 +115,63 @@ describe('TagStream', () => {
115115
})
116116
})
117117
})
118+
119+
describe('disabling tags', () => {
120+
afterEach(() => {
121+
vi.unstubAllEnvs()
122+
})
123+
124+
it('passes on the string without the tags in CYPRESS_INTERNAL_ENV development mode', async () => {
125+
vi.stubEnv('CYPRESS_INTERNAL_ENV', 'development')
126+
const cb = vi.fn()
127+
128+
await tagStream.transform(strInput, 'utf-8', cb)
129+
expect(tagStream.push).toHaveBeenCalledWith(Buffer.from(strInput))
130+
expect(cb).toHaveBeenCalled()
131+
})
132+
133+
describe('when ELECTRON_ENABLE_LOGGING is enabled', () => {
134+
beforeEach(() => {
135+
vi.stubEnv('ELECTRON_ENABLE_LOGGING', '1')
136+
})
137+
138+
it('does not add the tags when transforming', async () => {
139+
const cb = vi.fn()
140+
141+
await tagStream.transform(strInput, 'utf-8', cb)
142+
expect(tagStream.push).toHaveBeenCalledWith(Buffer.from(strInput))
143+
expect(cb).toHaveBeenCalled()
144+
})
145+
146+
it('does not add the tags when flushing', async () => {
147+
const cb = vi.fn()
148+
149+
mockStringDecoder.end.mockReturnValue(strInput)
150+
await tagStream.flush(cb)
151+
expect(cb).toHaveBeenCalledWith(undefined, Buffer.from(strInput))
152+
})
153+
})
154+
155+
describe('when CYPRESS_INTERNAL_ENV is development', () => {
156+
beforeEach(() => {
157+
vi.stubEnv('CYPRESS_INTERNAL_ENV', 'development')
158+
})
159+
160+
it('does not add the tags when transforming', async () => {
161+
const cb = vi.fn()
162+
163+
await tagStream.transform(strInput, 'utf-8', cb)
164+
expect(tagStream.push).toHaveBeenCalledWith(Buffer.from(strInput))
165+
expect(cb).toHaveBeenCalled()
166+
})
167+
168+
it('does not add the tags when flushing', async () => {
169+
const cb = vi.fn()
170+
171+
mockStringDecoder.end.mockReturnValue(strInput)
172+
await tagStream.flush(cb)
173+
expect(cb).toHaveBeenCalledWith(undefined, Buffer.from(strInput))
174+
})
175+
})
176+
})
118177
})

packages/stderr-filtering/lib/__spec__/logError.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ describe('logError', () => {
1313
afterEach(() => {
1414
// Restore the original console.error
1515
consoleErrorSpy.mockRestore()
16+
vi.unstubAllEnvs()
1617
})
1718

1819
describe('START_TAG and END_TAG constants', () => {
@@ -105,6 +106,22 @@ describe('logError', () => {
105106
expect(consoleErrorSpy).toHaveBeenCalledTimes(1)
106107
expect(consoleErrorSpy).toHaveBeenCalledWith(START_TAG, error, END_TAG)
107108
})
109+
110+
it('does not add tags in CYPRESS_INTERNAL_ENV development mode', () => {
111+
vi.stubEnv('CYPRESS_INTERNAL_ENV', 'development')
112+
logError('Test error')
113+
114+
expect(consoleErrorSpy).toHaveBeenCalledTimes(1)
115+
expect(consoleErrorSpy).toHaveBeenCalledWith('Test error')
116+
})
117+
118+
it('does not add tags in ELECTRON_ENABLE_LOGGING enabled', () => {
119+
vi.stubEnv('ELECTRON_ENABLE_LOGGING', '1')
120+
logError('Test error')
121+
122+
expect(consoleErrorSpy).toHaveBeenCalledTimes(1)
123+
expect(consoleErrorSpy).toHaveBeenCalledWith('Test error')
124+
})
108125
})
109126

110127
describe('integration with console.error', () => {

packages/stderr-filtering/lib/logError.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/**
2-
* Standard error logging tags used for stderr filtering.a
2+
* Standard error logging tags used for stderr filtering
33
*/
44
import { START_TAG, END_TAG } from './constants'
5+
import { tagsDisabled } from './tagsDisabled'
56

67
/**
78
* Logs error messages with special tags for stderr filtering.
@@ -14,12 +15,10 @@ import { START_TAG, END_TAG } from './constants'
1415
* @param args The arguments to log as an error message
1516
*/
1617

17-
const DISABLE_TAGS = process.env.ELECTRON_ENABLE_LOGGING === '1'
18-
1918
export const logError = (...args: any[]) => {
2019
// When electron debug is enabled, the output will not be filtered, so
2120
// these tags are not needed.
22-
if (DISABLE_TAGS) {
21+
if (tagsDisabled()) {
2322
// eslint-disable-next-line no-console
2423
console.error(...args)
2524
} else {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function tagsDisabled () {
2+
return process.env.ELECTRON_ENABLE_LOGGING === '1' || process.env.CYPRESS_INTERNAL_ENV === 'development'
3+
}

0 commit comments

Comments
 (0)