Skip to content

Commit

Permalink
fix(cache): adds project's dep versions to cache key
Browse files Browse the repository at this point in the history
Includes the real version of each dependency of the containing project
in the cache key digest calculation.

Closes #785
  • Loading branch information
huafu committed Oct 6, 2018
1 parent 7b2dd01 commit 6cacbea
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 5 deletions.
49 changes: 46 additions & 3 deletions src/config/config-set.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,23 +489,63 @@ describe('babelJestTransformer', () => {
})
}) // babelJestTransformer

describe('projectDependencies', () => {
const pkg = {
optionalDependencies: { opt: '1.2.3' },
peerDependencies: { peer: '1.2.4' },
devDependencies: { dev: '1.2.5' },
dependencies: { std: '1.2.6' },
}
const realVersions: any = {
peer: '0.1.0',
dev: '4.3.2',
std: '9.10.2',
}
it('should list all deps with their real version', () => {
jest.doMock('peer/package.json', () => ({ version: realVersions.peer }), { virtual: true })
jest.doMock('dev/package.json', () => ({ version: realVersions.dev }), { virtual: true })
jest.doMock('std/package.json', () => ({ version: realVersions.std }), { virtual: true })
const cs = createConfigSet({
tsJestConfig: { tsConfig: false } as any,
projectPackageJson: pkg,
})
expect(cs.projectDependencies).toEqual(realVersions)
jest.dontMock('peer/package.json')
jest.dontMock('dev/package.json')
jest.dontMock('std/package.json')
})
}) // projectDependencies

describe('cacheKey', () => {
it('should be a string', () => {
const cs = createConfigSet({ tsJestConfig: { tsConfig: false } as any })
const cs = createConfigSet({
tsJestConfig: { tsConfig: false } as any,
projectDependencies: {
opt: '1.2.3',
peer: '1.2.4',
dev: '1.2.5',
std: '1.2.6',
},
})
// we tested those and don't want the snapshot to change all the time we upgrade
const val = cs.jsonValue.value
delete val.versions
cs.jsonValue.value = val
// digest is mocked in src/__mocks__/index.ts
expect(cs.cacheKey).toMatchInlineSnapshot(
`"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"transformers\\":[]},\\"tsconfig\\":{\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"outDir\\":\\"$$ts-jest$$\\",\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1}}"`,
'"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"transformers\\":[]},\\"tsconfig\\":{\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"outDir\\":\\"$$ts-jest$$\\",\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1}}"',
)
})
}) // cacheKey

describe('jsonValue', () => {
it('should create jsonValue based on each config and version', () => {
const cs = createConfigSet({ tsJestConfig: { tsConfig: false } as any })
const cs = createConfigSet({
tsJestConfig: { tsConfig: false } as any,
projectDependencies: {
'some-module': '1.2.3',
},
})
const val = cs.jsonValue.valueOf()
expect(cs.toJSON()).toEqual(val)
// it will change each time we upgrade – we tested those in the `version` block
Expand All @@ -521,6 +561,9 @@ Object {
"__backported": true,
"globals": Object {},
},
"projectDepVersions": Object {
"some-module": "1.2.3",
},
"transformers": Array [
"hoisting-jest-mock@1",
],
Expand Down
42 changes: 40 additions & 2 deletions src/config/config-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* with the complete, object version of it.
*/
import { LogContexts, Logger } from 'bs-logger'
import { existsSync, readFileSync } from 'fs'
import { existsSync, readFileSync, realpathSync } from 'fs'
import json5 from 'json5'
import { dirname, isAbsolute, join, normalize, resolve } from 'path'
import semver from 'semver'
Expand Down Expand Up @@ -112,6 +112,41 @@ const toDiagnosticCodeList = (items: any, into: number[] = []): number[] => {
}

export class ConfigSet {
@Memoize()
get projectPackageJson(): Record<string, any> {
const tsJestRoot = resolve(__dirname, '..', '..')
let pkgPath = resolve(tsJestRoot, '..', '..', 'package.json')
let exists = existsSync(pkgPath)
if (!exists) {
if (realpathSync(this.rootDir) === realpathSync(tsJestRoot)) {
pkgPath = resolve(tsJestRoot, 'package.json')
exists = true
} else {
this.logger.warn(Errors.UnableToFindProjectRoot)
}
}
return exists ? require(pkgPath) : {}
}

@Memoize()
get projectDependencies(): Record<string, string> {
const { projectPackageJson: pkg } = this
const names = Object.keys({
...pkg.optionalDependencies,
...pkg.peerDependencies,
...pkg.devDependencies,
...pkg.dependencies,
})
return names.reduce(
(map, name) => {
const version = getPackageVersion(name)
if (version) map[name] = version
return map
},
{} as Record<string, string>,
)
}

@Memoize()
get jest(): jest.ProjectConfig {
const config = backportJestConfig(this.logger, this._jestConfig)
Expand Down Expand Up @@ -440,14 +475,16 @@ export class ConfigSet {
const cacheSuffix = sha1(
stringify({
version: this.compilerModule.version,
digest: this.tsJestDigest,
dependencies: this.projectDependencies,
compiler: this.tsJest.compiler,
compilerOptions: this.typescript.options,
isolatedModules: this.tsJest.isolatedModules,
diagnostics: this.tsJest.diagnostics,
}),
)
const res = join(this.jest.cacheDirectory, 'ts-jest', cacheSuffix.substr(0, 2), cacheSuffix.substr(2))
logger.debug({ cacheDirectory: res }, `will use file caching`)
logger.debug({ cacheDirectory: res }, 'will use file caching')
return res
}

Expand Down Expand Up @@ -519,6 +556,7 @@ export class ConfigSet {

return new JsonableValue({
versions: this.versions,
projectDepVersions: this.projectDependencies,
digest: this.tsJestDigest,
transformers: this.astTransformers.map(t => `${t.name}@${t.version}`),
jest,
Expand Down
1 change: 1 addition & 0 deletions src/util/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export enum Errors {
GotUnknownFileTypeWithoutBabel = 'Got a unknown file type to compile (file: {{path}}). To fix this, in your Jest config change the `transform` key which value is `ts-jest` so that it does not match this kind of files anymore.',
GotUnknownFileTypeWithBabel = 'Got a unknown file type to compile (file: {{path}}). To fix this, in your Jest config change the `transform` key which value is `ts-jest` so that it does not match this kind of files anymore. If you still want Babel to process it, add another entry to the `transform` option with value `babel-jest` which key matches this type of files.',
ConfigNoModuleInterop = 'If you have issues related to imports, you should consider setting `esModuleInterop` to `true` in your TypeScript configuration file (usually `tsconfig.json`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information.',
UnableToFindProjectRoot = 'Unable to find the root of the project where ts-jest has been installed.',
}

/**
Expand Down

0 comments on commit 6cacbea

Please sign in to comment.