Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow extending processAsync and getCacheKeyAsync #3047

Merged
merged 1 commit into from Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions e2e/__tests__/enum.test.ts
Expand Up @@ -3,13 +3,13 @@ import { extractSortedSummary } from '../utils'

const DIR = 'enum'

test('partial successfully runs the tests inside `enum/` with `isolatedModules: true`', () => {
test('partial successfully runs the tests inside `enum/` with `isolatedModules: false`', () => {
const result = runJest(DIR)

expect(extractSortedSummary(result.stderr).rest).toMatchSnapshot()
})

test('partial successfully runs the tests inside `enum/` with `isolatedModules: false`', () => {
test('partial successfully runs the tests inside `enum/` with `isolatedModules: true`', () => {
const result = runJest(DIR, ['-c=jest-isolated.config.js'])

expect(extractSortedSummary(result.stderr).rest).toMatchSnapshot()
Expand Down
15 changes: 15 additions & 0 deletions e2e/__tests__/extend-ts-jest.test.ts
@@ -0,0 +1,15 @@
import { json as runWithJson, onNodeVersions } from '../run-jest'

const DIR = 'extend-ts-jest'

// Only need to test in ESM because ESM makes `this` context become `undefined`
onNodeVersions('>=12.16.0', () => {
test(`successfully runs the tests inside ${DIR}`, () => {
const { json } = runWithJson(DIR, undefined, {
nodeOptions: '--experimental-vm-modules --no-warnings',
})

expect(json.success).toBe(true)
expect(json.numTotalTestSuites).toBe(1)
})
})
3 changes: 3 additions & 0 deletions e2e/extend-ts-jest/__tests__/foo.spec.ts
@@ -0,0 +1,3 @@
test('should pass', () => {
expect(true).toBe(true)
})
10 changes: 10 additions & 0 deletions e2e/extend-ts-jest/foo-transformer.js
@@ -0,0 +1,10 @@
const tsJestTransformer = require('../../dist/ts-jest-transformer')

class FooTransformer extends tsJestTransformer.TsJestTransformer {
async processAsync(sourceText, sourcePath, transformOptions) {
return new Promise((resolve) => resolve(this.process(sourceText, sourcePath, transformOptions)))
}
}
module.exports = {
createTransformer: () => new FooTransformer(),
}
12 changes: 12 additions & 0 deletions e2e/extend-ts-jest/package.json
@@ -0,0 +1,12 @@
{
"jest": {
"globals": {
"ts-jest": {
"isolatedModules": true
}
},
"transform": {
"^.+\\.tsx?$": "./foo-transformer.js"
}
}
}
110 changes: 24 additions & 86 deletions src/ts-jest-transformer.spec.ts
@@ -1,23 +1,28 @@
import fs from 'fs'
import { join } from 'path'
import path from 'path'

import { Logger, LogLevels } from 'bs-logger'
import { LogLevels } from 'bs-logger'
import { removeSync, writeFileSync } from 'fs-extra'

import { createConfigSet } from './__helpers__/fakers'
import { logTargetMock } from './__helpers__/mocks'
import { SOURCE_MAPPING_PREFIX } from './compiler/compiler-utils'
import { TsCompiler } from './compiler/ts-compiler'
import { TsJestCompiler } from './compiler/ts-jest-compiler'
import { ConfigSet } from './config/config-set'
import { CACHE_KEY_EL_SEPARATOR, TsJestTransformer } from './ts-jest-transformer'
import type { DepGraphInfo, ProjectConfigTsJest, StringMap } from './types'
import type { DepGraphInfo } from './types'
import { stringify } from './utils/json'
import { sha1 } from './utils/sha1'
import { VersionCheckers } from './utils/version-checkers'

const logTarget = logTargetMock()
const cacheDir = join(process.cwd(), 'tmp')
const cacheDir = path.join(process.cwd(), 'tmp')
const baseTransformOptions = {
config: {
testMatch: [],
testRegex: [],
extensionsToTreatAsEsm: [],
},
cacheFS: new Map(),
} as any // eslint-disable-line @typescript-eslint/no-explicit-any

beforeEach(() => {
logTarget.clear()
Expand All @@ -36,16 +41,16 @@ describe('TsJestTransformer', () => {

// @ts-expect-error testing purpose
expect(Object.keys(TsJestTransformer._cachedConfigSets[0])).toMatchInlineSnapshot(`
Array [
"jestConfig",
"configSet",
"transformerCfgStr",
"compiler",
"depGraphs",
"tsResolvedModulesCachePath",
"watchMode",
]
`)
Array [
"jestConfig",
"configSet",
"transformerCfgStr",
"compiler",
"depGraphs",
"tsResolvedModulesCachePath",
"watchMode",
]
`)
})

test(
Expand Down Expand Up @@ -124,7 +129,7 @@ Array [
fileContent: 'const foo = 1',
resolvedModuleNames: [],
})
const resolvedModulesCacheDir = join(tsCacheDir, sha1('ts-jest-resolved-modules', CACHE_KEY_EL_SEPARATOR))
const resolvedModulesCacheDir = path.join(tsCacheDir, sha1('ts-jest-resolved-modules', CACHE_KEY_EL_SEPARATOR))
fs.mkdirSync(tsCacheDir, { recursive: true })
writeFileSync(resolvedModulesCacheDir, stringify([...depGraphs]))

Expand Down Expand Up @@ -262,7 +267,7 @@ Array [
test('should be different with non existed imported modules', () => {
jest
.spyOn(TsJestCompiler.prototype, 'getResolvedModules')
.mockReturnValueOnce([join(process.cwd(), 'src', '__mocks__', 'thing.ts')])
.mockReturnValueOnce([path.join(process.cwd(), 'src', '__mocks__', 'thing.ts')])

const cacheKey1 = tr.getCacheKey(input.fileContent, input.fileName, transformOptionsWithCache)

Expand All @@ -280,14 +285,6 @@ Array [
})

describe('process', () => {
const baseTransformOptions = {
config: {
testMatch: [],
testRegex: [],
extensionsToTreatAsEsm: [],
},
cacheFS: new Map(),
} as any // eslint-disable-line @typescript-eslint/no-explicit-any
let tr!: TsJestTransformer

beforeEach(() => {
Expand Down Expand Up @@ -435,63 +432,4 @@ Array [
}
})
})

describe('subclass extends TsJestTransformer', () => {
class MyTsCompiler extends TsCompiler {
constructor(readonly configSet: ConfigSet, readonly runtimeCacheFS: StringMap) {
super(configSet, runtimeCacheFS)
}
}

class MyConfigSet extends ConfigSet {
constructor(readonly jestConfig: ProjectConfigTsJest, readonly parentLogger?: Logger) {
super(jestConfig, parentLogger)
}
}

class MyTransformer extends TsJestTransformer {
protected _createCompiler(configSet: ConfigSet, cacheFS: StringMap): void {
this._compiler = new MyTsCompiler(configSet, cacheFS)
}

// eslint-disable-next-line class-methods-use-this
protected _createConfigSet(config: ProjectConfigTsJest): MyConfigSet {
return new MyConfigSet(config)
}
}
let tr: MyTransformer

beforeEach(() => {
tr = new MyTransformer()
})

test('should have jest version checking', () => {
VersionCheckers.jest.warn = jest.fn()

new MyTransformer()

expect(VersionCheckers.jest.warn).toHaveBeenCalled()
})

test('should create MyTsCompiler instance', () => {
// @ts-expect-error testing purpose
tr._createCompiler(createConfigSet(), new Map())

// @ts-expect-error testing purpose
expect(tr._compiler).toBeInstanceOf(MyTsCompiler)
})

test('should create MyConfigSet instance', () => {
expect(
// @ts-expect-error testing purpose
tr._createConfigSet({
cwd: process.cwd(),
extensionsToTreatAsEsm: [],
globals: Object.create(null),
testMatch: [],
testRegex: [],
}),
).toBeInstanceOf(MyConfigSet)
})
})
})
18 changes: 18 additions & 0 deletions src/ts-jest-transformer.ts
Expand Up @@ -53,7 +53,9 @@ export class TsJestTransformer implements SyncTransformer {
* when running Jest in ESM mode
*/
this.getCacheKey = this.getCacheKey.bind(this)
this.getCacheKeyAsync = this.getCacheKeyAsync.bind(this)
this.process = this.process.bind(this)
this.processAsync = this.processAsync.bind(this)

this._logger.debug('created new transformer')
process.env.TS_JEST = '1'
Expand Down Expand Up @@ -183,6 +185,14 @@ export class TsJestTransformer implements SyncTransformer {
return result
}

async processAsync(
sourceText: string,
sourcePath: Config.Path,
transformOptions: TransformOptionsTsJest,
): Promise<TransformedSource | string> {
return new Promise((resolve) => resolve(this.process(sourceText, sourcePath, transformOptions)))
}

/**
* Jest uses this to cache the compiled version of a file
*
Expand Down Expand Up @@ -248,6 +258,14 @@ export class TsJestTransformer implements SyncTransformer {
return sha1(...constructingCacheKeyElements)
}

async getCacheKeyAsync(
sourceText: string,
sourcePath: string,
transformOptions: TransformOptionsTsJest,
): Promise<string> {
return new Promise((resolve) => resolve(this.getCacheKey(sourceText, sourcePath, transformOptions)))
}

/**
* Subclasses extends `TsJestTransformer` can call this method to get resolved module disk cache
*/
Expand Down