Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5 - Unknown file extension ".ts" when running with mocha #1568

Closed
GuyKh opened this issue Jan 1, 2024 · 11 comments
Closed

v5 - Unknown file extension ".ts" when running with mocha #1568

GuyKh opened this issue Jan 1, 2024 · 11 comments

Comments

@GuyKh
Copy link

GuyKh commented Jan 1, 2024

In my tests, I only use import { expect } from "chai".

npm run test (mocha) returns:

TypeError: Unknown file extension ".ts" for /Users/me/git/myProj/test/app.test.ts
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
    at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
    at defaultLoad (node:internal/modules/esm/load:143:22)
    at async ModuleLoader.load (node:internal/modules/esm/loader:409:7)
    at async ModuleLoader.moduleProvider (node:internal/modules/esm/loader:291:45)
    at async link (node:internal/modules/esm/module_job:76:21)

This wasn't happening before the change with "chai": "4.3.10"

Other files:

  • .mocharc.json
{
    "diff": true,
    "extension": ["ts"],
    "opts": false,
    "package": "./package.json",
    "require": ["ts-node/register", "chai/register-expect.js"],
    "reporter": "spec",
    "slow": 75,
    "timeout": 2000,
    "watch-files": ["test/**/*.ts"],
    "ui": "bdd"
  }
  • package.json
"devDependencies": {
    "@types/chai": "4.3.11",
    "@types/mocha": "10.0.6",
    "chai": "^5.0.0",
    "mocha": "10.2.0",
...
...
  "scripts": {
"test": "mocha --recursive",
} 
@GuyKh
Copy link
Author

GuyKh commented Jan 1, 2024

Failing PR
GuyKh/10bis.Slackbot#1021

@GuyKh GuyKh changed the title After upgrading to Chai v5 - Unknown file extension ".ts" when running mocha v5 - Unknown file extension ".ts" when running with mocha Jan 1, 2024
@MuTsunTsai
Copy link

Having the same issue here. Need to stay in v4 for now.

@43081j
Copy link
Contributor

43081j commented Jan 2, 2024

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).

@GuyKh
Copy link
Author

GuyKh commented Jan 2, 2024

@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?

@43081j
Copy link
Contributor

43081j commented Jan 2, 2024

@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:

  • your project is also ESM (package.json as "type": "module")
  • you use a bundler which supports esm/cjs mixes (e.g. esbuild)
  • you use dynamic import instead to import chai (e.g. 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

@DarioMagniPLRM
Copy link

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/).

@Stwissel
Copy link

Stwissel commented Jan 3, 2024

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?

@43081j
Copy link
Contributor

43081j commented Jan 3, 2024

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

@MuTsunTsai
Copy link

MuTsunTsai commented Jan 10, 2024

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).

@43081j
Copy link
Contributor

43081j commented Jan 10, 2024

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

@43081j
Copy link
Contributor

43081j commented Jan 10, 2024

here's an example of mocha 10 + chai 5 + ts-node:

https://gist.github.com/43081j/78ce1392abb5043b02a29355006880a5

@chaijs chaijs locked and limited conversation to collaborators Jan 10, 2024
@keithamus keithamus converted this issue into discussion #1575 Jan 10, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants