From 02aa43c07f2b29f7d45b9191622f81cf9a7362fa Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 9 Feb 2019 23:51:45 +0100 Subject: [PATCH] chore: migrate jest-util to TypeScript --- CHANGELOG.md | 1 + packages/jest-circus/src/index.js | 1 + packages/jest-circus/src/utils.js | 1 + packages/jest-message-util/src/index.ts | 11 +- packages/jest-runner/src/runTest.js | 2 - .../src/SourceMaps.ts} | 7 +- packages/jest-types/src/TestResult.ts | 9 +- packages/jest-types/src/index.ts | 3 +- packages/jest-util/package.json | 8 +- packages/jest-util/src/BufferedConsole.js | 167 ------ packages/jest-util/src/BufferedConsole.ts | 161 ++++++ packages/jest-util/src/CustomConsole.js | 143 ------ packages/jest-util/src/CustomConsole.ts | 143 ++++++ .../{ErrorWithStack.js => ErrorWithStack.ts} | 4 +- .../src/{FakeTimers.js => FakeTimers.ts} | 133 ++--- .../src/{NullConsole.js => NullConsole.ts} | 2 - ...s.test.js.snap => fakeTimers.test.ts.snap} | 0 ...onsole.test.js => bufferedConsole.test.ts} | 4 +- .../{console.test.js => console.test.ts} | 2 - ...ct.test.js => createProcessObject.test.ts} | 3 + ...licCopy.test.js => deepCyclicCopy.test.ts} | 21 +- ...thStack.test.js => errorWithStack.test.ts} | 2 - ...{fakeTimers.test.js => fakeTimers.test.ts} | 479 +++++++++++++----- ...ults.test.js => formatTestResults.test.ts} | 7 +- ...etCallsite.test.js => getCallsite.test.ts} | 7 +- ...shot.test.js => getFailedSnapshot.test.ts} | 5 + ...s.test.js => installCommonGlobals.test.ts} | 7 +- ...eractive.test.js => isInteractive.test.ts} | 10 +- .../src/{clearLine.js => clearLine.ts} | 5 +- ...String.js => convertDescriptorToString.ts} | 6 +- ...{createDirectory.js => createDirectory.ts} | 7 +- ...rocessObject.js => createProcessObject.ts} | 12 +- .../{deepCyclicCopy.js => deepCyclicCopy.ts} | 48 +- ...matTestResults.js => formatTestResults.ts} | 39 +- .../src/{getCallsite.js => getCallsite.ts} | 26 +- ...etConsoleOutput.js => getConsoleOutput.ts} | 11 +- ...shotTests.js => getFailedSnapshotTests.ts} | 8 +- packages/jest-util/src/{index.js => index.ts} | 4 +- ...mmonGlobals.js => installCommonGlobals.ts} | 17 +- .../{isInteractive.js => isInteractive.ts} | 2 +- ...SepForGlob.js => replacePathSepForGlob.ts} | 6 +- packages/jest-util/src/setGlobal.ts | 15 + .../src/{specialChars.js => specialChars.ts} | 2 - packages/jest-util/tsconfig.json | 8 + yarn.lock | 20 +- 45 files changed, 889 insertions(+), 690 deletions(-) rename packages/{jest-util/src/setGlobal.js => jest-types/src/SourceMaps.ts} (60%) delete mode 100644 packages/jest-util/src/BufferedConsole.js create mode 100644 packages/jest-util/src/BufferedConsole.ts delete mode 100644 packages/jest-util/src/CustomConsole.js create mode 100644 packages/jest-util/src/CustomConsole.ts rename packages/jest-util/src/{ErrorWithStack.js => ErrorWithStack.ts} (85%) rename packages/jest-util/src/{FakeTimers.js => FakeTimers.ts} (83%) rename packages/jest-util/src/{NullConsole.js => NullConsole.ts} (97%) rename packages/jest-util/src/__tests__/__snapshots__/{fakeTimers.test.js.snap => fakeTimers.test.ts.snap} (100%) rename packages/jest-util/src/__tests__/{bufferedConsole.test.js => bufferedConsole.test.ts} (99%) rename packages/jest-util/src/__tests__/{console.test.js => console.test.ts} (99%) rename packages/jest-util/src/__tests__/{createProcessObject.test.js => createProcessObject.test.ts} (98%) rename packages/jest-util/src/__tests__/{deepCyclicCopy.test.js => deepCyclicCopy.test.ts} (94%) rename packages/jest-util/src/__tests__/{errorWithStack.test.js => errorWithStack.test.ts} (98%) rename packages/jest-util/src/__tests__/{fakeTimers.test.js => fakeTimers.test.ts} (73%) rename packages/jest-util/src/__tests__/{formatTestResults.test.js => formatTestResults.test.ts} (88%) rename packages/jest-util/src/__tests__/{getCallsite.test.js => getCallsite.test.ts} (90%) rename packages/jest-util/src/__tests__/{getFailedSnapshot.test.js => getFailedSnapshot.test.ts} (95%) rename packages/jest-util/src/__tests__/{installCommonGlobals.test.js => installCommonGlobals.test.ts} (90%) rename packages/jest-util/src/__tests__/{isInteractive.test.js => isInteractive.test.ts} (90%) rename packages/jest-util/src/{clearLine.js => clearLine.ts} (73%) rename packages/jest-util/src/{convertDescriptorToString.js => convertDescriptorToString.ts} (96%) rename packages/jest-util/src/{createDirectory.js => createDirectory.ts} (76%) rename packages/jest-util/src/{createProcessObject.js => createProcessObject.ts} (92%) rename packages/jest-util/src/{deepCyclicCopy.js => deepCyclicCopy.ts} (72%) rename packages/jest-util/src/{formatTestResults.js => formatTestResults.ts} (69%) rename packages/jest-util/src/{getCallsite.js => getCallsite.ts} (72%) rename packages/jest-util/src/{getConsoleOutput.js => getConsoleOutput.ts} (88%) rename packages/jest-util/src/{getFailedSnapshotTests.js => getFailedSnapshotTests.ts} (76%) rename packages/jest-util/src/{index.js => index.ts} (97%) rename packages/jest-util/src/{installCommonGlobals.js => installCommonGlobals.ts} (84%) rename packages/jest-util/src/{isInteractive.js => isInteractive.ts} (56%) rename packages/jest-util/src/{replacePathSepForGlob.js => replacePathSepForGlob.ts} (68%) create mode 100644 packages/jest-util/src/setGlobal.ts rename packages/jest-util/src/{specialChars.js => specialChars.ts} (97%) create mode 100644 packages/jest-util/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 817d95ea1333..ea78999740ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - `[jest-serializer]`: Migrate to TypeScript ([#7841](https://github.com/facebook/jest/pull/7841)) - `[jest-message-util]`: Migrate to TypeScript ([#7834](https://github.com/facebook/jest/pull/7834)) - `[@jest/types]`: New package to handle shared types ([#7834](https://github.com/facebook/jest/pull/7834)) +- `[jest-util]`: Migrate to TypeScript ([#7844](https://github.com/facebook/jest/pull/7844)) ### Performance diff --git a/packages/jest-circus/src/index.js b/packages/jest-circus/src/index.js index 150fd8b6cb87..ca770f8f07ca 100644 --- a/packages/jest-circus/src/index.js +++ b/packages/jest-circus/src/index.js @@ -18,6 +18,7 @@ import type { TestMode, } from 'types/Circus'; import {bind as bindEach} from 'jest-each'; +// $FlowFixMe: Converted to TS import {ErrorWithStack} from 'jest-util'; import {dispatch} from './state'; diff --git a/packages/jest-circus/src/utils.js b/packages/jest-circus/src/utils.js index 4f079ece8c6e..80a58fc2d9cd 100644 --- a/packages/jest-circus/src/utils.js +++ b/packages/jest-circus/src/utils.js @@ -22,6 +22,7 @@ import type { TestName, TestResults, } from 'types/Circus'; +// $FlowFixMe: Converted to TS import {convertDescriptorToString} from 'jest-util'; import isGeneratorFn from 'is-generator-fn'; import co from 'co'; diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index a95be08b6332..4e1b969f5d23 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -14,7 +14,6 @@ import slash from 'slash'; import {codeFrameColumns} from '@babel/code-frame'; import StackUtils from 'stack-utils'; -type Glob = Config.Glob; type Path = Config.Path; type AssertionResult = TestResult.AssertionResult; type SerializableError = TestResult.SerializableError; @@ -33,12 +32,12 @@ try { // node internals in the browser though, so no issue. } -type StackTraceConfig = { - rootDir: string; - testMatch: Array; -}; +export type StackTraceConfig = Pick< + Config.ProjectConfig, + 'rootDir' | 'testMatch' +>; -type StackTraceOptions = { +export type StackTraceOptions = { noStackTrace: boolean; }; diff --git a/packages/jest-runner/src/runTest.js b/packages/jest-runner/src/runTest.js index f609e09d4c8d..88fe237666cb 100644 --- a/packages/jest-runner/src/runTest.js +++ b/packages/jest-runner/src/runTest.js @@ -39,7 +39,6 @@ function freezeConsole( testConsole: BufferedConsole | Console | NullConsole, config: ProjectConfig, ) { - // $FlowFixMe: overwrite it for pretty errors testConsole._log = function fakeConsolePush(_type, message) { const error = new ErrorWithStack( `${chalk.red( @@ -89,7 +88,6 @@ async function runTestInternal( if (customEnvironment) { testEnvironment = getTestEnvironment({ ...config, - // $FlowFixMe testEnvironment: customEnvironment, }); } diff --git a/packages/jest-util/src/setGlobal.js b/packages/jest-types/src/SourceMaps.ts similarity index 60% rename from packages/jest-util/src/setGlobal.js rename to packages/jest-types/src/SourceMaps.ts index c9c836aaddbd..e7a298633114 100644 --- a/packages/jest-util/src/setGlobal.js +++ b/packages/jest-types/src/SourceMaps.ts @@ -3,11 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {Global} from 'types/Global'; - -export default (global: Global, key: string, value: any) => - (global[key] = value); +export type SourceMapRegistry = {[key: string]: string}; diff --git a/packages/jest-types/src/TestResult.ts b/packages/jest-types/src/TestResult.ts index 7c3b082836fd..841064692ff1 100644 --- a/packages/jest-types/src/TestResult.ts +++ b/packages/jest-types/src/TestResult.ts @@ -123,6 +123,7 @@ export type AssertionResult = { }; export type FormattedAssertionResult = { + ancestorTitles: Array; failureMessages: Array | null; fullName: string; location: Callsite | null | undefined; @@ -150,7 +151,7 @@ export type AggregatedResultWithoutCoverage = { }; export type AggregatedResult = AggregatedResultWithoutCoverage & { - coverageMap?: CoverageMap | null | undefined; + coverageMap?: CoverageMap | null; }; export type Suite = { @@ -160,10 +161,10 @@ export type Suite = { }; export type TestResult = { - console: ConsoleBuffer | null | undefined; + console?: ConsoleBuffer | null; coverage?: RawCoverage; - displayName: string | null | undefined; - failureMessage: string | null | undefined; + displayName?: string | null; + failureMessage?: string | null; leaks: boolean; memoryUsage?: Bytes; numFailingTests: number; diff --git a/packages/jest-types/src/index.ts b/packages/jest-types/src/index.ts index 60df27cb7dfd..61dfddbf9407 100644 --- a/packages/jest-types/src/index.ts +++ b/packages/jest-types/src/index.ts @@ -7,6 +7,7 @@ import * as Config from './Config'; import * as Console from './Console'; +import * as SourceMaps from './SourceMaps'; import * as TestResult from './TestResult'; -export {Config, Console, TestResult}; +export {Config, Console, SourceMaps, TestResult}; diff --git a/packages/jest-util/package.json b/packages/jest-util/package.json index 85f3410824a8..9394b4ec8d75 100644 --- a/packages/jest-util/package.json +++ b/packages/jest-util/package.json @@ -9,21 +9,25 @@ "license": "MIT", "main": "build/index.js", "dependencies": { + "@jest/types": "^24.1.0", + "@types/node": "*", "callsites": "^3.0.0", "chalk": "^2.0.1", "graceful-fs": "^4.1.15", "is-ci": "^2.0.0", "jest-message-util": "^24.0.0", + "jest-mock": "^24.0.0", "mkdirp": "^0.5.1", + "readable-stream": "^3.1.1", "slash": "^2.0.0", "source-map": "^0.6.0" }, "devDependencies": { - "@types/callsites": "^2.0.0", "@types/graceful-fs": "^4.1.2", "@types/is-ci": "^1.0.10", "@types/mkdirp": "^0.5.2", - "jest-mock": "^24.0.0" + "@types/readable-stream": "^2.3.0", + "@types/slash": "^2.0.0" }, "engines": { "node": ">= 6" diff --git a/packages/jest-util/src/BufferedConsole.js b/packages/jest-util/src/BufferedConsole.js deleted file mode 100644 index 53695331c7f3..000000000000 --- a/packages/jest-util/src/BufferedConsole.js +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type { - ConsoleBuffer, - LogMessage, - LogType, - LogCounters, - LogTimers, -} from 'types/Console'; - -import type {SourceMapRegistry} from 'types/SourceMaps'; - -import assert from 'assert'; -import {Console} from 'console'; -import {format} from 'util'; -import chalk from 'chalk'; -import getCallsite from './getCallsite'; - -export default class BufferedConsole extends Console { - _buffer: ConsoleBuffer; - _counters: LogCounters; - _timers: LogTimers; - _groupDepth: number; - _getSourceMaps: () => ?SourceMapRegistry; - - constructor(getSourceMaps: () => ?SourceMapRegistry) { - const buffer = []; - super({ - write: message => - BufferedConsole.write(buffer, 'log', message, null, getSourceMaps()), - }); - this._getSourceMaps = getSourceMaps; - this._buffer = buffer; - this._counters = {}; - this._timers = {}; - this._groupDepth = 0; - } - - static write( - buffer: ConsoleBuffer, - type: LogType, - message: LogMessage, - level: ?number, - sourceMaps: ?SourceMapRegistry, - ) { - const callsite = getCallsite(level != null ? level : 2, sourceMaps); - const origin = callsite.getFileName() + ':' + callsite.getLineNumber(); - - buffer.push({ - message, - origin, - type, - }); - - return buffer; - } - - _log(type: LogType, message: LogMessage) { - BufferedConsole.write( - this._buffer, - type, - ' '.repeat(this._groupDepth) + message, - 3, - this._getSourceMaps(), - ); - } - - assert(...args: Array) { - try { - assert(...args); - } catch (error) { - this._log('assert', error.toString()); - } - } - - count(label: string = 'default') { - if (!this._counters[label]) { - this._counters[label] = 0; - } - - this._log('count', format(`${label}: ${++this._counters[label]}`)); - } - - countReset(label: string = 'default') { - this._counters[label] = 0; - } - - debug(...args: Array) { - this._log('debug', format(...args)); - } - - dir(...args: Array) { - this._log('dir', format(...args)); - } - - dirxml(...args: Array) { - this._log('dirxml', format(...args)); - } - - error(...args: Array) { - this._log('error', format(...args)); - } - - group(...args: Array) { - this._groupDepth++; - - if (args.length > 0) { - this._log('group', chalk.bold(format(...args))); - } - } - - groupCollapsed(...args: Array) { - this._groupDepth++; - - if (args.length > 0) { - this._log('groupCollapsed', chalk.bold(format(...args))); - } - } - - groupEnd() { - if (this._groupDepth > 0) { - this._groupDepth--; - } - } - - info(...args: Array) { - this._log('info', format(...args)); - } - - log(...args: Array) { - this._log('log', format(...args)); - } - - time(label: string = 'default') { - if (this._timers[label]) { - return; - } - - this._timers[label] = new Date(); - } - - timeEnd(label: string = 'default') { - const startTime = this._timers[label]; - - if (startTime) { - const endTime = new Date(); - const time = endTime - startTime; - this._log('time', format(`${label}: ${time}ms`)); - delete this._timers[label]; - } - } - - warn(...args: Array) { - this._log('warn', format(...args)); - } - - getBuffer() { - return this._buffer; - } -} diff --git a/packages/jest-util/src/BufferedConsole.ts b/packages/jest-util/src/BufferedConsole.ts new file mode 100644 index 000000000000..8312b314444f --- /dev/null +++ b/packages/jest-util/src/BufferedConsole.ts @@ -0,0 +1,161 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import assert from 'assert'; +import {Console} from 'console'; +import {format} from 'util'; +import {Writable} from 'readable-stream'; +import chalk from 'chalk'; +import {Console as ConsoleType, SourceMaps} from '@jest/types'; +import getCallsite from './getCallsite'; + +export default class BufferedConsole extends Console { + private _buffer: ConsoleType.ConsoleBuffer; + private _counters: ConsoleType.LogCounters; + private _timers: ConsoleType.LogTimers; + private _groupDepth: number; + private _getSourceMaps: () => SourceMaps.SourceMapRegistry | null | undefined; + + constructor( + getSourceMaps: () => SourceMaps.SourceMapRegistry | null | undefined, + ) { + const buffer: ConsoleType.ConsoleBuffer = []; + super( + new Writable({ + write: message => + BufferedConsole.write(buffer, 'log', message, null, getSourceMaps()), + }), + ); + this._getSourceMaps = getSourceMaps; + this._buffer = buffer; + this._counters = {}; + this._timers = {}; + this._groupDepth = 0; + } + + static write( + buffer: ConsoleType.ConsoleBuffer, + type: ConsoleType.LogType, + message: ConsoleType.LogMessage, + level?: number | null, + sourceMaps?: SourceMaps.SourceMapRegistry | null, + ) { + const callsite = getCallsite(level != null ? level : 2, sourceMaps); + const origin = callsite.getFileName() + ':' + callsite.getLineNumber(); + + buffer.push({ + message, + origin, + type, + }); + + return buffer; + } + + private _log(type: ConsoleType.LogType, message: ConsoleType.LogMessage) { + BufferedConsole.write( + this._buffer, + type, + ' '.repeat(this._groupDepth) + message, + 3, + this._getSourceMaps(), + ); + } + + assert(value: any, message?: string | Error) { + try { + assert(value, message); + } catch (error) { + this._log('assert', error.toString()); + } + } + + count(label: string = 'default') { + if (!this._counters[label]) { + this._counters[label] = 0; + } + + this._log('count', format(`${label}: ${++this._counters[label]}`)); + } + + countReset(label: string = 'default') { + this._counters[label] = 0; + } + + debug(firstArg: any, ...rest: Array) { + this._log('debug', format(firstArg, ...rest)); + } + + dir(firstArg: any, ...rest: Array) { + this._log('dir', format(firstArg, ...rest)); + } + + dirxml(firstArg: any, ...rest: Array) { + this._log('dirxml', format(firstArg, ...rest)); + } + + error(firstArg: any, ...rest: Array) { + this._log('error', format(firstArg, ...rest)); + } + + group(title?: string, ...rest: Array) { + this._groupDepth++; + + if (title || rest.length > 0) { + this._log('group', chalk.bold(format(title, ...rest))); + } + } + + groupCollapsed(title?: string, ...rest: Array) { + this._groupDepth++; + + if (title || rest.length > 0) { + this._log('groupCollapsed', chalk.bold(format(title, ...rest))); + } + } + + groupEnd() { + if (this._groupDepth > 0) { + this._groupDepth--; + } + } + + info(firstArg: any, ...rest: Array) { + this._log('info', format(firstArg, ...rest)); + } + + log(firstArg: any, ...rest: Array) { + this._log('log', format(firstArg, ...rest)); + } + + time(label: string = 'default') { + if (this._timers[label]) { + return; + } + + this._timers[label] = new Date(); + } + + timeEnd(label: string = 'default') { + const startTime = this._timers[label]; + + if (startTime) { + const endTime = new Date(); + const time = endTime.getTime() - startTime.getTime(); + this._log('time', format(`${label}: ${time}ms`)); + delete this._timers[label]; + } + } + + warn(firstArg: any, ...rest: Array) { + this._log('warn', format(firstArg, ...rest)); + } + + getBuffer(): ConsoleType.ConsoleBuffer { + return this._buffer; + } +} diff --git a/packages/jest-util/src/CustomConsole.js b/packages/jest-util/src/CustomConsole.js deleted file mode 100644 index 3084dc3f38c7..000000000000 --- a/packages/jest-util/src/CustomConsole.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ -/* global stream$Writable */ - -import type {LogType, LogMessage, LogCounters, LogTimers} from 'types/Console'; - -import assert from 'assert'; -import {format} from 'util'; -import {Console} from 'console'; -import chalk from 'chalk'; -import clearLine from './clearLine'; - -type Formatter = (type: LogType, message: LogMessage) => string; - -export default class CustomConsole extends Console { - _stdout: stream$Writable; - _formatBuffer: Formatter; - _counters: LogCounters; - _timers: LogTimers; - _groupDepth: number; - - constructor( - stdout: stream$Writable, - stderr: stream$Writable, - formatBuffer: ?Formatter, - ) { - super(stdout, stderr); - this._formatBuffer = formatBuffer || ((type, message) => message); - this._counters = {}; - this._timers = {}; - this._groupDepth = 0; - } - - _logToParentConsole(message: string) { - super.log(message); - } - - _log(type: LogType, message: string) { - clearLine(this._stdout); - this._logToParentConsole( - this._formatBuffer(type, ' '.repeat(this._groupDepth) + message), - ); - } - - assert(...args: Array) { - try { - assert(...args); - } catch (error) { - this._log('assert', error.toString()); - } - } - - count(label: string = 'default') { - if (!this._counters[label]) { - this._counters[label] = 0; - } - - this._log('count', format(`${label}: ${++this._counters[label]}`)); - } - - countReset(label: string = 'default') { - this._counters[label] = 0; - } - - debug(...args: Array) { - this._log('debug', format(...args)); - } - - dir(...args: Array) { - this._log('dir', format(...args)); - } - - dirxml(...args: Array) { - this._log('dirxml', format(...args)); - } - - error(...args: Array) { - this._log('error', format(...args)); - } - - group(...args: Array) { - this._groupDepth++; - - if (args.length > 0) { - this._log('group', chalk.bold(format(...args))); - } - } - - groupCollapsed(...args: Array) { - this._groupDepth++; - - if (args.length > 0) { - this._log('groupCollapsed', chalk.bold(format(...args))); - } - } - - groupEnd() { - if (this._groupDepth > 0) { - this._groupDepth--; - } - } - - info(...args: Array) { - this._log('info', format(...args)); - } - - log(...args: Array) { - this._log('log', format(...args)); - } - - time(label: string = 'default') { - if (this._timers[label]) { - return; - } - - this._timers[label] = new Date(); - } - - timeEnd(label: string = 'default') { - const startTime = this._timers[label]; - - if (startTime) { - const endTime = new Date(); - const time = endTime - startTime; - this._log('time', format(`${label}: ${time}ms`)); - delete this._timers[label]; - } - } - - warn(...args: Array) { - this._log('warn', format(...args)); - } - - getBuffer() { - return null; - } -} diff --git a/packages/jest-util/src/CustomConsole.ts b/packages/jest-util/src/CustomConsole.ts new file mode 100644 index 000000000000..a2a3fb9a8950 --- /dev/null +++ b/packages/jest-util/src/CustomConsole.ts @@ -0,0 +1,143 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import assert from 'assert'; +import {format} from 'util'; +import {Console} from 'console'; +import chalk from 'chalk'; +import {Console as ConsoleType} from '@jest/types'; +import clearLine from './clearLine'; + +type Formatter = ( + type: ConsoleType.LogType, + message: ConsoleType.LogMessage, +) => string; + +export default class CustomConsole extends Console { + private _stdout: NodeJS.WritableStream; + private _formatBuffer: Formatter; + private _counters: ConsoleType.LogCounters; + private _timers: ConsoleType.LogTimers; + private _groupDepth: number; + + constructor( + stdout: NodeJS.WritableStream, + stderr: NodeJS.WritableStream, + formatBuffer: Formatter = (_type, message) => message, + ) { + super(stdout, stderr); + this._stdout = stdout; + this._formatBuffer = formatBuffer; + this._counters = {}; + this._timers = {}; + this._groupDepth = 0; + } + + private _logToParentConsole(message: string) { + super.log(message); + } + + private _log(type: ConsoleType.LogType, message: string) { + clearLine(this._stdout); + this._logToParentConsole( + this._formatBuffer(type, ' '.repeat(this._groupDepth) + message), + ); + } + + assert(value: any, message?: string | Error) { + try { + assert(value, message); + } catch (error) { + this._log('assert', error.toString()); + } + } + + count(label: string = 'default') { + if (!this._counters[label]) { + this._counters[label] = 0; + } + + this._log('count', format(`${label}: ${++this._counters[label]}`)); + } + + countReset(label: string = 'default') { + this._counters[label] = 0; + } + + debug(firstArg: any, ...args: Array) { + this._log('debug', format(firstArg, ...args)); + } + + dir(firstArg: any, ...args: Array) { + this._log('dir', format(firstArg, ...args)); + } + + dirxml(firstArg: any, ...args: Array) { + this._log('dirxml', format(firstArg, ...args)); + } + + error(firstArg: any, ...args: Array) { + this._log('error', format(firstArg, ...args)); + } + + group(title?: string, ...args: Array) { + this._groupDepth++; + + if (title || args.length > 0) { + this._log('group', chalk.bold(format(title, ...args))); + } + } + + groupCollapsed(title?: string, ...args: Array) { + this._groupDepth++; + + if (title || args.length > 0) { + this._log('groupCollapsed', chalk.bold(format(title, ...args))); + } + } + + groupEnd() { + if (this._groupDepth > 0) { + this._groupDepth--; + } + } + + info(firstArg: any, ...args: Array) { + this._log('info', format(firstArg, ...args)); + } + + log(firstArg: any, ...args: Array) { + this._log('log', format(firstArg, ...args)); + } + + time(label: string = 'default') { + if (this._timers[label]) { + return; + } + + this._timers[label] = new Date(); + } + + timeEnd(label: string = 'default') { + const startTime = this._timers[label]; + + if (startTime) { + const endTime = new Date().getTime(); + const time = endTime - startTime.getTime(); + this._log('time', format(`${label}: ${time}ms`)); + delete this._timers[label]; + } + } + + warn(firstArg: any, ...args: Array) { + this._log('warn', format(firstArg, ...args)); + } + + getBuffer() { + return null; + } +} diff --git a/packages/jest-util/src/ErrorWithStack.js b/packages/jest-util/src/ErrorWithStack.ts similarity index 85% rename from packages/jest-util/src/ErrorWithStack.js rename to packages/jest-util/src/ErrorWithStack.ts index 73015ce15c6f..871f44498c22 100644 --- a/packages/jest-util/src/ErrorWithStack.js +++ b/packages/jest-util/src/ErrorWithStack.ts @@ -3,12 +3,10 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ export default class ErrorWithStack extends Error { - constructor(message: ?string, callsite: Function) { + constructor(message: string | undefined, callsite: Function) { super(message); if (Error.captureStackTrace) { Error.captureStackTrace(this, callsite); diff --git a/packages/jest-util/src/FakeTimers.js b/packages/jest-util/src/FakeTimers.ts similarity index 83% rename from packages/jest-util/src/FakeTimers.js rename to packages/jest-util/src/FakeTimers.ts index c00a3c30da25..d8cfac38d266 100644 --- a/packages/jest-util/src/FakeTimers.js +++ b/packages/jest-util/src/FakeTimers.ts @@ -3,15 +3,14 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {ProjectConfig} from 'types/Config'; -import type {Global} from 'types/Global'; -import type {ModuleMocker} from 'types/Mock'; +// not yet migrated to TS +// import {ModuleMocker} from 'jest-mock'; + +type ModuleMocker = any; -import {formatStackTrace} from 'jest-message-util'; +import {formatStackTrace, StackTraceConfig} from 'jest-message-util'; import setGlobal from './setGlobal'; /** @@ -23,57 +22,50 @@ type Callback = (...args: any) => void; type TimerID = string; -type Tick = {| - uuid: string, - callback: Callback, -|}; +type Tick = { + uuid: string; + callback: Callback; +}; -type Timer = {| - type: string, - callback: Callback, - expiry: number, - interval: ?number, -|}; +type Timer = { + type: string; + callback: Callback; + expiry: number; + interval?: number; +}; type TimerAPI = { - clearImmediate(timeoutId?: number): void, - clearInterval(intervalId?: number): void, - clearTimeout(timeoutId?: number): void, - nextTick: (callback: Callback) => void, - - /** - * The additional arguments in the following methods are passed to the - * callback and thus we don't know their types ahead of time as they can be - * anything, which is why we are disabling the flowtype/no-weak-types rule - * here. - */ - - setImmediate(callback: Callback, ms?: number, ...args: Array): number, - setInterval(callback: Callback, ms?: number, ...args: Array): number, - setTimeout(callback: Callback, ms?: number, ...args: Array): number, + clearImmediate: typeof global.clearImmediate; + clearInterval: typeof global.clearInterval; + clearTimeout: typeof global.clearTimeout; + nextTick: typeof process.nextTick; + + setImmediate: typeof global.setImmediate; + setInterval: typeof global.setInterval; + setTimeout: typeof global.setTimeout; }; -type TimerConfig = {| - idToRef: (id: number) => Ref, - refToId: (ref: Ref) => ?number, -|}; +type TimerConfig = { + idToRef: (id: number) => Ref; + refToId: (ref: Ref) => number | void; +}; const MS_IN_A_YEAR = 31536000000; export default class FakeTimers { - _cancelledImmediates: {[key: TimerID]: boolean}; - _cancelledTicks: {[key: TimerID]: boolean}; - _config: ProjectConfig; - _disposed: boolean; - _fakeTimerAPIs: TimerAPI; - _global: Global; - _immediates: Array; + _cancelledImmediates!: {[key: string]: boolean}; + _cancelledTicks!: {[key: string]: boolean}; + _config: StackTraceConfig; + _disposed?: boolean; + _fakeTimerAPIs!: TimerAPI; + _global: NodeJS.Global; + _immediates!: Array; _maxLoops: number; _moduleMocker: ModuleMocker; - _now: number; - _ticks: Array; + _now!: number; + _ticks!: Array; _timerAPIs: TimerAPI; - _timers: {[key: TimerID]: Timer}; + _timers!: {[key: string]: Timer}; _uuidCounter: number; _timerConfig: TimerConfig; @@ -84,11 +76,11 @@ export default class FakeTimers { config, maxLoops, }: { - global: Global, - moduleMocker: ModuleMocker, - timerConfig: TimerConfig, - config: ProjectConfig, - maxLoops?: number, + global: NodeJS.Global; + moduleMocker: ModuleMocker; + timerConfig: TimerConfig; + config: StackTraceConfig; + maxLoops?: number; }) { this._global = global; this._timerConfig = timerConfig; @@ -355,7 +347,7 @@ export default class FakeTimers { `default configuration change in Jest 15.\n\n` + `Release Blog Post: https://jestjs.io/blog/2016/09/01/jest-15.html\n` + `Stack Trace:\n` + - formatStackTrace(new Error().stack, this._config, { + formatStackTrace(new Error().stack!, this._config, { noStackTrace: false, }), ); @@ -363,7 +355,8 @@ export default class FakeTimers { } _createMocks() { - const fn = impl => this._moduleMocker.fn().mockImplementation(impl); + const fn = (impl: Function) => + this._moduleMocker.fn().mockImplementation(impl); this._fakeTimerAPIs = { clearImmediate: fn(this._fakeClearImmediate.bind(this)), @@ -388,16 +381,11 @@ export default class FakeTimers { this._cancelledImmediates[uuid] = true; } - _fakeNextTick(callback: Callback) { + _fakeNextTick(callback: Callback, ...args: Array) { if (this._disposed) { return; } - const args = []; - for (let ii = 1, ll = arguments.length; ii < ll; ii++) { - args.push(arguments[ii]); - } - const uuid = String(this._uuidCounter++); this._ticks.push({ @@ -415,16 +403,11 @@ export default class FakeTimers { }); } - _fakeSetImmediate(callback: Callback) { + _fakeSetImmediate(callback: Callback, ...args: Array) { if (this._disposed) { return null; } - const args = []; - for (let ii = 1, ll = arguments.length; ii < ll; ii++) { - args.push(arguments[ii]); - } - const uuid = this._uuidCounter++; this._immediates.push({ @@ -444,7 +427,11 @@ export default class FakeTimers { return uuid; } - _fakeSetInterval(callback: Callback, intervalDelay?: number) { + _fakeSetInterval( + callback: Callback, + intervalDelay?: number, + ...args: Array + ) { if (this._disposed) { return null; } @@ -453,11 +440,6 @@ export default class FakeTimers { intervalDelay = 0; } - const args = []; - for (let ii = 2, ll = arguments.length; ii < ll; ii++) { - args.push(arguments[ii]); - } - const uuid = this._uuidCounter++; this._timers[String(uuid)] = { @@ -470,7 +452,7 @@ export default class FakeTimers { return this._timerConfig.idToRef(uuid); } - _fakeSetTimeout(callback: Callback, delay?: number) { + _fakeSetTimeout(callback: Callback, delay?: number, ...args: Array) { if (this._disposed) { return null; } @@ -478,17 +460,12 @@ export default class FakeTimers { // eslint-disable-next-line no-bitwise delay = Number(delay) | 0; - const args = []; - for (let ii = 2, ll = arguments.length; ii < ll; ii++) { - args.push(arguments[ii]); - } - const uuid = this._uuidCounter++; this._timers[String(uuid)] = { callback: () => callback.apply(null, args), expiry: this._now + delay, - interval: null, + interval: undefined, type: 'timeout', }; @@ -526,7 +503,7 @@ export default class FakeTimers { break; case 'interval': - timer.expiry = this._now + timer.interval; + timer.expiry = this._now + (timer.interval || 0); timer.callback(); break; diff --git a/packages/jest-util/src/NullConsole.js b/packages/jest-util/src/NullConsole.ts similarity index 97% rename from packages/jest-util/src/NullConsole.js rename to packages/jest-util/src/NullConsole.ts index 7c073abd2948..7f9f59ebad78 100644 --- a/packages/jest-util/src/NullConsole.js +++ b/packages/jest-util/src/NullConsole.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import CustomConsole from './CustomConsole'; diff --git a/packages/jest-util/src/__tests__/__snapshots__/fakeTimers.test.js.snap b/packages/jest-util/src/__tests__/__snapshots__/fakeTimers.test.ts.snap similarity index 100% rename from packages/jest-util/src/__tests__/__snapshots__/fakeTimers.test.js.snap rename to packages/jest-util/src/__tests__/__snapshots__/fakeTimers.test.ts.snap diff --git a/packages/jest-util/src/__tests__/bufferedConsole.test.js b/packages/jest-util/src/__tests__/bufferedConsole.test.ts similarity index 99% rename from packages/jest-util/src/__tests__/bufferedConsole.test.js rename to packages/jest-util/src/__tests__/bufferedConsole.test.ts index 1e8c7c3b1680..dbd3ce39d2eb 100644 --- a/packages/jest-util/src/__tests__/bufferedConsole.test.js +++ b/packages/jest-util/src/__tests__/bufferedConsole.test.ts @@ -3,15 +3,13 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import chalk from 'chalk'; import BufferedConsole from '../BufferedConsole'; describe('CustomConsole', () => { - let _console; + let _console: BufferedConsole; const stdout = () => _console .getBuffer() diff --git a/packages/jest-util/src/__tests__/console.test.js b/packages/jest-util/src/__tests__/console.test.ts similarity index 99% rename from packages/jest-util/src/__tests__/console.test.js rename to packages/jest-util/src/__tests__/console.test.ts index da8fdea7fddd..4b994fc6e888 100644 --- a/packages/jest-util/src/__tests__/console.test.js +++ b/packages/jest-util/src/__tests__/console.test.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import chalk from 'chalk'; diff --git a/packages/jest-util/src/__tests__/createProcessObject.test.js b/packages/jest-util/src/__tests__/createProcessObject.test.ts similarity index 98% rename from packages/jest-util/src/__tests__/createProcessObject.test.js rename to packages/jest-util/src/__tests__/createProcessObject.test.ts index b64cdc9796ed..4eca00c977a2 100644 --- a/packages/jest-util/src/__tests__/createProcessObject.test.js +++ b/packages/jest-util/src/__tests__/createProcessObject.test.ts @@ -18,7 +18,9 @@ it('creates a process object that looks like the original one', () => { // "_events" property is checked to ensure event emitter properties are // properly copied. ['argv', 'env', '_events'].forEach(key => { + // @ts-ignore expect(fakeProcess[key]).toEqual(process[key]); + // @ts-ignore expect(fakeProcess[key]).not.toBe(process[key]); }); @@ -36,6 +38,7 @@ it('checks that process.env works as expected on Linux platforms', () => { // Existing properties inside process.env are copied to the fake environment. process.env.PROP_STRING = 'foo'; + // @ts-ignore process.env.PROP_NUMBER = 3; process.env.PROP_UNDEFINED = undefined; diff --git a/packages/jest-util/src/__tests__/deepCyclicCopy.test.js b/packages/jest-util/src/__tests__/deepCyclicCopy.test.ts similarity index 94% rename from packages/jest-util/src/__tests__/deepCyclicCopy.test.js rename to packages/jest-util/src/__tests__/deepCyclicCopy.test.ts index 43b4645211a2..41bb93570f17 100644 --- a/packages/jest-util/src/__tests__/deepCyclicCopy.test.js +++ b/packages/jest-util/src/__tests__/deepCyclicCopy.test.ts @@ -23,6 +23,7 @@ it('returns the same value for primitive or function values', () => { it('does not execute getters/setters, but copies them', () => { const fn = jest.fn(); const obj = { + // @ts-ignore get foo() { fn(); }, @@ -48,7 +49,7 @@ it('copies arrays as array objects', () => { }); it('handles cyclic dependencies', () => { - const cyclic = {a: 42, subcycle: {}}; + const cyclic: any = {a: 42, subcycle: {}}; cyclic.subcycle.baz = cyclic; cyclic.bar = cyclic; @@ -83,9 +84,13 @@ it('uses the blacklist to avoid copying properties on the first level', () => { }); it('does not keep the prototype by default when top level is object', () => { + // @ts-ignore const sourceObject = new function() {}(); + // @ts-ignore sourceObject.nestedObject = new function() {}(); + // @ts-ignore sourceObject.nestedArray = new function() { + // @ts-ignore this.length = 0; }(); @@ -119,7 +124,9 @@ it('does not keep the prototype by default when top level is object', () => { it('does not keep the prototype by default when top level is array', () => { const spy = jest.spyOn(Array, 'isArray').mockImplementation(() => true); + // @ts-ignore const sourceArray = new function() { + // @ts-ignore this.length = 0; }(); @@ -135,7 +142,9 @@ it('does not keep the prototype by default when top level is array', () => { it('does not keep the prototype of arrays when keepPrototype = false', () => { const spy = jest.spyOn(Array, 'isArray').mockImplementation(() => true); + // @ts-ignore const sourceArray = new function() { + // @ts-ignore this.length = 0; }(); @@ -151,7 +160,9 @@ it('does not keep the prototype of arrays when keepPrototype = false', () => { it('keeps the prototype of arrays when keepPrototype = true', () => { const spy = jest.spyOn(Array, 'isArray').mockImplementation(() => true); + // @ts-ignore const sourceArray = new function() { + // @ts-ignore this.length = 0; }(); @@ -162,9 +173,13 @@ it('keeps the prototype of arrays when keepPrototype = true', () => { }); it('does not keep the prototype for objects when keepPrototype = false', () => { + // @ts-ignore const sourceobject = new function() {}(); + // @ts-ignore sourceobject.nestedObject = new function() {}(); + // @ts-ignore sourceobject.nestedArray = new function() { + // @ts-ignore this.length = 0; }(); @@ -195,9 +210,13 @@ it('does not keep the prototype for objects when keepPrototype = false', () => { }); it('keeps the prototype for objects when keepPrototype = true', () => { + // @ts-ignore const sourceObject = new function() {}(); + // @ts-ignore sourceObject.nestedObject = new function() {}(); + // @ts-ignore sourceObject.nestedArray = new function() { + // @ts-ignore this.length = 0; }(); diff --git a/packages/jest-util/src/__tests__/errorWithStack.test.js b/packages/jest-util/src/__tests__/errorWithStack.test.ts similarity index 98% rename from packages/jest-util/src/__tests__/errorWithStack.test.js rename to packages/jest-util/src/__tests__/errorWithStack.test.ts index 9c86c46f4003..e2c79e4de9eb 100644 --- a/packages/jest-util/src/__tests__/errorWithStack.test.js +++ b/packages/jest-util/src/__tests__/errorWithStack.test.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import ErrorWithStack from '../ErrorWithStack'; diff --git a/packages/jest-util/src/__tests__/fakeTimers.test.js b/packages/jest-util/src/__tests__/fakeTimers.test.ts similarity index 73% rename from packages/jest-util/src/__tests__/fakeTimers.test.js rename to packages/jest-util/src/__tests__/fakeTimers.test.ts index c39fb0c2a4e4..3a14fed27b93 100644 --- a/packages/jest-util/src/__tests__/fakeTimers.test.js +++ b/packages/jest-util/src/__tests__/fakeTimers.test.ts @@ -3,76 +3,109 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * */ -'use strict'; +import vm from 'vm'; +// @ts-ignore: not yet migrated +import mock, {ModuleMocker} from 'jest-mock'; +import FakeTimers from '../FakeTimers'; + +const timerConfig = { + idToRef: (id: number) => id, + refToId: (ref: number) => ref, +}; -const vm = require('vm'); +const config = { + rootDir: '/', + testMatch: [], +}; describe('FakeTimers', () => { - let FakeTimers, moduleMocker, timerConfig; + let moduleMocker: ModuleMocker; beforeEach(() => { - FakeTimers = require('../FakeTimers').default; - const mock = require('jest-mock'); const global = vm.runInNewContext('this'); moduleMocker = new mock.ModuleMocker(global); - - timerConfig = { - idToRef: (id: number) => id, - refToId: (ref: number) => ref, - }; }); describe('construction', () => { it('installs setTimeout mock', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(global.setTimeout).not.toBe(undefined); }); it('installs clearTimeout mock', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(global.clearTimeout).not.toBe(undefined); }); it('installs setInterval mock', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(global.setInterval).not.toBe(undefined); }); it('installs clearInterval mock', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(global.clearInterval).not.toBe(undefined); }); it('mocks process.nextTick if it exists on global', () => { const origNextTick = () => {}; - const global = { + const global = ({ process: { nextTick: origNextTick, }, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(global.process.nextTick).not.toBe(origNextTick); }); it('mocks setImmediate if it exists on global', () => { const origSetImmediate = () => {}; - const global = { + const global = ({ process, setImmediate: origSetImmediate, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(global.setImmediate).not.toBe(origSetImmediate); }); @@ -80,12 +113,17 @@ describe('FakeTimers', () => { it('mocks clearImmediate if setImmediate is on global', () => { const origSetImmediate = () => {}; const origClearImmediate = () => {}; - const global = { + const global = ({ clearImmediate: origClearImmediate, process, setImmediate: origSetImmediate, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(global.clearImmediate).not.toBe(origClearImmediate); }); @@ -93,16 +131,21 @@ describe('FakeTimers', () => { describe('runAllTicks', () => { it('runs all ticks, in order', () => { - const global = { + const global = ({ process: { nextTick: () => {}, }, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); - const runOrder = []; + const runOrder: Array = []; const mock1 = jest.fn(() => runOrder.push('mock1')); const mock2 = jest.fn(() => runOrder.push('mock2')); @@ -121,13 +164,18 @@ describe('FakeTimers', () => { it('does nothing when no ticks have been scheduled', () => { const nextTick = jest.fn(); - const global = { + const global = ({ process: { nextTick, }, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); timers.runAllTicks(); @@ -135,13 +183,18 @@ describe('FakeTimers', () => { }); it('only runs a scheduled callback once', () => { - const global = { + const global = ({ process: { nextTick: () => {}, }, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -158,13 +211,18 @@ describe('FakeTimers', () => { it('cancels a callback even from native nextTick', () => { const nativeNextTick = jest.fn(); - const global = { + const global = ({ process: { nextTick: nativeNextTick, }, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -182,12 +240,17 @@ describe('FakeTimers', () => { it('cancels a callback even from native setImmediate', () => { const nativeSetImmediate = jest.fn(); - const global = { + const global = ({ process, setImmediate: nativeSetImmediate, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -204,13 +267,18 @@ describe('FakeTimers', () => { it('doesnt run a tick callback if native nextTick already did', () => { const nativeNextTick = jest.fn(); - const global = { + const global = ({ process: { nextTick: nativeNextTick, }, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -228,12 +296,17 @@ describe('FakeTimers', () => { it('doesnt run immediate if native setImmediate already did', () => { const nativeSetImmediate = jest.fn(); - const global = { + const global = ({ process, setImmediate: nativeSetImmediate, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -251,12 +324,17 @@ describe('FakeTimers', () => { it('native doesnt run immediate if fake already did', () => { const nativeSetImmediate = jest.fn(); - const global = { + const global = ({ process, setImmediate: nativeSetImmediate, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -273,13 +351,14 @@ describe('FakeTimers', () => { }); it('throws before allowing infinite recursion', () => { - const global = { + const global = ({ process: { nextTick: () => {}, }, - }; + } as unknown) as NodeJS.Global; const timers = new FakeTimers({ + config, global, maxLoops: 100, moduleMocker, @@ -305,11 +384,16 @@ describe('FakeTimers', () => { describe('runAllTimers', () => { it('runs all timers in order', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); - const runOrder = []; + const runOrder: Array = []; const mock1 = jest.fn(() => runOrder.push('mock1')); const mock2 = jest.fn(() => runOrder.push('mock2')); const mock3 = jest.fn(() => runOrder.push('mock3')); @@ -339,11 +423,13 @@ describe('FakeTimers', () => { }); it('warns when trying to advance timers while real timers are used', () => { - const consoleWarn = console.warn; - console.warn = jest.fn(); + const consoleWarn = jest + .spyOn(console, 'warn') + .mockImplementation(() => {}); const timers = new FakeTimers({ config: { rootDir: __dirname, + testMatch: [], }, global, moduleMocker, @@ -351,26 +437,36 @@ describe('FakeTimers', () => { }); timers.runAllTimers(); expect( - console.warn.mock.calls[0][0].split('\nStack Trace')[0], + consoleWarn.mock.calls[0][0].split('\nStack Trace')[0], ).toMatchSnapshot(); - console.warn = consoleWarn; + consoleWarn.mockRestore(); }); it('does nothing when no timers have been scheduled', () => { const nativeSetTimeout = jest.fn(); - const global = { + const global = ({ process, setTimeout: nativeSetTimeout, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); timers.runAllTimers(); }); it('only runs a setTimeout callback once (ever)', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const fn = jest.fn(); @@ -385,8 +481,13 @@ describe('FakeTimers', () => { }); it('runs callbacks with arguments after the interval', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const fn = jest.fn(); @@ -400,12 +501,17 @@ describe('FakeTimers', () => { it('doesnt pass the callback to native setTimeout', () => { const nativeSetTimeout = jest.fn(); - const global = { + const global = ({ process, setTimeout: nativeSetTimeout, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -417,8 +523,9 @@ describe('FakeTimers', () => { }); it('throws before allowing infinite recursion', () => { - const global = {process}; + const global = ({process} as unknown) as NodeJS.Global; const timers = new FakeTimers({ + config, global, maxLoops: 100, moduleMocker, @@ -441,8 +548,13 @@ describe('FakeTimers', () => { }); it('also clears ticks', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const fn = jest.fn(); @@ -458,11 +570,16 @@ describe('FakeTimers', () => { describe('advanceTimersByTime', () => { it('runs timers in order', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); - const runOrder = []; + const runOrder: Array = []; const mock1 = jest.fn(() => runOrder.push('mock1')); const mock2 = jest.fn(() => runOrder.push('mock2')); const mock3 = jest.fn(() => runOrder.push('mock3')); @@ -497,16 +614,22 @@ describe('FakeTimers', () => { }); it('does nothing when no timers have been scheduled', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); timers.advanceTimersByTime(100); }); it('throws before allowing infinite recursion', () => { - const global = {process}; + const global = ({process} as unknown) as NodeJS.Global; const timers = new FakeTimers({ + config, global, maxLoops: 100, moduleMocker, @@ -531,8 +654,13 @@ describe('FakeTimers', () => { describe('reset', () => { it('resets all pending setTimeouts', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -544,8 +672,13 @@ describe('FakeTimers', () => { }); it('resets all pending setIntervals', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -557,13 +690,18 @@ describe('FakeTimers', () => { }); it('resets all pending ticks callbacks & immediates', () => { - const global = { + const global = ({ process: { nextTick: () => {}, }, setImmediate: () => {}, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -577,8 +715,13 @@ describe('FakeTimers', () => { }); it('resets current advanceTimersByTime time cursor', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const mock1 = jest.fn(); @@ -597,15 +740,20 @@ describe('FakeTimers', () => { it('runs all timers in order', () => { const nativeSetImmediate = jest.fn(); - const global = { + const global = ({ process, setImmediate: nativeSetImmediate, - }; + } as unknown) as NodeJS.Global; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); - const runOrder = []; + const runOrder: Array = []; global.setTimeout(function cb() { runOrder.push('mock1'); @@ -649,8 +797,13 @@ describe('FakeTimers', () => { }); it('does not run timers that were cleared in another timer', () => { - const global = {process}; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const global = ({process} as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); const fn = jest.fn(); @@ -671,40 +824,45 @@ describe('FakeTimers', () => { const nativeSetInterval = jest.fn(); const nativeSetTimeout = jest.fn(); - const global = { + const global = ({ clearInterval: nativeClearInterval, clearTimeout: nativeClearTimeout, process, setInterval: nativeSetInterval, setTimeout: nativeSetTimeout, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); // clearInterval() timers.runWithRealTimers(() => { - global.clearInterval(); + (global as any).clearInterval(); }); expect(nativeClearInterval).toHaveBeenCalledTimes(1); expect(global.clearInterval).toHaveBeenCalledTimes(0); // clearTimeout() timers.runWithRealTimers(() => { - global.clearTimeout(); + (global as any).clearTimeout(); }); expect(nativeClearTimeout).toHaveBeenCalledTimes(1); expect(global.clearTimeout).toHaveBeenCalledTimes(0); // setInterval() timers.runWithRealTimers(() => { - global.setInterval(); + (global as any).setInterval(); }); expect(nativeSetInterval).toHaveBeenCalledTimes(1); expect(global.setInterval).toHaveBeenCalledTimes(0); // setTimeout() timers.runWithRealTimers(() => { - global.setTimeout(); + (global as any).setTimeout(); }); expect(nativeSetTimeout).toHaveBeenCalledTimes(1); expect(global.setTimeout).toHaveBeenCalledTimes(0); @@ -716,80 +874,90 @@ describe('FakeTimers', () => { const nativeSetInterval = jest.fn(); const nativeSetTimeout = jest.fn(); - const global = { + const global = ({ clearInterval: nativeClearInterval, clearTimeout: nativeClearTimeout, process, setInterval: nativeSetInterval, setTimeout: nativeSetTimeout, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); // clearInterval() timers.runWithRealTimers(() => { - global.clearInterval(); + (global as any).clearInterval(); }); expect(nativeClearInterval).toHaveBeenCalledTimes(1); expect(global.clearInterval).toHaveBeenCalledTimes(0); - global.clearInterval(); + (global as any).clearInterval(); expect(nativeClearInterval).toHaveBeenCalledTimes(1); expect(global.clearInterval).toHaveBeenCalledTimes(1); // clearTimeout() timers.runWithRealTimers(() => { - global.clearTimeout(); + (global as any).clearTimeout(); }); expect(nativeClearTimeout).toHaveBeenCalledTimes(1); expect(global.clearTimeout).toHaveBeenCalledTimes(0); - global.clearTimeout(); + (global as any).clearTimeout(); expect(nativeClearTimeout).toHaveBeenCalledTimes(1); expect(global.clearTimeout).toHaveBeenCalledTimes(1); // setInterval() timers.runWithRealTimers(() => { - global.setInterval(); + (global as any).setInterval(); }); expect(nativeSetInterval).toHaveBeenCalledTimes(1); expect(global.setInterval).toHaveBeenCalledTimes(0); - global.setInterval(); + (global as any).setInterval(); expect(nativeSetInterval).toHaveBeenCalledTimes(1); expect(global.setInterval).toHaveBeenCalledTimes(1); // setTimeout() timers.runWithRealTimers(() => { - global.setTimeout(); + (global as any).setTimeout(); }); expect(nativeSetTimeout).toHaveBeenCalledTimes(1); expect(global.setTimeout).toHaveBeenCalledTimes(0); - global.setTimeout(); + (global as any).setTimeout(); expect(nativeSetTimeout).toHaveBeenCalledTimes(1); expect(global.setTimeout).toHaveBeenCalledTimes(1); }); it('resets mock timer functions even if callback throws', () => { const nativeSetTimeout = jest.fn(); - const global = { + const global = ({ process, setTimeout: nativeSetTimeout, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); expect(() => { timers.runWithRealTimers(() => { - global.setTimeout(); + (global as any).setTimeout(); throw new Error('test'); }); }).toThrow(new Error('test')); expect(nativeSetTimeout).toHaveBeenCalledTimes(1); expect(global.setTimeout).toHaveBeenCalledTimes(0); - global.setTimeout(); + (global as any).setTimeout(); expect(nativeSetTimeout).toHaveBeenCalledTimes(1); expect(global.setTimeout).toHaveBeenCalledTimes(1); }); @@ -802,14 +970,19 @@ describe('FakeTimers', () => { const nativeClearTimeout = jest.fn(); const nativeClearInterval = jest.fn(); - const global = { + const global = ({ clearInterval: nativeClearInterval, clearTimeout: nativeClearTimeout, process, setInterval: nativeSetInterval, setTimeout: nativeSetTimeout, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); // Ensure that timers has overridden the native timer APIs @@ -830,10 +1003,15 @@ describe('FakeTimers', () => { it('resets native process.nextTick when present', () => { const nativeProcessNextTick = jest.fn(); - const global = { + const global = ({ process: {nextTick: nativeProcessNextTick}, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); // Ensure that timers has overridden the native timer APIs @@ -849,12 +1027,17 @@ describe('FakeTimers', () => { const nativeSetImmediate = jest.fn(); const nativeClearImmediate = jest.fn(); - const global = { + const global = ({ clearImmediate: nativeClearImmediate, process, setImmediate: nativeSetImmediate, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); // Ensure that timers has overridden the native timer APIs @@ -876,14 +1059,19 @@ describe('FakeTimers', () => { const nativeClearTimeout = jest.fn(); const nativeClearInterval = jest.fn(); - const global = { + const global = ({ clearInterval: nativeClearInterval, clearTimeout: nativeClearTimeout, process, setInterval: nativeSetInterval, setTimeout: nativeSetTimeout, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useRealTimers(); // Ensure that the real timers are installed at this point @@ -904,10 +1092,15 @@ describe('FakeTimers', () => { it('resets mock process.nextTick when present', () => { const nativeProcessNextTick = jest.fn(); - const global = { + const global = ({ process: {nextTick: nativeProcessNextTick}, - }; - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useRealTimers(); // Ensure that the real timers are installed at this point @@ -923,12 +1116,17 @@ describe('FakeTimers', () => { const nativeSetImmediate = jest.fn(); const nativeClearImmediate = jest.fn(); - const global = { + const global = ({ clearImmediate: nativeClearImmediate, process, setImmediate: nativeSetImmediate, - }; - const fakeTimers = new FakeTimers({global, moduleMocker, timerConfig}); + } as unknown) as NodeJS.Global; + const fakeTimers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); fakeTimers.useRealTimers(); // Ensure that the real timers are installed at this point @@ -945,7 +1143,12 @@ describe('FakeTimers', () => { describe('getTimerCount', () => { it('returns the correct count', () => { - const timers = new FakeTimers({global, moduleMocker, timerConfig}); + const timers = new FakeTimers({ + config, + global, + moduleMocker, + timerConfig, + }); timers.useFakeTimers(); diff --git a/packages/jest-util/src/__tests__/formatTestResults.test.js b/packages/jest-util/src/__tests__/formatTestResults.test.ts similarity index 88% rename from packages/jest-util/src/__tests__/formatTestResults.test.js rename to packages/jest-util/src/__tests__/formatTestResults.test.ts index 83f7987538de..09bd58b9a786 100644 --- a/packages/jest-util/src/__tests__/formatTestResults.test.js +++ b/packages/jest-util/src/__tests__/formatTestResults.test.ts @@ -3,11 +3,9 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * */ -'use strict'; - +import {TestResult} from '@jest/types'; import formatTestResults from '../formatTestResults'; describe('formatTestResults', () => { @@ -17,11 +15,12 @@ describe('formatTestResults', () => { title: 'returns true', }; - const results = { + const results: TestResult.AggregatedResult = { testResults: [ { numFailingTests: 0, perfStats: {end: 2, start: 1}, + // @ts-ignore testResults: [assertion], }, ], diff --git a/packages/jest-util/src/__tests__/getCallsite.test.js b/packages/jest-util/src/__tests__/getCallsite.test.ts similarity index 90% rename from packages/jest-util/src/__tests__/getCallsite.test.js rename to packages/jest-util/src/__tests__/getCallsite.test.ts index d73c7c80dfae..f375645d679d 100644 --- a/packages/jest-util/src/__tests__/getCallsite.test.js +++ b/packages/jest-util/src/__tests__/getCallsite.test.ts @@ -22,7 +22,7 @@ describe('getCallsite', () => { }); test('ignores errors when fs throws', () => { - fs.readFileSync.mockImplementation(() => { + (fs.readFileSync as jest.Mock).mockImplementation(() => { throw new Error('Mock error'); }); @@ -35,12 +35,13 @@ describe('getCallsite', () => { }); test('reads source map file to determine line and column', () => { - fs.readFileSync.mockImplementation(() => 'file data'); + (fs.readFileSync as jest.Mock).mockImplementation(() => 'file data'); const sourceMapColumn = 1; const sourceMapLine = 2; + // @ts-ignore SourceMap.SourceMapConsumer = class { - originalPositionFor(params) { + originalPositionFor(params: Object) { expect(params).toMatchObject({ column: expect.any(Number), line: expect.any(Number), diff --git a/packages/jest-util/src/__tests__/getFailedSnapshot.test.js b/packages/jest-util/src/__tests__/getFailedSnapshot.test.ts similarity index 95% rename from packages/jest-util/src/__tests__/getFailedSnapshot.test.js rename to packages/jest-util/src/__tests__/getFailedSnapshot.test.ts index 4afa658efe6e..d1dbcd19d10b 100644 --- a/packages/jest-util/src/__tests__/getFailedSnapshot.test.js +++ b/packages/jest-util/src/__tests__/getFailedSnapshot.test.ts @@ -20,6 +20,7 @@ test('return a list of path', () => { }, ], }; + // @ts-ignore expect(getFailedSnapshotTests(param)).toEqual([targetFilename]); }); @@ -33,6 +34,7 @@ test('handle missing snapshot object', () => { }, ], }; + // @ts-ignore expect(getFailedSnapshotTests(param)).toEqual([]); }); @@ -40,6 +42,7 @@ test('handle missing testResults object', () => { const param = { numFailedTests: 1, }; + // @ts-ignore expect(getFailedSnapshotTests(param)).toEqual([]); }); @@ -47,6 +50,7 @@ test('return empty if not failed tests', () => { const param = { numFailedTests: 0, }; + // @ts-ignore expect(getFailedSnapshotTests(param)).toEqual([]); }); @@ -63,5 +67,6 @@ test('return empty if not failed snapshot tests', () => { }, ], }; + // @ts-ignore expect(getFailedSnapshotTests(param)).toEqual([]); }); diff --git a/packages/jest-util/src/__tests__/installCommonGlobals.test.js b/packages/jest-util/src/__tests__/installCommonGlobals.test.ts similarity index 90% rename from packages/jest-util/src/__tests__/installCommonGlobals.test.js rename to packages/jest-util/src/__tests__/installCommonGlobals.test.ts index 2aa6c0b131e3..3dc16aa63536 100644 --- a/packages/jest-util/src/__tests__/installCommonGlobals.test.js +++ b/packages/jest-util/src/__tests__/installCommonGlobals.test.ts @@ -7,15 +7,16 @@ import vm from 'vm'; -let installCommonGlobals; -let fake; +let installCommonGlobals: any; +let fake: jest.Mock; -function getGlobal() { +function getGlobal(): NodeJS.Global { return vm.runInContext('this', vm.createContext()); } beforeEach(() => { fake = jest.fn(); + // @ts-ignore global.DTRACE_NET_SERVER_CONNECTION = fake; installCommonGlobals = require('../installCommonGlobals').default; diff --git a/packages/jest-util/src/__tests__/isInteractive.test.js b/packages/jest-util/src/__tests__/isInteractive.test.ts similarity index 90% rename from packages/jest-util/src/__tests__/isInteractive.test.js rename to packages/jest-util/src/__tests__/isInteractive.test.ts index 4a65cbc2f071..79201ed801b6 100644 --- a/packages/jest-util/src/__tests__/isInteractive.test.js +++ b/packages/jest-util/src/__tests__/isInteractive.test.ts @@ -1,7 +1,7 @@ // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. -let oldIsTTY; -let oldTERM; +let oldIsTTY: typeof process.stdout.isTTY; +let oldTERM: string | undefined; beforeEach(() => { oldIsTTY = process.stdout.isTTY; @@ -29,7 +29,7 @@ it('Returns false when running on a non-interactive environment', () => { // Test with is-ci being true and isTTY false jest.doMock('is-ci', () => true); - process.stdout.isTTY = false; + process.stdout.isTTY = undefined; process.env.TERM = 'xterm-256color'; isInteractive = require('../isInteractive').default; expect(isInteractive).toBe(expectedResult); @@ -37,7 +37,7 @@ it('Returns false when running on a non-interactive environment', () => { // Test with is-ci being false and isTTY false jest.resetModules(); jest.doMock('is-ci', () => false); - process.stdout.isTTY = false; + process.stdout.isTTY = undefined; process.env.TERM = 'xterm-256color'; isInteractive = require('../isInteractive').default; expect(isInteractive).toBe(expectedResult); @@ -53,7 +53,7 @@ it('Returns false when running on a non-interactive environment', () => { // Test with dumb terminal jest.resetModules(); jest.doMock('is-ci', () => false); - process.stdout.isTTY = false; + process.stdout.isTTY = undefined; process.env.TERM = 'dumb'; isInteractive = require('../isInteractive').default; expect(isInteractive).toBe(expectedResult); diff --git a/packages/jest-util/src/clearLine.js b/packages/jest-util/src/clearLine.ts similarity index 73% rename from packages/jest-util/src/clearLine.js rename to packages/jest-util/src/clearLine.ts index 65f0f77ac98a..c16f99c7c3fc 100644 --- a/packages/jest-util/src/clearLine.js +++ b/packages/jest-util/src/clearLine.ts @@ -3,12 +3,9 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -/* global stream$Writable */ -export default (stream: stream$Writable | tty$WriteStream) => { +export default (stream: NodeJS.WritableStream) => { if (process.stdout.isTTY) { stream.write('\x1b[999D\x1b[K'); } diff --git a/packages/jest-util/src/convertDescriptorToString.js b/packages/jest-util/src/convertDescriptorToString.ts similarity index 96% rename from packages/jest-util/src/convertDescriptorToString.js rename to packages/jest-util/src/convertDescriptorToString.ts index 447284c5d442..154178a23654 100644 --- a/packages/jest-util/src/convertDescriptorToString.js +++ b/packages/jest-util/src/convertDescriptorToString.ts @@ -3,14 +3,12 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ // See: https://github.com/facebook/jest/pull/5154 export default function convertDescriptorToString( descriptor: string | Function, -) { +): string { if ( typeof descriptor === 'string' || typeof descriptor === 'number' || @@ -31,7 +29,9 @@ export default function convertDescriptorToString( const stringified = descriptor.toString(); const typeDescriptorMatch = stringified.match(/class|function/); const indexOfNameSpace = + // @ts-ignore typeDescriptorMatch.index + typeDescriptorMatch[0].length; + // @ts-ignore const indexOfNameAfterSpace = stringified.search(/\(|\{/, indexOfNameSpace); const name = stringified.substring(indexOfNameSpace, indexOfNameAfterSpace); return name.trim(); diff --git a/packages/jest-util/src/createDirectory.js b/packages/jest-util/src/createDirectory.ts similarity index 76% rename from packages/jest-util/src/createDirectory.js rename to packages/jest-util/src/createDirectory.ts index 929eabb66cd0..7da0783bbb44 100644 --- a/packages/jest-util/src/createDirectory.js +++ b/packages/jest-util/src/createDirectory.ts @@ -3,15 +3,12 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {Path} from 'types/Config'; - import mkdirp from 'mkdirp'; +import {Config} from '@jest/types'; -export default function createDirectory(path: Path) { +export default function createDirectory(path: Config.Path) { try { mkdirp.sync(path, '777'); } catch (e) { diff --git a/packages/jest-util/src/createProcessObject.js b/packages/jest-util/src/createProcessObject.ts similarity index 92% rename from packages/jest-util/src/createProcessObject.js rename to packages/jest-util/src/createProcessObject.ts index b816d32a78ad..b5be6442fe8b 100644 --- a/packages/jest-util/src/createProcessObject.js +++ b/packages/jest-util/src/createProcessObject.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import deepCyclicCopy from './deepCyclicCopy'; @@ -16,17 +14,17 @@ const BLACKLIST = new Set(['env', 'mainModule', '_events']); // string; and third, it is case-insensitive in Windows. We use a proxy here to // mimic it (see https://nodejs.org/api/process.html#process_process_env). -function createProcessEnv() { +function createProcessEnv(): NodeJS.ProcessEnv { if (typeof Proxy === 'undefined') { return deepCyclicCopy(process.env); } const proto: Object = Object.getPrototypeOf(process.env); const real = Object.create(proto); - const lookup = {}; + const lookup: typeof process.env = {}; const proxy = new Proxy(real, { - deleteProperty(target, key) { + deleteProperty(_target, key) { for (const name in real) { if (real.hasOwnProperty(name)) { if (typeof key === 'string' && process.platform === 'win32') { @@ -46,7 +44,7 @@ function createProcessEnv() { return true; }, - get(target, key) { + get(_target, key) { if (typeof key === 'string' && process.platform === 'win32') { return lookup[key in proto ? key : key.toLowerCase()]; } else { @@ -54,7 +52,7 @@ function createProcessEnv() { } }, - set(target, key, value) { + set(_target, key, value) { const strValue = '' + value; if (typeof key === 'string') { diff --git a/packages/jest-util/src/deepCyclicCopy.js b/packages/jest-util/src/deepCyclicCopy.ts similarity index 72% rename from packages/jest-util/src/deepCyclicCopy.js rename to packages/jest-util/src/deepCyclicCopy.ts index 79a3674a91a7..0cecc4086b5c 100644 --- a/packages/jest-util/src/deepCyclicCopy.js +++ b/packages/jest-util/src/deepCyclicCopy.ts @@ -3,37 +3,40 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ const EMPTY = new Set(); -export type DeepCyclicCopyOptions = {| - blacklist: Set, - keepPrototype: boolean, -|}; +export type DeepCyclicCopyOptions = { + blacklist?: Set; + keepPrototype?: boolean; +}; -// $FlowFixMe: Node 6 does not have gOPDs, so we define a simple polyfill for it. +// Node 6 does not have gOPDs, so we define a simple polyfill for it. if (!Object.getOwnPropertyDescriptors) { - // $FlowFixMe: polyfill + // @ts-ignore: polyfill Object.getOwnPropertyDescriptors = obj => { - const list = {}; + const list: {[key: string]: PropertyDescriptor | undefined} = {}; Object.getOwnPropertyNames(obj) + // @ts-ignore: assignment with a Symbol is OK. .concat(Object.getOwnPropertySymbols(obj)) - // $FlowFixMe: assignment with a Symbol is OK. - .forEach(key => (list[key] = Object.getOwnPropertyDescriptor(obj, key))); + .forEach( + (key: string) => + (list[key] = Object.getOwnPropertyDescriptor(obj, key)), + ); return list; }; } -export default function deepCyclicCopy( - value: any, - options?: DeepCyclicCopyOptions = {blacklist: EMPTY, keepPrototype: false}, +Symbol.for('hello'); + +export default function deepCyclicCopy( + value: T, + options: DeepCyclicCopyOptions = {blacklist: EMPTY, keepPrototype: false}, cycles: WeakMap = new WeakMap(), -): any { +): T { if (typeof value !== 'object' || value === null) { return value; } else if (cycles.has(value)) { @@ -45,11 +48,11 @@ export default function deepCyclicCopy( } } -function deepCyclicCopyObject( - object: Object, +function deepCyclicCopyObject( + object: T, options: DeepCyclicCopyOptions, cycles: WeakMap, -): Object { +): T { const newObject = options.keepPrototype ? Object.create(Object.getPrototypeOf(object)) : {}; @@ -80,14 +83,13 @@ function deepCyclicCopyObject( return Object.defineProperties(newObject, descriptors); } -function deepCyclicCopyArray( - array: Array, +function deepCyclicCopyArray( + array: Array, options: DeepCyclicCopyOptions, cycles: WeakMap, -): Array { +): T { const newArray = options.keepPrototype - ? // $FlowFixMe: getPrototypeOf an array is OK. - new (Object.getPrototypeOf(array)).constructor(array.length) + ? new (Object.getPrototypeOf(array)).constructor(array.length) : []; const length = array.length; diff --git a/packages/jest-util/src/formatTestResults.js b/packages/jest-util/src/formatTestResults.ts similarity index 69% rename from packages/jest-util/src/formatTestResults.js rename to packages/jest-util/src/formatTestResults.ts index f6b64cc533b9..bda6c3750ef8 100644 --- a/packages/jest-util/src/formatTestResults.js +++ b/packages/jest-util/src/formatTestResults.ts @@ -3,28 +3,17 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type { - AggregatedResult, - AssertionResult, - CodeCoverageFormatter, - CodeCoverageReporter, - FormattedAssertionResult, - FormattedTestResult, - FormattedTestResults, - TestResult, -} from 'types/TestResult'; +import {TestResult} from '@jest/types'; const formatResult = ( - testResult: TestResult, - codeCoverageFormatter: CodeCoverageFormatter, - reporter: CodeCoverageReporter, -): FormattedTestResult => { + testResult: TestResult.TestResult, + codeCoverageFormatter: TestResult.CodeCoverageFormatter, + reporter: TestResult.CodeCoverageReporter, +): TestResult.FormattedTestResult => { const now = Date.now(); - const output: FormattedTestResult = { + const output: TestResult.FormattedTestResult = { assertionResults: [], coverage: {}, endTime: now, @@ -56,9 +45,9 @@ const formatResult = ( }; function formatTestAssertion( - assertion: AssertionResult, -): FormattedAssertionResult { - const result: FormattedAssertionResult = { + assertion: TestResult.AssertionResult, +): TestResult.FormattedAssertionResult { + const result: TestResult.FormattedAssertionResult = { ancestorTitles: assertion.ancestorTitles, failureMessages: null, fullName: assertion.fullName, @@ -73,17 +62,17 @@ function formatTestAssertion( } export default function formatTestResults( - results: AggregatedResult, - codeCoverageFormatter?: CodeCoverageFormatter, - reporter?: CodeCoverageReporter, -): FormattedTestResults { + results: TestResult.AggregatedResult, + codeCoverageFormatter?: TestResult.CodeCoverageFormatter | null, + reporter?: TestResult.CodeCoverageReporter, +): TestResult.FormattedTestResults { const formatter = codeCoverageFormatter || (coverage => coverage); const testResults = results.testResults.map(testResult => formatResult(testResult, formatter, reporter), ); - return Object.assign((Object.create(null): any), results, { + return Object.assign(Object.create(null) as any, results, { testResults, }); } diff --git a/packages/jest-util/src/getCallsite.js b/packages/jest-util/src/getCallsite.ts similarity index 72% rename from packages/jest-util/src/getCallsite.js rename to packages/jest-util/src/getCallsite.ts index 6ce4135c35f8..6a266c9823de 100644 --- a/packages/jest-util/src/getCallsite.js +++ b/packages/jest-util/src/getCallsite.ts @@ -3,27 +3,27 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {SourceMapRegistry} from 'types/SourceMaps'; - import fs from 'graceful-fs'; -import callsites from 'callsites'; +import callsites, {CallSite} from 'callsites'; import {SourceMapConsumer} from 'source-map'; +import {SourceMaps} from '@jest/types'; // Copied from https://github.com/rexxars/sourcemap-decorate-callsites/blob/5b9735a156964973a75dc62fd2c7f0c1975458e8/lib/index.js#L113-L158 -const addSourceMapConsumer = (callsite, consumer) => { +const addSourceMapConsumer = ( + callsite: CallSite, + consumer: SourceMapConsumer, +) => { const getLineNumber = callsite.getLineNumber; const getColumnNumber = callsite.getColumnNumber; - let position = null; + let position: ReturnType | null = null; function getPosition() { if (!position) { position = consumer.originalPositionFor({ - column: getColumnNumber.call(callsite), - line: getLineNumber.call(callsite), + column: getColumnNumber.call(callsite) || -1, + line: getLineNumber.call(callsite) || -1, }); } @@ -46,14 +46,18 @@ const addSourceMapConsumer = (callsite, consumer) => { }); }; -export default (level: number, sourceMaps: ?SourceMapRegistry) => { +export default ( + level: number, + sourceMaps?: SourceMaps.SourceMapRegistry | null, +) => { const levelAfterThisCall = level + 1; const stack = callsites()[levelAfterThisCall]; - const sourceMapFileName = sourceMaps && sourceMaps[stack.getFileName()]; + const sourceMapFileName = sourceMaps && sourceMaps[stack.getFileName() || '']; if (sourceMapFileName) { try { const sourceMap = fs.readFileSync(sourceMapFileName, 'utf8'); + // @ts-ignore: Not allowed to pass string addSourceMapConsumer(stack, new SourceMapConsumer(sourceMap)); } catch (e) { // ignore diff --git a/packages/jest-util/src/getConsoleOutput.js b/packages/jest-util/src/getConsoleOutput.ts similarity index 88% rename from packages/jest-util/src/getConsoleOutput.js rename to packages/jest-util/src/getConsoleOutput.ts index 1f72e74a90bf..1d3b9da964e2 100644 --- a/packages/jest-util/src/getConsoleOutput.js +++ b/packages/jest-util/src/getConsoleOutput.ts @@ -3,17 +3,18 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {ConsoleBuffer} from 'types/Console'; - import path from 'path'; import chalk from 'chalk'; import slash from 'slash'; +import {Console} from '@jest/types'; -export default (root: string, verbose: boolean, buffer: ConsoleBuffer) => { +export default ( + root: string, + verbose: boolean, + buffer: Console.ConsoleBuffer, +) => { const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; diff --git a/packages/jest-util/src/getFailedSnapshotTests.js b/packages/jest-util/src/getFailedSnapshotTests.ts similarity index 76% rename from packages/jest-util/src/getFailedSnapshotTests.js rename to packages/jest-util/src/getFailedSnapshotTests.ts index 99df31bf4500..192fa524a4b7 100644 --- a/packages/jest-util/src/getFailedSnapshotTests.js +++ b/packages/jest-util/src/getFailedSnapshotTests.ts @@ -3,14 +3,12 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {AggregatedResult} from 'types/TestResult'; +import {Config, TestResult} from '@jest/types'; -function getFailedSnapshotTests(testResults: AggregatedResult) { - const failedTestPaths = []; +function getFailedSnapshotTests(testResults: TestResult.AggregatedResult) { + const failedTestPaths: Array = []; if (testResults.numFailedTests === 0 || !testResults.testResults) { return failedTestPaths; } diff --git a/packages/jest-util/src/index.js b/packages/jest-util/src/index.ts similarity index 97% rename from packages/jest-util/src/index.js rename to packages/jest-util/src/index.ts index 04aed91a67bb..5ea75756a5c5 100644 --- a/packages/jest-util/src/index.js +++ b/packages/jest-util/src/index.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ import BufferedConsole from './BufferedConsole'; @@ -26,7 +24,7 @@ import convertDescriptorToString from './convertDescriptorToString'; import * as specialChars from './specialChars'; import replacePathSepForGlob from './replacePathSepForGlob'; -module.exports = { +export = { BufferedConsole, Console: CustomConsole, ErrorWithStack, diff --git a/packages/jest-util/src/installCommonGlobals.js b/packages/jest-util/src/installCommonGlobals.ts similarity index 84% rename from packages/jest-util/src/installCommonGlobals.js rename to packages/jest-util/src/installCommonGlobals.ts index 34e166379adf..d873ee4dff49 100644 --- a/packages/jest-util/src/installCommonGlobals.js +++ b/packages/jest-util/src/installCommonGlobals.ts @@ -3,23 +3,22 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {ConfigGlobals} from 'types/Config'; -import type {Global} from 'types/Global'; - import fs from 'fs'; +import {Config} from '@jest/types'; import createProcessObject from './createProcessObject'; import deepCyclicCopy from './deepCyclicCopy'; const DTRACE = Object.keys(global).filter(key => key.startsWith('DTRACE')); -export default function(globalObject: Global, globals: ConfigGlobals) { +export default function( + globalObject: NodeJS.Global, + globals: Config.ConfigGlobals, +): NodeJS.Global & Config.ConfigGlobals { globalObject.process = createProcessObject(); - const symbol = globalObject.Symbol; + const symbol = (globalObject.Symbol as unknown) as SymbolConstructor; // Keep a reference to some globals that Jest needs Object.defineProperties(globalObject, { [symbol.for('jest-native-promise')]: { @@ -56,7 +55,9 @@ export default function(globalObject: Global, globals: ConfigGlobals) { // Forward some APIs. DTRACE.forEach(dtrace => { - globalObject[dtrace] = function(...args) { + // @ts-ignore + globalObject[dtrace] = function(...args: Array) { + // @ts-ignore return global[dtrace].apply(this, args); }; }); diff --git a/packages/jest-util/src/isInteractive.js b/packages/jest-util/src/isInteractive.ts similarity index 56% rename from packages/jest-util/src/isInteractive.js rename to packages/jest-util/src/isInteractive.ts index 5597b9fdae9b..0dca9ee48f88 100644 --- a/packages/jest-util/src/isInteractive.js +++ b/packages/jest-util/src/isInteractive.ts @@ -2,4 +2,4 @@ import isCI from 'is-ci'; -export default process.stdout.isTTY && process.env.TERM !== 'dumb' && !isCI; +export default !!process.stdout.isTTY && process.env.TERM !== 'dumb' && !isCI; diff --git a/packages/jest-util/src/replacePathSepForGlob.js b/packages/jest-util/src/replacePathSepForGlob.ts similarity index 68% rename from packages/jest-util/src/replacePathSepForGlob.js rename to packages/jest-util/src/replacePathSepForGlob.ts index 1c4362b02d81..01b59b3b2950 100644 --- a/packages/jest-util/src/replacePathSepForGlob.js +++ b/packages/jest-util/src/replacePathSepForGlob.ts @@ -3,12 +3,10 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ -import type {Path, Glob} from 'types/Config'; +import {Config} from '@jest/types'; -export default function replacePathSepForGlob(path: Path): Glob { +export default function replacePathSepForGlob(path: Config.Path): Config.Glob { return path.replace(/\\(?![{}()+?.^$])/g, '/'); } diff --git a/packages/jest-util/src/setGlobal.ts b/packages/jest-util/src/setGlobal.ts new file mode 100644 index 000000000000..e7eb341f05a0 --- /dev/null +++ b/packages/jest-util/src/setGlobal.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +export default ( + globalToMutate: NodeJS.Global | Window, + key: string, + value: unknown, +) => { + // @ts-ignore: no index + globalToMutate[key] = value; +}; diff --git a/packages/jest-util/src/specialChars.js b/packages/jest-util/src/specialChars.ts similarity index 97% rename from packages/jest-util/src/specialChars.js rename to packages/jest-util/src/specialChars.ts index 878ce9130daa..0319f5850112 100644 --- a/packages/jest-util/src/specialChars.js +++ b/packages/jest-util/src/specialChars.ts @@ -3,8 +3,6 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - * - * @flow */ const isWindows = process.platform === 'win32'; diff --git a/packages/jest-util/tsconfig.json b/packages/jest-util/tsconfig.json new file mode 100644 index 000000000000..931ea0e1de53 --- /dev/null +++ b/packages/jest-util/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build" + }, + "references": [{"path": "../jest-types"}] +} diff --git a/yarn.lock b/yarn.lock index dffaf5b9881c..e28de1a42440 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1533,11 +1533,6 @@ dependencies: "@types/resolve" "*" -"@types/callsites@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/callsites/-/callsites-2.0.0.tgz#df0db68ea34053651caee9975294be902fd04751" - integrity sha512-kUvhIE1ZlV4dYEyFnZ2lJLXMEOc7eLN6ejolVBQm0boUCX2t6p0M2nx+20UkEtDMJYtRQffuhcwO1h/U029QAw== - "@types/camelcase@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@types/camelcase/-/camelcase-4.1.0.tgz#e054f7986f31658d49936261b5cd4588ef29d1ee" @@ -1694,9 +1689,9 @@ "@types/node" "*" "@types/node@*": - version "10.12.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" - integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== + version "10.12.24" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.24.tgz#b13564af612a22a20b5d95ca40f1bffb3af315cf" + integrity sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ== "@types/prompts@^1.2.0": version "1.2.0" @@ -1728,6 +1723,13 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/readable-stream@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.0.tgz#52e4b8bd8c2c222cadbe5366c833bc75fc975763" + integrity sha512-c0+lRjSeBakp3YJaP4BixI+sWWO5JFsG3wKAlUNl2olBB5sbXY8rgRbFbBwLkuuX3xSxNqpCZzeROJzMlsCdig== + dependencies: + "@types/node" "*" + "@types/resolve@*": version "0.0.8" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" @@ -11033,7 +11035,7 @@ read@1, read@~1.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.3, readable-stream@^3.0.6: +readable-stream@^3.0.3, readable-stream@^3.0.6, readable-stream@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==