From f2f99c3a46ac18a1fd6cc98922329b71a7e8c4e8 Mon Sep 17 00:00:00 2001 From: Ahn Date: Thu, 21 Jan 2021 19:11:35 +0100 Subject: [PATCH] feat(config): replace `pathRegex` with `exclude` (#2295) Replace `pathRegex` by `exclude` which uses Glob patterns, similar to tsconfig `exclude` option. This will make it easier to configure files to exclude from type checking. BREAKING CHANGE One is currently using `pathRegex` should use `exclude` with Glob patterns --- .../__snapshots__/ts-compiler.spec.ts.snap | 4 +- src/compiler/ts-compiler.spec.ts | 12 ++--- src/config/config-set.spec.ts | 44 ++++++++++--------- src/config/config-set.ts | 30 ++++++++----- src/types.ts | 7 ++- .../__snapshots__/backports.spec.ts.snap | 4 +- src/utils/backports.ts | 2 +- website/docs/options/diagnostics.md | 10 +++-- 8 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/compiler/__snapshots__/ts-compiler.spec.ts.snap b/src/compiler/__snapshots__/ts-compiler.spec.ts.snap index 83c23bd306..8225e676e9 100644 --- a/src/compiler/__snapshots__/ts-compiler.spec.ts.snap +++ b/src/compiler/__snapshots__/ts-compiler.spec.ts.snap @@ -53,9 +53,9 @@ exports[`TsCompiler isolatedModule false should compile codes with useESM true 1 //# " `; -exports[`TsCompiler isolatedModule true diagnostics should report diagnostics related to codes with pathRegex config is undefined 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; +exports[`TsCompiler isolatedModule true diagnostics should report diagnostics related to codes with exclude config is undefined 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; -exports[`TsCompiler isolatedModule true diagnostics should report diagnostics related to codes with pathRegex config matches file name 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; +exports[`TsCompiler isolatedModule true diagnostics should report diagnostics related to codes with exclude config matches file name 1`] = `"foo.ts(2,23): error TS1005: '=>' expected."`; exports[`TsCompiler isolatedModule true jsx option should compile tsx file for jsx preserve 1`] = ` "\\"use strict\\"; diff --git a/src/compiler/ts-compiler.spec.ts b/src/compiler/ts-compiler.spec.ts index 28e035a840..2aa82b6836 100644 --- a/src/compiler/ts-compiler.spec.ts +++ b/src/compiler/ts-compiler.spec.ts @@ -130,7 +130,7 @@ const v: boolean = t ).not.toThrowError() }) - it('should report diagnostics related to codes with pathRegex config is undefined', () => { + it('should report diagnostics related to codes with exclude config is undefined', () => { const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsconfig: false } }) expect(() => @@ -145,9 +145,9 @@ const t: string = f(5) ).toThrowErrorMatchingSnapshot() }) - it('should report diagnostics related to codes with pathRegex config matches file name', () => { + it('should report diagnostics related to codes with exclude config matches file name', () => { const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, tsconfig: false, diagnostics: { pathRegex: 'foo.ts' } }, + tsJestConfig: { ...baseTsJestConfig, tsconfig: false, diagnostics: { exclude: ['foo.ts'] } }, }) expect(() => @@ -162,9 +162,9 @@ const t: string = f(5) ).toThrowErrorMatchingSnapshot() }) - it('should not report diagnostics related to codes with pathRegex config does not match file name', () => { + it('should not report diagnostics related to codes with exclude config does not match file name', () => { const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, tsconfig: false, diagnostics: { pathRegex: 'bar.ts' } }, + tsJestConfig: { ...baseTsJestConfig, tsconfig: false, diagnostics: { exclude: ['bar.ts'] } }, }) expect(() => @@ -410,7 +410,7 @@ const t: string = f(5) { tsJestConfig: { ...baseTsJestConfig, - diagnostics: { pathRegex: 'foo.spec.ts' }, + diagnostics: { exclude: ['foo.spec.ts'] }, }, }, jestCacheFS, diff --git a/src/config/config-set.spec.ts b/src/config/config-set.spec.ts index 7fcd3cf5ae..b15f6061f0 100644 --- a/src/config/config-set.spec.ts +++ b/src/config/config-set.spec.ts @@ -432,13 +432,20 @@ describe('isTestFile', () => { describe('shouldStringifyContent', () => { it('should return correct value is defined', () => { - const cs = createConfigSet({ tsJestConfig: { tsconfig: false, stringifyContentPathRegex: '\\.str$' } as any }) - expect(cs.shouldStringifyContent('/foo/bar.ts')).toBe(false) - expect(cs.shouldStringifyContent('/foo/bar.str')).toBe(true) + const cs1 = createConfigSet({ tsJestConfig: { tsconfig: false, stringifyContentPathRegex: '\\.str$' } as any }) + + expect(cs1.shouldStringifyContent('/foo/bar.ts')).toBe(false) + expect(cs1.shouldStringifyContent('/foo/bar.str')).toBe(true) + + const cs2 = createConfigSet({ tsJestConfig: { tsconfig: false, stringifyContentPathRegex: /\.str$/ } as any }) + + expect(cs2.shouldStringifyContent('/foo/bar.ts')).toBe(false) + expect(cs2.shouldStringifyContent('/foo/bar.str')).toBe(true) }) it('should return correct value when stringifyContentPathRegex is undefined', () => { const cs = createConfigSet({ tsJestConfig: { tsconfig: false } as any }) + expect(cs.shouldStringifyContent('/foo/bar.ts')).toBe(false) }) }) // shouldStringifyContent @@ -487,10 +494,10 @@ describe('raiseDiagnostics', () => { code = 9999, category = ts.DiagnosticCategory.Warning, }: Partial = {}): ts.Diagnostic => ({ messageText, code, category } as any) - it('should throw when diagnostics contains file path and pathRegex config matches file path', () => { + it('should throw when diagnostics contains file path and exclude config matches file path', () => { const cs = createConfigSet({ logger, - tsJestConfig: { diagnostics: { pathRegex: 'src/__mocks__/index.ts', pretty: false } }, + tsJestConfig: { diagnostics: { exclude: ['src/__mocks__/index.ts'], pretty: false } }, }) logger.target.clear() @@ -499,10 +506,10 @@ describe('raiseDiagnostics', () => { ).toThrowErrorMatchingInlineSnapshot(`"warning TS9999: foo"`) }) - it("should not throw when diagnostics contains file path and pathRegex config doesn't match file path", () => { + it("should not throw when diagnostics contains file path and exclude config doesn't match file path", () => { const cs = createConfigSet({ logger, - tsJestConfig: { diagnostics: { warnOnly: true, pathRegex: '/bar/', pretty: false } }, + tsJestConfig: { diagnostics: { warnOnly: true, exclude: ['/bar/'], pretty: false } }, }) logger.target.clear() @@ -524,20 +531,20 @@ describe('raiseDiagnostics', () => { file = program.getSourceFiles().find((sourceFile) => sourceFile.fileName === 'src/__mocks__/index.ts'), }: Partial = {}): ts.Diagnostic => ({ messageText, code, category, file } as any) - it("should not throw when pathRegex config doesn't match source file path", () => { + it("should not throw when exclude config doesn't match source file path", () => { const cs = createConfigSet({ logger, - tsJestConfig: { diagnostics: { pathRegex: '/foo/', pretty: false, ignoreCodes: [1111] } }, + tsJestConfig: { diagnostics: { exclude: ['/foo/'], pretty: false, ignoreCodes: [1111] } }, }) logger.target.clear() expect(() => cs.raiseDiagnostics([makeDiagnostic()])).not.toThrow() }) - it("should throw when pathRegex config doesn't match source file path", () => { + it("should throw when exclude config doesn't match source file path", () => { const cs = createConfigSet({ logger, - tsJestConfig: { diagnostics: { pathRegex: 'src/__mocks__/index.ts', pretty: false } }, + tsJestConfig: { diagnostics: { exclude: ['src/__mocks__/index.ts'], pretty: false } }, }) logger.target.clear() @@ -553,7 +560,7 @@ describe('shouldReportDiagnostics', () => { let cs = createConfigSet({ tsJestConfig: { tsconfig: false, - diagnostics: { pathRegex: '/foo/' }, + diagnostics: { exclude: ['**/foo/*.ts', '**/foo/*.tsx'] }, } as any, }) @@ -570,7 +577,7 @@ describe('shouldReportDiagnostics', () => { let cs = createConfigSet({ tsJestConfig: { tsconfig: { checkJs: false }, - diagnostics: { pathRegex: '/foo/' }, + diagnostics: { exclude: ['foo/*'] }, }, }) @@ -580,17 +587,12 @@ describe('shouldReportDiagnostics', () => { cs = createConfigSet({ tsJestConfig: { tsconfig: { checkJs: true }, - diagnostics: { pathRegex: '/foo/' }, + diagnostics: { exclude: ['**/foo/*.js', '**/foo/*.jsx'] }, }, }) expect(cs.shouldReportDiagnostics('/foo/index.js')).toBe(true) expect(cs.shouldReportDiagnostics('/foo/index.jsx')).toBe(true) - - cs = createConfigSet({ tsJestConfig: { tsconfig: { checkJs: true } } }) - - expect(cs.shouldReportDiagnostics('/foo/index.js')).toBe(true) - expect(cs.shouldReportDiagnostics('/foo/index.jsx')).toBe(true) }) }) // shouldReportDiagnostics @@ -950,7 +952,7 @@ describe('diagnostics', () => { { diagnostics: { ignoreCodes: '10, 25', - pathRegex: '\\.test\\.ts', + exclude: ['\\.test\\.ts'], pretty: false, }, }, @@ -958,7 +960,7 @@ describe('diagnostics', () => { diagnostics: { ignoreCodes: ['10', 25], pretty: false, - pathRegex: RegExp('\\.test\\.ts'), + exclude: ['\\.test\\.ts'], }, }, { diagnostics: { warnOnly: true } }, diff --git a/src/config/config-set.ts b/src/config/config-set.ts index 82e8ee2245..8e2d6ec95f 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -147,7 +147,11 @@ export class ConfigSet { /** * @internal */ - private readonly _isMatch: (str: Config.Path) => boolean + private readonly _matchTestFilePath: (filePath: string) => boolean + /** + * @internal + */ + private _shouldGetDiagnosticsForFile!: (filePath: string) => boolean /** * @internal */ @@ -201,7 +205,7 @@ export class ConfigSet { if (!this._matchablePatterns.length) { this._matchablePatterns.push(...DEFAULT_JEST_TEST_MATCH) } - this._isMatch = globsToMatcher( + this._matchTestFilePath = globsToMatcher( this._matchablePatterns.filter((pattern: any) => typeof pattern === 'string') as string[], ) } @@ -270,17 +274,21 @@ export class ConfigSet { } this._diagnostics = { pretty: diagnosticsOpt.pretty ?? true, + exclude: diagnosticsOpt.exclude ?? [], ignoreCodes: toDiagnosticCodeList(ignoreList), - pathRegex: normalizeRegex(diagnosticsOpt.pathRegex), throws: !diagnosticsOpt.warnOnly, } } else { this._diagnostics = { ignoreCodes: diagnosticsOpt ? toDiagnosticCodeList(ignoreList) : [], + exclude: [], pretty: true, throws: diagnosticsOpt, } } + this._shouldGetDiagnosticsForFile = this._diagnostics.exclude.length + ? globsToMatcher(this._diagnostics.exclude) + : () => true this.logger.debug({ diagnostics: this._diagnostics }, 'normalized diagnostics config via ts-jest option') @@ -377,6 +385,9 @@ export class ConfigSet { } } + /** + * @internal + */ private _getAndResolveTsConfig(compilerOptions?: CompilerOptions, resolvedConfigFile?: string): ParsedCommandLine { const result = this._resolveTsConfig(compilerOptions, resolvedConfigFile) as ParsedCommandLine const { _overriddenCompilerOptions: forcedOptions } = this @@ -494,7 +505,7 @@ export class ConfigSet { isTestFile(fileName: string): boolean { return this._matchablePatterns.some((pattern) => - typeof pattern === 'string' ? this._isMatch(fileName) : pattern.test(fileName), + typeof pattern === 'string' ? this._matchTestFilePath(fileName) : pattern.test(fileName), ) } @@ -527,16 +538,11 @@ export class ConfigSet { } shouldReportDiagnostics(filePath: string): boolean { - const { pathRegex } = this._diagnostics const fileExtension = extname(filePath) - const { checkJs } = this.parsedTsConfig.options - if (pathRegex) { - const regex = new RegExp(pathRegex) - return JS_JSX_EXTENSIONS.includes(fileExtension) ? checkJs && regex.test(filePath) : regex.test(filePath) - } else { - return JS_JSX_EXTENSIONS.includes(fileExtension) ? checkJs : true - } + return JS_JSX_EXTENSIONS.includes(fileExtension) + ? this.parsedTsConfig.options.checkJs && this._shouldGetDiagnosticsForFile(filePath) + : this._shouldGetDiagnosticsForFile(filePath) } /** diff --git a/src/types.ts b/src/types.ts index 8168b57881..942028b9da 100644 --- a/src/types.ts +++ b/src/types.ts @@ -102,10 +102,9 @@ export interface TsJestGlobalOptions { */ ignoreCodes?: number | string | (number | string)[] /** - * If specified, diagnostics of source files which path does **not** match - * will be ignored + * If specified, diagnostics of source files which path **matches** will be ignored */ - pathRegex?: RegExp | string + exclude?: Config.Glob[] /** * Logs TypeScript errors to stderr instead of throwing exceptions * @@ -152,7 +151,7 @@ type TsJestConfig$tsConfig = TsJestConfig$tsConfig$file | TsJestConfig$tsConfig$ export interface TsJestDiagnosticsCfg { pretty: boolean ignoreCodes: number[] - pathRegex?: string | undefined + exclude: Config.Glob[] throws: boolean warnOnly?: boolean } diff --git a/src/utils/__snapshots__/backports.spec.ts.snap b/src/utils/__snapshots__/backports.spec.ts.snap index 1a92b8d20f..46276af0ff 100644 --- a/src/utils/__snapshots__/backports.spec.ts.snap +++ b/src/utils/__snapshots__/backports.spec.ts.snap @@ -98,7 +98,9 @@ Object { "globals": Object { "ts-jest": Object { "diagnostics": Object { - "pathRegex": "\\\\.spec\\\\.ts$", + "exclude": Array [ + "\\\\.spec\\\\.ts$", + ], "warnOnly": true, }, }, diff --git a/src/utils/backports.ts b/src/utils/backports.ts index d37cf866a0..2bf5bae900 100644 --- a/src/utils/backports.ts +++ b/src/utils/backports.ts @@ -64,7 +64,7 @@ export const backportJestConfig =