Jest: Very poor performance on basic tests

Created on 23 Feb 2019  ·  62Comments  ·  Source: facebook/jest

🐛 Bug Report

I've created a simple test with no configuration. You can find it here. It takes 7.6 seconds just to start jest, and then, on file change, it takes 5 seconds to re-run.
There's clearly something wrong here.

Mocha and Chai, for example, start in around 4 seconds, but afterward, the re-run is almost instant.

It's weird that Jest reports that the test takes 14ms but shows me the result in 5 seconds.

image

On top of this, if you add more basic tests, the time just seems to go up.

image

To Reproduce

Clone my minimal repository, yarn install and yarn test.

Expected behavior

It should be faster than this.

Link to repl or repo (highly encouraged)

https://github.com/cozmy/jest-performance

Run npx envinfo --preset jest

Paste the results here:

  System:
    OS: Windows 10
    CPU: (8) x64 Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
  Binaries:
    Node: 8.12.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.13.0 - C:\Users\CosminCristian\AppData\Roaming\npm\yarn.CMD
    npm: 6.8.0 - C:\Program Files\nodejs\npm.CMD
Bug

Most helpful comment

The main startup delay seems to come from require()-ing all the dependencies.

time-require reports around 10 seconds worth of require() calls on my current system.

Main culprits, according to that tool are:

  • babel - this might just be specific to my setup (@babel/preset-env takes 3.6 seconds)
  • jsdom - 1.2 seconds in isolation
  • sane - 0.5 seconds in isolation, most of which is caused by micromatch 3.

For JSDOM, there is already some work for cutting down dependencies and thus improving load times. They also have an active issue regarding request, which takes my machine .25 seconds to load.

An actionable item for the jest team might be replacing sane.

This right here is the issue ☝️

I really, _really_ wish Jest would provide an option not to reload the entire module tree on every single test suite. We write our code in a mostly pure style and do not use mutable global state so it is a complete waste for us to be reloading modules every time. And it is a _huge_ waste: a typical test suite in our code base takes 16 seconds to run, and < 1 second of that is running the actual test!

All 62 comments

Your repo takes way less time for me:
4ms test case
0.7s according to jest
1.4s according to time
Reruns are pretty much instant.

On Windows, startup performance (of any Node process and especially if you do a lot of IO) will always be noticeably slower. You can try upgrading the Node version to 10 or 11 (8 is quite old), I'd expect a 10-20% speedup coming from that.
I'd try to profile the performance issue a bit, but I can't reproduce the terrible performance on my systems :/

Test: 8-10ms
Total: 2.4-2.8s

Reruns are very erratic if the rerun was triggered by a file change:

Test: 2-14ms
Total: 0.8-3.3s (typically on the upper end though, <2.5s is uncommon).

If it was triggered manually then it is pretty consistent with the first run. Interestingly, if I run with --no-cache then the first run is similar, but reruns on file changes are 0.8-0.9s and manual reruns are <0.2s. I think this might be because it throws away the timings of each run and causes Jest to run in-band (no extra workers). I usually run in-band on Windows because it's nearly always the fastest option, at least in watch mode. In WSL the performance is not quite as bad (though well short of native Linux) so I typically let Jest do whatever it wants.

As a side note, my runs seems to have been quite a bit faster than yours despite this machine having pretty dated hardware. That's pretty strange in itself.

  System:
    OS: Windows 8.1
    CPU: x64 Intel(R) Core(TM) i7 CPU         920  @ 2.67GHz
  Binaries:
    Node: 8.11.3
    Yarn: 1.7.0
    npm: 5.6.0
  npmPackages:
    jest:
      wanted: ^24.1.0
      installed: 24.1.0

To give you a bit of background, I was trying to set up the test environment on my work laptop and I noticed that my React tests were way to slow. That's when I've discovered the poor performance. I've also tested this on Linux and it's 2x as fast, but still, 3seconds on re-run for some basic tests it's too much.

It's weird that Jest reports that a test runs in 10ms but the reported time is 5seconds.

Even on my work laptop, running the tests on create-react-app are slow, on re-run:

image

I guess this issue is a duplicate of https://github.com/facebook/jest/issues/7619 and https://github.com/facebook/jest/issues/6694 so most likely it can be closed.

Mocha doesn't take 4 seconds to initialise in this case. I changed your test to do require('assert').equal(1, 112) and it took less than 200ms:

fabio@fabio-thinkpad ♥  time mocha index.spec.js 


  jest performance
    1) should be fast


  0 passing (6ms)
  1 failing

  1) jest performance
       should be fast:

      AssertionError [ERR_ASSERTION]: 1 == 112
      + expected - actual

      -1
      +112

      at Context.<anonymous> (index.spec.js:3:23)




real    0m0.173s
user    0m0.153s
sys     0m0.024s

Which by the way, if you add another test it doesn't take 173ms * 2 to run.

I've never seen a testing framework that takes more than 500ms to perform a single equality check. There must be some configuration option we can set here, and if there is, I would like to make the case for it to be in the defaults.

Just copied the original test 50 times to make sure. Results:

real    0m0.193s
user    0m0.157s
sys     0m0.040s

Tests run fine for me.

image

I tried this out on my Mac and got run times of 3-4s, so a bit closer to what you are describing. There is nothing that takes way longer than expected in the profile though, as I said it's just that IO performance is very OS-dependent, most of this is require loading modules:
image
One thing caught my eye in the flame chart though
image
Setting up a JSDOM environment is very expensive (the middle part of the chart). Setting testEnvironment to node if the tests don't need it cut the test time in half for me. I find it a bit unfortunate that the default is jsdom. @SimenB has there been any discussion on the default testEnvironment?

Also, I noticed that watch mode is not running inBand, which I think it should in this case. After setting the test environment to node and passing --watchAll --runInBand reruns are pretty much instant. I'll try to find out by Jest doesn't decide to runInBand automatically in this case.

@SimenB has there been any discussion on the default testEnvironment?

Yes, #5815. If you use jest --init, it defaults to node as well. I'd forgotten #5815 was accepted, would be nice to get done for 25.

After some investigation, the reason why Jest does not run the test inBand is the following:

  • On the first run, we do not know whether the one test will be fast, so we decide not to runInBand in order to keep the main thread unblocked and make sure the TTY remains responsive
  • Because this first run is not inBand, the overhead causes it to take about 2.2s on my device (even without JSDOM)
  • On rerun, Jest sees that the test took longer than 1s (the current SLOW_TEST_TIME threshold), so it again decides not to runInBand
  • You will never get out of this until you force runInBand once (and do one rerun, because the first runInBand execution also has to load everything which is slow), which causes the test time to go down to <100ms

I don't have a good solution to this other than making the threshold more generous right now

Because this first run is not inBand, the overhead causes it to take about 2.2s on my device (even without JSDOM)

Can you test with node worker threads? Still some overhead, but maybe not so much

@SimenB no noticeable change. jasmine2() has 1.5s total time when it initially requires all the modules, it's not really the worker overhead itself. In band the modules will be loaded after the first run so subsequent runs are almost instant.

(jest-circus is not significantly faster to load either)

There's no mechanism in place to reuse workers across watch runs, is there? Would it be unsafe to do so in case there is some kind of leftover state in the worker?

Workers are always reused, do you mean the sandbox? If so, no - we want every test to run in isolation

However, we want to lift jasmine/circus out of the sandbox and inject some integration points. Might help?

Workers are always reused

That's not what I'm seeing though, this is the first part of a rerun:
image

This is (like some other issues mentioned) definitely a regression introduced in 23.0.0
In 22.4.4, jasmine2() only takes about 600ms (less than half the time)

That should be fixed - the worker pool should be reused.

Could you bisect?

Will do, but it's not what causes the performance issue here. After quite a bit of profiling I've determined the culprit to be micromatch@3. I'll open a PR where we can discuss how to handle this.

I've determined the culprit to be micromatch@3

Really? Interesting! Looking forward to the analysis 🙂

Still no conclusion? :(

See #8032 / #8046 for the latest info

any updates now that micromatch@4 has released?

Seeing as it's a major, we'll probably upgrade in Jest 25 to be on the safe side

@SimenB i took a look in diagonal to all the posts @jeysal posted. great work!!

questions

  1. Can we put this micromatch fix at the begginning of the work for jest25? so we can play with it and see if it cover the major problem present on windows machines or needs more investigations?
  1. You have a branch next for futur release or it's master to contain the micromatch fix ?

Assuming no breaking changes, you can use yarn resolutions to test yourself.

https://yarnpkg.com/lang/en/docs/selective-version-resolutions/

I've been using yarn resolutions + micromatch v4 with no issues.

@jeysal well done!

A little followup my side with a repo test.
https://github.com/nasreddineskandrani/benchmark_jest
I took the initial code of this issue and did the test. It's working near jest@22 perf. if not better with micromatch4 and jest@24 so for me => it's conclusive. (check README(s))

waiting for jest@25 to try it at the job with Angular and npm (no way to yarn for now...)we have more than 2000 utests :) it ll be quick to see the diff.


@SimenB an idea:
you should add an automated test to check the timing it takes in your CI with the previous released version vs the current branch of jest (or one run nightly against master).
Let say if its more than 2x the previous time you fail it. I don't know if this way it will be a stable test => but jest needs a benchmark automation :)

would be nice to have the ability to see how long each test takes.

Looks like micromatch was bumped to 4.x in https://github.com/facebook/jest/pull/8852

Correct - you can install jest@next to test it out

The next version actually made tests run even longer in my case.

I'm still noticing a performance hit on both memory and execution time with jest@next.

Peak Memory Usage ([email protected])
jest-memory-23 6 0

Peak Memory Usage (jest@next)
jest-memory-next

Execution Time ([email protected])

real    4m11.202s
user    24m26.390s
sys 2m28.008s

Execution Time (jest@next)

real    7m29.054s
user    38m46.197s
sys 6m17.779s

Any tips on profiling this further? Perhaps a dependency of jest is still using [email protected] which is why the yarn resolution method fixed it for other people? The following jest dependencies are still tied to [email protected]:

For added context, my upgrade from 23.6.0 to next requires a jest.config.js change that looks like:

setupTestFrameworkScriptFile: '<rootDir>/test-utils/jest.setup.js',

to

setupFilesAfterEnv: [
    '<rootDir>/node_modules/regenerator-runtime/runtime.js', 
    '<rootDir>/test-utils/jest.setup.js'
],

So it's also possible there are other factors in play with my performance numbers.

And just for more information, here is my run with jest@next and the yarn resolution for [email protected]:

Peak Memory Usage (jest@next w/ [email protected] resolution):
jest-memory-next-with-resolution
Note: Memory usage does go down and plateau around 600mb though.

Execution Time (jest@next w/ [email protected] resolution):

real    5m45.275s
user    28m0.123s
sys 5m25.041s

@j3tan one regression has been identified and fixed in #8890, diffs for patch-package can be found in https://github.com/facebook/jest/issues/7811#issuecomment-527107215. Could you test with those?

sane has an issue for Micromatch 4 here: https://github.com/amasad/sane/issues/151
test-exclude seems to have replaced micromatch with minimatch a year ago: https://github.com/istanbuljs/istanbuljs/commit/01096aedc7c6a2615028bfab6e86202290514861#diff-d812e77478dc2316c1698d88682d3b05R37

You can run yarn why micromatch in your project to identify where it comes from. Running it on a clean install of jest@next gives this output:

[1/4] 🤔  Why do we have the module "micromatch"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "[email protected]"
info Has been hoisted to "micromatch"
info Reasons this module exists
   - Hoisted from "jest#jest-cli#@jest#core#micromatch"
   - Hoisted from "jest#jest-cli#jest-config#micromatch"
   - Hoisted from "jest#jest-cli#@jest#core#@jest#transform#micromatch"
   - Hoisted from "jest#jest-cli#@jest#core#jest-haste-map#micromatch"
   - Hoisted from "jest#jest-cli#@jest#core#jest-message-util#micromatch"
info Disk size without dependencies: "72KB"
info Disk size with unique dependencies: "256KB"
info Disk size with transitive dependencies: "404KB"
info Number of shared dependencies: 7
=> Found "sane#[email protected]"
info Reasons this module exists
   - "jest#jest-cli#@jest#core#jest-haste-map#sane" depends on it
   - Hoisted from "jest#jest-cli#@jest#core#jest-haste-map#sane#anymatch#micromatch"
info Disk size without dependencies: "108KB"
info Disk size with unique dependencies: "1.91MB"
info Disk size with transitive dependencies: "4.48MB"
info Number of shared dependencies: 29

So as soon as sane updates it should be gone from the dependency tree

Thanks for the feedback, I misread the diff in my upgrade for test-exclude

Here is my yarn why micromatch:

=> Found "[email protected]"
info Has been hoisted to "micromatch"
info Reasons this module exists
   - Hoisted from "readdirp#micromatch"
   - Hoisted from "add-asset-html-webpack-plugin#micromatch"
   - Hoisted from "anymatch#micromatch"
   - Hoisted from "webpack#micromatch"
   - Hoisted from "webpack-cli#findup-sync#micromatch"
   - Hoisted from "globby#fast-glob#micromatch"
   - Hoisted from "stylelint-config-rational-order#stylelint#micromatch"
   - Hoisted from "jest#jest-cli#@jest#core#jest-haste-map#sane#micromatch"

Looks like I'll have to wait for sane to upgrade to verify, though I may try out https://yarnpkg.com/lang/en/docs/selective-version-resolutions/ targeting sane if I have the chance

Running with the patch-package fix you mentioned yielded good results!

real    2m47.592s
user    15m9.926s
sys 1m31.482s

Memory usage still peaked around 800MB per node process though.

And what to do for npm users?)

NPM users can still use https://www.npmjs.com/package/patch-package

You can either downgrade to [email protected], use patch-package with the diff found here https://github.com/facebook/jest/issues/7811#issuecomment-527107215, or wait for https://github.com/facebook/jest/pull/8890 to merge and use jest@next

Edit: https://github.com/facebook/jest/pull/8890 is merged but has not been released yet, please wait for an official announcement before trying to use jest@next. Follow along in this issue instead (https://github.com/facebook/jest/issues/7811#issuecomment-529203848)

So #8890 was merged, but nothing has changed(

@romua it's merged, but not released yet. Patience.

Makes a lot of sense. Thanks for the answer)

@thymikee any updates?)

"jest": "^25.0.0" still sooo slooooooow, subsequent save/test 7.89s.
One file 4 simple asserts.
"test": "jest --watch -- calc.test.js"
--runInBand does not make significant difference. 4.29s

Tried also: "test": "jest --watch --runInBand --env=node -- calc.spec.js"no change.

In comparison jasmin => 1s and mocha blazing fast => 50ms - 500ms ...

It takes a long time for very simple tests
image

jest: v25.1.0

It is undeterministic though, sometime it completes within 2s.

experiencing the same issue with "jest": "^25.1.0",

The main startup delay seems to come from require()-ing all the dependencies.

time-require reports around 10 seconds worth of require() calls on my current system.

Main culprits, according to that tool are:

  • babel - this might just be specific to my setup (@babel/preset-env takes 3.6 seconds)
  • jsdom - 1.2 seconds in isolation
  • sane - 0.5 seconds in isolation, most of which is caused by micromatch 3.

For JSDOM, there is already some work for cutting down dependencies and thus improving load times. They also have an active issue regarding request, which takes my machine .25 seconds to load.

An actionable item for the jest team might be replacing sane.

I'm trying to do some looking into this and when I profile a suite of 100 example tests (which takes a bit over 8s w/ jest --runInBand, and about 1.5s w/ mocha), I see that vm's compileFunction is taking most of the time.

As far as I can tell, it's called for over 700 modules for each test file. Below is the list of files. Pretty much all of these are files I would not want to be loaded more than once.

Is there a way to disable the registry isolation for tests? (I realize this will break mocking and I am quite okay with that).

Also timing and files compiled are pretty much identical w/ and w/o jest-circus.


files

app/node_modules/source-map-support/source-map-support.js
app/node_modules/source-map/source-map.js
app/node_modules/source-map/lib/source-map-generator.js
app/node_modules/source-map/lib/base64-vlq.js
app/node_modules/source-map/lib/base64.js
app/node_modules/source-map/lib/util.js
app/node_modules/source-map/lib/array-set.js
app/node_modules/source-map/lib/mapping-list.js
app/node_modules/source-map/lib/source-map-consumer.js
app/node_modules/source-map/lib/binary-search.js
app/node_modules/source-map/lib/quick-sort.js
app/node_modules/source-map/lib/source-node.js
app/node_modules/buffer-from/index.js
app/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js
app/node_modules/@jest/test-result/build/index.js
app/node_modules/@jest/test-result/build/formatTestResults.js
app/node_modules/@jest/test-result/build/helpers.js
app/node_modules/expect/build/index.js
app/node_modules/jest-matcher-utils/build/index.js
app/node_modules/chalk/source/index.js
app/node_modules/ansi-styles/index.js
app/node_modules/supports-color/index.js
app/node_modules/supports-color/node_modules/has-flag/index.js
app/node_modules/chalk/source/util.js
app/node_modules/jest-diff/build/index.js
app/node_modules/pretty-format/build/index.js
app/node_modules/pretty-format/build/collections.js
app/node_modules/pretty-format/build/plugins/AsymmetricMatcher.js
app/node_modules/pretty-format/build/plugins/ConvertAnsi.js
app/node_modules/pretty-format/node_modules/ansi-regex/index.js
app/node_modules/pretty-format/build/plugins/DOMCollection.js
app/node_modules/pretty-format/build/plugins/DOMElement.js
app/node_modules/pretty-format/build/plugins/lib/markup.js
app/node_modules/pretty-format/build/plugins/lib/escapeHTML.js
app/node_modules/pretty-format/build/plugins/Immutable.js
app/node_modules/pretty-format/build/plugins/ReactElement.js
app/node_modules/react-is/index.js
app/node_modules/react-is/cjs/react-is.development.js
app/node_modules/pretty-format/build/plugins/ReactTestComponent.js
app/node_modules/jest-get-type/build/index.js
app/node_modules/jest-diff/build/cleanupSemantic.js
app/node_modules/jest-diff/build/diffLines.js
app/node_modules/diff-sequences/build/index.js
app/node_modules/jest-diff/build/normalizeDiffOptions.js
app/node_modules/jest-diff/build/printDiffs.js
app/node_modules/jest-diff/build/diffStrings.js
app/node_modules/jest-diff/build/getAlignedDiffs.js
app/node_modules/jest-diff/build/joinAlignedDiffs.js
app/node_modules/jest-diff/build/constants.js
app/node_modules/jest-matcher-utils/build/Replaceable.js
app/node_modules/jest-matcher-utils/build/deepCyclicCopyReplaceable.js
app/node_modules/expect/build/utils.js
app/node_modules/expect/build/jasmineUtils.js
app/node_modules/expect/build/matchers.js
app/node_modules/expect/build/print.js
app/node_modules/expect/build/spyMatchers.js
app/node_modules/expect/build/toThrowMatchers.js
app/node_modules/jest-message-util/build/index.js
app/node_modules/jest-message-util/node_modules/micromatch/index.js
app/node_modules/jest-message-util/node_modules/braces/index.js
app/node_modules/jest-message-util/node_modules/braces/lib/stringify.js
app/node_modules/jest-message-util/node_modules/braces/lib/utils.js
app/node_modules/jest-message-util/node_modules/braces/lib/compile.js
app/node_modules/jest-message-util/node_modules/fill-range/index.js
app/node_modules/jest-message-util/node_modules/to-regex-range/index.js
app/node_modules/jest-message-util/node_modules/is-number/index.js
app/node_modules/jest-message-util/node_modules/braces/lib/expand.js
app/node_modules/jest-message-util/node_modules/braces/lib/parse.js
app/node_modules/jest-message-util/node_modules/braces/lib/constants.js
app/node_modules/picomatch/index.js
app/node_modules/picomatch/lib/picomatch.js
app/node_modules/picomatch/lib/scan.js
app/node_modules/picomatch/lib/utils.js
app/node_modules/picomatch/lib/constants.js
app/node_modules/picomatch/lib/parse.js
app/node_modules/slash/index.js
app/node_modules/@babel/code-frame/lib/index.js
app/node_modules/@babel/highlight/lib/index.js
app/node_modules/js-tokens/index.js
app/node_modules/@babel/helper-validator-identifier/lib/index.js
app/node_modules/@babel/helper-validator-identifier/lib/identifier.js
app/node_modules/@babel/helper-validator-identifier/lib/keyword.js
app/node_modules/@babel/highlight/node_modules/chalk/index.js
app/node_modules/escape-string-regexp/index.js
app/node_modules/@babel/highlight/node_modules/ansi-styles/index.js
app/node_modules/color-convert/index.js
app/node_modules/color-convert/conversions.js
app/node_modules/color-convert/node_modules/color-name/index.js
app/node_modules/color-convert/route.js
app/node_modules/@babel/highlight/node_modules/supports-color/index.js
app/node_modules/has-flag/index.js
app/node_modules/@babel/highlight/node_modules/chalk/templates.js
app/node_modules/stack-utils/index.js
app/node_modules/expect/build/asymmetricMatchers.js
app/node_modules/expect/build/jestMatchersObject.js
app/node_modules/expect/build/extractExpectedAssertionsErrors.js
app/node_modules/jest-snapshot/build/index.js
app/node_modules/jest-snapshot/build/snapshot_resolver.js
app/node_modules/jest-snapshot/build/State.js
app/node_modules/jest-snapshot/build/utils.js
app/node_modules/make-dir/index.js
app/node_modules/semver/semver.js
app/node_modules/natural-compare/index.js
app/node_modules/jest-snapshot/build/plugins.js
app/node_modules/jest-snapshot/build/mock_serializer.js
app/node_modules/jest-snapshot/build/inline_snapshots.js
app/node_modules/@babel/types/lib/index.js
app/node_modules/@babel/types/lib/validators/react/isReactComponent.js
app/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js
app/node_modules/@babel/types/lib/validators/matchesPattern.js
app/node_modules/@babel/types/lib/validators/generated/index.js
app/node_modules/@babel/types/lib/utils/shallowEqual.js
app/node_modules/@babel/types/lib/validators/react/isCompatTag.js
app/node_modules/@babel/types/lib/builders/react/buildChildren.js
app/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js
app/node_modules/@babel/types/lib/builders/generated/index.js
app/node_modules/@babel/types/lib/builders/builder.js
app/node_modules/lodash/clone.js
app/node_modules/lodash/_baseClone.js
app/node_modules/lodash/_Stack.js
app/node_modules/lodash/_ListCache.js
app/node_modules/lodash/_listCacheClear.js
app/node_modules/lodash/_listCacheDelete.js
app/node_modules/lodash/_assocIndexOf.js
app/node_modules/lodash/eq.js
app/node_modules/lodash/_listCacheGet.js
app/node_modules/lodash/_listCacheHas.js
app/node_modules/lodash/_listCacheSet.js
app/node_modules/lodash/_stackClear.js
app/node_modules/lodash/_stackDelete.js
app/node_modules/lodash/_stackGet.js
app/node_modules/lodash/_stackHas.js
app/node_modules/lodash/_stackSet.js
app/node_modules/lodash/_Map.js
app/node_modules/lodash/_getNative.js
app/node_modules/lodash/_baseIsNative.js
app/node_modules/lodash/isFunction.js
app/node_modules/lodash/_baseGetTag.js
app/node_modules/lodash/_Symbol.js
app/node_modules/lodash/_root.js
app/node_modules/lodash/_freeGlobal.js
app/node_modules/lodash/_getRawTag.js
app/node_modules/lodash/_objectToString.js
app/node_modules/lodash/isObject.js
app/node_modules/lodash/_isMasked.js
app/node_modules/lodash/_coreJsData.js
app/node_modules/lodash/_toSource.js
app/node_modules/lodash/_getValue.js
app/node_modules/lodash/_MapCache.js
app/node_modules/lodash/_mapCacheClear.js
app/node_modules/lodash/_Hash.js
app/node_modules/lodash/_hashClear.js
app/node_modules/lodash/_nativeCreate.js
app/node_modules/lodash/_hashDelete.js
app/node_modules/lodash/_hashGet.js
app/node_modules/lodash/_hashHas.js
app/node_modules/lodash/_hashSet.js
app/node_modules/lodash/_mapCacheDelete.js
app/node_modules/lodash/_getMapData.js
app/node_modules/lodash/_isKeyable.js
app/node_modules/lodash/_mapCacheGet.js
app/node_modules/lodash/_mapCacheHas.js
app/node_modules/lodash/_mapCacheSet.js
app/node_modules/lodash/_arrayEach.js
app/node_modules/lodash/_assignValue.js
app/node_modules/lodash/_baseAssignValue.js
app/node_modules/lodash/_defineProperty.js
app/node_modules/lodash/_baseAssign.js
app/node_modules/lodash/_copyObject.js
app/node_modules/lodash/keys.js
app/node_modules/lodash/_arrayLikeKeys.js
app/node_modules/lodash/_baseTimes.js
app/node_modules/lodash/isArguments.js
app/node_modules/lodash/_baseIsArguments.js
app/node_modules/lodash/isObjectLike.js
app/node_modules/lodash/isArray.js
app/node_modules/lodash/isBuffer.js
app/node_modules/lodash/stubFalse.js
app/node_modules/lodash/_isIndex.js
app/node_modules/lodash/isTypedArray.js
app/node_modules/lodash/_baseIsTypedArray.js
app/node_modules/lodash/isLength.js
app/node_modules/lodash/_baseUnary.js
app/node_modules/lodash/_nodeUtil.js
app/node_modules/lodash/_baseKeys.js
app/node_modules/lodash/_isPrototype.js
app/node_modules/lodash/_nativeKeys.js
app/node_modules/lodash/_overArg.js
app/node_modules/lodash/isArrayLike.js
app/node_modules/lodash/_baseAssignIn.js
app/node_modules/lodash/keysIn.js
app/node_modules/lodash/_baseKeysIn.js
app/node_modules/lodash/_nativeKeysIn.js
app/node_modules/lodash/_cloneBuffer.js
app/node_modules/lodash/_copyArray.js
app/node_modules/lodash/_copySymbols.js
app/node_modules/lodash/_getSymbols.js
app/node_modules/lodash/_arrayFilter.js
app/node_modules/lodash/stubArray.js
app/node_modules/lodash/_copySymbolsIn.js
app/node_modules/lodash/_getSymbolsIn.js
app/node_modules/lodash/_arrayPush.js
app/node_modules/lodash/_getPrototype.js
app/node_modules/lodash/_getAllKeys.js
app/node_modules/lodash/_baseGetAllKeys.js
app/node_modules/lodash/_getAllKeysIn.js
app/node_modules/lodash/_getTag.js
app/node_modules/lodash/_DataView.js
app/node_modules/lodash/_Promise.js
app/node_modules/lodash/_Set.js
app/node_modules/lodash/_WeakMap.js
app/node_modules/lodash/_initCloneArray.js
app/node_modules/lodash/_initCloneByTag.js
app/node_modules/lodash/_cloneArrayBuffer.js
app/node_modules/lodash/_Uint8Array.js
app/node_modules/lodash/_cloneDataView.js
app/node_modules/lodash/_cloneRegExp.js
app/node_modules/lodash/_cloneSymbol.js
app/node_modules/lodash/_cloneTypedArray.js
app/node_modules/lodash/_initCloneObject.js
app/node_modules/lodash/_baseCreate.js
app/node_modules/lodash/isMap.js
app/node_modules/lodash/_baseIsMap.js
app/node_modules/lodash/isSet.js
app/node_modules/lodash/_baseIsSet.js
app/node_modules/@babel/types/lib/definitions/index.js
app/node_modules/to-fast-properties/index.js
app/node_modules/@babel/types/lib/definitions/core.js
app/node_modules/@babel/types/lib/validators/is.js
app/node_modules/@babel/types/lib/validators/isType.js
app/node_modules/@babel/types/lib/validators/isPlaceholderType.js
app/node_modules/@babel/types/lib/validators/isValidIdentifier.js
app/node_modules/@babel/types/lib/constants/index.js
app/node_modules/@babel/types/lib/definitions/utils.js
app/node_modules/@babel/types/lib/validators/validate.js
app/node_modules/@babel/types/lib/definitions/es2015.js
app/node_modules/@babel/types/lib/definitions/flow.js
app/node_modules/@babel/types/lib/definitions/jsx.js
app/node_modules/@babel/types/lib/definitions/misc.js
app/node_modules/@babel/types/lib/definitions/placeholders.js
app/node_modules/@babel/types/lib/definitions/experimental.js
app/node_modules/@babel/types/lib/definitions/typescript.js
app/node_modules/@babel/types/lib/asserts/assertNode.js
app/node_modules/@babel/types/lib/validators/isNode.js
app/node_modules/@babel/types/lib/asserts/generated/index.js
app/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js
app/node_modules/@babel/types/lib/builders/flow/createUnionTypeAnnotation.js
app/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js
app/node_modules/@babel/types/lib/clone/cloneNode.js
app/node_modules/@babel/types/lib/clone/clone.js
app/node_modules/@babel/types/lib/clone/cloneDeep.js
app/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js
app/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js
app/node_modules/@babel/types/lib/comments/addComment.js
app/node_modules/@babel/types/lib/comments/addComments.js
app/node_modules/@babel/types/lib/comments/inheritInnerComments.js
app/node_modules/@babel/types/lib/utils/inherit.js
app/node_modules/lodash/uniq.js
app/node_modules/lodash/_baseUniq.js
app/node_modules/lodash/_SetCache.js
app/node_modules/lodash/_setCacheAdd.js
app/node_modules/lodash/_setCacheHas.js
app/node_modules/lodash/_arrayIncludes.js
app/node_modules/lodash/_baseIndexOf.js
app/node_modules/lodash/_baseFindIndex.js
app/node_modules/lodash/_baseIsNaN.js
app/node_modules/lodash/_strictIndexOf.js
app/node_modules/lodash/_arrayIncludesWith.js
app/node_modules/lodash/_cacheHas.js
app/node_modules/lodash/_createSet.js
app/node_modules/lodash/noop.js
app/node_modules/lodash/_setToArray.js
app/node_modules/@babel/types/lib/comments/inheritLeadingComments.js
app/node_modules/@babel/types/lib/comments/inheritsComments.js
app/node_modules/@babel/types/lib/comments/inheritTrailingComments.js
app/node_modules/@babel/types/lib/comments/removeComments.js
app/node_modules/@babel/types/lib/constants/generated/index.js
app/node_modules/@babel/types/lib/converters/ensureBlock.js
app/node_modules/@babel/types/lib/converters/toBlock.js
app/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js
app/node_modules/@babel/types/lib/converters/toIdentifier.js
app/node_modules/@babel/types/lib/converters/toComputedKey.js
app/node_modules/@babel/types/lib/converters/toExpression.js
app/node_modules/@babel/types/lib/converters/toKeyAlias.js
app/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js
app/node_modules/@babel/types/lib/traverse/traverseFast.js
app/node_modules/@babel/types/lib/modifications/removeProperties.js
app/node_modules/@babel/types/lib/converters/toSequenceExpression.js
app/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js
app/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js
app/node_modules/@babel/types/lib/converters/toStatement.js
app/node_modules/@babel/types/lib/converters/valueToNode.js
app/node_modules/lodash/isPlainObject.js
app/node_modules/lodash/isRegExp.js
app/node_modules/lodash/_baseIsRegExp.js
app/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js
app/node_modules/@babel/types/lib/modifications/inherits.js
app/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js
app/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js
app/node_modules/@babel/types/lib/traverse/traverse.js
app/node_modules/@babel/types/lib/validators/isBinding.js
app/node_modules/@babel/types/lib/validators/isBlockScoped.js
app/node_modules/@babel/types/lib/validators/isLet.js
app/node_modules/@babel/types/lib/validators/isImmutable.js
app/node_modules/@babel/types/lib/validators/isNodesEquivalent.js
app/node_modules/@babel/types/lib/validators/isReferenced.js
app/node_modules/@babel/types/lib/validators/isScope.js
app/node_modules/@babel/types/lib/validators/isSpecifierDefault.js
app/node_modules/@babel/types/lib/validators/isValidES3Identifier.js
app/node_modules/@babel/types/lib/validators/isVar.js
app/node_modules/jest-snapshot/build/printSnapshot.js
app/node_modules/jest-snapshot/build/colors.js
app/node_modules/jest-snapshot/build/dedentLines.js
app/node_modules/ansi-styles/node_modules/color-convert/index.js
app/node_modules/ansi-styles/node_modules/color-convert/conversions.js
app/node_modules/color-name/index.js
app/node_modules/ansi-styles/node_modules/color-convert/route.js
app/node_modules/throat/index.js
app/node_modules/jest-circus/build/state.js
app/node_modules/jest-circus/build/types.js
app/node_modules/jest-circus/build/utils.js
app/node_modules/jest-util/build/index.js
app/node_modules/jest-util/build/clearLine.js
app/node_modules/jest-util/build/createDirectory.js
app/node_modules/jest-util/build/ErrorWithStack.js
app/node_modules/jest-util/build/installCommonGlobals.js
app/node_modules/jest-util/build/createProcessObject.js
app/node_modules/jest-util/build/deepCyclicCopy.js
app/node_modules/jest-util/build/interopRequireDefault.js
app/node_modules/jest-util/build/isInteractive.js
app/node_modules/is-ci/index.js
app/node_modules/ci-info/index.js
app/node_modules/jest-util/build/isPromise.js
app/node_modules/jest-util/build/setGlobal.js
app/node_modules/jest-util/build/convertDescriptorToString.js
app/node_modules/jest-util/build/specialChars.js
app/node_modules/jest-util/build/replacePathSepForGlob.js
app/node_modules/jest-util/build/testPathPatternToRegExp.js
app/node_modules/jest-util/build/preRunMessage.js
app/node_modules/jest-util/build/pluralize.js
app/node_modules/is-generator-fn/index.js
app/node_modules/co/index.js
app/node_modules/jest-circus/build/eventHandler.js
app/node_modules/jest-circus/build/globalErrorHandlers.js
app/node_modules/jest-circus/build/formatNodeAssertErrors.js
app/node_modules/jest-circus/build/run.js
app/node_modules/jest-circus/build/index.js
app/node_modules/jest-each/build/index.js
app/node_modules/jest-each/build/bind.js
app/node_modules/jest-each/build/table/array.js
app/node_modules/jest-each/build/table/template.js
app/node_modules/jest-each/build/validation.js
app/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestExpect.js
app/test/example-90.test.ts
app/node_modules/source-map-support/source-map-support.js
app/node_modules/source-map/source-map.js
app/node_modules/source-map/lib/source-map-generator.js
app/node_modules/source-map/lib/base64-vlq.js
app/node_modules/source-map/lib/base64.js
app/node_modules/source-map/lib/util.js
app/node_modules/source-map/lib/array-set.js
app/node_modules/source-map/lib/mapping-list.js
app/node_modules/source-map/lib/source-map-consumer.js
app/node_modules/source-map/lib/binary-search.js
app/node_modules/source-map/lib/quick-sort.js
app/node_modules/source-map/lib/source-node.js
app/node_modules/buffer-from/index.js
app/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js
app/node_modules/@jest/test-result/build/index.js
app/node_modules/@jest/test-result/build/formatTestResults.js
app/node_modules/@jest/test-result/build/helpers.js
app/node_modules/expect/build/index.js
app/node_modules/jest-matcher-utils/build/index.js
app/node_modules/chalk/source/index.js
app/node_modules/ansi-styles/index.js
app/node_modules/supports-color/index.js
app/node_modules/supports-color/node_modules/has-flag/index.js
app/node_modules/chalk/source/util.js
app/node_modules/jest-diff/build/index.js
app/node_modules/pretty-format/build/index.js
app/node_modules/pretty-format/build/collections.js
app/node_modules/pretty-format/build/plugins/AsymmetricMatcher.js
app/node_modules/pretty-format/build/plugins/ConvertAnsi.js
app/node_modules/pretty-format/node_modules/ansi-regex/index.js
app/node_modules/pretty-format/build/plugins/DOMCollection.js
app/node_modules/pretty-format/build/plugins/DOMElement.js
app/node_modules/pretty-format/build/plugins/lib/markup.js
app/node_modules/pretty-format/build/plugins/lib/escapeHTML.js
app/node_modules/pretty-format/build/plugins/Immutable.js
app/node_modules/pretty-format/build/plugins/ReactElement.js
app/node_modules/react-is/index.js
app/node_modules/react-is/cjs/react-is.development.js
app/node_modules/pretty-format/build/plugins/ReactTestComponent.js
app/node_modules/jest-get-type/build/index.js
app/node_modules/jest-diff/build/cleanupSemantic.js
app/node_modules/jest-diff/build/diffLines.js
app/node_modules/diff-sequences/build/index.js
app/node_modules/jest-diff/build/normalizeDiffOptions.js
app/node_modules/jest-diff/build/printDiffs.js
app/node_modules/jest-diff/build/diffStrings.js
app/node_modules/jest-diff/build/getAlignedDiffs.js
app/node_modules/jest-diff/build/joinAlignedDiffs.js
app/node_modules/jest-diff/build/constants.js
app/node_modules/jest-matcher-utils/build/Replaceable.js
app/node_modules/jest-matcher-utils/build/deepCyclicCopyReplaceable.js
app/node_modules/expect/build/utils.js
app/node_modules/expect/build/jasmineUtils.js
app/node_modules/expect/build/matchers.js
app/node_modules/expect/build/print.js
app/node_modules/expect/build/spyMatchers.js
app/node_modules/expect/build/toThrowMatchers.js
app/node_modules/jest-message-util/build/index.js
app/node_modules/jest-message-util/node_modules/micromatch/index.js
app/node_modules/jest-message-util/node_modules/braces/index.js
app/node_modules/jest-message-util/node_modules/braces/lib/stringify.js
app/node_modules/jest-message-util/node_modules/braces/lib/utils.js
app/node_modules/jest-message-util/node_modules/braces/lib/compile.js
app/node_modules/jest-message-util/node_modules/fill-range/index.js
app/node_modules/jest-message-util/node_modules/to-regex-range/index.js
app/node_modules/jest-message-util/node_modules/is-number/index.js
app/node_modules/jest-message-util/node_modules/braces/lib/expand.js
app/node_modules/jest-message-util/node_modules/braces/lib/parse.js
app/node_modules/jest-message-util/node_modules/braces/lib/constants.js
app/node_modules/picomatch/index.js
app/node_modules/picomatch/lib/picomatch.js
app/node_modules/picomatch/lib/scan.js
app/node_modules/picomatch/lib/utils.js
app/node_modules/picomatch/lib/constants.js
app/node_modules/picomatch/lib/parse.js
app/node_modules/slash/index.js
app/node_modules/@babel/code-frame/lib/index.js
app/node_modules/@babel/highlight/lib/index.js
app/node_modules/js-tokens/index.js
app/node_modules/@babel/helper-validator-identifier/lib/index.js
app/node_modules/@babel/helper-validator-identifier/lib/identifier.js
app/node_modules/@babel/helper-validator-identifier/lib/keyword.js
app/node_modules/@babel/highlight/node_modules/chalk/index.js
app/node_modules/escape-string-regexp/index.js
app/node_modules/@babel/highlight/node_modules/ansi-styles/index.js
app/node_modules/color-convert/index.js
app/node_modules/color-convert/conversions.js
app/node_modules/color-convert/node_modules/color-name/index.js
app/node_modules/color-convert/route.js
app/node_modules/@babel/highlight/node_modules/supports-color/index.js
app/node_modules/has-flag/index.js
app/node_modules/@babel/highlight/node_modules/chalk/templates.js
app/node_modules/stack-utils/index.js
app/node_modules/expect/build/asymmetricMatchers.js
app/node_modules/expect/build/jestMatchersObject.js
app/node_modules/expect/build/extractExpectedAssertionsErrors.js
app/node_modules/jest-snapshot/build/index.js
app/node_modules/jest-snapshot/build/snapshot_resolver.js
app/node_modules/jest-snapshot/build/State.js
app/node_modules/jest-snapshot/build/utils.js
app/node_modules/make-dir/index.js
app/node_modules/semver/semver.js
app/node_modules/natural-compare/index.js
app/node_modules/jest-snapshot/build/plugins.js
app/node_modules/jest-snapshot/build/mock_serializer.js
app/node_modules/jest-snapshot/build/inline_snapshots.js
app/node_modules/@babel/types/lib/index.js
app/node_modules/@babel/types/lib/validators/react/isReactComponent.js
app/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js
app/node_modules/@babel/types/lib/validators/matchesPattern.js
app/node_modules/@babel/types/lib/validators/generated/index.js
app/node_modules/@babel/types/lib/utils/shallowEqual.js
app/node_modules/@babel/types/lib/validators/react/isCompatTag.js
app/node_modules/@babel/types/lib/builders/react/buildChildren.js
app/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js
app/node_modules/@babel/types/lib/builders/generated/index.js
app/node_modules/@babel/types/lib/builders/builder.js
app/node_modules/lodash/clone.js
app/node_modules/lodash/_baseClone.js
app/node_modules/lodash/_Stack.js
app/node_modules/lodash/_ListCache.js
app/node_modules/lodash/_listCacheClear.js
app/node_modules/lodash/_listCacheDelete.js
app/node_modules/lodash/_assocIndexOf.js
app/node_modules/lodash/eq.js
app/node_modules/lodash/_listCacheGet.js
app/node_modules/lodash/_listCacheHas.js
app/node_modules/lodash/_listCacheSet.js
app/node_modules/lodash/_stackClear.js
app/node_modules/lodash/_stackDelete.js
app/node_modules/lodash/_stackGet.js
app/node_modules/lodash/_stackHas.js
app/node_modules/lodash/_stackSet.js
app/node_modules/lodash/_Map.js
app/node_modules/lodash/_getNative.js
app/node_modules/lodash/_baseIsNative.js
app/node_modules/lodash/isFunction.js
app/node_modules/lodash/_baseGetTag.js
app/node_modules/lodash/_Symbol.js
app/node_modules/lodash/_root.js
app/node_modules/lodash/_freeGlobal.js
app/node_modules/lodash/_getRawTag.js
app/node_modules/lodash/_objectToString.js
app/node_modules/lodash/isObject.js
app/node_modules/lodash/_isMasked.js
app/node_modules/lodash/_coreJsData.js
app/node_modules/lodash/_toSource.js
app/node_modules/lodash/_getValue.js
app/node_modules/lodash/_MapCache.js
app/node_modules/lodash/_mapCacheClear.js
app/node_modules/lodash/_Hash.js
app/node_modules/lodash/_hashClear.js
app/node_modules/lodash/_nativeCreate.js
app/node_modules/lodash/_hashDelete.js
app/node_modules/lodash/_hashGet.js
app/node_modules/lodash/_hashHas.js
app/node_modules/lodash/_hashSet.js
app/node_modules/lodash/_mapCacheDelete.js
app/node_modules/lodash/_getMapData.js
app/node_modules/lodash/_isKeyable.js
app/node_modules/lodash/_mapCacheGet.js
app/node_modules/lodash/_mapCacheHas.js
app/node_modules/lodash/_mapCacheSet.js
app/node_modules/lodash/_arrayEach.js
app/node_modules/lodash/_assignValue.js
app/node_modules/lodash/_baseAssignValue.js
app/node_modules/lodash/_defineProperty.js
app/node_modules/lodash/_baseAssign.js
app/node_modules/lodash/_copyObject.js
app/node_modules/lodash/keys.js
app/node_modules/lodash/_arrayLikeKeys.js
app/node_modules/lodash/_baseTimes.js
app/node_modules/lodash/isArguments.js
app/node_modules/lodash/_baseIsArguments.js
app/node_modules/lodash/isObjectLike.js
app/node_modules/lodash/isArray.js
app/node_modules/lodash/isBuffer.js
app/node_modules/lodash/stubFalse.js
app/node_modules/lodash/_isIndex.js
app/node_modules/lodash/isTypedArray.js
app/node_modules/lodash/_baseIsTypedArray.js
app/node_modules/lodash/isLength.js
app/node_modules/lodash/_baseUnary.js
app/node_modules/lodash/_nodeUtil.js
app/node_modules/lodash/_baseKeys.js
app/node_modules/lodash/_isPrototype.js
app/node_modules/lodash/_nativeKeys.js
app/node_modules/lodash/_overArg.js
app/node_modules/lodash/isArrayLike.js
app/node_modules/lodash/_baseAssignIn.js
app/node_modules/lodash/keysIn.js
app/node_modules/lodash/_baseKeysIn.js
app/node_modules/lodash/_nativeKeysIn.js
app/node_modules/lodash/_cloneBuffer.js
app/node_modules/lodash/_copyArray.js
app/node_modules/lodash/_copySymbols.js
app/node_modules/lodash/_getSymbols.js
app/node_modules/lodash/_arrayFilter.js
app/node_modules/lodash/stubArray.js
app/node_modules/lodash/_copySymbolsIn.js
app/node_modules/lodash/_getSymbolsIn.js
app/node_modules/lodash/_arrayPush.js
app/node_modules/lodash/_getPrototype.js
app/node_modules/lodash/_getAllKeys.js
app/node_modules/lodash/_baseGetAllKeys.js
app/node_modules/lodash/_getAllKeysIn.js
app/node_modules/lodash/_getTag.js
app/node_modules/lodash/_DataView.js
app/node_modules/lodash/_Promise.js
app/node_modules/lodash/_Set.js
app/node_modules/lodash/_WeakMap.js
app/node_modules/lodash/_initCloneArray.js
app/node_modules/lodash/_initCloneByTag.js
app/node_modules/lodash/_cloneArrayBuffer.js
app/node_modules/lodash/_Uint8Array.js
app/node_modules/lodash/_cloneDataView.js
app/node_modules/lodash/_cloneRegExp.js
app/node_modules/lodash/_cloneSymbol.js
app/node_modules/lodash/_cloneTypedArray.js
app/node_modules/lodash/_initCloneObject.js
app/node_modules/lodash/_baseCreate.js
app/node_modules/lodash/isMap.js
app/node_modules/lodash/_baseIsMap.js
app/node_modules/lodash/isSet.js
app/node_modules/lodash/_baseIsSet.js
app/node_modules/@babel/types/lib/definitions/index.js
app/node_modules/to-fast-properties/index.js
app/node_modules/@babel/types/lib/definitions/core.js
app/node_modules/@babel/types/lib/validators/is.js
app/node_modules/@babel/types/lib/validators/isType.js
app/node_modules/@babel/types/lib/validators/isPlaceholderType.js
app/node_modules/@babel/types/lib/validators/isValidIdentifier.js
app/node_modules/@babel/types/lib/constants/index.js
app/node_modules/@babel/types/lib/definitions/utils.js
app/node_modules/@babel/types/lib/validators/validate.js
app/node_modules/@babel/types/lib/definitions/es2015.js
app/node_modules/@babel/types/lib/definitions/flow.js
app/node_modules/@babel/types/lib/definitions/jsx.js
app/node_modules/@babel/types/lib/definitions/misc.js
app/node_modules/@babel/types/lib/definitions/placeholders.js
app/node_modules/@babel/types/lib/definitions/experimental.js
app/node_modules/@babel/types/lib/definitions/typescript.js
app/node_modules/@babel/types/lib/asserts/assertNode.js
app/node_modules/@babel/types/lib/validators/isNode.js
app/node_modules/@babel/types/lib/asserts/generated/index.js
app/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js
app/node_modules/@babel/types/lib/builders/flow/createUnionTypeAnnotation.js
app/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js
app/node_modules/@babel/types/lib/clone/cloneNode.js
app/node_modules/@babel/types/lib/clone/clone.js
app/node_modules/@babel/types/lib/clone/cloneDeep.js
app/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js
app/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js
app/node_modules/@babel/types/lib/comments/addComment.js
app/node_modules/@babel/types/lib/comments/addComments.js
app/node_modules/@babel/types/lib/comments/inheritInnerComments.js
app/node_modules/@babel/types/lib/utils/inherit.js
app/node_modules/lodash/uniq.js
app/node_modules/lodash/_baseUniq.js
app/node_modules/lodash/_SetCache.js
app/node_modules/lodash/_setCacheAdd.js
app/node_modules/lodash/_setCacheHas.js
app/node_modules/lodash/_arrayIncludes.js
app/node_modules/lodash/_baseIndexOf.js
app/node_modules/lodash/_baseFindIndex.js
app/node_modules/lodash/_baseIsNaN.js
app/node_modules/lodash/_strictIndexOf.js
app/node_modules/lodash/_arrayIncludesWith.js
app/node_modules/lodash/_cacheHas.js
app/node_modules/lodash/_createSet.js
app/node_modules/lodash/noop.js
app/node_modules/lodash/_setToArray.js
app/node_modules/@babel/types/lib/comments/inheritLeadingComments.js
app/node_modules/@babel/types/lib/comments/inheritsComments.js
app/node_modules/@babel/types/lib/comments/inheritTrailingComments.js
app/node_modules/@babel/types/lib/comments/removeComments.js
app/node_modules/@babel/types/lib/constants/generated/index.js
app/node_modules/@babel/types/lib/converters/ensureBlock.js
app/node_modules/@babel/types/lib/converters/toBlock.js
app/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js
app/node_modules/@babel/types/lib/converters/toIdentifier.js
app/node_modules/@babel/types/lib/converters/toComputedKey.js
app/node_modules/@babel/types/lib/converters/toExpression.js
app/node_modules/@babel/types/lib/converters/toKeyAlias.js
app/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js
app/node_modules/@babel/types/lib/traverse/traverseFast.js
app/node_modules/@babel/types/lib/modifications/removeProperties.js
app/node_modules/@babel/types/lib/converters/toSequenceExpression.js
app/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js
app/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js
app/node_modules/@babel/types/lib/converters/toStatement.js
app/node_modules/@babel/types/lib/converters/valueToNode.js
app/node_modules/lodash/isPlainObject.js
app/node_modules/lodash/isRegExp.js
app/node_modules/lodash/_baseIsRegExp.js
app/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js
app/node_modules/@babel/types/lib/modifications/inherits.js
app/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js
app/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js
app/node_modules/@babel/types/lib/traverse/traverse.js
app/node_modules/@babel/types/lib/validators/isBinding.js
app/node_modules/@babel/types/lib/validators/isBlockScoped.js
app/node_modules/@babel/types/lib/validators/isLet.js
app/node_modules/@babel/types/lib/validators/isImmutable.js
app/node_modules/@babel/types/lib/validators/isNodesEquivalent.js
app/node_modules/@babel/types/lib/validators/isReferenced.js
app/node_modules/@babel/types/lib/validators/isScope.js
app/node_modules/@babel/types/lib/validators/isSpecifierDefault.js
app/node_modules/@babel/types/lib/validators/isValidES3Identifier.js
app/node_modules/@babel/types/lib/validators/isVar.js
app/node_modules/jest-snapshot/build/printSnapshot.js
app/node_modules/jest-snapshot/build/colors.js
app/node_modules/jest-snapshot/build/dedentLines.js
app/node_modules/ansi-styles/node_modules/color-convert/index.js
app/node_modules/ansi-styles/node_modules/color-convert/conversions.js
app/node_modules/color-name/index.js
app/node_modules/ansi-styles/node_modules/color-convert/route.js
app/node_modules/throat/index.js
app/node_modules/jest-circus/build/state.js
app/node_modules/jest-circus/build/types.js
app/node_modules/jest-circus/build/utils.js
app/node_modules/jest-util/build/index.js
app/node_modules/jest-util/build/clearLine.js
app/node_modules/jest-util/build/createDirectory.js
app/node_modules/jest-util/build/ErrorWithStack.js
app/node_modules/jest-util/build/installCommonGlobals.js
app/node_modules/jest-util/build/createProcessObject.js
app/node_modules/jest-util/build/deepCyclicCopy.js
app/node_modules/jest-util/build/interopRequireDefault.js
app/node_modules/jest-util/build/isInteractive.js
app/node_modules/is-ci/index.js
app/node_modules/ci-info/index.js
app/node_modules/jest-util/build/isPromise.js
app/node_modules/jest-util/build/setGlobal.js
app/node_modules/jest-util/build/convertDescriptorToString.js
app/node_modules/jest-util/build/specialChars.js
app/node_modules/jest-util/build/replacePathSepForGlob.js
app/node_modules/jest-util/build/testPathPatternToRegExp.js
app/node_modules/jest-util/build/preRunMessage.js
app/node_modules/jest-util/build/pluralize.js
app/node_modules/is-generator-fn/index.js
app/node_modules/co/index.js
app/node_modules/jest-circus/build/eventHandler.js
app/node_modules/jest-circus/build/globalErrorHandlers.js
app/node_modules/jest-circus/build/formatNodeAssertErrors.js
app/node_modules/jest-circus/build/run.js
app/node_modules/jest-circus/build/index.js
app/node_modules/jest-each/build/index.js
app/node_modules/jest-each/build/bind.js
app/node_modules/jest-each/build/table/array.js
app/node_modules/jest-each/build/table/template.js
app/node_modules/jest-each/build/validation.js
app/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestExpect.js
app/test/example-42.test.ts

Adding --runInBand didn't help in my case. I have this in my package.json. Should I get an improvement?

  "scripts": {
    "test": "jest --runInBand"
  },

I was using Jasmine before when a frontend developer told me OMG you're not using Jest, you're so 2017! So I tried Jest and bam, now I wait 4 seconds for the simplest test.

The main startup delay seems to come from require()-ing all the dependencies.

time-require reports around 10 seconds worth of require() calls on my current system.

Main culprits, according to that tool are:

  • babel - this might just be specific to my setup (@babel/preset-env takes 3.6 seconds)
  • jsdom - 1.2 seconds in isolation
  • sane - 0.5 seconds in isolation, most of which is caused by micromatch 3.

For JSDOM, there is already some work for cutting down dependencies and thus improving load times. They also have an active issue regarding request, which takes my machine .25 seconds to load.

An actionable item for the jest team might be replacing sane.

This right here is the issue ☝️

I really, _really_ wish Jest would provide an option not to reload the entire module tree on every single test suite. We write our code in a mostly pure style and do not use mutable global state so it is a complete waste for us to be reloading modules every time. And it is a _huge_ waste: a typical test suite in our code base takes 16 seconds to run, and < 1 second of that is running the actual test!

The main startup delay seems to come from require()-ing all the dependencies.
time-require reports around 10 seconds worth of require() calls on my current system.
Main culprits, according to that tool are:

  • babel - this might just be specific to my setup (@babel/preset-env takes 3.6 seconds)
  • jsdom - 1.2 seconds in isolation
  • sane - 0.5 seconds in isolation, most of which is caused by micromatch 3.

For JSDOM, there is already some work for cutting down dependencies and thus improving load times. They also have an active issue regarding request, which takes my machine .25 seconds to load.
An actionable item for the jest team might be replacing sane.

This right here is the issue ☝️

I really, _really_ wish Jest would provide an option not to reload the entire module tree on every single test suite. We write our code in a mostly pure style and do not use mutable global state so it is a complete waste for us to be reloading modules every time. And it is a _huge_ waste: a typical test suite in our code base takes 16 seconds to run, and < 1 second of that is running the actual test!

What are the team's intentions for moving forward? Will jest require minmum hardware specs or fix the issue?

I am wondering if it would cause any performance gain if we bundle Jest with all the dependencies in single file. For example using rollup. Will try to test this out using a postinstall script. Something similar Deno is doing when executing TypeScript code.

Back then, I was using Windows, and I think the issue was from my Antivirus. Running the same test again (the one from this repo: https://github.com/cozmy/jest-performance), on Ubuntu, I don't have any performance issues.

Back then, I was using Windows, and I think the issue was from my Antivirus. Running the same test again (the one from this repo: https://github.com/cozmy/jest-performance), on Ubuntu, I don't have any performance issues.

I experience this issue on a headless server and a macbook. The macbook is corporate property and does indeed have an antivirus, though i do not know to what extend that affects the performance, it certainly isn't an option for me to remove it.

@gtsop I'm experiencing the issue as well without anti-virus. For what it's worth, what @cozmy is referring to, if I'm not mistaken, is a slow-down related to applications that would suddenly create a ton of new files on disk (say, during a build process back in the days, with traditional C compilers creating hundreds or thousands of .obj files). The anti-virus would suddenly kick-in and attempt to scan them all for viruses, needlessly. The workaround, for example (and when possible), was to add an exception in the anti-virus for your build directory.

I know these kinds of numbers are not the gains many people here are looking for, but just to say that #7792 will (aside from the feature it introduces) improve speed by 1.05x~1.1x (benchmarked on 64 test files with a noop test case each, to measure overhead per test file) by loading prettier once per worker instead of once per test file. The numbers are on Linux and could be a bigger difference on Win/macOS, but I haven't checked.
I'm also looking at optimizing in other places using the same technique, perhaps I can achieve some other gains.

Also, switching from JSDOM to Node environment by default in Jest 27 will help a lot of people who were using JSDOM without realizing or needing it because JSDOM is still the biggest perf killer.

JSDOM is still the biggest perf killer.

This is great insight, and I should know this because I've made some mad science with it in the past.

Does each test file get a new JSDOM, or is it require()d once for each?

Does each test file get a new JSDOM, or is it require()d once for each?

Just a new JSDOM per test file, require('jsdom') already happens only once per worker, so unfortunately no more room for optimization there.

I have significantly improved perfomance by:

  1. removing all enzyme imports (replaced by @testing-library/react)
  2. switching default test environment to node (from jsdom)

Results: from 50-60 secs to ~35 secs (with -i flag) / ~13 secs (without -i flag)

I have significantly improved perfomance by:

1. removing all enzyme imports (replaced by @testing-library/react)

2. switching default test environment to node (from jsdom)

Results: from 50-60 secs to ~35 secs (with -i flag) / ~13 secs (without -i flag)

Very interesting to explore if enzyme is significantly contributing to the performance penalty. In the project I have the biggest problem on I do use enzyme indeed, however I'm currently using testing-library and although faster, I still think it's not as fast as expected. So it could be the case that both jest and enzyme are contributing to this problem.

So I think apart from not using JSDOM if one does not need it (which will be a huge win to do by default for many people), there are two problems affecting this kind of test run that make it slow even on a warm cache.
Both of which are mostly down to the amount of I/O operations done through requires, and both of which thus disproportionately affecting Windows and macOS users because I/O is expensive there.

  1. Jest startup is slow, even when there are just a couple of files in the directory to scan (so I'm not talking about other issues people are having when scanning the directory takes a long time). This appears to be mostly due to the loading of all of Jest's modules and dependencies itself. Fortunately, this does not apply to reruns in watch mode.
    I think the main thing to explore to tackle this is shipping bundles of Jest+dependencies to reduce the number of I/O operations needed. Unfortunately, for a project like Jest, I doubt this will be as trivial as writing a couple of lines of webpack config.

  2. Each test file introduces a lot of overhead, even when it does barely anything and does not run in JSDOM. This appears to be mostly due to the per-test file loading of some dependencies, like Babel, Prettier, Chalk, et cetera. This bit will become a lot better in Jest 27. I've now set up a Windows VM to benchmark in, and it seems master is already ~68% faster at this than 26.6.3, mostly due to optimizations in #7792. Using the same kind of optimization applied elsewhere, after some quick hacks I think I can get it down to almost 100% faster than 26.6.3. Note that this you will almost certainly not see this amount of speedup on your tests. For the repro at the top of this issue, I believe problem number 1) dominates. The changes in 27 will help you only if you have a lot of very fast test files. The benchmark was run on 500 almost-empty test files, to isolate the per-test file overhead impact.
    Edit: Looks like the numbers are more like master is ~50% faster at this than 26.6.3 and I expect to get it down to about ~70% faster at this than 26.6.3.

Was this page helpful?
0 / 5 - 0 ratings