Closed GuyKh closed 7 months ago
Having the same issue here. Need to stay in v4 for now.
this is likely because of esm vs commonjs.
your project builds as commonjs ("module": "commonjs"
in tsconfig), while chai 5.x is pure ESM.
i would stick on chai 4.x until you can move your project to es modules instead (i.e. "module": "nodenext"
in tsconfig, and "type": "module"
in package.json).
@43081j - does this mean that chai 5.x will not run on anything but ESM? Also - a tutorial in terms of how to migrate to ESM?
@GuyKh i put a little more info in #1561 at the end
basically, chai 5.x ships as ESM, which means you can only use it if one or more of the following is true:
package.json
as "type": "module"
)const chai = await import('chai')
)many projects will be simple to migrate to ESM, especially those used only in node. i don't have a tutorial but if i find a good example repo to migrate, i'd be happy to write up how i did it.
importantly too, it is fine to stick with chai 4.x for now
my tsconfig.json: "target": "es2022" "module": "commonjs"
After some testing, I can confirm that
the following code, which worked with version 4.3.10, no longer works with the latest version and generates the error in the subject.
const chai = require('chai')
chai.use(require('chai-json'))
chai.use(require('chai-xml'))
With version 5.0.0 it should become
import chai from 'chai'
import jsonObj from 'chai-json'
import chaiXml from 'chai-xml'
chai.use(jsonObj);
chai.use(chaiXml);
unfortunately, not all plugins have types definitions (like chai-json - see issue) and therefore cannot be used.
installing chai-xml and @types/chai-xml, using v5.0.0, the following code is working
import chai from 'chai'
import chaiXml from 'chai-xml'
chai.use(chaiXml);
It would be useful to add type definitions to all plugins and update the documentation, which currently no longer conforms to the latest breaking changes (i.e.: https://www.chaijs.com/plugins/chai-json/).
The problem with Mocha runs a little deeper than changing your project to module. This part in the .mocharc.json
points to the issue:
{
"require": ["ts-node/register", "chai/register-expect.js"],
}
Mocha seems to use require under the hood, which won't work with 5.0. The Mocha team might have advice?
mocha supports ESM just fine, you just need to do this instead:
{
"loader": "ts-node/esm",
"require": ["chai/register-expect.js"]
}
some more info on that here:
https://typestrong.org/ts-node/docs/recipes/mocha/
i'll try put a few examples together tonight if i get time, as this mostly seems like gaps in understanding than limitations
After several days of playing around, I finally found a solution to use chai v5 with the rest of established toolchain (mocha + ts-node + istanbul).
The trick is NOT to import expect
(or any other stuffs) from chai at all in any of the test/spec files. Instead, register the things you need as global members:
// mocha.env.mjs
import { Assertion, expect } from "chai";
globalThis.Assertion = Assertion;
globalThis.expect = expect;
// these are for ts-node
process.env.NODE_ENV = "test";
process.env.TS_NODE_PROJECT = "test/tsconfig.json";
(Note that chai/register-expect.js is doing similar thing and you can use that one also. I wrote my own because I also need Assertion
static object to define custom chai methods.)
And then add it to your .mocharc.json, in my case it looks like this:
{
"extension": [
"ts"
],
"spec": [
"test/specs/**/*.ts"
],
"timeout": "0",
"require": [
"./test/mocha.env.mjs",
"ts-node/register",
"tsconfig-paths/register"
]
}
Next you just remove all import { expect } from "chai"
in the test files. Of course, you would also need to define the global functions to silence TypeScript errors:
// chai.d.ts
import type * as chai from "chai";
declare global {
declare const expect: typeof chai.expect;
declare const Assertion: typeof chai.Assertion;
}
And that's all you need. No need to change tsconfig.json or package.json. Yes, there are other solutions that make chai v5 works by modifying these two, but those solutions break other toolchains (especially istanbul, and I don't want to use c8).
you shouldn't need to do that, we use mocha 10, chai 5, and typescript with regular imports.
i also tried using ts-node with the ts-node/esm
loader and it worked fine.
i suspect something must be missing if you need to avoid importing it like that
here's an example of mocha 10 + chai 5 + ts-node:
https://gist.github.com/43081j/78ce1392abb5043b02a29355006880a5
In my tests, I only use
import { expect } from "chai"
.npm run test
(mocha) returns:This wasn't happening before the change with
"chai": "4.3.10"
Other files: