1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', {
|
4 | value: true
|
5 | });
|
6 | exports.default = runTest;
|
7 | function _chalk() {
|
8 | const data = _interopRequireDefault(require('chalk'));
|
9 | _chalk = function () {
|
10 | return data;
|
11 | };
|
12 | return data;
|
13 | }
|
14 | function fs() {
|
15 | const data = _interopRequireWildcard(require('graceful-fs'));
|
16 | fs = function () {
|
17 | return data;
|
18 | };
|
19 | return data;
|
20 | }
|
21 | function _sourceMapSupport() {
|
22 | const data = _interopRequireDefault(require('source-map-support'));
|
23 | _sourceMapSupport = function () {
|
24 | return data;
|
25 | };
|
26 | return data;
|
27 | }
|
28 | function _console() {
|
29 | const data = require('@jest/console');
|
30 | _console = function () {
|
31 | return data;
|
32 | };
|
33 | return data;
|
34 | }
|
35 | function _transform() {
|
36 | const data = require('@jest/transform');
|
37 | _transform = function () {
|
38 | return data;
|
39 | };
|
40 | return data;
|
41 | }
|
42 | function docblock() {
|
43 | const data = _interopRequireWildcard(require('jest-docblock'));
|
44 | docblock = function () {
|
45 | return data;
|
46 | };
|
47 | return data;
|
48 | }
|
49 | function _jestLeakDetector() {
|
50 | const data = _interopRequireDefault(require('jest-leak-detector'));
|
51 | _jestLeakDetector = function () {
|
52 | return data;
|
53 | };
|
54 | return data;
|
55 | }
|
56 | function _jestMessageUtil() {
|
57 | const data = require('jest-message-util');
|
58 | _jestMessageUtil = function () {
|
59 | return data;
|
60 | };
|
61 | return data;
|
62 | }
|
63 | function _jestResolve() {
|
64 | const data = require('jest-resolve');
|
65 | _jestResolve = function () {
|
66 | return data;
|
67 | };
|
68 | return data;
|
69 | }
|
70 | function _jestUtil() {
|
71 | const data = require('jest-util');
|
72 | _jestUtil = function () {
|
73 | return data;
|
74 | };
|
75 | return data;
|
76 | }
|
77 | function _getRequireWildcardCache(nodeInterop) {
|
78 | if (typeof WeakMap !== 'function') return null;
|
79 | var cacheBabelInterop = new WeakMap();
|
80 | var cacheNodeInterop = new WeakMap();
|
81 | return (_getRequireWildcardCache = function (nodeInterop) {
|
82 | return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
83 | })(nodeInterop);
|
84 | }
|
85 | function _interopRequireWildcard(obj, nodeInterop) {
|
86 | if (!nodeInterop && obj && obj.__esModule) {
|
87 | return obj;
|
88 | }
|
89 | if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
|
90 | return {default: obj};
|
91 | }
|
92 | var cache = _getRequireWildcardCache(nodeInterop);
|
93 | if (cache && cache.has(obj)) {
|
94 | return cache.get(obj);
|
95 | }
|
96 | var newObj = {};
|
97 | var hasPropertyDescriptor =
|
98 | Object.defineProperty && Object.getOwnPropertyDescriptor;
|
99 | for (var key in obj) {
|
100 | if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
|
101 | var desc = hasPropertyDescriptor
|
102 | ? Object.getOwnPropertyDescriptor(obj, key)
|
103 | : null;
|
104 | if (desc && (desc.get || desc.set)) {
|
105 | Object.defineProperty(newObj, key, desc);
|
106 | } else {
|
107 | newObj[key] = obj[key];
|
108 | }
|
109 | }
|
110 | }
|
111 | newObj.default = obj;
|
112 | if (cache) {
|
113 | cache.set(obj, newObj);
|
114 | }
|
115 | return newObj;
|
116 | }
|
117 | function _interopRequireDefault(obj) {
|
118 | return obj && obj.__esModule ? obj : {default: obj};
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | function freezeConsole(testConsole, config) {
|
129 |
|
130 | testConsole._log = function fakeConsolePush(_type, message) {
|
131 | const error = new (_jestUtil().ErrorWithStack)(
|
132 | `${_chalk().default.red(
|
133 | `${_chalk().default.bold(
|
134 | 'Cannot log after tests are done.'
|
135 | )} Did you forget to wait for something async in your test?`
|
136 | )}\nAttempted to log "${message}".`,
|
137 | fakeConsolePush
|
138 | );
|
139 | const formattedError = (0, _jestMessageUtil().formatExecError)(
|
140 | error,
|
141 | config,
|
142 | {
|
143 | noStackTrace: false
|
144 | },
|
145 | undefined,
|
146 | true
|
147 | );
|
148 | process.stderr.write(`\n${formattedError}\n`);
|
149 | process.exitCode = 1;
|
150 | };
|
151 | }
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 | async function runTestInternal(
|
163 | path,
|
164 | globalConfig,
|
165 | projectConfig,
|
166 | resolver,
|
167 | context,
|
168 | sendMessageToJest
|
169 | ) {
|
170 | const testSource = fs().readFileSync(path, 'utf8');
|
171 | const docblockPragmas = docblock().parse(docblock().extract(testSource));
|
172 | const customEnvironment = docblockPragmas['jest-environment'];
|
173 | let testEnvironment = projectConfig.testEnvironment;
|
174 | if (customEnvironment) {
|
175 | if (Array.isArray(customEnvironment)) {
|
176 | throw new Error(
|
177 | `You can only define a single test environment through docblocks, got "${customEnvironment.join(
|
178 | ', '
|
179 | )}"`
|
180 | );
|
181 | }
|
182 | testEnvironment = (0, _jestResolve().resolveTestEnvironment)({
|
183 | ...projectConfig,
|
184 | requireResolveFunction: require.resolve,
|
185 | testEnvironment: customEnvironment
|
186 | });
|
187 | }
|
188 | const cacheFS = new Map([[path, testSource]]);
|
189 | const transformer = await (0, _transform().createScriptTransformer)(
|
190 | projectConfig,
|
191 | cacheFS
|
192 | );
|
193 | const TestEnvironment = await transformer.requireAndTranspileModule(
|
194 | testEnvironment
|
195 | );
|
196 | const testFramework = await transformer.requireAndTranspileModule(
|
197 | process.env.JEST_JASMINE === '1'
|
198 | ? require.resolve('jest-jasmine2')
|
199 | : projectConfig.testRunner
|
200 | );
|
201 | const Runtime = (0, _jestUtil().interopRequireDefault)(
|
202 | projectConfig.runtime
|
203 | ? require(projectConfig.runtime)
|
204 | : require('jest-runtime')
|
205 | ).default;
|
206 | const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout;
|
207 | const consoleFormatter = (type, message) =>
|
208 | (0, _console().getConsoleOutput)(
|
209 |
|
210 | _console().BufferedConsole.write([], type, message, 4),
|
211 | projectConfig,
|
212 | globalConfig
|
213 | );
|
214 | let testConsole;
|
215 | if (globalConfig.silent) {
|
216 | testConsole = new (_console().NullConsole)(
|
217 | consoleOut,
|
218 | consoleOut,
|
219 | consoleFormatter
|
220 | );
|
221 | } else if (globalConfig.verbose) {
|
222 | testConsole = new (_console().CustomConsole)(
|
223 | consoleOut,
|
224 | consoleOut,
|
225 | consoleFormatter
|
226 | );
|
227 | } else {
|
228 | testConsole = new (_console().BufferedConsole)();
|
229 | }
|
230 | let extraTestEnvironmentOptions;
|
231 | const docblockEnvironmentOptions =
|
232 | docblockPragmas['jest-environment-options'];
|
233 | if (typeof docblockEnvironmentOptions === 'string') {
|
234 | extraTestEnvironmentOptions = JSON.parse(docblockEnvironmentOptions);
|
235 | }
|
236 | const environment = new TestEnvironment(
|
237 | {
|
238 | globalConfig,
|
239 | projectConfig: extraTestEnvironmentOptions
|
240 | ? {
|
241 | ...projectConfig,
|
242 | testEnvironmentOptions: {
|
243 | ...projectConfig.testEnvironmentOptions,
|
244 | ...extraTestEnvironmentOptions
|
245 | }
|
246 | }
|
247 | : projectConfig
|
248 | },
|
249 | {
|
250 | console: testConsole,
|
251 | docblockPragmas,
|
252 | testPath: path
|
253 | }
|
254 | );
|
255 | if (typeof environment.getVmContext !== 'function') {
|
256 | console.error(
|
257 | `Test environment found at "${testEnvironment}" does not export a "getVmContext" method, which is mandatory from Jest 27. This method is a replacement for "runScript".`
|
258 | );
|
259 | process.exit(1);
|
260 | }
|
261 | const leakDetector = projectConfig.detectLeaks
|
262 | ? new (_jestLeakDetector().default)(environment)
|
263 | : null;
|
264 | (0, _jestUtil().setGlobal)(environment.global, 'console', testConsole);
|
265 | const runtime = new Runtime(
|
266 | projectConfig,
|
267 | environment,
|
268 | resolver,
|
269 | transformer,
|
270 | cacheFS,
|
271 | {
|
272 | changedFiles: context.changedFiles,
|
273 | collectCoverage: globalConfig.collectCoverage,
|
274 | collectCoverageFrom: globalConfig.collectCoverageFrom,
|
275 | coverageProvider: globalConfig.coverageProvider,
|
276 | sourcesRelatedToTestsInChangedFiles:
|
277 | context.sourcesRelatedToTestsInChangedFiles
|
278 | },
|
279 | path,
|
280 | globalConfig
|
281 | );
|
282 | let isTornDown = false;
|
283 | const tearDownEnv = async () => {
|
284 | if (!isTornDown) {
|
285 | runtime.teardown();
|
286 | await environment.teardown();
|
287 | isTornDown = true;
|
288 | }
|
289 | };
|
290 | const start = Date.now();
|
291 | for (const path of projectConfig.setupFiles) {
|
292 | const esm = runtime.unstable_shouldLoadAsEsm(path);
|
293 | if (esm) {
|
294 | await runtime.unstable_importModule(path);
|
295 | } else {
|
296 | const setupFile = runtime.requireModule(path);
|
297 | if (typeof setupFile === 'function') {
|
298 | await setupFile();
|
299 | }
|
300 | }
|
301 | }
|
302 | const sourcemapOptions = {
|
303 | environment: 'node',
|
304 | handleUncaughtExceptions: false,
|
305 | retrieveSourceMap: source => {
|
306 | const sourceMapSource = runtime.getSourceMaps()?.get(source);
|
307 | if (sourceMapSource) {
|
308 | try {
|
309 | return {
|
310 | map: JSON.parse(fs().readFileSync(sourceMapSource, 'utf8')),
|
311 | url: source
|
312 | };
|
313 | } catch {}
|
314 | }
|
315 | return null;
|
316 | }
|
317 | };
|
318 |
|
319 |
|
320 | runtime
|
321 | .requireInternalModule(require.resolve('source-map-support'))
|
322 | .install(sourcemapOptions);
|
323 |
|
324 |
|
325 | _sourceMapSupport().default.install(sourcemapOptions);
|
326 | if (
|
327 | environment.global &&
|
328 | environment.global.process &&
|
329 | environment.global.process.exit
|
330 | ) {
|
331 | const realExit = environment.global.process.exit;
|
332 | environment.global.process.exit = function exit(...args) {
|
333 | const error = new (_jestUtil().ErrorWithStack)(
|
334 | `process.exit called with "${args.join(', ')}"`,
|
335 | exit
|
336 | );
|
337 | const formattedError = (0, _jestMessageUtil().formatExecError)(
|
338 | error,
|
339 | projectConfig,
|
340 | {
|
341 | noStackTrace: false
|
342 | },
|
343 | undefined,
|
344 | true
|
345 | );
|
346 | process.stderr.write(formattedError);
|
347 | return realExit(...args);
|
348 | };
|
349 | }
|
350 |
|
351 |
|
352 | const collectV8Coverage =
|
353 | globalConfig.collectCoverage &&
|
354 | globalConfig.coverageProvider === 'v8' &&
|
355 | typeof environment.getVmContext === 'function';
|
356 |
|
357 |
|
358 |
|
359 | Error.stackTraceLimit = 100;
|
360 | try {
|
361 | await environment.setup();
|
362 | let result;
|
363 | try {
|
364 | if (collectV8Coverage) {
|
365 | await runtime.collectV8Coverage();
|
366 | }
|
367 | result = await testFramework(
|
368 | globalConfig,
|
369 | projectConfig,
|
370 | environment,
|
371 | runtime,
|
372 | path,
|
373 | sendMessageToJest
|
374 | );
|
375 | } catch (err) {
|
376 |
|
377 | err.stack;
|
378 | throw err;
|
379 | } finally {
|
380 | if (collectV8Coverage) {
|
381 | await runtime.stopCollectingV8Coverage();
|
382 | }
|
383 | }
|
384 | freezeConsole(testConsole, projectConfig);
|
385 | const testCount =
|
386 | result.numPassingTests +
|
387 | result.numFailingTests +
|
388 | result.numPendingTests +
|
389 | result.numTodoTests;
|
390 | const end = Date.now();
|
391 | const testRuntime = end - start;
|
392 | result.perfStats = {
|
393 | end,
|
394 | runtime: testRuntime,
|
395 | slow: testRuntime / 1000 > projectConfig.slowTestThreshold,
|
396 | start
|
397 | };
|
398 | result.testFilePath = path;
|
399 | result.console = testConsole.getBuffer();
|
400 | result.skipped = testCount === result.numPendingTests;
|
401 | result.displayName = projectConfig.displayName;
|
402 | const coverage = runtime.getAllCoverageInfoCopy();
|
403 | if (coverage) {
|
404 | const coverageKeys = Object.keys(coverage);
|
405 | if (coverageKeys.length) {
|
406 | result.coverage = coverage;
|
407 | }
|
408 | }
|
409 | if (collectV8Coverage) {
|
410 | const v8Coverage = runtime.getAllV8CoverageInfoCopy();
|
411 | if (v8Coverage && v8Coverage.length > 0) {
|
412 | result.v8Coverage = v8Coverage;
|
413 | }
|
414 | }
|
415 | if (globalConfig.logHeapUsage) {
|
416 |
|
417 | globalThis.gc?.();
|
418 | result.memoryUsage = process.memoryUsage().heapUsed;
|
419 | }
|
420 | await tearDownEnv();
|
421 |
|
422 |
|
423 | return await new Promise(resolve => {
|
424 | setImmediate(() =>
|
425 | resolve({
|
426 | leakDetector,
|
427 | result
|
428 | })
|
429 | );
|
430 | });
|
431 | } finally {
|
432 | await tearDownEnv();
|
433 | _sourceMapSupport().default.resetRetrieveHandlers();
|
434 | }
|
435 | }
|
436 | async function runTest(
|
437 | path,
|
438 | globalConfig,
|
439 | config,
|
440 | resolver,
|
441 | context,
|
442 | sendMessageToJest
|
443 | ) {
|
444 | const {leakDetector, result} = await runTestInternal(
|
445 | path,
|
446 | globalConfig,
|
447 | config,
|
448 | resolver,
|
449 | context,
|
450 | sendMessageToJest
|
451 | );
|
452 | if (leakDetector) {
|
453 |
|
454 | await new Promise(resolve => setTimeout(resolve, 100));
|
455 |
|
456 |
|
457 | result.leaks = await leakDetector.isLeaking();
|
458 | } else {
|
459 | result.leaks = false;
|
460 | }
|
461 | return result;
|
462 | }
|