Skip to content

Commit dee8231

Browse files
authored
fix: revert usage of @jest/create-cache-key-function (#2108)
Closes #2080 Closes #2090 Closes #2104
1 parent a42de7a commit dee8231

File tree

5 files changed

+102
-96
lines changed

5 files changed

+102
-96
lines changed

e2e/__tests__/__snapshots__/coverage.test.ts.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`using template "default" should report coverages 1`] = `
3+
exports[`Code coverage should pass using template "default" 1`] = `
44
√ jest
55
↳ exit code: 0
66
===[ STDOUT ]===================================================================
@@ -23,7 +23,7 @@ exports[`using template "default" should report coverages 1`] = `
2323
================================================================================
2424
`;
2525

26-
exports[`using template "with-babel-7" should report coverages 1`] = `
26+
exports[`Code coverage should pass using template "with-babel-7" 1`] = `
2727
√ jest
2828
↳ exit code: 0
2929
===[ STDOUT ]===================================================================
@@ -46,7 +46,7 @@ exports[`using template "with-babel-7" should report coverages 1`] = `
4646
================================================================================
4747
`;
4848

49-
exports[`using template "with-babel-7-string-config" should report coverages 1`] = `
49+
exports[`Code coverage should pass using template "with-babel-7-string-config" 1`] = `
5050
√ jest
5151
↳ exit code: 0
5252
===[ STDOUT ]===================================================================

e2e/__tests__/coverage.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { allValidPackageSets } from '../__helpers__/templates'
22
import { configureTestCase } from '../__helpers__/test-case'
33

4-
const testCase = configureTestCase('simple', {
5-
jestConfig: { collectCoverage: true },
6-
})
4+
describe('Code coverage', () => {
5+
const testCase = configureTestCase('simple', {
6+
jestConfig: { collectCoverage: true },
7+
})
78

8-
testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { templateName }) => {
9-
describe(`using template "${templateName}"`, () => {
10-
const result = runTest()
9+
testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
10+
it(testLabel, () => {
11+
const result = runTest()
1112

12-
it(`should report coverages`, () => {
1313
expect(result.status).toBe(0)
1414
expect(result).toMatchSnapshot()
1515
})

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
},
5656
"homepage": "https://kulshekhar.github.io/ts-jest",
5757
"dependencies": {
58-
"@jest/create-cache-key-function": "^26.5.0",
5958
"@types/jest": "26.x",
6059
"bs-logger": "0.x",
6160
"buffer-from": "1.x",

src/ts-jest-transformer.spec.ts

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { LogLevels } from 'bs-logger'
2+
import { sep } from 'path'
23

34
import { TsJestTransformer } from './ts-jest-transformer'
45
import { ConfigSet } from './config/config-set'
@@ -12,39 +13,24 @@ beforeEach(() => {
1213
})
1314

1415
describe('TsJestTransformer', () => {
15-
describe('createOrResolveTransformerCfg', () => {
16-
it('should return the same config-set for same values with jest config string is not in cachedConfigSets', () => {
17-
const obj1 = { cwd: '/foo/.' } as any
18-
const tjT = new TsJestTransformer()
19-
20-
logTarget.clear()
21-
22-
tjT.getCacheKey('foo', 'foo', JSON.stringify(obj1), {
23-
config: obj1,
24-
} as any)
16+
describe('configFor', () => {
17+
it('should return the same config-set for same values with jest config string is not in configSetsIndex', () => {
18+
const obj1 = { cwd: '/foo/.', rootDir: '/bar//dummy/..', globals: {} }
19+
const cs3 = new TsJestTransformer().configsFor(obj1 as any)
2520

26-
expect(logTarget.lines[0]).toMatchInlineSnapshot(`
27-
"[level:30] no matching config-set found, creating a new one
28-
"
29-
`)
21+
expect(cs3.cwd).toBe(`${sep}foo`)
22+
expect(cs3.rootDir).toBe(`${sep}bar`)
3023
})
3124

32-
it('should return the same config-set for same values with jest config string in cachedConfigSets', () => {
25+
it('should return the same config-set for same values with jest config string in configSetsIndex', () => {
3326
const obj1 = { cwd: '/foo/.', rootDir: '/bar//dummy/..', globals: {} }
3427
const obj2 = { ...obj1 }
35-
const tjT1 = new TsJestTransformer()
36-
const tjT2 = new TsJestTransformer()
37-
38-
logTarget.clear()
28+
const cs1 = new TsJestTransformer().configsFor(obj1 as any)
29+
const cs2 = new TsJestTransformer().configsFor(obj2 as any)
3930

40-
tjT1.getCacheKey('foo', 'foo', JSON.stringify(obj1), {
41-
config: obj1,
42-
} as any)
43-
tjT2.getCacheKey('foo', 'foo', JSON.stringify(obj2), {
44-
config: obj2,
45-
} as any)
46-
47-
expect(logTarget.filteredLines(LogLevels.info)).toHaveLength(1)
31+
expect(cs1.cwd).toBe(`${sep}foo`)
32+
expect(cs1.rootDir).toBe(`${sep}bar`)
33+
expect(cs2).toBe(cs1)
4834
})
4935
})
5036

@@ -63,10 +49,13 @@ describe('TsJestTransformer', () => {
6349
tr.getCacheKey(input.fileContent, input.fileName, '{}', { ...input.options, instrument: true }),
6450
tr.getCacheKey(input.fileContent, input.fileName, '{}', { ...input.options, rootDir: '/bar' }),
6551
]
52+
6653
// each key should have correct length
6754
for (const key of keys) {
68-
expect(key).toHaveLength(32)
55+
expect(key).toHaveLength(40)
6956
}
57+
// unique array should have same length
58+
expect(keys.filter((k, i, all) => all.indexOf(k) === i)).toHaveLength(keys.length)
7059
})
7160
})
7261

src/ts-jest-transformer.ts

Lines changed: 75 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import createCacheKey from '@jest/create-cache-key-function'
21
import type { CacheKeyOptions, TransformedSource, Transformer, TransformOptions } from '@jest/transform'
32
import type { Config } from '@jest/types'
43
import type { Logger } from 'bs-logger'
@@ -9,6 +8,7 @@ import { stringify } from './utils/json'
98
import { JsonableValue } from './utils/jsonable-value'
109
import { rootLogger } from './utils/logger'
1110
import { Errors, interpolate } from './utils/messages'
11+
import { sha1 } from './utils/sha1'
1212

1313
interface CachedConfigSet {
1414
configSet: ConfigSet
@@ -25,14 +25,65 @@ export class TsJestTransformer implements Transformer {
2525
private static readonly _cachedConfigSets: CachedConfigSet[] = []
2626
protected readonly logger: Logger
2727
protected _transformCfgStr!: string
28-
protected _configSet!: ConfigSet
2928

3029
constructor() {
3130
this.logger = rootLogger.child({ namespace: 'ts-jest-transformer' })
3231

3332
this.logger.debug('created new transformer')
3433
}
3534

35+
/**
36+
* @public
37+
*/
38+
configsFor(jestConfig: Config.ProjectConfig): ConfigSet {
39+
const ccs: CachedConfigSet | undefined = TsJestTransformer._cachedConfigSets.find(
40+
(cs) => cs.jestConfig.value === jestConfig,
41+
)
42+
let configSet: ConfigSet
43+
if (ccs) {
44+
this._transformCfgStr = ccs.transformerCfgStr
45+
configSet = ccs.configSet
46+
} else {
47+
// try to look-it up by stringified version
48+
const serializedJestCfg = stringify(jestConfig)
49+
const serializedCcs = TsJestTransformer._cachedConfigSets.find(
50+
(cs) => cs.jestConfig.serialized === serializedJestCfg,
51+
)
52+
if (serializedCcs) {
53+
// update the object so that we can find it later
54+
// this happens because jest first calls getCacheKey with stringified version of
55+
// the config, and then it calls the transformer with the proper object
56+
serializedCcs.jestConfig.value = jestConfig
57+
this._transformCfgStr = serializedCcs.transformerCfgStr
58+
configSet = serializedCcs.configSet
59+
} else {
60+
// create the new record in the index
61+
this.logger.info('no matching config-set found, creating a new one')
62+
63+
configSet = new ConfigSet(jestConfig)
64+
this._transformCfgStr = new JsonableValue({
65+
digest: configSet.tsJestDigest,
66+
babel: configSet.babelConfig,
67+
...jestConfig,
68+
tsconfig: {
69+
options: configSet.parsedTsConfig.options,
70+
raw: configSet.parsedTsConfig.raw,
71+
},
72+
}).serialized
73+
TsJestTransformer._cachedConfigSets.push({
74+
jestConfig: new JsonableValue(jestConfig),
75+
configSet,
76+
transformerCfgStr: this._transformCfgStr,
77+
})
78+
}
79+
}
80+
81+
return configSet
82+
}
83+
84+
/**
85+
* @public
86+
*/
3687
process(
3788
input: string,
3889
filePath: Config.Path,
@@ -43,9 +94,10 @@ export class TsJestTransformer implements Transformer {
4394

4495
let result: string | TransformedSource
4596
const source: string = input
46-
const { hooks } = this._configSet
47-
const shouldStringifyContent = this._configSet.shouldStringifyContent(filePath)
48-
const babelJest = shouldStringifyContent ? undefined : this._configSet.babelJestTransformer
97+
const configs = this.configsFor(jestConfig)
98+
const { hooks } = configs
99+
const shouldStringifyContent = configs.shouldStringifyContent(filePath)
100+
const babelJest = shouldStringifyContent ? undefined : configs.babelJestTransformer
49101
const isDefinitionFile = filePath.endsWith(DECLARATION_TYPE_EXT)
50102
const isJsFile = JS_JSX_REGEX.test(filePath)
51103
const isTsFile = !isDefinitionFile && TS_TSX_REGEX.test(filePath)
@@ -55,15 +107,15 @@ export class TsJestTransformer implements Transformer {
55107
} else if (isDefinitionFile) {
56108
// do not try to compile declaration files
57109
result = ''
58-
} else if (!this._configSet.parsedTsConfig.options.allowJs && isJsFile) {
110+
} else if (!configs.parsedTsConfig.options.allowJs && isJsFile) {
59111
// we've got a '.js' but the compiler option `allowJs` is not set or set to false
60112
this.logger.warn({ fileName: filePath }, interpolate(Errors.GotJsFileButAllowJsFalse, { path: filePath }))
61113

62114
result = source
63115
} else if (isJsFile || isTsFile) {
64116
// transpile TS code (source maps are included)
65117
/* istanbul ignore if */
66-
result = this._configSet.tsCompiler.compile(source, filePath)
118+
result = configs.tsCompiler.compile(source, filePath)
67119
} else {
68120
// we should not get called for files with other extension than js[x], ts[x] and d.ts,
69121
// TypeScript will bail if we try to compile, and if it was to call babel, users can
@@ -99,66 +151,32 @@ export class TsJestTransformer implements Transformer {
99151
* Jest uses this to cache the compiled version of a file
100152
*
101153
* @see https://github.com/facebook/jest/blob/v23.5.0/packages/jest-runtime/src/script_transformer.js#L61-L90
154+
*
155+
* @public
102156
*/
103157
getCacheKey(
104158
fileContent: string,
105159
filePath: string,
106160
_jestConfigStr: string,
107161
transformOptions: CacheKeyOptions,
108162
): string {
109-
this.createOrResolveTransformerCfg(transformOptions.config)
163+
const configs = this.configsFor(transformOptions.config)
110164

111165
this.logger.debug({ fileName: filePath, transformOptions }, 'computing cache key for', filePath)
112166

113-
return createCacheKey()(fileContent, filePath, this._transformCfgStr, {
114-
config: transformOptions.config,
115-
instrument: false,
116-
})
117-
}
118-
119-
/**
120-
* Users can override this method and provide their own config class
121-
*/
122-
protected createOrResolveTransformerCfg(jestConfig: Config.ProjectConfig): void {
123-
const ccs: CachedConfigSet | undefined = TsJestTransformer._cachedConfigSets.find(
124-
(cs) => cs.jestConfig.value === jestConfig,
167+
// we do not instrument, ensure it is false all the time
168+
const { instrument = false, rootDir = configs.rootDir } = transformOptions
169+
170+
return sha1(
171+
this._transformCfgStr,
172+
'\x00',
173+
rootDir,
174+
'\x00',
175+
`instrument:${instrument ? 'on' : 'off'}`,
176+
'\x00',
177+
fileContent,
178+
'\x00',
179+
filePath,
125180
)
126-
if (ccs) {
127-
this._transformCfgStr = ccs.transformerCfgStr
128-
this._configSet = ccs.configSet
129-
} else {
130-
// try to look-it up by stringified version
131-
const serializedJestCfg = stringify(jestConfig)
132-
const serializedCcs = TsJestTransformer._cachedConfigSets.find(
133-
(cs) => cs.jestConfig.serialized === serializedJestCfg,
134-
)
135-
if (serializedCcs) {
136-
// update the object so that we can find it later
137-
// this happens because jest first calls getCacheKey with stringified version of
138-
// the config, and then it calls the transformer with the proper object
139-
serializedCcs.jestConfig.value = jestConfig
140-
this._transformCfgStr = serializedCcs.transformerCfgStr
141-
this._configSet = serializedCcs.configSet
142-
} else {
143-
// create the new record in the index
144-
this.logger.info('no matching config-set found, creating a new one')
145-
146-
this._configSet = new ConfigSet(jestConfig)
147-
this._transformCfgStr = new JsonableValue({
148-
digest: this._configSet.tsJestDigest,
149-
babel: this._configSet.babelConfig,
150-
...jestConfig,
151-
tsconfig: {
152-
options: this._configSet.parsedTsConfig.options,
153-
raw: this._configSet.parsedTsConfig.raw,
154-
},
155-
}).serialized
156-
TsJestTransformer._cachedConfigSets.push({
157-
jestConfig: new JsonableValue(jestConfig),
158-
configSet: this._configSet,
159-
transformerCfgStr: this._transformCfgStr,
160-
})
161-
}
162-
}
163181
}
164182
}

0 commit comments

Comments
 (0)