Skip to content

Commit 6a7f01f

Browse files
committed
feat: directly writes to stdio so jest does not swallow
1 parent 95e84ad commit 6a7f01f

7 files changed

Lines changed: 131 additions & 105 deletions

File tree

src/__helpers__/mocks.ts

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,58 +9,3 @@ export function spied<T>(
99
): T extends (...args: any[]) => any ? jest.SpyInstance<T> : jest.Mocked<T> {
1010
return val as any
1111
}
12-
13-
export function mockThese(
14-
map:
15-
| string[]
16-
| {
17-
[k: string]: () => any
18-
},
19-
) {
20-
const isArray = Array.isArray(map)
21-
const items: string[] = isArray ? (map as string[]) : Object.keys(map)
22-
items.forEach(item => {
23-
const val = isArray ? () => item : (map as any)[item]
24-
jest.doMock(item, val, { virtual: true })
25-
})
26-
}
27-
28-
export function spyThese<T extends object, K extends keyof T>(
29-
object: T,
30-
implementations: { [key in K]: T[K] | any | undefined },
31-
): { [key in K]: jest.SpyInstance<T[K]> } & {
32-
mockRestore: () => void
33-
mockReset: () => void
34-
mockClear: () => void
35-
} {
36-
const keys = Object.keys(implementations) as K[]
37-
const res = keys.reduce(
38-
(map, key) => {
39-
const actual = object[key] as any
40-
const spy = (map[key] = jest.spyOn(object, key as K))
41-
if (implementations[key]) {
42-
const impl = implementations[key] as (...args: any[]) => any
43-
if (impl.length && /\W\$super\W/.test(impl.toString())) {
44-
spy.mockImplementation(function(this: T, ...args: any[]) {
45-
return impl.call(this, () => actual.apply(this, args), ...args)
46-
})
47-
} else {
48-
spy.mockImplementation(impl)
49-
}
50-
}
51-
return map
52-
},
53-
{} as any,
54-
)
55-
// utility to restore/reset/clear all
56-
res.mockRestore = () => {
57-
keys.forEach(key => res[key].mockRestore())
58-
}
59-
res.mockReset = () => {
60-
keys.forEach(key => res[key].mockReset())
61-
}
62-
res.mockClear = () => {
63-
keys.forEach(key => res[key].mockClear())
64-
}
65-
return res
66-
}

src/lib/__snapshots__/backports.spec.ts.snap

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Object {
1616
}
1717
`;
1818

19-
exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to false should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead."`;
19+
exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to false should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead."`;
2020

2121
exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to true should have changed the config correctly: before 1`] = `
2222
Object {
@@ -36,7 +36,7 @@ Object {
3636
}
3737
`;
3838

39-
exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to true should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead."`;
39+
exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to true should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead."`;
4040

4141
exports[`backportJestConfig with "globals.__TS_CONFIG__" set to { foo: 'bar' } should have changed the config correctly: before 1`] = `
4242
Object {
@@ -60,7 +60,7 @@ Object {
6060
}
6161
`;
6262

63-
exports[`backportJestConfig with "globals.__TS_CONFIG__" set to { foo: 'bar' } should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.__TS_CONFIG__\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead."`;
63+
exports[`backportJestConfig with "globals.__TS_CONFIG__" set to { foo: 'bar' } should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.__TS_CONFIG__\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead."`;
6464

6565
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to '\\\\.spec\\\\.ts$' should have changed the config correctly: before 1`] = `
6666
Object {
@@ -84,7 +84,7 @@ Object {
8484
}
8585
`;
8686

87-
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to '\\\\.spec\\\\.ts$' should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`;
87+
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to '\\\\.spec\\\\.ts$' should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`;
8888

8989
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to false should have changed the config correctly: before 1`] = `
9090
Object {
@@ -106,7 +106,7 @@ Object {
106106
}
107107
`;
108108

109-
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to false should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`;
109+
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to false should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`;
110110

111111
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to true should have changed the config correctly: before 1`] = `
112112
Object {
@@ -128,7 +128,7 @@ Object {
128128
}
129129
`;
130130

131-
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to true should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`;
131+
exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to true should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`;
132132

133133
exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to false should have changed the config correctly: before 1`] = `
134134
Object {
@@ -150,7 +150,7 @@ Object {
150150
}
151151
`;
152152

153-
exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to false should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead."`;
153+
exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to false should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead."`;
154154

155155
exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to true should have changed the config correctly: before 1`] = `
156156
Object {
@@ -170,7 +170,7 @@ Object {
170170
}
171171
`;
172172

173-
exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to true should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead."`;
173+
exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to true should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead."`;
174174

175175
exports[`backportJestConfig with "globals.ts-jest.tsConfigFile" set to 'tsconfig.build.json' should have changed the config correctly: before 1`] = `
176176
Object {
@@ -192,7 +192,7 @@ Object {
192192
}
193193
`;
194194

195-
exports[`backportJestConfig with "globals.ts-jest.tsConfigFile" set to 'tsconfig.build.json' should wran the user 1`] = `"ts-jest: \\"[jest-config].globals.ts-jest.tsConfigFile\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead."`;
195+
exports[`backportJestConfig with "globals.ts-jest.tsConfigFile" set to 'tsconfig.build.json' should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.tsConfigFile\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead."`;
196196

197197
exports[`backportJestConfig with "globals.ts-jest.useBabelrc" set to false should have changed the config correctly: before 1`] = `
198198
Object {
@@ -215,7 +215,7 @@ Object {
215215
`;
216216

217217
exports[`backportJestConfig with "globals.ts-jest.useBabelrc" set to false should wran the user 1`] = `
218-
"ts-jest: \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead.
218+
"warn ts-jest: \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead.
219219
↳ See \`babel-jest\` related issue: https://github.com/facebook/jest/issues/3845"
220220
`;
221221

@@ -240,6 +240,6 @@ Object {
240240
`;
241241

242242
exports[`backportJestConfig with "globals.ts-jest.useBabelrc" set to true should wran the user 1`] = `
243-
"ts-jest: \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead.
243+
"warn ts-jest: \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead.
244244
↳ See \`babel-jest\` related issue: https://github.com/facebook/jest/issues/3845"
245245
`;

src/lib/backports.spec.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { backportJestConfig } from './backports'
2-
import { spyThese } from '../__helpers__/mocks'
32
import set from 'lodash.set'
43
import { inspect } from 'util'
4+
import { __setup } from './debug'
55

6-
const consoleSpies = spyThese(console, {
7-
warn: () => undefined,
8-
})
9-
afterEach(() => {
10-
consoleSpies.mockReset()
6+
const logger = jest.fn()
7+
__setup({ logger })
8+
beforeEach(() => {
9+
logger.mockClear()
1110
})
1211

1312
describe('backportJestConfig', () => {
@@ -21,8 +20,8 @@ describe('backportJestConfig', () => {
2120
describe(`with "${oldPath}" set to ${inspect(val)}`, () => {
2221
it(`should wran the user`, () => {
2322
backportJestConfig(original)
24-
expect(consoleSpies.warn).toHaveBeenCalledTimes(1)
25-
expect(consoleSpies.warn.mock.calls[0].join(' ')).toMatchSnapshot()
23+
expect(logger).toHaveBeenCalledTimes(1)
24+
expect(logger.mock.calls[0].join(' ')).toMatchSnapshot()
2625
}) // should warn the user
2726
it(`should have changed the config correctly`, () => {
2827
expect(original).toMatchSnapshot('before')

src/lib/debug.spec.ts

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,77 @@
1-
import { spyThese } from '../__helpers__/mocks'
2-
import { debug, wrapWithDebug, __setup } from './debug'
1+
import { debug, wrapWithDebug, __setup, warn } from './debug'
32

4-
const consoleSpies = spyThese(console, {
5-
log: () => void 0,
6-
warn: () => void 0,
7-
})
3+
const stdoutSpy = jest.spyOn(process.stdout, 'write')
4+
const stderrSpy = jest.spyOn(process.stderr, 'write')
85

96
beforeEach(() => {
107
delete process.env.TS_JEST_DEBUG
11-
consoleSpies.mockClear()
8+
stderrSpy.mockClear()
9+
stdoutSpy.mockClear()
10+
})
11+
afterAll(() => {
12+
stderrSpy.mockRestore()
13+
stdoutSpy.mockRestore()
1214
})
1315

1416
describe('debug', () => {
15-
it('should log when TS_JEST_DEBUG is truthy', () => {
17+
it('should log to stdout when TS_JEST_DEBUG is truthy', () => {
1618
process.env.TS_JEST_DEBUG = '1'
1719
__setup()
1820
debug('foo')
19-
expect(consoleSpies.log).toHaveBeenCalledTimes(1)
20-
expect(consoleSpies.log).toHaveBeenCalledWith('ts-jest:', 'foo')
21+
expect(stdoutSpy).toHaveBeenCalledTimes(1)
22+
expect(stdoutSpy).toHaveBeenCalledWith('ts-jest: foo\n')
2123
})
22-
it('should NOT log when TS_JEST_DEBUG is falsy', () => {
24+
it('should NOT log to stdout when TS_JEST_DEBUG is falsy', () => {
2325
process.env.TS_JEST_DEBUG = ''
2426
__setup()
2527
debug('foo')
26-
expect(consoleSpies.log).not.toHaveBeenCalled()
28+
expect(stdoutSpy).not.toHaveBeenCalled()
2729
})
28-
it('should NOT log when TS_JEST_DEBUG is not set', () => {
30+
it('should NOT log to stdout when TS_JEST_DEBUG is not set', () => {
2931
delete process.env.TS_JEST_DEBUG
3032
__setup()
3133
debug('foo')
32-
expect(consoleSpies.log).not.toHaveBeenCalled()
34+
expect(stdoutSpy).not.toHaveBeenCalled()
35+
})
36+
})
37+
describe('warn', () => {
38+
it('should log to stderr when TS_JEST_DEBUG is truthy', () => {
39+
process.env.TS_JEST_DEBUG = '1'
40+
__setup()
41+
warn('foo')
42+
expect(stderrSpy).toHaveBeenCalledTimes(1)
43+
expect(stderrSpy).toHaveBeenCalledWith('ts-jest: foo\n')
44+
})
45+
it('should log to stderr even when TS_JEST_DEBUG is falsy', () => {
46+
delete process.env.TS_JEST_DEBUG
47+
__setup()
48+
warn('foo')
49+
expect(stderrSpy).toHaveBeenCalledTimes(1)
50+
expect(stderrSpy).toHaveBeenCalledWith('ts-jest: foo\n')
3351
})
3452
})
3553

3654
describe('wrapWithDebug', () => {
3755
const subject = (val: string) => `hello ${val}`
3856
const wrapAndCall = (val: string) => wrapWithDebug('foo', subject)(val)
3957

40-
it('should log when TS_JEST_DEBUG is truthy', () => {
58+
it('should log to stdout when TS_JEST_DEBUG is truthy', () => {
4159
process.env.TS_JEST_DEBUG = '1'
4260
__setup()
4361
expect(wrapAndCall('bar')).toBe('hello bar')
44-
expect(consoleSpies.log).toHaveBeenCalledTimes(1)
45-
expect(consoleSpies.log).toHaveBeenCalledWith('ts-jest:', 'foo')
62+
expect(stdoutSpy).toHaveBeenCalledTimes(1)
63+
expect(stdoutSpy).toHaveBeenCalledWith('ts-jest: foo\n')
4664
})
47-
it('should NOT log when TS_JEST_DEBUG is falsy', () => {
65+
it('should NOT log to stdout when TS_JEST_DEBUG is falsy', () => {
4866
process.env.TS_JEST_DEBUG = ''
4967
__setup()
5068
expect(wrapAndCall('bar')).toBe('hello bar')
51-
expect(consoleSpies.log).not.toHaveBeenCalled()
69+
expect(stdoutSpy).not.toHaveBeenCalled()
5270
})
53-
it('should NOT log when TS_JEST_DEBUG is not set', () => {
71+
it('should NOT log to stdout when TS_JEST_DEBUG is not set', () => {
5472
delete process.env.TS_JEST_DEBUG
5573
__setup()
5674
expect(wrapAndCall('bar')).toBe('hello bar')
57-
expect(consoleSpies.log).not.toHaveBeenCalled()
75+
expect(stdoutSpy).not.toHaveBeenCalled()
5876
})
5977
})

src/lib/debug.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { format } from 'util'
2+
13
export let DEBUG_MODE!: boolean
24

35
export let debug!: typeof console.log
@@ -8,13 +10,22 @@ export let wrapWithDebug!: <T extends (...args: any[]) => any>(
810
func: T,
911
) => T
1012

11-
type LogKind = 'log' | 'warn' | 'debug' | 'info'
13+
type LogKind = 'log' | 'warn'
1214
type Logger = (kind: LogKind, ...args: any[]) => void
1315

1416
export let LOG_PREFIX = 'ts-jest:'
1517

16-
export const defaultLogger: Logger = (kind: LogKind, ...args: any[]) => {
17-
console[kind](...args)
18+
export const defaultLogger: Logger = (
19+
kind: LogKind,
20+
msg: string = '',
21+
...args: any[]
22+
) => {
23+
// we use stderr/stdout dirrectly so that the log won't be swallowed by jest
24+
if (kind === 'warn') {
25+
process.stderr.write(format(msg, ...args) + '\n')
26+
} else if (kind) {
27+
process.stdout.write(format(msg, ...args) + '\n')
28+
}
1829
}
1930

2031
interface SetupOptions {

0 commit comments

Comments
 (0)