From 33ff29f880340f17464b3cf26b4be818af813f9c Mon Sep 17 00:00:00 2001 From: Huafu Gandon Date: Wed, 3 Oct 2018 08:06:33 +0200 Subject: [PATCH] fix(helpers): deprecate import from ts-jest, now ts-jest/utils Importing from `ts-jest` everything will possibly make collision with future jest API. Also any star export or import might not be compatible with the target project. Now all helpers to be used in tests or config files have been moved to `ts-jest/utils`. Original ones have been kept in `ts-jest` for now, with a deprecation warning when using them. Closes #782 --- e2e/__cases__/test-helpers/deprecated.spec.ts | 9 +++++ e2e/__cases__/test-helpers/fail.spec.ts | 2 +- e2e/__cases__/test-helpers/pass.spec.ts | 2 +- e2e/__templates__/with-jest-22/jest.config.js | 4 +- .../__snapshots__/test-helpers.test.ts.snap | 29 -------------- e2e/__tests__/test-helpers.test.ts | 8 ++++ src/cli/config/migrate.ts | 2 +- src/config/create-jest-preset.ts | 11 +++++- src/index.spec.ts | 38 +++++++++++++++++++ src/index.ts | 21 +++++++--- src/types.ts | 38 ------------------- src/util/exported.spec.ts | 17 +++++++++ src/util/exported.ts | 3 ++ src/util/messages.ts | 1 + src/util/testing.ts | 26 ++++++++++++- utils/index.d.ts | 1 + utils/index.js | 1 + 17 files changed, 133 insertions(+), 80 deletions(-) create mode 100644 e2e/__cases__/test-helpers/deprecated.spec.ts delete mode 100644 e2e/__tests__/__snapshots__/test-helpers.test.ts.snap create mode 100644 src/util/exported.spec.ts create mode 100644 src/util/exported.ts create mode 100644 utils/index.d.ts create mode 100644 utils/index.js diff --git a/e2e/__cases__/test-helpers/deprecated.spec.ts b/e2e/__cases__/test-helpers/deprecated.spec.ts new file mode 100644 index 0000000000..14e482acf6 --- /dev/null +++ b/e2e/__cases__/test-helpers/deprecated.spec.ts @@ -0,0 +1,9 @@ +import { mocked } from 'ts-jest' +import { foo } from './to-mock' +jest.mock('./to-mock') + +test('foo', () => { + foo() + // it should log that the helper moved + expect(mocked(foo).mock.calls.length).toBe(1) +}) diff --git a/e2e/__cases__/test-helpers/fail.spec.ts b/e2e/__cases__/test-helpers/fail.spec.ts index f2f4d6372d..c8b48f1bd0 100644 --- a/e2e/__cases__/test-helpers/fail.spec.ts +++ b/e2e/__cases__/test-helpers/fail.spec.ts @@ -1,4 +1,4 @@ -import { mocked } from 'ts-jest' +import { mocked } from 'ts-jest/utils' import { foo, bar } from './to-mock' jest.mock('./to-mock') diff --git a/e2e/__cases__/test-helpers/pass.spec.ts b/e2e/__cases__/test-helpers/pass.spec.ts index a275fdb7ff..c0ee828af2 100644 --- a/e2e/__cases__/test-helpers/pass.spec.ts +++ b/e2e/__cases__/test-helpers/pass.spec.ts @@ -1,4 +1,4 @@ -import { mocked } from 'ts-jest' +import { mocked } from 'ts-jest/utils' import { foo, bar } from './to-mock' jest.mock('./to-mock') diff --git a/e2e/__templates__/with-jest-22/jest.config.js b/e2e/__templates__/with-jest-22/jest.config.js index dced9dcb57..9a6727f237 100644 --- a/e2e/__templates__/with-jest-22/jest.config.js +++ b/e2e/__templates__/with-jest-22/jest.config.js @@ -1,6 +1,6 @@ -const { jestPreset } = require('ts-jest') +const presets = require('ts-jest/presets') -module.exports = Object.assign({}, jestPreset, { +module.exports = Object.assign({}, presets.defaults, { testEnvironment: 'node', globals: { 'ts-jest': { tsConfig: {} } }, }) diff --git a/e2e/__tests__/__snapshots__/test-helpers.test.ts.snap b/e2e/__tests__/__snapshots__/test-helpers.test.ts.snap deleted file mode 100644 index a2a24c83b3..0000000000 --- a/e2e/__tests__/__snapshots__/test-helpers.test.ts.snap +++ /dev/null @@ -1,29 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`test-helpers 1`] = ` - × jest --no-cache - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - PASS ./pass.spec.ts - FAIL ./fail.spec.ts - ● Test suite failed to run - - TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): - fail.spec.ts:7:10 - error TS2554: Expected 0 arguments, but got 1. - - 7 expect(mocked(foo)('hello')).toBeUndefined() - ~~~~~~~~~~~~~~~~~~~~ - fail.spec.ts:9:46 - error TS2345: Argument of type '42' is not assignable to parameter of type 'string'. - - 9 expect(mocked(bar, true).dummy.deep.deeper(42)).toBeUndefined() - ~~ - - Test Suites: 1 failed, 1 passed, 2 total - Tests: 2 passed, 2 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; diff --git a/e2e/__tests__/test-helpers.test.ts b/e2e/__tests__/test-helpers.test.ts index df0bdaf8f8..3ecaa0763f 100644 --- a/e2e/__tests__/test-helpers.test.ts +++ b/e2e/__tests__/test-helpers.test.ts @@ -4,3 +4,11 @@ test('test-helpers', () => { const test = configureTestCase('test-helpers', { noCache: true }) expect(test.run(1)).toMatchSnapshot() }) + +test('with esModuleInterop set to false', () => { + const test = configureTestCase('test-helpers', { + noCache: true, + tsJestConfig: { tsConfig: { esModuleInterop: false, allowSyntheticDefaultImports: false } }, + }) + expect(test.run(1)).toMatchSnapshot() +}) diff --git a/src/cli/config/migrate.ts b/src/cli/config/migrate.ts index a4cae6b848..dfd4cd1d7a 100644 --- a/src/cli/config/migrate.ts +++ b/src/cli/config/migrate.ts @@ -6,7 +6,7 @@ import { basename, resolve } from 'path' import { Arguments } from 'yargs' import { CliCommand } from '..' -import { TsJestPresets } from '../../types' +import { TsJestPresets } from '../../config/create-jest-preset' import { backportJestConfig } from '../../util/backports' const DEFAULT_PRESET = 'ts-jest/presets/default' diff --git a/src/config/create-jest-preset.ts b/src/config/create-jest-preset.ts index 999c500c20..4b7d650c8f 100644 --- a/src/config/create-jest-preset.ts +++ b/src/config/create-jest-preset.ts @@ -1,6 +1,5 @@ import * as jestConfig from 'jest-config' -import { CreateJestPresetOptions, TsJestPresets } from '../types' import { rootLogger } from '../util/logger' const logger = rootLogger.child({ namespace: 'jest-preset' }) @@ -12,6 +11,16 @@ const defaults = jestConfig.defaults || { moduleFileExtensions: ['js', 'json', 'jsx', 'node'], } +export interface TsJestPresets { + transform: Record + testMatch: string[] + moduleFileExtensions: string[] +} + +export interface CreateJestPresetOptions { + allowJs?: boolean +} + export function createJestPreset( { allowJs = false }: CreateJestPresetOptions = {}, from?: jest.InitialOptions, diff --git a/src/index.spec.ts b/src/index.spec.ts index a489a7103a..a853a439ed 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -1,5 +1,8 @@ // tslint:disable:max-line-length +import { testing } from 'bs-logger' + import * as tsJest from '.' +import { logTargetMock } from './__helpers__/mocks' import { TsJestTransformer } from './ts-jest-transformer' jest.mock('./ts-jest-transformer', () => { @@ -58,6 +61,41 @@ Array [ }) }) +describe('moved helpers', () => { + let target: testing.LogTargetMock + beforeEach(() => { + target = logTargetMock() + target.clear() + }) + it('should warn when using mocked', () => { + tsJest.mocked(42) + expect(target.lines.warn).toMatchInlineSnapshot(` +Array [ + "[level:40] The \`mocked\` helper has been moved to \`ts-jest/utils\`. Use \`import { mocked } from 'ts-jest/utils'\` instead. +", +] +`) + }) + it('should warn when using createJestPreset', () => { + tsJest.createJestPreset() + expect(target.lines.warn).toMatchInlineSnapshot(` +Array [ + "[level:40] The \`createJestPreset\` helper has been moved to \`ts-jest/utils\`. Use \`import { createJestPreset } from 'ts-jest/utils'\` instead. +", +] +`) + }) + it('should warn when using pathsToModuleNameMapper', () => { + tsJest.pathsToModuleNameMapper({}) + expect(target.lines.warn).toMatchInlineSnapshot(` +Array [ + "[level:40] The \`pathsToModuleNameMapper\` helper has been moved to \`ts-jest/utils\`. Use \`import { pathsToModuleNameMapper } from 'ts-jest/utils'\` instead. +", +] +`) + }) +}) + describe('createTransformer', () => { it('should create different instances', () => { const tr1 = tsJest.createTransformer() diff --git a/src/index.ts b/src/index.ts index c658bd887f..3692dfad18 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,24 @@ +import { LogContexts, LogLevels } from 'bs-logger' import { readFileSync } from 'fs' import { resolve } from 'path' -import { createJestPreset } from './config/create-jest-preset' -import { pathsToModuleNameMapper } from './config/paths-to-module-name-mapper' +import { createJestPreset as createJestPresetCore } from './config/create-jest-preset' +import { pathsToModuleNameMapper as pathsToModuleNameMapperCore } from './config/paths-to-module-name-mapper' import { TsJestTransformer } from './ts-jest-transformer' import { TsJestGlobalOptions } from './types' +import { rootLogger } from './util/logger' +import { Deprecateds, interpolate } from './util/messages' +import { mocked as mockedCore } from './util/testing' import { VersionCheckers } from './util/version-checkers' -export * from './util/testing' +// deprecate helpers +const warn = rootLogger.child({ [LogContexts.logLevel]: LogLevels.warn }) +const helperMoved = any>(name: string, helper: T) => + warn.wrap(interpolate(Deprecateds.HelperMovedToUtils, { helper: name }), helper) + +export const mocked = helperMoved('mocked', mockedCore) +export const createJestPreset = helperMoved('createJestPreset', createJestPresetCore) +export const pathsToModuleNameMapper = helperMoved('pathsToModuleNameMapper', pathsToModuleNameMapperCore) // tslint:disable-next-line:no-var-requires export const version: string = require('../package.json').version @@ -41,7 +52,7 @@ export function getCacheKey(...args: any[]): any { // we let jest doing the instrumentation, it does it well export const canInstrument = false -const jestPreset = createJestPreset() +const jestPreset = createJestPresetCore() /** * @internal @@ -57,7 +68,5 @@ export const __resetModule = () => (transformer = undefined as any) export { // extra ================== - createJestPreset, jestPreset, - pathsToModuleNameMapper, } diff --git a/src/types.ts b/src/types.ts index 893f41785e..eeb389d24c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -69,12 +69,6 @@ export interface TsJestGlobalOptions { stringifyContentPathRegex?: string | RegExp } -export interface TsJestPresets { - transform: Record - testMatch: string[] - moduleFileExtensions: string[] -} - interface TsJestConfig$tsConfig$file { kind: 'file' value: string | undefined @@ -117,10 +111,6 @@ export interface TsJestHooksMap { afterProcess?(args: any[], result: string | jest.TransformedSource): string | jest.TransformedSource | void } -export interface CreateJestPresetOptions { - allowJs?: boolean -} - /** * @internal */ @@ -180,31 +170,3 @@ export interface AstTransformerDesc { version: number factory(cs: ConfigSet): TransformerFactory } - -// test helpers - -interface MockWithArgs extends Function, jest.MockInstance { - new (...args: ArgumentsOf): T - (...args: ArgumentsOf): any -} - -// tslint:disable-next-line:ban-types -type MethodKeysOf = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T] -// tslint:disable-next-line:ban-types -type PropertyKeysOf = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T] -type ArgumentsOf = T extends (...args: infer A) => any ? A : never -interface MockWithArgs extends Function, jest.MockInstance { - new (...args: ArgumentsOf): T - (...args: ArgumentsOf): any -} - -type MockedFunction = MockWithArgs & { [K in keyof T]: T[K] } -type MockedFunctionDeep = MockWithArgs & MockedObjectDeep -type MockedObject = { [K in MethodKeysOf]: MockedFunction } & { [K in PropertyKeysOf]: T[K] } -type MockedObjectDeep = { [K in MethodKeysOf]: MockedFunctionDeep } & - { [K in PropertyKeysOf]: MaybeMockedDeep } - -// tslint:disable-next-line:ban-types -export type MaybeMockedDeep = T extends Function ? MockedFunctionDeep : T extends object ? MockedObjectDeep : T -// tslint:disable-next-line:ban-types -export type MaybeMocked = T extends Function ? MockedFunction : T extends object ? MockedObject : T diff --git a/src/util/exported.spec.ts b/src/util/exported.spec.ts new file mode 100644 index 0000000000..200a13eed7 --- /dev/null +++ b/src/util/exported.spec.ts @@ -0,0 +1,17 @@ +import { createJestPreset } from '../config/create-jest-preset' +import { pathsToModuleNameMapper } from '../config/paths-to-module-name-mapper' + +import * as subject from './exported' +import { mocked } from './testing' + +describe('exported helpers', () => { + it('should have mocked', () => { + expect(subject).toHaveProperty('mocked', mocked) + }) + it('should have createJestPreset', () => { + expect(subject).toHaveProperty('createJestPreset', createJestPreset) + }) + it('should have pathsToModuleNameMapper', () => { + expect(subject).toHaveProperty('pathsToModuleNameMapper', pathsToModuleNameMapper) + }) +}) diff --git a/src/util/exported.ts b/src/util/exported.ts new file mode 100644 index 0000000000..f051fd7e00 --- /dev/null +++ b/src/util/exported.ts @@ -0,0 +1,3 @@ +export { mocked } from './testing' +export { createJestPreset } from '../config/create-jest-preset' +export { pathsToModuleNameMapper } from '../config/paths-to-module-name-mapper' diff --git a/src/util/messages.ts b/src/util/messages.ts index b46d448abe..8f371158bc 100644 --- a/src/util/messages.ts +++ b/src/util/messages.ts @@ -40,6 +40,7 @@ export enum Deprecateds { ConfigOption = '"[jest-config].{{oldPath}}" is deprecated, use "[jest-config].{{newPath}}" instead.', ConfigOptionWithNote = '"[jest-config].{{oldPath}}" is deprecated, use "[jest-config].{{newPath}}" instead.\n ↳ {{note}}', ConfigOptionUseBabelRcNote = 'See `babel-jest` related issue: https://github.com/facebook/jest/issues/3845', + HelperMovedToUtils = "The `{{helper}}` helper has been moved to `ts-jest/utils`. Use `import { {{helper}} } from 'ts-jest/utils'` instead.", } /** diff --git a/src/util/testing.ts b/src/util/testing.ts index a45b27cb72..7e83fd76fd 100644 --- a/src/util/testing.ts +++ b/src/util/testing.ts @@ -1,4 +1,28 @@ -import { MaybeMocked, MaybeMockedDeep } from '../types' +interface MockWithArgs extends Function, jest.MockInstance { + new (...args: ArgumentsOf): T + (...args: ArgumentsOf): any +} + +// tslint:disable-next-line:ban-types +type MethodKeysOf = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T] +// tslint:disable-next-line:ban-types +type PropertyKeysOf = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T] +type ArgumentsOf = T extends (...args: infer A) => any ? A : never +interface MockWithArgs extends Function, jest.MockInstance { + new (...args: ArgumentsOf): T + (...args: ArgumentsOf): any +} + +type MockedFunction = MockWithArgs & { [K in keyof T]: T[K] } +type MockedFunctionDeep = MockWithArgs & MockedObjectDeep +type MockedObject = { [K in MethodKeysOf]: MockedFunction } & { [K in PropertyKeysOf]: T[K] } +type MockedObjectDeep = { [K in MethodKeysOf]: MockedFunctionDeep } & + { [K in PropertyKeysOf]: MaybeMockedDeep } + +// tslint:disable-next-line:ban-types +export type MaybeMockedDeep = T extends Function ? MockedFunctionDeep : T extends object ? MockedObjectDeep : T +// tslint:disable-next-line:ban-types +export type MaybeMocked = T extends Function ? MockedFunction : T extends object ? MockedObject : T // the typings test helper export function mocked(item: T, deep?: false): MaybeMocked diff --git a/utils/index.d.ts b/utils/index.d.ts new file mode 100644 index 0000000000..10294287ca --- /dev/null +++ b/utils/index.d.ts @@ -0,0 +1 @@ +export * from '../dist/util/exported' diff --git a/utils/index.js b/utils/index.js new file mode 100644 index 0000000000..11c963bb85 --- /dev/null +++ b/utils/index.js @@ -0,0 +1 @@ +module.exports = require('../dist/util/exported')