Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 101x 101x 101x 97x 202x 202x 19x 19x 19x 19x 19x 19x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 6x 6x 6x 202x 202x 97x 101x 101x 101x 101x 25368x 737x 737x 737x 24631x 24631x 24631x 25368x 12293x 12293x 101x 101x 10644x 10644x 101x 101x 101x 101x 101x 101x 101x 101x 101x 101x 100x 100x 100x 100x 100x 100x 100x 101x 101x 101x 3x 3x 101x 101x 101x 101x 101x 101x 101x 10x 10x 10x 101x 101x 101x 101x 101x 101x 101x 97x 97x 664x 664x 66x 66x 66x 13x 66x 66x 664x 664x 97x 244x 244x 244x 244x 97x 194x 194x 307x 307x 307x 113x 113x 307x 194x 194x 298x 194x 194x 194x 388x 9x 388x 194x 194x 194x 97x 388x 388x 19x 19x 388x 388x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x 97x | 'use strict'; const { ArrayPrototypeForEach, SafeMap, SafeWeakSet, } = primordials; const { createHook, executionAsyncId, } = require('async_hooks'); const { codes: { ERR_TEST_FAILURE, }, } = require('internal/errors'); const { kEmptyObject } = require('internal/util'); const { getOptionValue } = require('internal/options'); const { kCancelledByParent, Test, ItTest, Suite } = require('internal/test_runner/test'); const { bigint: hrtime } = process.hrtime; const isTestRunnerCli = getOptionValue('--test'); const testResources = new SafeMap(); const wasRootSetup = new SafeWeakSet(); function createTestTree(options = kEmptyObject) { return setup(new Test({ __proto__: null, ...options, name: '<root>' })); } function createProcessEventHandler(eventName, rootTest) { return (err) => { // Check if this error is coming from a test. If it is, fail the test. const test = testResources.get(executionAsyncId()); if (!test) { throw err; } if (test.finished) { // If the test is already finished, report this as a top level // diagnostic since this is a malformed test. const msg = `Warning: Test "${test.name}" generated asynchronous ` + 'activity after the test ended. This activity created the error ' + `"${err}" and would have caused the test to fail, but instead ` + `triggered an ${eventName} event.`; rootTest.diagnostic(msg); return; } test.fail(new ERR_TEST_FAILURE(err, eventName)); test.postRun(); }; } function setup(root) { if (wasRootSetup.has(root)) { return root; } const hook = createHook({ init(asyncId, type, triggerAsyncId, resource) { if (resource instanceof Test) { testResources.set(asyncId, resource); return; } const parent = testResources.get(triggerAsyncId); if (parent !== undefined) { testResources.set(asyncId, parent); } }, destroy(asyncId) { testResources.delete(asyncId); } }); hook.enable(); const exceptionHandler = createProcessEventHandler('uncaughtException', root); const rejectionHandler = createProcessEventHandler('unhandledRejection', root); const exitHandler = () => { root.postRun(new ERR_TEST_FAILURE( 'Promise resolution is still pending but the event loop has already resolved', kCancelledByParent)); hook.disable(); process.removeListener('unhandledRejection', rejectionHandler); process.removeListener('uncaughtException', exceptionHandler); }; const terminationHandler = () => { exitHandler(); process.exit(); }; process.on('uncaughtException', exceptionHandler); process.on('unhandledRejection', rejectionHandler); process.on('beforeExit', exitHandler); // TODO(MoLow): Make it configurable to hook when isTestRunnerCli === false. if (isTestRunnerCli) { process.on('SIGINT', terminationHandler); process.on('SIGTERM', terminationHandler); } root.startTime = hrtime(); root.reporter.version(); wasRootSetup.add(root); return root; } let globalRoot; function getGlobalRoot() { if (!globalRoot) { globalRoot = createTestTree(); globalRoot.reporter.pipe(process.stdout); globalRoot.reporter.once('test:fail', () => { process.exitCode = 1; }); } return globalRoot; } function test(name, options, fn) { const subtest = getGlobalRoot().createSubtest(Test, name, options, fn); return subtest.start(); } function runInParentContext(Factory) { function run(name, options, fn, overrides) { const parent = testResources.get(executionAsyncId()) || getGlobalRoot(); const subtest = parent.createSubtest(Factory, name, options, fn, overrides); if (parent === getGlobalRoot()) { subtest.start(); } } const cb = (name, options, fn) => { run(name, options, fn); }; ArrayPrototypeForEach(['skip', 'todo'], (keyword) => { cb[keyword] = (name, options, fn) => { run(name, options, fn, { [keyword]: true }); }; }); return cb; } function hook(hook) { return (fn, options) => { const parent = testResources.get(executionAsyncId()) || getGlobalRoot(); parent.createHook(hook, fn, options); }; } module.exports = { createTestTree, test, describe: runInParentContext(Suite), it: runInParentContext(ItTest), before: hook('before'), after: hook('after'), beforeEach: hook('beforeEach'), afterEach: hook('afterEach'), }; |