| 'use strict'; |
| |
| function _url() { |
| const data = require('url'); |
| |
| _url = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function path() { |
| const data = _interopRequireWildcard(require('path')); |
| |
| path = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _vm() { |
| const data = require('vm'); |
| |
| _vm = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function nativeModule() { |
| const data = _interopRequireWildcard(require('module')); |
| |
| nativeModule = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _fakeTimers() { |
| const data = require('@jest/fake-timers'); |
| |
| _fakeTimers = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _jestMessageUtil() { |
| const data = require('jest-message-util'); |
| |
| _jestMessageUtil = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _jestUtil() { |
| const data = require('jest-util'); |
| |
| _jestUtil = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _jestRegexUtil() { |
| const data = require('jest-regex-util'); |
| |
| _jestRegexUtil = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _transform() { |
| const data = require('@jest/transform'); |
| |
| _transform = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _collectV8Coverage() { |
| const data = require('collect-v8-coverage'); |
| |
| _collectV8Coverage = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function fs() { |
| const data = _interopRequireWildcard(require('graceful-fs')); |
| |
| fs = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _jestMock() { |
| const data = _interopRequireDefault(require('jest-mock')); |
| |
| _jestMock = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _jestHasteMap() { |
| const data = _interopRequireDefault(require('jest-haste-map')); |
| |
| _jestHasteMap = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _jestResolve() { |
| const data = _interopRequireDefault(require('jest-resolve')); |
| |
| _jestResolve = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _jestSnapshot() { |
| const data = _interopRequireDefault(require('jest-snapshot')); |
| |
| _jestSnapshot = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _stripBom() { |
| const data = _interopRequireDefault(require('strip-bom')); |
| |
| _stripBom = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| var _helpers = require('./helpers'); |
| |
| var _args = require('./cli/args'); |
| |
| var _cli = require('./cli'); |
| |
| var _Object$fromEntries; |
| |
| function _interopRequireDefault(obj) { |
| return obj && obj.__esModule ? obj : {default: obj}; |
| } |
| |
| function _getRequireWildcardCache() { |
| if (typeof WeakMap !== 'function') return null; |
| var cache = new WeakMap(); |
| _getRequireWildcardCache = function () { |
| return cache; |
| }; |
| return cache; |
| } |
| |
| function _interopRequireWildcard(obj) { |
| if (obj && obj.__esModule) { |
| return obj; |
| } |
| if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) { |
| return {default: obj}; |
| } |
| var cache = _getRequireWildcardCache(); |
| if (cache && cache.has(obj)) { |
| return cache.get(obj); |
| } |
| var newObj = {}; |
| var hasPropertyDescriptor = |
| Object.defineProperty && Object.getOwnPropertyDescriptor; |
| for (var key in obj) { |
| if (Object.prototype.hasOwnProperty.call(obj, key)) { |
| var desc = hasPropertyDescriptor |
| ? Object.getOwnPropertyDescriptor(obj, key) |
| : null; |
| if (desc && (desc.get || desc.set)) { |
| Object.defineProperty(newObj, key, desc); |
| } else { |
| newObj[key] = obj[key]; |
| } |
| } |
| } |
| newObj.default = obj; |
| if (cache) { |
| cache.set(obj, newObj); |
| } |
| return newObj; |
| } |
| |
| function _defineProperty(obj, key, value) { |
| if (key in obj) { |
| Object.defineProperty(obj, key, { |
| value: value, |
| enumerable: true, |
| configurable: true, |
| writable: true |
| }); |
| } else { |
| obj[key] = value; |
| } |
| return obj; |
| } |
| |
| const defaultTransformOptions = { |
| isInternalModule: false, |
| supportsDynamicImport: false, |
| supportsStaticESM: false |
| }; |
| const OUTSIDE_JEST_VM_RESOLVE_OPTION = Symbol.for( |
| 'OUTSIDE_JEST_VM_RESOLVE_OPTION' |
| ); |
| const fromEntries = |
| (_Object$fromEntries = Object.fromEntries) !== null && |
| _Object$fromEntries !== void 0 |
| ? _Object$fromEntries |
| : function fromEntries(iterable) { |
| return [...iterable].reduce((obj, [key, val]) => { |
| obj[key] = val; |
| return obj; |
| }, {}); |
| }; |
| const testTimeoutSymbol = Symbol.for('TEST_TIMEOUT_SYMBOL'); |
| const retryTimesSymbol = Symbol.for('RETRY_TIMES'); |
| const NODE_MODULES = path().sep + 'node_modules' + path().sep; |
| |
| const getModuleNameMapper = config => { |
| if ( |
| Array.isArray(config.moduleNameMapper) && |
| config.moduleNameMapper.length |
| ) { |
| return config.moduleNameMapper.map(([regex, moduleName]) => ({ |
| moduleName, |
| regex: new RegExp(regex) |
| })); |
| } |
| |
| return null; |
| }; |
| |
| const unmockRegExpCache = new WeakMap(); |
| const EVAL_RESULT_VARIABLE = 'Object.<anonymous>'; |
| const runtimeSupportsVmModules = typeof _vm().SyntheticModule === 'function'; |
| |
| class Runtime { |
| constructor( |
| config, |
| environment, |
| resolver, |
| cacheFS = {}, |
| coverageOptions, // TODO: Make mandatory in Jest 27 |
| testPath |
| ) { |
| _defineProperty(this, '_cacheFS', void 0); |
| |
| _defineProperty(this, '_config', void 0); |
| |
| _defineProperty(this, '_coverageOptions', void 0); |
| |
| _defineProperty(this, '_currentlyExecutingModulePath', void 0); |
| |
| _defineProperty(this, '_environment', void 0); |
| |
| _defineProperty(this, '_explicitShouldMock', void 0); |
| |
| _defineProperty(this, '_fakeTimersImplementation', void 0); |
| |
| _defineProperty(this, '_internalModuleRegistry', void 0); |
| |
| _defineProperty(this, '_isCurrentlyExecutingManualMock', void 0); |
| |
| _defineProperty(this, '_mainModule', void 0); |
| |
| _defineProperty(this, '_mockFactories', void 0); |
| |
| _defineProperty(this, '_mockMetaDataCache', void 0); |
| |
| _defineProperty(this, '_mockRegistry', void 0); |
| |
| _defineProperty(this, '_isolatedMockRegistry', void 0); |
| |
| _defineProperty(this, '_moduleMocker', void 0); |
| |
| _defineProperty(this, '_isolatedModuleRegistry', void 0); |
| |
| _defineProperty(this, '_moduleRegistry', void 0); |
| |
| _defineProperty(this, '_esmoduleRegistry', void 0); |
| |
| _defineProperty(this, '_testPath', void 0); |
| |
| _defineProperty(this, '_resolver', void 0); |
| |
| _defineProperty(this, '_shouldAutoMock', void 0); |
| |
| _defineProperty(this, '_shouldMockModuleCache', void 0); |
| |
| _defineProperty(this, '_shouldUnmockTransitiveDependenciesCache', void 0); |
| |
| _defineProperty(this, '_sourceMapRegistry', void 0); |
| |
| _defineProperty(this, '_scriptTransformer', void 0); |
| |
| _defineProperty(this, '_fileTransforms', void 0); |
| |
| _defineProperty(this, '_v8CoverageInstrumenter', void 0); |
| |
| _defineProperty(this, '_v8CoverageResult', void 0); |
| |
| _defineProperty(this, '_transitiveShouldMock', void 0); |
| |
| _defineProperty(this, '_unmockList', void 0); |
| |
| _defineProperty(this, '_virtualMocks', void 0); |
| |
| _defineProperty(this, '_moduleImplementation', void 0); |
| |
| _defineProperty(this, 'jestObjectCaches', void 0); |
| |
| _defineProperty(this, 'jestGlobals', void 0); |
| |
| _defineProperty( |
| this, |
| 'unstable_shouldLoadAsEsm', |
| _jestResolve().default.unstable_shouldLoadAsEsm |
| ); |
| |
| this._cacheFS = new Map(Object.entries(cacheFS)); |
| this._config = config; |
| this._coverageOptions = coverageOptions || { |
| changedFiles: undefined, |
| collectCoverage: false, |
| collectCoverageFrom: [], |
| collectCoverageOnlyFrom: undefined, |
| coverageProvider: 'babel', |
| sourcesRelatedToTestsInChangedFiles: undefined |
| }; |
| this._currentlyExecutingModulePath = ''; |
| this._environment = environment; |
| this._explicitShouldMock = new Map(); |
| this._internalModuleRegistry = new Map(); |
| this._isCurrentlyExecutingManualMock = null; |
| this._mainModule = null; |
| this._mockFactories = new Map(); |
| this._mockRegistry = new Map(); // during setup, this cannot be null (and it's fine to explode if it is) |
| |
| this._moduleMocker = this._environment.moduleMocker; |
| this._isolatedModuleRegistry = null; |
| this._isolatedMockRegistry = null; |
| this._moduleRegistry = new Map(); |
| this._esmoduleRegistry = new Map(); |
| this._testPath = testPath; |
| this._resolver = resolver; |
| this._scriptTransformer = new (_transform().ScriptTransformer)(config); |
| this._shouldAutoMock = config.automock; |
| this._sourceMapRegistry = new Map(); |
| this._fileTransforms = new Map(); |
| this._virtualMocks = new Map(); |
| this.jestObjectCaches = new Map(); |
| this._mockMetaDataCache = new Map(); |
| this._shouldMockModuleCache = new Map(); |
| this._shouldUnmockTransitiveDependenciesCache = new Map(); |
| this._transitiveShouldMock = new Map(); |
| this._fakeTimersImplementation = |
| config.timers === 'modern' |
| ? this._environment.fakeTimersModern |
| : this._environment.fakeTimers; |
| this._unmockList = unmockRegExpCache.get(config); |
| |
| if (!this._unmockList && config.unmockedModulePathPatterns) { |
| this._unmockList = new RegExp( |
| config.unmockedModulePathPatterns.join('|') |
| ); |
| unmockRegExpCache.set(config, this._unmockList); |
| } |
| |
| if (config.automock) { |
| const virtualMocks = fromEntries(this._virtualMocks); |
| config.setupFiles.forEach(filePath => { |
| if (filePath && filePath.includes(NODE_MODULES)) { |
| const moduleID = this._resolver.getModuleID(virtualMocks, filePath); |
| |
| this._transitiveShouldMock.set(moduleID, false); |
| } |
| }); |
| } |
| |
| this.resetModules(); |
| } |
| |
| static createContext(config, options) { |
| (0, _jestUtil().createDirectory)(config.cacheDirectory); |
| const instance = Runtime.createHasteMap(config, { |
| console: options.console, |
| maxWorkers: options.maxWorkers, |
| resetCache: !config.cache, |
| watch: options.watch, |
| watchman: options.watchman |
| }); |
| return instance.build().then( |
| hasteMap => ({ |
| config, |
| hasteFS: hasteMap.hasteFS, |
| moduleMap: hasteMap.moduleMap, |
| resolver: Runtime.createResolver(config, hasteMap.moduleMap) |
| }), |
| error => { |
| throw error; |
| } |
| ); |
| } |
| |
| static createHasteMap(config, options) { |
| const ignorePatternParts = [ |
| ...config.modulePathIgnorePatterns, |
| ...(options && options.watch ? config.watchPathIgnorePatterns : []), |
| config.cacheDirectory.startsWith(config.rootDir + path().sep) && |
| config.cacheDirectory |
| ].filter(Boolean); |
| const ignorePattern = |
| ignorePatternParts.length > 0 |
| ? new RegExp(ignorePatternParts.join('|')) |
| : undefined; |
| return new (_jestHasteMap().default)({ |
| cacheDirectory: config.cacheDirectory, |
| computeSha1: config.haste.computeSha1, |
| console: options && options.console, |
| dependencyExtractor: config.dependencyExtractor, |
| extensions: [_jestSnapshot().default.EXTENSION].concat( |
| config.moduleFileExtensions |
| ), |
| hasteImplModulePath: config.haste.hasteImplModulePath, |
| ignorePattern, |
| maxWorkers: (options && options.maxWorkers) || 1, |
| mocksPattern: (0, _jestRegexUtil().escapePathForRegex)( |
| path().sep + '__mocks__' + path().sep |
| ), |
| name: config.name, |
| platforms: config.haste.platforms || ['ios', 'android'], |
| resetCache: options && options.resetCache, |
| retainAllFiles: false, |
| rootDir: config.rootDir, |
| roots: config.roots, |
| throwOnModuleCollision: config.haste.throwOnModuleCollision, |
| useWatchman: options && options.watchman, |
| watch: options && options.watch |
| }); |
| } |
| |
| static createResolver(config, moduleMap) { |
| return new (_jestResolve().default)(moduleMap, { |
| defaultPlatform: config.haste.defaultPlatform, |
| extensions: config.moduleFileExtensions.map(extension => '.' + extension), |
| hasCoreModules: true, |
| moduleDirectories: config.moduleDirectories, |
| moduleNameMapper: getModuleNameMapper(config), |
| modulePaths: config.modulePaths, |
| platforms: config.haste.platforms, |
| resolver: config.resolver, |
| rootDir: config.rootDir |
| }); |
| } |
| |
| static runCLI(args, info) { |
| return (0, _cli.run)(args, info); |
| } |
| |
| static getCLIOptions() { |
| return _args.options; |
| } // unstable as it should be replaced by https://github.com/nodejs/modules/issues/393, and we don't want people to use it |
| |
| async loadEsmModule(modulePath, query = '') { |
| const cacheKey = modulePath + query; |
| |
| if (!this._esmoduleRegistry.has(cacheKey)) { |
| invariant( |
| typeof this._environment.getVmContext === 'function', |
| 'ES Modules are only supported if your test environment has the `getVmContext` function' |
| ); |
| |
| const context = this._environment.getVmContext(); |
| |
| invariant(context); |
| |
| if (this._resolver.isCoreModule(modulePath)) { |
| const core = await this._importCoreModule(modulePath, context); |
| |
| this._esmoduleRegistry.set(cacheKey, core); |
| |
| return core; |
| } |
| |
| const transformedCode = this.transformFile(modulePath, { |
| isInternalModule: false, |
| supportsDynamicImport: true, |
| supportsStaticESM: true |
| }); |
| const module = new (_vm().SourceTextModule)(transformedCode, { |
| context, |
| identifier: modulePath, |
| importModuleDynamically: (specifier, referencingModule) => |
| this.linkModules( |
| specifier, |
| referencingModule.identifier, |
| referencingModule.context |
| ), |
| |
| initializeImportMeta(meta) { |
| meta.url = (0, _url().pathToFileURL)(modulePath).href; |
| } |
| }); |
| |
| this._esmoduleRegistry.set( |
| cacheKey, // we wanna put the linking promise in the cache so modules loaded in |
| // parallel can all await it. We then await it synchronously below, so |
| // we shouldn't get any unhandled rejections |
| module |
| .link((specifier, referencingModule) => |
| this.linkModules( |
| specifier, |
| referencingModule.identifier, |
| referencingModule.context |
| ) |
| ) |
| .then(() => module.evaluate()) |
| .then(() => module) |
| ); |
| } |
| |
| const module = this._esmoduleRegistry.get(cacheKey); |
| |
| invariant(module); |
| return module; |
| } |
| |
| linkModules(specifier, referencingIdentifier, context) { |
| if (specifier === '@jest/globals') { |
| const fromCache = this._esmoduleRegistry.get('@jest/globals'); |
| |
| if (fromCache) { |
| return fromCache; |
| } |
| |
| const globals = this.getGlobalsForEsm(referencingIdentifier, context); |
| |
| this._esmoduleRegistry.set('@jest/globals', globals); |
| |
| return globals; |
| } |
| |
| const [path, query] = specifier.split('?'); |
| |
| const resolved = this._resolveModule(referencingIdentifier, path); |
| |
| if ( |
| this._resolver.isCoreModule(resolved) || |
| this.unstable_shouldLoadAsEsm(resolved) |
| ) { |
| return this.loadEsmModule(resolved, query); |
| } |
| |
| return this.loadCjsAsEsm(referencingIdentifier, resolved, context); |
| } |
| |
| async unstable_importModule(from, moduleName) { |
| invariant( |
| runtimeSupportsVmModules, |
| 'You need to run with a version of node that supports ES Modules in the VM API.' |
| ); |
| const [path, query] = (moduleName !== null && moduleName !== void 0 |
| ? moduleName |
| : '' |
| ).split('?'); |
| |
| const modulePath = this._resolveModule(from, path); |
| |
| return this.loadEsmModule(modulePath, query); |
| } |
| |
| loadCjsAsEsm(from, modulePath, context) { |
| // CJS loaded via `import` should share cache with other CJS: https://github.com/nodejs/modules/issues/503 |
| const cjs = this.requireModuleOrMock(from, modulePath); |
| const module = new (_vm().SyntheticModule)( |
| ['default'], |
| function () { |
| // @ts-expect-error: TS doesn't know what `this` is |
| this.setExport('default', cjs); |
| }, |
| { |
| context, |
| identifier: modulePath |
| } |
| ); |
| return evaluateSyntheticModule(module); |
| } |
| |
| requireModule(from, moduleName, options, isRequireActual) { |
| const moduleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from, |
| moduleName |
| ); |
| |
| let modulePath; // Some old tests rely on this mocking behavior. Ideally we'll change this |
| // to be more explicit. |
| |
| const moduleResource = moduleName && this._resolver.getModule(moduleName); |
| |
| const manualMock = |
| moduleName && this._resolver.getMockModule(from, moduleName); |
| |
| if ( |
| !(options === null || options === void 0 |
| ? void 0 |
| : options.isInternalModule) && |
| !isRequireActual && |
| !moduleResource && |
| manualMock && |
| manualMock !== this._isCurrentlyExecutingManualMock && |
| this._explicitShouldMock.get(moduleID) !== false |
| ) { |
| modulePath = manualMock; |
| } |
| |
| if (moduleName && this._resolver.isCoreModule(moduleName)) { |
| return this._requireCoreModule(moduleName); |
| } |
| |
| if (!modulePath) { |
| modulePath = this._resolveModule(from, moduleName); |
| } |
| |
| let moduleRegistry; |
| |
| if ( |
| options === null || options === void 0 ? void 0 : options.isInternalModule |
| ) { |
| moduleRegistry = this._internalModuleRegistry; |
| } else { |
| if ( |
| this._moduleRegistry.get(modulePath) || |
| !this._isolatedModuleRegistry |
| ) { |
| moduleRegistry = this._moduleRegistry; |
| } else { |
| moduleRegistry = this._isolatedModuleRegistry; |
| } |
| } |
| |
| const module = moduleRegistry.get(modulePath); |
| |
| if (module) { |
| return module.exports; |
| } // We must register the pre-allocated module object first so that any |
| // circular dependencies that may arise while evaluating the module can |
| // be satisfied. |
| |
| const localModule = { |
| children: [], |
| exports: {}, |
| filename: modulePath, |
| id: modulePath, |
| loaded: false, |
| path: path().dirname(modulePath) |
| }; |
| moduleRegistry.set(modulePath, localModule); |
| |
| this._loadModule( |
| localModule, |
| from, |
| moduleName, |
| modulePath, |
| options, |
| moduleRegistry |
| ); |
| |
| return localModule.exports; |
| } |
| |
| requireInternalModule(from, to) { |
| if (to) { |
| const outsideJestVmPath = (0, _helpers.decodePossibleOutsideJestVmPath)( |
| to |
| ); |
| |
| if (outsideJestVmPath) { |
| return require(outsideJestVmPath); |
| } |
| } |
| |
| return this.requireModule(from, to, { |
| isInternalModule: true, |
| supportsDynamicImport: false, |
| supportsStaticESM: false |
| }); |
| } |
| |
| requireActual(from, moduleName) { |
| return this.requireModule(from, moduleName, undefined, true); |
| } |
| |
| requireMock(from, moduleName) { |
| const moduleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from, |
| moduleName |
| ); |
| |
| if ( |
| this._isolatedMockRegistry && |
| this._isolatedMockRegistry.get(moduleID) |
| ) { |
| return this._isolatedMockRegistry.get(moduleID); |
| } else if (this._mockRegistry.get(moduleID)) { |
| return this._mockRegistry.get(moduleID); |
| } |
| |
| const mockRegistry = this._isolatedMockRegistry || this._mockRegistry; |
| |
| if (this._mockFactories.has(moduleID)) { |
| // has check above makes this ok |
| const module = this._mockFactories.get(moduleID)(); |
| |
| mockRegistry.set(moduleID, module); |
| return module; |
| } |
| |
| const manualMockOrStub = this._resolver.getMockModule(from, moduleName); |
| |
| let modulePath = |
| this._resolver.getMockModule(from, moduleName) || |
| this._resolveModule(from, moduleName); |
| |
| let isManualMock = |
| manualMockOrStub && |
| !this._resolver.resolveStubModuleName(from, moduleName); |
| |
| if (!isManualMock) { |
| // If the actual module file has a __mocks__ dir sitting immediately next |
| // to it, look to see if there is a manual mock for this file. |
| // |
| // subDir1/my_module.js |
| // subDir1/__mocks__/my_module.js |
| // subDir2/my_module.js |
| // subDir2/__mocks__/my_module.js |
| // |
| // Where some other module does a relative require into each of the |
| // respective subDir{1,2} directories and expects a manual mock |
| // corresponding to that particular my_module.js file. |
| const moduleDir = path().dirname(modulePath); |
| const moduleFileName = path().basename(modulePath); |
| const potentialManualMock = path().join( |
| moduleDir, |
| '__mocks__', |
| moduleFileName |
| ); |
| |
| if (fs().existsSync(potentialManualMock)) { |
| isManualMock = true; |
| modulePath = potentialManualMock; |
| } |
| } |
| |
| if (isManualMock) { |
| const localModule = { |
| children: [], |
| exports: {}, |
| filename: modulePath, |
| id: modulePath, |
| loaded: false, |
| path: path().dirname(modulePath) |
| }; |
| |
| this._loadModule( |
| localModule, |
| from, |
| moduleName, |
| modulePath, |
| undefined, |
| mockRegistry |
| ); |
| |
| mockRegistry.set(moduleID, localModule.exports); |
| } else { |
| // Look for a real module to generate an automock from |
| mockRegistry.set(moduleID, this._generateMock(from, moduleName)); |
| } |
| |
| return mockRegistry.get(moduleID); |
| } |
| |
| _loadModule( |
| localModule, |
| from, |
| moduleName, |
| modulePath, |
| options, |
| moduleRegistry |
| ) { |
| if (path().extname(modulePath) === '.json') { |
| const text = (0, _stripBom().default)(this.readFile(modulePath)); |
| |
| const transformedFile = this._scriptTransformer.transformJson( |
| modulePath, |
| this._getFullTransformationOptions(options), |
| text |
| ); |
| |
| localModule.exports = this._environment.global.JSON.parse( |
| transformedFile |
| ); |
| } else if (path().extname(modulePath) === '.node') { |
| localModule.exports = require(modulePath); |
| } else { |
| // Only include the fromPath if a moduleName is given. Else treat as root. |
| const fromPath = moduleName ? from : null; |
| |
| this._execModule(localModule, options, moduleRegistry, fromPath); |
| } |
| |
| localModule.loaded = true; |
| } |
| |
| _getFullTransformationOptions(options = defaultTransformOptions) { |
| return {...options, ...this._coverageOptions}; |
| } |
| |
| requireModuleOrMock(from, moduleName) { |
| // this module is unmockable |
| if (moduleName === '@jest/globals') { |
| // @ts-expect-error: we don't care that it's not assignable to T |
| return this.getGlobalsForCjs(from); |
| } |
| |
| try { |
| if (this._shouldMock(from, moduleName)) { |
| return this.requireMock(from, moduleName); |
| } else { |
| return this.requireModule(from, moduleName); |
| } |
| } catch (e) { |
| const moduleNotFound = _jestResolve().default.tryCastModuleNotFoundError( |
| e |
| ); |
| |
| if (moduleNotFound) { |
| if ( |
| moduleNotFound.siblingWithSimilarExtensionFound === null || |
| moduleNotFound.siblingWithSimilarExtensionFound === undefined |
| ) { |
| moduleNotFound.hint = (0, _helpers.findSiblingsWithFileExtension)( |
| this._config.moduleFileExtensions, |
| from, |
| moduleNotFound.moduleName || moduleName |
| ); |
| moduleNotFound.siblingWithSimilarExtensionFound = Boolean( |
| moduleNotFound.hint |
| ); |
| } |
| |
| moduleNotFound.buildMessage(this._config.rootDir); |
| throw moduleNotFound; |
| } |
| |
| throw e; |
| } |
| } |
| |
| isolateModules(fn) { |
| if (this._isolatedModuleRegistry || this._isolatedMockRegistry) { |
| throw new Error( |
| 'isolateModules cannot be nested inside another isolateModules.' |
| ); |
| } |
| |
| this._isolatedModuleRegistry = new Map(); |
| this._isolatedMockRegistry = new Map(); |
| |
| try { |
| fn(); |
| } finally { |
| var _this$_isolatedModule, _this$_isolatedMockRe; |
| |
| // might be cleared within the callback |
| (_this$_isolatedModule = this._isolatedModuleRegistry) === null || |
| _this$_isolatedModule === void 0 |
| ? void 0 |
| : _this$_isolatedModule.clear(); |
| (_this$_isolatedMockRe = this._isolatedMockRegistry) === null || |
| _this$_isolatedMockRe === void 0 |
| ? void 0 |
| : _this$_isolatedMockRe.clear(); |
| this._isolatedModuleRegistry = null; |
| this._isolatedMockRegistry = null; |
| } |
| } |
| |
| resetModules() { |
| var _this$_isolatedModule2, _this$_isolatedMockRe2; |
| |
| (_this$_isolatedModule2 = this._isolatedModuleRegistry) === null || |
| _this$_isolatedModule2 === void 0 |
| ? void 0 |
| : _this$_isolatedModule2.clear(); |
| (_this$_isolatedMockRe2 = this._isolatedMockRegistry) === null || |
| _this$_isolatedMockRe2 === void 0 |
| ? void 0 |
| : _this$_isolatedMockRe2.clear(); |
| this._isolatedModuleRegistry = null; |
| this._isolatedMockRegistry = null; |
| |
| this._mockRegistry.clear(); |
| |
| this._moduleRegistry.clear(); |
| |
| this._esmoduleRegistry.clear(); |
| |
| if (this._environment) { |
| if (this._environment.global) { |
| const envGlobal = this._environment.global; |
| Object.keys(envGlobal).forEach(key => { |
| const globalMock = envGlobal[key]; |
| |
| if ( |
| ((typeof globalMock === 'object' && globalMock !== null) || |
| typeof globalMock === 'function') && |
| globalMock._isMockFunction === true |
| ) { |
| globalMock.mockClear(); |
| } |
| }); |
| } |
| |
| if (this._environment.fakeTimers) { |
| this._environment.fakeTimers.clearAllTimers(); |
| } |
| } |
| } |
| |
| async collectV8Coverage() { |
| this._v8CoverageInstrumenter = new (_collectV8Coverage().CoverageInstrumenter)(); |
| await this._v8CoverageInstrumenter.startInstrumenting(); |
| } |
| |
| async stopCollectingV8Coverage() { |
| if (!this._v8CoverageInstrumenter) { |
| throw new Error('You need to call `collectV8Coverage` first.'); |
| } |
| |
| this._v8CoverageResult = await this._v8CoverageInstrumenter.stopInstrumenting(); |
| } |
| |
| getAllCoverageInfoCopy() { |
| return (0, _jestUtil().deepCyclicCopy)( |
| this._environment.global.__coverage__ |
| ); |
| } |
| |
| getAllV8CoverageInfoCopy() { |
| if (!this._v8CoverageResult) { |
| throw new Error('You need to `stopCollectingV8Coverage` first'); |
| } |
| |
| return this._v8CoverageResult |
| .filter(res => res.url.startsWith('file://')) |
| .map(res => ({...res, url: (0, _url().fileURLToPath)(res.url)})) |
| .filter( |
| ( |
| res // TODO: will this work on windows? It might be better if `shouldInstrument` deals with it anyways |
| ) => |
| res.url.startsWith(this._config.rootDir) && |
| this._fileTransforms.has(res.url) && |
| (0, _transform().shouldInstrument)( |
| res.url, |
| this._coverageOptions, |
| this._config |
| ) |
| ) |
| .map(result => { |
| const transformedFile = this._fileTransforms.get(result.url); |
| |
| return { |
| codeTransformResult: transformedFile, |
| result |
| }; |
| }); |
| } // TODO - remove in Jest 27 |
| |
| getSourceMapInfo(_coveredFiles) { |
| return {}; |
| } |
| |
| getSourceMaps() { |
| return fromEntries(this._sourceMapRegistry); |
| } |
| |
| setMock(from, moduleName, mockFactory, options) { |
| if (options === null || options === void 0 ? void 0 : options.virtual) { |
| const mockPath = this._resolver.getModulePath(from, moduleName); |
| |
| this._virtualMocks.set(mockPath, true); |
| } |
| |
| const moduleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from, |
| moduleName |
| ); |
| |
| this._explicitShouldMock.set(moduleID, true); |
| |
| this._mockFactories.set(moduleID, mockFactory); |
| } |
| |
| restoreAllMocks() { |
| this._moduleMocker.restoreAllMocks(); |
| } |
| |
| resetAllMocks() { |
| this._moduleMocker.resetAllMocks(); |
| } |
| |
| clearAllMocks() { |
| this._moduleMocker.clearAllMocks(); |
| } |
| |
| teardown() { |
| this.restoreAllMocks(); |
| this.resetAllMocks(); |
| this.resetModules(); |
| |
| this._internalModuleRegistry.clear(); |
| |
| this._mainModule = null; |
| |
| this._mockFactories.clear(); |
| |
| this._mockMetaDataCache.clear(); |
| |
| this._shouldMockModuleCache.clear(); |
| |
| this._shouldUnmockTransitiveDependenciesCache.clear(); |
| |
| this._explicitShouldMock.clear(); |
| |
| this._transitiveShouldMock.clear(); |
| |
| this._virtualMocks.clear(); |
| |
| this._cacheFS.clear(); |
| |
| this._unmockList = undefined; |
| |
| this._sourceMapRegistry.clear(); |
| |
| this._fileTransforms.clear(); |
| |
| this.jestObjectCaches.clear(); |
| this._v8CoverageResult = []; |
| this._v8CoverageInstrumenter = undefined; |
| this._moduleImplementation = undefined; |
| } |
| |
| _resolveModule(from, to) { |
| return to ? this._resolver.resolveModule(from, to) : from; |
| } |
| |
| _requireResolve(from, moduleName, options = {}) { |
| if (moduleName == null) { |
| throw new Error( |
| 'The first argument to require.resolve must be a string. Received null or undefined.' |
| ); |
| } |
| |
| const {paths} = options; |
| |
| if (paths) { |
| for (const p of paths) { |
| const absolutePath = path().resolve(from, '..', p); |
| |
| const module = this._resolver.resolveModuleFromDirIfExists( |
| absolutePath, |
| moduleName, // required to also resolve files without leading './' directly in the path |
| { |
| paths: [absolutePath] |
| } |
| ); |
| |
| if (module) { |
| return module; |
| } |
| } |
| |
| throw new (_jestResolve().default.ModuleNotFoundError)( |
| `Cannot resolve module '${moduleName}' from paths ['${paths.join( |
| "', '" |
| )}'] from ${from}` |
| ); |
| } |
| |
| try { |
| return this._resolveModule(from, moduleName); |
| } catch (err) { |
| const module = this._resolver.getMockModule(from, moduleName); |
| |
| if (module) { |
| return module; |
| } else { |
| throw err; |
| } |
| } |
| } |
| |
| _requireResolvePaths(from, moduleName) { |
| if (moduleName == null) { |
| throw new Error( |
| 'The first argument to require.resolve.paths must be a string. Received null or undefined.' |
| ); |
| } |
| |
| if (!moduleName.length) { |
| throw new Error( |
| 'The first argument to require.resolve.paths must not be the empty string.' |
| ); |
| } |
| |
| if (moduleName[0] === '.') { |
| return [path().resolve(from, '..')]; |
| } |
| |
| if (this._resolver.isCoreModule(moduleName)) { |
| return null; |
| } |
| |
| return this._resolver.getModulePaths(path().resolve(from, '..')); |
| } |
| |
| _execModule(localModule, options, moduleRegistry, from) { |
| // If the environment was disposed, prevent this module from being executed. |
| if (!this._environment.global) { |
| return; |
| } |
| |
| const module = localModule; |
| const filename = module.filename; |
| const lastExecutingModulePath = this._currentlyExecutingModulePath; |
| this._currentlyExecutingModulePath = filename; |
| const origCurrExecutingManualMock = this._isCurrentlyExecutingManualMock; |
| this._isCurrentlyExecutingManualMock = filename; |
| module.children = []; |
| Object.defineProperty(module, 'parent', { |
| enumerable: true, |
| |
| get() { |
| const key = from || ''; |
| return moduleRegistry.get(key) || null; |
| } |
| }); |
| module.paths = this._resolver.getModulePaths(module.path); |
| Object.defineProperty(module, 'require', { |
| value: this._createRequireImplementation(module, options) |
| }); |
| const transformedCode = this.transformFile(filename, options); |
| let compiledFunction = null; |
| const script = this.createScriptFromCode(transformedCode, filename); |
| let runScript = null; // Use this if available instead of deprecated `JestEnvironment.runScript` |
| |
| if (typeof this._environment.getVmContext === 'function') { |
| const vmContext = this._environment.getVmContext(); |
| |
| if (vmContext) { |
| runScript = script.runInContext(vmContext, { |
| filename |
| }); |
| } |
| } else { |
| runScript = this._environment.runScript(script); |
| } |
| |
| if (runScript !== null) { |
| compiledFunction = runScript[EVAL_RESULT_VARIABLE]; |
| } |
| |
| if (compiledFunction === null) { |
| this._logFormattedReferenceError( |
| 'You are trying to `import` a file after the Jest environment has been torn down.' |
| ); |
| |
| process.exitCode = 1; |
| return; |
| } |
| |
| const jestObject = this._createJestObjectFor(filename); |
| |
| this.jestObjectCaches.set(filename, jestObject); |
| const lastArgs = [ |
| this._config.injectGlobals ? jestObject : undefined, // jest object |
| this._config.extraGlobals.map(globalVariable => { |
| if (this._environment.global[globalVariable]) { |
| return this._environment.global[globalVariable]; |
| } |
| |
| throw new Error( |
| `You have requested '${globalVariable}' as a global variable, but it was not present. Please check your config or your global environment.` |
| ); |
| }) |
| ]; |
| |
| if (!this._mainModule && filename === this._testPath) { |
| this._mainModule = module; |
| } |
| |
| Object.defineProperty(module, 'main', { |
| enumerable: true, |
| value: this._mainModule |
| }); |
| |
| try { |
| compiledFunction.call( |
| module.exports, |
| module, // module object |
| module.exports, // module exports |
| module.require, // require implementation |
| module.path, // __dirname |
| module.filename, // __filename |
| this._environment.global, // global object |
| ...lastArgs.filter(notEmpty) |
| ); |
| } catch (error) { |
| this.handleExecutionError(error, module); |
| } |
| |
| this._isCurrentlyExecutingManualMock = origCurrExecutingManualMock; |
| this._currentlyExecutingModulePath = lastExecutingModulePath; |
| } |
| |
| transformFile(filename, options) { |
| const source = this.readFile(filename); |
| |
| if ( |
| options === null || options === void 0 ? void 0 : options.isInternalModule |
| ) { |
| return source; |
| } |
| |
| const transformedFile = this._scriptTransformer.transform( |
| filename, |
| this._getFullTransformationOptions(options), |
| source |
| ); |
| |
| this._fileTransforms.set(filename, { |
| ...transformedFile, |
| wrapperLength: this.constructModuleWrapperStart().length |
| }); |
| |
| if (transformedFile.sourceMapPath) { |
| this._sourceMapRegistry.set(filename, transformedFile.sourceMapPath); |
| } |
| |
| return transformedFile.code; |
| } |
| |
| createScriptFromCode(scriptSource, filename) { |
| try { |
| const scriptFilename = this._resolver.isCoreModule(filename) |
| ? `jest-nodejs-core-${filename}` |
| : filename; |
| return new (_vm().Script)(this.wrapCodeInModuleWrapper(scriptSource), { |
| displayErrors: true, |
| filename: scriptFilename, |
| // @ts-expect-error: Experimental ESM API |
| importModuleDynamically: specifier => { |
| var _this$_environment$ge, _this$_environment; |
| |
| const context = |
| (_this$_environment$ge = (_this$_environment = this._environment) |
| .getVmContext) === null || _this$_environment$ge === void 0 |
| ? void 0 |
| : _this$_environment$ge.call(_this$_environment); |
| invariant(context); |
| return this.linkModules(specifier, scriptFilename, context); |
| } |
| }); |
| } catch (e) { |
| throw (0, _transform().handlePotentialSyntaxError)(e); |
| } |
| } |
| |
| _requireCoreModule(moduleName) { |
| if (moduleName === 'process') { |
| return this._environment.global.process; |
| } |
| |
| if (moduleName === 'module') { |
| return this._getMockedNativeModule(); |
| } |
| |
| return require(moduleName); |
| } |
| |
| _importCoreModule(moduleName, context) { |
| const required = this._requireCoreModule(moduleName); |
| |
| const module = new (_vm().SyntheticModule)( |
| ['default', ...Object.keys(required)], |
| function () { |
| // @ts-expect-error: TS doesn't know what `this` is |
| this.setExport('default', required); |
| Object.entries(required).forEach(([key, value]) => { |
| // @ts-expect-error: TS doesn't know what `this` is |
| this.setExport(key, value); |
| }); |
| }, // should identifier be `node://${moduleName}`? |
| { |
| context, |
| identifier: moduleName |
| } |
| ); |
| return evaluateSyntheticModule(module); |
| } |
| |
| _getMockedNativeModule() { |
| if (this._moduleImplementation) { |
| return this._moduleImplementation; |
| } |
| |
| const createRequire = modulePath => { |
| const filename = |
| typeof modulePath === 'string' |
| ? modulePath.startsWith('file:///') |
| ? (0, _url().fileURLToPath)(new (_url().URL)(modulePath)) |
| : modulePath |
| : (0, _url().fileURLToPath)(modulePath); |
| |
| if (!path().isAbsolute(filename)) { |
| const error = new TypeError( |
| `The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received '${filename}'` |
| ); // @ts-expect-error |
| |
| error.code = 'ERR_INVALID_ARG_TYPE'; |
| throw error; |
| } |
| |
| return this._createRequireImplementation({ |
| children: [], |
| exports: {}, |
| filename, |
| id: filename, |
| loaded: false, |
| path: path().dirname(filename) |
| }); |
| }; // should we implement the class ourselves? |
| |
| class Module extends nativeModule().Module {} |
| |
| Object.entries(nativeModule().Module).forEach(([key, value]) => { |
| // @ts-expect-error |
| Module[key] = value; |
| }); |
| Module.Module = Module; |
| |
| if ('createRequire' in nativeModule()) { |
| Module.createRequire = createRequire; |
| } |
| |
| if ('createRequireFromPath' in nativeModule()) { |
| Module.createRequireFromPath = function createRequireFromPath(filename) { |
| if (typeof filename !== 'string') { |
| const error = new TypeError( |
| `The argument 'filename' must be string. Received '${filename}'.${ |
| filename instanceof _url().URL |
| ? ' Use createRequire for URL filename.' |
| : '' |
| }` |
| ); // @ts-expect-error |
| |
| error.code = 'ERR_INVALID_ARG_TYPE'; |
| throw error; |
| } |
| |
| return createRequire(filename); |
| }; |
| } |
| |
| if ('syncBuiltinESMExports' in nativeModule()) { |
| Module.syncBuiltinESMExports = function syncBuiltinESMExports() {}; |
| } |
| |
| this._moduleImplementation = Module; |
| return Module; |
| } |
| |
| _generateMock(from, moduleName) { |
| const modulePath = |
| this._resolver.resolveStubModuleName(from, moduleName) || |
| this._resolveModule(from, moduleName); |
| |
| if (!this._mockMetaDataCache.has(modulePath)) { |
| // This allows us to handle circular dependencies while generating an |
| // automock |
| this._mockMetaDataCache.set( |
| modulePath, |
| this._moduleMocker.getMetadata({}) || {} |
| ); // In order to avoid it being possible for automocking to potentially |
| // cause side-effects within the module environment, we need to execute |
| // the module in isolation. This could cause issues if the module being |
| // mocked has calls into side-effectful APIs on another module. |
| |
| const origMockRegistry = this._mockRegistry; |
| const origModuleRegistry = this._moduleRegistry; |
| this._mockRegistry = new Map(); |
| this._moduleRegistry = new Map(); |
| const moduleExports = this.requireModule(from, moduleName); // Restore the "real" module/mock registries |
| |
| this._mockRegistry = origMockRegistry; |
| this._moduleRegistry = origModuleRegistry; |
| |
| const mockMetadata = this._moduleMocker.getMetadata(moduleExports); |
| |
| if (mockMetadata == null) { |
| throw new Error( |
| `Failed to get mock metadata: ${modulePath}\n\n` + |
| `See: https://jestjs.io/docs/manual-mocks.html#content` |
| ); |
| } |
| |
| this._mockMetaDataCache.set(modulePath, mockMetadata); |
| } |
| |
| return this._moduleMocker.generateFromMetadata( |
| // added above if missing |
| this._mockMetaDataCache.get(modulePath) |
| ); |
| } |
| |
| _shouldMock(from, moduleName) { |
| const explicitShouldMock = this._explicitShouldMock; |
| |
| const moduleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from, |
| moduleName |
| ); |
| |
| const key = from + path().delimiter + moduleID; |
| |
| if (explicitShouldMock.has(moduleID)) { |
| // guaranteed by `has` above |
| return explicitShouldMock.get(moduleID); |
| } |
| |
| if ( |
| !this._shouldAutoMock || |
| this._resolver.isCoreModule(moduleName) || |
| this._shouldUnmockTransitiveDependenciesCache.get(key) |
| ) { |
| return false; |
| } |
| |
| if (this._shouldMockModuleCache.has(moduleID)) { |
| // guaranteed by `has` above |
| return this._shouldMockModuleCache.get(moduleID); |
| } |
| |
| let modulePath; |
| |
| try { |
| modulePath = this._resolveModule(from, moduleName); |
| } catch (e) { |
| const manualMock = this._resolver.getMockModule(from, moduleName); |
| |
| if (manualMock) { |
| this._shouldMockModuleCache.set(moduleID, true); |
| |
| return true; |
| } |
| |
| throw e; |
| } |
| |
| if (this._unmockList && this._unmockList.test(modulePath)) { |
| this._shouldMockModuleCache.set(moduleID, false); |
| |
| return false; |
| } // transitive unmocking for package managers that store flat packages (npm3) |
| |
| const currentModuleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from |
| ); |
| |
| if ( |
| this._transitiveShouldMock.get(currentModuleID) === false || |
| (from.includes(NODE_MODULES) && |
| modulePath.includes(NODE_MODULES) && |
| ((this._unmockList && this._unmockList.test(from)) || |
| explicitShouldMock.get(currentModuleID) === false)) |
| ) { |
| this._transitiveShouldMock.set(moduleID, false); |
| |
| this._shouldUnmockTransitiveDependenciesCache.set(key, true); |
| |
| return false; |
| } |
| |
| this._shouldMockModuleCache.set(moduleID, true); |
| |
| return true; |
| } |
| |
| _createRequireImplementation(from, options) { |
| const resolve = (moduleName, resolveOptions) => { |
| const resolved = this._requireResolve( |
| from.filename, |
| moduleName, |
| resolveOptions |
| ); |
| |
| if ( |
| (resolveOptions === null || resolveOptions === void 0 |
| ? void 0 |
| : resolveOptions[OUTSIDE_JEST_VM_RESOLVE_OPTION]) && |
| (options === null || options === void 0 |
| ? void 0 |
| : options.isInternalModule) |
| ) { |
| return (0, _helpers.createOutsideJestVmPath)(resolved); |
| } |
| |
| return resolved; |
| }; |
| |
| resolve.paths = moduleName => |
| this._requireResolvePaths(from.filename, moduleName); |
| |
| const moduleRequire = ( |
| options === null || options === void 0 ? void 0 : options.isInternalModule |
| ) |
| ? moduleName => this.requireInternalModule(from.filename, moduleName) |
| : this.requireModuleOrMock.bind(this, from.filename); |
| moduleRequire.extensions = Object.create(null); |
| moduleRequire.resolve = resolve; |
| |
| moduleRequire.cache = (() => { |
| // TODO: consider warning somehow that this does nothing. We should support deletions, anyways |
| const notPermittedMethod = () => true; |
| |
| return new Proxy(Object.create(null), { |
| defineProperty: notPermittedMethod, |
| deleteProperty: notPermittedMethod, |
| get: (_target, key) => |
| typeof key === 'string' ? this._moduleRegistry.get(key) : undefined, |
| |
| getOwnPropertyDescriptor() { |
| return { |
| configurable: true, |
| enumerable: true |
| }; |
| }, |
| |
| has: (_target, key) => |
| typeof key === 'string' && this._moduleRegistry.has(key), |
| ownKeys: () => Array.from(this._moduleRegistry.keys()), |
| set: notPermittedMethod |
| }); |
| })(); |
| |
| Object.defineProperty(moduleRequire, 'main', { |
| enumerable: true, |
| value: this._testPath ? this._moduleRegistry.get(this._testPath) : null |
| }); |
| return moduleRequire; |
| } |
| |
| _createJestObjectFor(from) { |
| const disableAutomock = () => { |
| this._shouldAutoMock = false; |
| return jestObject; |
| }; |
| |
| const enableAutomock = () => { |
| this._shouldAutoMock = true; |
| return jestObject; |
| }; |
| |
| const unmock = moduleName => { |
| const moduleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from, |
| moduleName |
| ); |
| |
| this._explicitShouldMock.set(moduleID, false); |
| |
| return jestObject; |
| }; |
| |
| const deepUnmock = moduleName => { |
| const moduleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from, |
| moduleName |
| ); |
| |
| this._explicitShouldMock.set(moduleID, false); |
| |
| this._transitiveShouldMock.set(moduleID, false); |
| |
| return jestObject; |
| }; |
| |
| const mock = (moduleName, mockFactory, options) => { |
| if (mockFactory !== undefined) { |
| return setMockFactory(moduleName, mockFactory, options); |
| } |
| |
| const moduleID = this._resolver.getModuleID( |
| fromEntries(this._virtualMocks), |
| from, |
| moduleName |
| ); |
| |
| this._explicitShouldMock.set(moduleID, true); |
| |
| return jestObject; |
| }; |
| |
| const setMockFactory = (moduleName, mockFactory, options) => { |
| this.setMock(from, moduleName, mockFactory, options); |
| return jestObject; |
| }; |
| |
| const clearAllMocks = () => { |
| this.clearAllMocks(); |
| return jestObject; |
| }; |
| |
| const resetAllMocks = () => { |
| this.resetAllMocks(); |
| return jestObject; |
| }; |
| |
| const restoreAllMocks = () => { |
| this.restoreAllMocks(); |
| return jestObject; |
| }; |
| |
| const _getFakeTimers = () => { |
| if ( |
| !(this._environment.fakeTimers || this._environment.fakeTimersModern) |
| ) { |
| this._logFormattedReferenceError( |
| 'You are trying to access a property or method of the Jest environment after it has been torn down.' |
| ); |
| |
| process.exitCode = 1; |
| } |
| |
| return this._fakeTimersImplementation; |
| }; |
| |
| const useFakeTimers = (type = 'legacy') => { |
| if (type === 'modern') { |
| this._fakeTimersImplementation = this._environment.fakeTimersModern; |
| } else { |
| this._fakeTimersImplementation = this._environment.fakeTimers; |
| } |
| |
| this._fakeTimersImplementation.useFakeTimers(); |
| |
| return jestObject; |
| }; |
| |
| const useRealTimers = () => { |
| _getFakeTimers().useRealTimers(); |
| |
| return jestObject; |
| }; |
| |
| const resetModules = () => { |
| this.resetModules(); |
| return jestObject; |
| }; |
| |
| const isolateModules = fn => { |
| this.isolateModules(fn); |
| return jestObject; |
| }; |
| |
| const fn = this._moduleMocker.fn.bind(this._moduleMocker); |
| |
| const spyOn = this._moduleMocker.spyOn.bind(this._moduleMocker); |
| |
| const setTimeout = timeout => { |
| if (this._environment.global.jasmine) { |
| this._environment.global.jasmine._DEFAULT_TIMEOUT_INTERVAL = timeout; |
| } else { |
| // @ts-expect-error: https://github.com/Microsoft/TypeScript/issues/24587 |
| this._environment.global[testTimeoutSymbol] = timeout; |
| } |
| |
| return jestObject; |
| }; |
| |
| const retryTimes = numTestRetries => { |
| // @ts-expect-error: https://github.com/Microsoft/TypeScript/issues/24587 |
| this._environment.global[retryTimesSymbol] = numTestRetries; |
| return jestObject; |
| }; |
| |
| const jestObject = { |
| addMatchers: matchers => |
| this._environment.global.jasmine.addMatchers(matchers), |
| advanceTimersByTime: msToRun => |
| _getFakeTimers().advanceTimersByTime(msToRun), |
| advanceTimersToNextTimer: steps => |
| _getFakeTimers().advanceTimersToNextTimer(steps), |
| autoMockOff: disableAutomock, |
| autoMockOn: enableAutomock, |
| clearAllMocks, |
| clearAllTimers: () => _getFakeTimers().clearAllTimers(), |
| createMockFromModule: moduleName => this._generateMock(from, moduleName), |
| deepUnmock, |
| disableAutomock, |
| doMock: mock, |
| dontMock: unmock, |
| enableAutomock, |
| fn, |
| genMockFromModule: moduleName => this._generateMock(from, moduleName), |
| getRealSystemTime: () => { |
| const fakeTimers = _getFakeTimers(); |
| |
| if (fakeTimers instanceof _fakeTimers().ModernFakeTimers) { |
| return fakeTimers.getRealSystemTime(); |
| } else { |
| throw new TypeError( |
| 'getRealSystemTime is not available when not using modern timers' |
| ); |
| } |
| }, |
| getTimerCount: () => _getFakeTimers().getTimerCount(), |
| isMockFunction: this._moduleMocker.isMockFunction, |
| isolateModules, |
| mock, |
| requireActual: this.requireActual.bind(this, from), |
| requireMock: this.requireMock.bind(this, from), |
| resetAllMocks, |
| resetModuleRegistry: resetModules, |
| resetModules, |
| restoreAllMocks, |
| retryTimes, |
| runAllImmediates: () => { |
| const fakeTimers = _getFakeTimers(); |
| |
| if (fakeTimers instanceof _fakeTimers().LegacyFakeTimers) { |
| fakeTimers.runAllImmediates(); |
| } else { |
| throw new TypeError( |
| 'runAllImmediates is not available when using modern timers' |
| ); |
| } |
| }, |
| runAllTicks: () => _getFakeTimers().runAllTicks(), |
| runAllTimers: () => _getFakeTimers().runAllTimers(), |
| runOnlyPendingTimers: () => _getFakeTimers().runOnlyPendingTimers(), |
| runTimersToTime: msToRun => _getFakeTimers().advanceTimersByTime(msToRun), |
| setMock: (moduleName, mock) => setMockFactory(moduleName, () => mock), |
| setSystemTime: now => { |
| const fakeTimers = _getFakeTimers(); |
| |
| if (fakeTimers instanceof _fakeTimers().ModernFakeTimers) { |
| fakeTimers.setSystemTime(now); |
| } else { |
| throw new TypeError( |
| 'setSystemTime is not available when not using modern timers' |
| ); |
| } |
| }, |
| setTimeout, |
| spyOn, |
| unmock, |
| useFakeTimers, |
| useRealTimers |
| }; |
| return jestObject; |
| } |
| |
| _logFormattedReferenceError(errorMessage) { |
| const originalStack = new ReferenceError(errorMessage).stack |
| .split('\n') // Remove this file from the stack (jest-message-utils will keep one line) |
| .filter(line => line.indexOf(__filename) === -1) |
| .join('\n'); |
| const {message, stack} = (0, _jestMessageUtil().separateMessageFromStack)( |
| originalStack |
| ); |
| console.error( |
| `\n${message}\n` + |
| (0, _jestMessageUtil().formatStackTrace)(stack, this._config, { |
| noStackTrace: false |
| }) |
| ); |
| } |
| |
| wrapCodeInModuleWrapper(content) { |
| return this.constructModuleWrapperStart() + content + '\n}});'; |
| } |
| |
| constructModuleWrapperStart() { |
| const args = this.constructInjectedModuleParameters(); |
| return '({"' + EVAL_RESULT_VARIABLE + `":function(${args.join(',')}){`; |
| } |
| |
| constructInjectedModuleParameters() { |
| return [ |
| 'module', |
| 'exports', |
| 'require', |
| '__dirname', |
| '__filename', |
| 'global', |
| this._config.injectGlobals ? 'jest' : undefined, |
| ...this._config.extraGlobals |
| ].filter(notEmpty); |
| } |
| |
| handleExecutionError(e, module) { |
| const moduleNotFoundError = _jestResolve().default.tryCastModuleNotFoundError( |
| e |
| ); |
| |
| if (moduleNotFoundError) { |
| if (!moduleNotFoundError.requireStack) { |
| moduleNotFoundError.requireStack = [module.filename || module.id]; |
| |
| for (let cursor = module.parent; cursor; cursor = cursor.parent) { |
| moduleNotFoundError.requireStack.push(cursor.filename || cursor.id); |
| } |
| |
| moduleNotFoundError.buildMessage(this._config.rootDir); |
| } |
| |
| throw moduleNotFoundError; |
| } |
| |
| throw e; |
| } |
| |
| getGlobalsForCjs(from) { |
| const jest = this.jestObjectCaches.get(from); |
| invariant(jest, 'There should always be a Jest object already'); |
| return {...this.getGlobalsFromEnvironment(), jest}; |
| } |
| |
| getGlobalsForEsm(from, context) { |
| let jest = this.jestObjectCaches.get(from); |
| |
| if (!jest) { |
| jest = this._createJestObjectFor(from); |
| this.jestObjectCaches.set(from, jest); |
| } |
| |
| const globals = {...this.getGlobalsFromEnvironment(), jest}; |
| const module = new (_vm().SyntheticModule)( |
| Object.keys(globals), |
| function () { |
| Object.entries(globals).forEach(([key, value]) => { |
| // @ts-expect-error: TS doesn't know what `this` is |
| this.setExport(key, value); |
| }); |
| }, |
| { |
| context, |
| identifier: '@jest/globals' |
| } |
| ); |
| return evaluateSyntheticModule(module); |
| } |
| |
| getGlobalsFromEnvironment() { |
| if (this.jestGlobals) { |
| return {...this.jestGlobals}; |
| } |
| |
| return { |
| afterAll: this._environment.global.afterAll, |
| afterEach: this._environment.global.afterEach, |
| beforeAll: this._environment.global.beforeAll, |
| beforeEach: this._environment.global.beforeEach, |
| describe: this._environment.global.describe, |
| expect: this._environment.global.expect, |
| fdescribe: this._environment.global.fdescribe, |
| fit: this._environment.global.fit, |
| it: this._environment.global.it, |
| test: this._environment.global.test, |
| xdescribe: this._environment.global.xdescribe, |
| xit: this._environment.global.xit, |
| xtest: this._environment.global.xtest |
| }; |
| } |
| |
| readFile(filename) { |
| let source = this._cacheFS.get(filename); |
| |
| if (!source) { |
| source = fs().readFileSync(filename, 'utf8'); |
| |
| this._cacheFS.set(filename, source); |
| } |
| |
| return source; |
| } |
| |
| setGlobalsForRuntime(globals) { |
| this.jestGlobals = globals; |
| } |
| } |
| |
| _defineProperty(Runtime, 'shouldInstrument', _transform().shouldInstrument); |
| |
| function invariant(condition, message) { |
| if (!condition) { |
| throw new Error(message); |
| } |
| } |
| |
| function notEmpty(value) { |
| return value !== null && value !== undefined; |
| } |
| |
| async function evaluateSyntheticModule(module) { |
| await module.link(() => { |
| throw new Error('This should never happen'); |
| }); |
| await module.evaluate(); |
| return module; |
| } |
| |
| module.exports = Runtime; |