enzyme icon indicating copy to clipboard operation
enzyme copied to clipboard

Cannot find module 'cheerio' from 'node_modules/enzyme/build/Utils.js'

Open mmarshad opened this issue 3 years ago • 32 comments

I just start receiving this message to my unit tests today, although it was working fine before

Cannot find module 'cheerio' from 'node_modules/enzyme/build/Utils.js'

Require stack:
  node_modules/enzyme/build/Utils.js
  node_modules/enzyme/build/ShallowWrapper.js
  node_modules/enzyme-to-json/utils.js
  node_modules/enzyme-to-json/createSerializer.js
  node_modules/enzyme-to-json/serializer.js

  at Resolver.resolveModule (node_modules/jest-runtime/node_modules/jest-resolve/build/index.js:306:11)
  at Object.<anonymous> (node_modules/enzyme/src/Utils.js:9:1)

Is there anything changed in serlizer.js? "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.6", "enzyme-to-json": "^3.6.1",

mmarshad avatar May 06 '21 19:05 mmarshad

enzyme-to-json is not maintained by the enzyme team, so you'd have to ask them.

ljharb avatar May 06 '21 19:05 ljharb

Same here for me:

` Cannot find module 'cheerio' from 'node_modules/enzyme/build/Utils.js'

Require stack:
  node_modules/enzyme/build/Utils.js
  node_modules/enzyme/build/ReactWrapper.js
  node_modules/enzyme/build/index.js

  at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:306:11)
  at Object.<anonymous> (node_modules/enzyme/build/Utils.js:80:16)
  `

My dependencies: "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.5"

Mahdiyeh avatar May 07 '21 10:05 Mahdiyeh

Please try pinning cheerio to =1.0.0.rc-3, ensure it's installed, and let me know if the issue persists.

ljharb avatar May 07 '21 14:05 ljharb

Adding an override doesn't fix the issue with enzyme incorrectly using a loose RC pattern for a hard dependency.

  "overrides": {
    "enzyme": {
      "cheerio": "1.0.0.rc-3"
    }
  },

Cheerio is now a dual CommonJS and ESM module. That means that deep imports will now fail in newer versions of Node. https://github.com/cheeriojs/cheerio/releases/tag/v1.0.0-rc.11

rxgx avatar May 20 '22 17:05 rxgx

@rxgx while that should work - file an issue with npm if it doesn't - simply adding "cheerio": "=1.0.0.rc-3" to your devDependencies should be sufficient, no overrides required.

ljharb avatar May 20 '22 17:05 ljharb

@ljharb what old version of npm are you using?

npm ERR! code EINVALIDTAGNAME
npm ERR! Invalid tag name "=1.0.0.rc-3" of package "cheerio@=1.0.0.rc-3": Tags may not have any characters that encodeURIComponent encodes.

rxgx avatar May 20 '22 17:05 rxgx

works fine with every version of npm, through the latest. That's a version specifier, not a tag name.

It's what the next release of enzyme will use: https://github.com/enzymejs/enzyme/blob/master/packages/enzyme/package.json#L42

ljharb avatar May 20 '22 17:05 ljharb

Is it possible that this version is missing from the registry? I get these errors even with rm node_modules and npm cache verify. OR something up with npm itself

lerna notice cli v4.0.0
lerna ERR! cheerio: No matching version found for [email protected].
lerna ERR!     at module.exports (/Users/rgasparini/Code/monorepo/node_modules/npm-pick-manifest/index.js:209:23)
lerna ERR! lerna No matching version found for [email protected].
$ npm i -D [email protected] 
npm ERR! code ETARGET
npm ERR! notarget No matching version found for [email protected].
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.
$ npm i -D cheerio@=1.0.0.rc-3
npm ERR! code EINVALIDTAGNAME
npm ERR! Invalid tag name "=1.0.0.rc-3" of package "cheerio@=1.0.0.rc-3": Tags may not have any characters that encodeURIComponent encodes.

rxgx avatar May 20 '22 18:05 rxgx

Is it possible you're not using the public registry? It's quite there: https://unpkg.com/browse/[email protected]/

ljharb avatar May 20 '22 18:05 ljharb

Here's what I originally thought was the resolution before being derailed by the invalid = syntax. I got the hyphen and dots mixed up.

  "overrides": {
    "enzyme": {
      "cheerio": "1.0.0-rc.3"
    }
  },

If you manually change the version of the dependencies or devDependencies, your lock file is unfortunately going to be out of sync.

rxgx avatar May 20 '22 18:05 rxgx

The = syntax is a range; overrides takes a specific version - it’s not invalid in general, i just wasn’t providing an override. Overrides should be used only as a last resort.

ljharb avatar May 20 '22 20:05 ljharb

Looks like the change to pin it here: https://github.com/enzymejs/enzyme/commit/cafdb2b86ed8865527cdd6ae31c42593d3728ceb was never published: https://unpkg.com/browse/[email protected]/package.json. Can somebody publish it? Thank you!

nspector avatar May 20 '22 22:05 nspector

@nspector correct; it hasn't been published yet. it'll be in the next release.

Again, you can get the benefit now merely by doing npm install --save-dev cheerio@=1.0.0-rc.3.

ljharb avatar May 20 '22 22:05 ljharb

Try lock your cheerio version to 1.0.0-rc.10 E.g. by yarn resolutions. 1.0.0-rc.11 will throw the error.

tonnyskk avatar May 21 '22 10:05 tonnyskk

This worked for me

   "resolutions": {
+    "cheerio": "1.0.0-rc.10"
   },

billnbell avatar May 22 '22 19:05 billnbell

Same here for me:

` Cannot find module 'cheerio' from 'node_modules/enzyme/build/Utils.js'

Require stack:
  node_modules/enzyme/build/Utils.js
  node_modules/enzyme/build/ReactWrapper.js
  node_modules/enzyme/build/index.js

  at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:306:11)
  at Object.<anonymous> (node_modules/enzyme/build/Utils.js:80:16)
  `

My dependencies: "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.5"

Do you resolve this one? I have the same issue

richard1230 avatar May 24 '22 17:05 richard1230

This worked for me

   "resolutions": {
+    "cheerio": "1.0.0-rc.10"
   },

which file should it be put?

richard1230 avatar May 24 '22 17:05 richard1230

@richard1230 in package.json. resolutions only applies to yarn tho.

You should add "cheerio": "=1.0.0-rc.3" to your devDependencies in package.json instead.

ljharb avatar May 24 '22 18:05 ljharb

Well devDependencies did not help. When I added "resolutions" it works.

billnbell avatar May 24 '22 19:05 billnbell

@devinm-hrbl no.

ljharb avatar Jun 01 '22 22:06 ljharb

This worked perfectly! If you copy/paste the above ☝️ then make sure there isn't a period at the end! That was causing the invalid tag name issue for me

mjperales avatar Jun 07 '22 16:06 mjperales

I also have this issue. I am using Yarn with workspaces. Normally, after a yarn install, all dependencies are stored in node_modules in the root folder. My tests are inside a subfolder with its own package.json.

So to hot fix the issue temporarily, I run npm i in the subfolder to install all dependencies AGAIN in node_modules in subfolder. I can delete everything in node_modules in subfolder except these three: enzyme, enzyme-adaptor-preact-pure, enzyme-to-json. Then all the tests pass again.

new-carrot avatar Jun 10 '22 06:06 new-carrot

This is happening because in ./build/Utils.js, enzyme is doing this:

https://github.com/enzymejs/enzyme/blob/3d286a4f45f5c1b9c649fd5ee63fe9fd57e0d597/packages/enzyme/src/Utils.js#L11

Notice how this imports a specific internal module from deep inside the guts of cheerio, ./lib/utils.js.

This bypasses the public API of cheerio, which intends for users to either import ... from 'cheerio', or import ... from 'cheerio/lib/slim' only. Bypassing the public API of a package in this way is always hazardous, because it means that if cheerio rearranges its internal modules, this usage will break. This is an anti-pattern, and it is almost never officially supported by the package you're using.

Recently, webpack has started allowing a new field, "exports", to be used in package.json. This is intended to enable package maintainers to have greater control over this kind of direct import, and how Node.js resolves these dependencies. This field allows two things: firstly, an import like 'cheerio/lib/slim' doesn't have to resolve to ./lib/slim.js, it can be made to resolve to anything the maintainers want - this enables maintainers to rearrange their internals without breaking consumers. Secondly, it means all other deep imports like 'cheerio/lib/utils' now deliberately do not work at all. This disables that API bypass anti-pattern, and reduces the public interface of the package to only what the maintainers choose.

cheerio began using "exports" in https://github.com/cheeriojs/cheerio/pull/2508, which went into [email protected], which was released on 20 May 2022, thereby officially dropping support for deep imports. I don't know if deep imports were ever officially supported by cheerio, but they are no longer supported. Technically this is a breaking change, but [email protected] is only a release candidate, which I'm guessing doesn't have any kind of commitment to avoiding breaking changes, so cheerio is entirely within its rights to do this.

The real problem, then, is that [email protected] specifies a dependency on a range of unstable release candidate versions of cheerio, which can break without warning in exactly this way:

https://github.com/enzymejs/enzyme/blob/6e990c0cef99061006de5a883301d707f32aa6f0/packages/enzyme/package.json#L42

The fix for this is for enzyme to pin to a specific RC of cheerio, which in fact has already been done, in December 2020. However, no new version of enzyme has been released since then.

s100 avatar Jun 13 '22 13:06 s100

The public api of a package is everything reachable inside it, and deep imports are always preferable since they obviate the need for treeshaking.

The exports field is a node thing, webpack just supports it, and rc11 added a breaking change to use it, but as you note, prereleases can have those. Prior to this, this file was absolutely part of the public api of cheerio.

You are also correct that enzyme just needs a release to fix this issue.

ljharb avatar Jun 13 '22 13:06 ljharb

@ljharb Is this package still actively maintained?

s100 avatar Jun 14 '22 09:06 s100

@s100 yes, as you can see by my comment yesterday.

ljharb avatar Jun 14 '22 14:06 ljharb

@s100 yes, as you can see by my comment yesterday.

Awesome... so, when can we expect a new release with this fix?

s100 avatar Jun 14 '22 14:06 s100

@s100 i don't commit to specific release schedules, and the lack of a release is unrelated to whether the package is maintained.

ljharb avatar Jun 14 '22 15:06 ljharb

Hello, I also found the error: Cannot find module 'cheerio/lib/utils' from 'node_modules/enzyme/build/Utils.js'

Require stack:
  node_modules/enzyme/build/Utils.js
  node_modules/enzyme/build/ReactWrapper.js
  node_modules/enzyme/build/index.js
  src/__tests__/Button/button.test.tsx

My devDependencies list include enzyme are:

"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.3.5",

So, now we can't solve the problem?

fengxinhhh avatar Jun 17 '22 14:06 fengxinhhh

I also ran into this issue and made this PR in the Cheerio repository: https://github.com/cheeriojs/cheerio/pull/2601

Though since it's such a simple function (which could be replaced by /<[a-zA-Z!][^>]*>/.test(str)) that follows a spec and has no need of knowledge of behaviors within Cheerio, one could argue the better solution is to just embed it into Enzyme to avoid depending on the internal structure of another package.

blixt avatar Jun 18 '22 14:06 blixt