From e48cd88e72cf187679c5ab88e0f02a721d06051c Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 27 Feb 2019 12:35:38 +0100 Subject: [PATCH] fix a couple more type errors --- packages/jest-core/src/SearchSource.ts | 35 +++++---- .../jest-core/src/SnapshotInteractiveMode.ts | 6 +- packages/jest-core/src/getNoTestFound.ts | 2 +- .../jest-core/src/getNoTestFoundVerbose.ts | 9 ++- .../jest-core/src/lib/update_global_config.ts | 1 + packages/jest-core/src/plugins/quit.ts | 2 + .../plugins/update_snapshots_interactive.ts | 5 +- packages/jest-core/src/types.ts | 25 +++++- packages/jest-core/src/watch.ts | 77 ++++++++++++------- packages/jest-haste-map/src/index.ts | 14 ++-- packages/jest-haste-map/src/types.ts | 13 ++++ 11 files changed, 126 insertions(+), 63 deletions(-) diff --git a/packages/jest-core/src/SearchSource.ts b/packages/jest-core/src/SearchSource.ts index 0c34b0bc38a1..4a9c3fed0236 100644 --- a/packages/jest-core/src/SearchSource.ts +++ b/packages/jest-core/src/SearchSource.ts @@ -16,10 +16,11 @@ import {escapePathForRegex} from 'jest-regex-util'; import {replaceRootDirInPath} from 'jest-config'; import {buildSnapshotResolver} from 'jest-snapshot'; import {replacePathSepForGlob, testPathPatternToRegExp} from 'jest-util'; +import {Stats, TestPathCases, TestPathCasesWithPathPattern} from './types'; type SearchResult = { noSCM?: boolean; - stats?: {[key: string]: number}; + stats?: Stats; collectCoverageFrom?: Set; tests: Array; total?: number; @@ -40,14 +41,6 @@ type FilterResult = { message: string; }; -type TestPathCases = { - roots: (path: Config.Path) => boolean; - testMatch: (path: Config.Path) => boolean; - testRegex: (path: Config.Path) => boolean; - testPathIgnorePatterns: (path: Config.Path) => boolean; - testPathPattern?: (path: Config.Path) => boolean; -}; - const globsToMatcher = (globs?: Array | null) => { if (globs == null || globs.length === 0) { return () => true; @@ -105,11 +98,16 @@ export default class SearchSource { testPathPattern?: string, ): SearchResult { const data: { - stats: {[key in keyof TestPathCases]: number}; + stats: Stats; tests: Array; total: number; } = { - stats: {}, + stats: { + roots: 0, + testMatch: 0, + testPathIgnorePatterns: 0, + testRegex: 0, + }, tests: [], total: allPaths.length, }; @@ -117,15 +115,17 @@ export default class SearchSource { const testCases = Object.assign({}, this._testPathCases); if (testPathPattern) { const regex = testPathPatternToRegExp(testPathPattern); - testCases.testPathPattern = (path: Config.Path) => regex.test(path); + (testCases as TestPathCasesWithPathPattern).testPathPattern = ( + path: Config.Path, + ) => regex.test(path); } - const testCasesKeys = Object.keys(testCases) as Array; + const testCasesKeys = Object.keys(testCases) as Array; data.tests = allPaths.filter(test => testCasesKeys.reduce((flag, key) => { if (testCases[key](test.path)) { if (data.stats[key] === undefined) { - data.stats[key] = 1; + data.stats[key] = 0; } ++data.stats[key]!; return flag && true; @@ -135,6 +135,13 @@ export default class SearchSource { }, true), ); + // TODO: Is this necessary? Done to keep the object the same as before the TS migration + testCasesKeys.forEach(key => { + if (data.stats[key] === 0) { + delete data.stats[key]; + } + }); + return data; } diff --git a/packages/jest-core/src/SnapshotInteractiveMode.ts b/packages/jest-core/src/SnapshotInteractiveMode.ts index 6768bb7d67bb..ab09e39c6979 100644 --- a/packages/jest-core/src/SnapshotInteractiveMode.ts +++ b/packages/jest-core/src/SnapshotInteractiveMode.ts @@ -18,12 +18,12 @@ const {ARROW, CLEAR} = specialChars; export default class SnapshotInteractiveMode { private _pipe: NodeJS.WritableStream; private _isActive: boolean; - private _updateTestRunnerConfig: ( + private _updateTestRunnerConfig!: ( assertion: TestResult.AssertionLocation | null, shouldUpdateSnapshot: boolean, ) => unknown; - private _testAssertions: Array; - private _countPaths: number; + private _testAssertions!: Array; + private _countPaths!: number; private _skippedNum: number; constructor(pipe: NodeJS.WritableStream) { diff --git a/packages/jest-core/src/getNoTestFound.ts b/packages/jest-core/src/getNoTestFound.ts index 6cd7585edf94..0b06f44ae696 100644 --- a/packages/jest-core/src/getNoTestFound.ts +++ b/packages/jest-core/src/getNoTestFound.ts @@ -15,7 +15,7 @@ export default function getNoTestFound( globalConfig: Config.GlobalConfig, ): string { const testFiles = testRunData.reduce( - (current, testRun) => current + testRun.matches.total || 0, + (current, testRun) => current + (testRun.matches.total || 0) || 0, 0, ); let dataMessage; diff --git a/packages/jest-core/src/getNoTestFoundVerbose.ts b/packages/jest-core/src/getNoTestFoundVerbose.ts index 451badb94226..e1389f7ef423 100644 --- a/packages/jest-core/src/getNoTestFoundVerbose.ts +++ b/packages/jest-core/src/getNoTestFoundVerbose.ts @@ -3,24 +3,25 @@ import chalk from 'chalk'; import {Config} from '@jest/types'; import pluralize from './pluralize'; -import {TestRunData} from './types'; +import {Stats, TestRunData} from './types'; export default function getNoTestFoundVerbose( testRunData: TestRunData, globalConfig: Config.GlobalConfig, ): string { const individualResults = testRunData.map(testRun => { - const stats = testRun.matches.stats || {}; + const stats = testRun.matches.stats || ({} as Stats); const config = testRun.context.config; - const statsMessage = Object.keys(stats) + const statsMessage = (Object.keys(stats) as Array) .map(key => { if (key === 'roots' && config.roots.length === 1) { return null; } const value = config[key]; if (value) { + const valueAsString = Array.isArray(value) ? value.join(', ') : value; const matches = pluralize('match', stats[key], 'es'); - return ` ${key}: ${chalk.yellow(value)} - ${matches}`; + return ` ${key}: ${chalk.yellow(valueAsString)} - ${matches}`; } return null; }) diff --git a/packages/jest-core/src/lib/update_global_config.ts b/packages/jest-core/src/lib/update_global_config.ts index 048422876e89..b6fd00027520 100644 --- a/packages/jest-core/src/lib/update_global_config.ts +++ b/packages/jest-core/src/lib/update_global_config.ts @@ -68,6 +68,7 @@ export default ( newConfig.coverageReporters = options.coverageReporters; } + // @ts-ignore: does it make sense to be able to set this? if (options.noSCM) { newConfig.noSCM = true; } diff --git a/packages/jest-core/src/plugins/quit.ts b/packages/jest-core/src/plugins/quit.ts index 3a7a64769d78..bc8286bb94ac 100644 --- a/packages/jest-core/src/plugins/quit.ts +++ b/packages/jest-core/src/plugins/quit.ts @@ -19,7 +19,9 @@ class QuitPlugin extends BaseWatchPlugin { } async run() { + // @ts-ignore if (typeof this._stdin.setRawMode === 'function') { + // @ts-ignore this._stdin.setRawMode(false); } this._stdout.write('\n'); diff --git a/packages/jest-core/src/plugins/update_snapshots_interactive.ts b/packages/jest-core/src/plugins/update_snapshots_interactive.ts index 517cfa7d3bc6..31861da33db6 100644 --- a/packages/jest-core/src/plugins/update_snapshots_interactive.ts +++ b/packages/jest-core/src/plugins/update_snapshots_interactive.ts @@ -10,9 +10,8 @@ import {BaseWatchPlugin, JestHookSubscriber} from 'jest-watcher'; import SnapshotInteractiveMode from '../SnapshotInteractiveMode'; class UpdateSnapshotInteractivePlugin extends BaseWatchPlugin { - _snapshotInteractiveMode: SnapshotInteractiveMode; - _failedSnapshotTestPaths: Array; - _failedSnapshotTestAssertions: Array; + private _snapshotInteractiveMode: SnapshotInteractiveMode; + private _failedSnapshotTestAssertions: Array; isInternal: true; constructor(options: { diff --git a/packages/jest-core/src/types.ts b/packages/jest-core/src/types.ts index 57f626664aea..ce4218f4f526 100644 --- a/packages/jest-core/src/types.ts +++ b/packages/jest-core/src/types.ts @@ -7,13 +7,34 @@ import {Context} from 'jest-runtime'; import {Test} from 'jest-runner'; -import {TestResult} from '@jest/types'; +import {Config, TestResult} from '@jest/types'; export type TestRunData = Array<{ context: Context; - matches: {allTests: number; tests: Array; total?: number}; + matches: { + allTests: number; + tests: Array; + total?: number; + stats?: Stats; + }; }>; +export type Stats = Record< + keyof (TestPathCases | TestPathCasesWithPathPattern), + number +>; + +export type TestPathCases = { + roots: (path: Config.Path) => boolean; + testMatch: (path: Config.Path) => boolean; + testPathIgnorePatterns: (path: Config.Path) => boolean; + testRegex: (path: Config.Path) => boolean; +}; + +export type TestPathCasesWithPathPattern = TestPathCases & { + testPathPattern: (path: Config.Path) => boolean; +}; + // TODO: Obtain this from @jest/reporters once its been migrated export type ReporterOnStartOptions = { estimatedTime: number; diff --git a/packages/jest-core/src/watch.ts b/packages/jest-core/src/watch.ts index 52d22aa41ff7..28b231121a90 100644 --- a/packages/jest-core/src/watch.ts +++ b/packages/jest-core/src/watch.ts @@ -8,7 +8,7 @@ import ansiEscapes from 'ansi-escapes'; import chalk from 'chalk'; import exit from 'exit'; -import HasteMap from 'jest-haste-map'; +import HasteMap, {HasteChangeEvent} from 'jest-haste-map'; import {formatExecError} from 'jest-message-util'; import {isInteractive, preRunMessage, specialChars} from 'jest-util'; // @ts-ignore: Not migrated to TS @@ -35,6 +35,15 @@ import { } from './lib/watch_plugins_helpers'; import activeFilters from './lib/active_filters_message'; +type ReservedInfo = { + forbiddenOverwriteMessage?: string; + key?: string; + overwritable: boolean; + plugin: WatchPlugin; +}; + +type WatchPluginKeysMap = Map; + const {print: preRunMessagePrint} = preRunMessage; let hasExitListener = false; @@ -47,16 +56,20 @@ const INTERNAL_PLUGINS = [ QuitPlugin, ]; -const RESERVED_KEY_PLUGINS = new Map([ +// TODO: Is it correct with constructor here? +const RESERVED_KEY_PLUGINS = new Map< + WatchPlugin, + {forbiddenOverwriteMessage: string; key?: string} +>([ [ - UpdateSnapshotsPlugin, + UpdateSnapshotsPlugin.constructor, {forbiddenOverwriteMessage: 'updating snapshots', key: 'u'}, ], [ - UpdateSnapshotsInteractivePlugin, + UpdateSnapshotsInteractivePlugin.constructor, {forbiddenOverwriteMessage: 'updating snapshots interactively', key: 'i'}, ], - [QuitPlugin, {forbiddenOverwriteMessage: 'quitting watch mode'}], + [QuitPlugin.constructor, {forbiddenOverwriteMessage: 'quitting watch mode'}], ]); export default function watch( @@ -134,9 +147,10 @@ export default function watch( }); if (globalConfig.watchPlugins != null) { - const watchPluginKeys = new Map(); + const watchPluginKeys: WatchPluginKeysMap = new Map(); for (const plugin of watchPlugins) { - const reservedInfo = RESERVED_KEY_PLUGINS.get(plugin.constructor) || {}; + const reservedInfo = + RESERVED_KEY_PLUGINS.get(plugin.constructor) || ({} as ReservedInfo); const key = reservedInfo.key || getPluginKey(plugin, globalConfig); if (!key) { continue; @@ -190,34 +204,38 @@ export default function watch( emitFileChange(); hasteMapInstances.forEach((hasteMapInstance, index) => { - hasteMapInstance.on('change', ({eventsQueue, hasteFS, moduleMap}) => { - const validPaths = eventsQueue.filter(({filePath}) => - isValidPath(globalConfig, filePath), - ); - - if (validPaths.length) { - const context = (contexts[index] = createContext( - contexts[index].config, - {hasteFS, moduleMap}, - )); - - activePlugin = null; + hasteMapInstance.on( + 'change', + ({eventsQueue, hasteFS, moduleMap}: HasteChangeEvent) => { + const validPaths = eventsQueue.filter(({filePath}) => + isValidPath(globalConfig, filePath), + ); - searchSources = searchSources.slice(); - searchSources[index] = { - context, - searchSource: new SearchSource(context), - }; - emitFileChange(); - startRun(globalConfig); - } - }); + if (validPaths.length) { + const context = (contexts[index] = createContext( + contexts[index].config, + {hasteFS, moduleMap}, + )); + + activePlugin = null; + + searchSources = searchSources.slice(); + searchSources[index] = { + context, + searchSource: new SearchSource(context), + }; + emitFileChange(); + startRun(globalConfig); + } + }, + ); }); if (!hasExitListener) { hasExitListener = true; process.on('exit', () => { if (activePlugin) { + // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33423 outputStream.write(ansiEscapes.cursorDown()); outputStream.write(ansiEscapes.eraseDown); } @@ -383,6 +401,7 @@ export default function watch( break; case 'w': if (!shouldDisplayWatchUsage && !isWatchUsageDisplayed) { + // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33423 outputStream.write(ansiEscapes.cursorUp()); outputStream.write(ansiEscapes.eraseDown); outputStream.write(usage(globalConfig, watchPlugins)); @@ -413,7 +432,7 @@ export default function watch( } const checkForConflicts = ( - watchPluginKeys, + watchPluginKeys: WatchPluginKeysMap, plugin: WatchPlugin, globalConfig: Config.GlobalConfig, ) => { diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index 21b167d6e1f8..3a7d1926539e 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -31,6 +31,8 @@ import watchmanCrawl from './crawlers/watchman'; import WatchmanWatcher from './lib/WatchmanWatcher'; import * as fastPath from './lib/fast_path'; import { + ChangeEvent, + EventsQueue, FileMetaData, HasteMap as InternalHasteMapObject, HasteRegExp, @@ -104,6 +106,7 @@ namespace HasteMap { export type SerializableModuleMap = HasteSerializableModuleMap; export type FS = HasteFS; export type HasteMapObject = InternalHasteMapObject; + export type HasteChangeEvent = ChangeEvent; } const CHANGE_INTERVAL = 30; @@ -764,11 +767,7 @@ class HasteMap extends EventEmitter { const rootDir = this._options.rootDir; let changeQueue: Promise = Promise.resolve(); - let eventsQueue: Array<{ - filePath: Config.Path; - stat: fs.Stats | undefined; - type: string; - }> = []; + let eventsQueue: EventsQueue = []; // We only need to copy the entire haste map once on every "frame". let mustCopy = true; @@ -797,7 +796,7 @@ class HasteMap extends EventEmitter { const emitChange = () => { if (eventsQueue.length) { mustCopy = true; - this.emit('change', { + const changeEvent: ChangeEvent = { eventsQueue, hasteFS: new HasteFS({ files: hasteMap.files, @@ -809,7 +808,8 @@ class HasteMap extends EventEmitter { mocks: hasteMap.mocks, rootDir, }), - }); + }; + this.emit('change', changeEvent); eventsQueue = []; } }; diff --git a/packages/jest-haste-map/src/types.ts b/packages/jest-haste-map/src/types.ts index c5e85fc8d9b9..59d2f8022330 100644 --- a/packages/jest-haste-map/src/types.ts +++ b/packages/jest-haste-map/src/types.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +import fs from 'fs'; import {Config} from '@jest/types'; import ModuleMap from './ModuleMap'; import HasteFS from './HasteFS'; @@ -102,3 +103,15 @@ export type HType = { }; export type HTypeValue = HType[keyof HType]; + +export type EventsQueue = Array<{ + filePath: Config.Path; + stat: fs.Stats | undefined; + type: string; +}>; + +export type ChangeEvent = { + eventsQueue: EventsQueue; + hasteFS: HasteFS; + moduleMap: ModuleMap; +};