fastify-autoload icon indicating copy to clipboard operation
fastify-autoload copied to clipboard

Typescript complication error when running tests using Vitest

Open charklewis opened this issue 2 years ago • 8 comments

Prerequisites

  • [X] I have written a descriptive issue title
  • [X] I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.28.0

Node.js version

16

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

12.3

Description

I would like to test my fastify app using vitest, however I have noticed there is a typescript error I can't seem to get around.

When I run my tests Fastify errors, fastify-autoload cannot import plugin ... . To fix this error compile TypeScript to JavaScript or use 'ts-node' to run your app..

I can successfully run the tests when I compile them to Javascript and import the javascript version in the test. This does however, feel a bit hacky. It can also impact the code coverage (depending on how you are generating the javascript).

Steps to Reproduce

Stackbliz link: https://stackblitz.com/edit/node-sdwsoh

Run the npm run test command.

Expected Behavior

Tests can be run in vitest using Typescript without having to compile first, and import the javascript version.

charklewis avatar Apr 19 '22 11:04 charklewis

Just FYI I worked on this issue for a while and tried solving it by adding a ts-node register call instead of throwing here, that would handle all require calls for typescript files, transpiling and typechecking them before executing.

I had some typescript errors that I wasn't able to solve. It complained about the file not having exports despite having a default export. I also tried using a named export or using both but the error persisted and it also threw errors regarding missing fastify types that were being imported. I tried multiple settings without success and kinda ran out of options.

I'm also not entirely sure about the performance implications a change like this would have. I assume it probably wouldn't be that bad since it would only affect performance when initializing the plugins, but this should be verified if this approach ends up being used.

guilhermelimak avatar Apr 29 '22 03:04 guilhermelimak

I think that would be an amazing fix. However ts-node could not be there, so we must catch those error specifically and provide some instructions. Would you like to send a Pull Request to address this issue? Remember to add unit tests.

mcollina avatar Apr 29 '22 07:04 mcollina

We decided to put this on hold because we couldn't come to a solution within a reasonable timeframe, but we may go back to this some time in the future

simoneb avatar Apr 29 '22 12:04 simoneb

I'm getting similar error when trying to use autoload plugin with vite-plugin-node.

I've created reproducible project on stackblitz.

Is there a way to help resolving this issue as I currently can't use autoload with vite + typescript

ranyefet avatar May 26 '22 11:05 ranyefet

Update, I decided to remove vite and vite-plugin-node and use other tools to have a fast typescript environment during development.

I've tried @esbuild-kit/esm-loader @swc-node/register tsx and none of them worked. At the end I looked at the code for this library and I saw there is a special case for tsm, tried that and it worked perfectly.

Conclusion: use node -r tsm ./src/server.ts and make sure you don't have type: module in your package.json.

ranyefet avatar May 27 '22 06:05 ranyefet

Unfortunately all those tools needs special handling in this library to work :(. I don't know if there is a way to handle it otherwise.

PRs are welcomed!

mcollina avatar May 27 '22 11:05 mcollina

Can you explain why each tool need different handling? As I understand these tools transpile modules on the fly from ts to js. After that step everything should work the same, no?

ranyefet avatar May 27 '22 11:05 ranyefet

Unfortunately their ways of doing things is different, specifically when targeting ESM.

mcollina avatar May 27 '22 18:05 mcollina

Reopen due to 6adc2966ba5f9414139af22033eb78b3cb0c1f91

climba03003 avatar Sep 02 '22 06:09 climba03003

Just now seeing that #264 broke things mentioned in #266. Will take a look at that tomorrow and hopefully have a PR next week.

kylerush avatar Sep 08 '22 19:09 kylerush

I have the same issue with jest global setup, when I use autoload in globalSetup.ts I got the same error

fastify-autoload cannot import plugin ... . To fix this error compile TypeScript to JavaScript or use 'ts-node' to run your app.

alrramezani avatar Sep 10 '22 19:09 alrramezani

There's some active conversation about this in a vitest issue here: https://github.com/vitest-dev/vitest/issues/2028

I think getting autoload to actually run in vitest again will not be hard, but the problem I ran into is the code coverage from vitest is very whacky when using autoload because vitest is not aware of the files that autoload loads. To me this makes vitest not a workable solution so I'm hoping we can figure out a solution with some of the vitest contributors 🤞

kylerush avatar Sep 13 '22 18:09 kylerush

@alrramezani - If you use version 5.3.0 of autoload your Jest tests should work. You can see that working here: https://github.com/kylerush/vitest-v-tap

kylerush avatar Sep 13 '22 18:09 kylerush

While setting up a repro for a "vitest alias" issue, I came across different kind of issues I never came across with my main app. One of the things is getting @fastify/autoload to work. For now I got it working with following versions (and no additional config):

  "dependencies": {
    "@fastify/autoload": "5.3.0",
    "@fastify/cors": "^8.1.0",
    "@fastify/env": "^4.1.0",
    "@prisma/client": "^4.4.0",
    "@trpc/server": "10.0.0-proxy-beta.15",
    "fastify-plugin": "^4.2.1",
    "fastify": "^4.8.1",
    "zod": "^3.19.1"
  },
  "devDependencies": {
    "@trpc/client": "10.0.0-proxy-beta.15",
    "@types/node": "^18.8.4",
    "cross-env": "^7.0.3",
    "dotenv-cli": "^6.0.0",
    "esbuild": "^0.15.10",
    "esbuild-plugin-pino": "1.2.4",
    "fastify-tsconfig": "^1.0.1",
    "pino": "^8.6.1",
    "pino-pretty": "^9.1.1",
    "prisma": "^4.4.0",
    "tiny-glob": "^0.2.9",
    "tsx": "^3.10.1",
    "typescript": "^4.8.4",
    "vitest": "^0.24.1",
    "ts-node": "^10.9.1"
  },

Somehow, for my main app I have the same versions, except no ts-node explicitly installed 🤔

jclaessens97 avatar Oct 11 '22 08:10 jclaessens97

After some investigation it also seems that @fastify/autoload is overriding the alias config of vitest. I'm currently using 5.3.0 since it's the only version I come close to get it working.

I understand that code coverage should be working, but I'm not sure if it should be blocking to make @fastify/autoload work with vitest again? @kylerush

I'm willing to help wherever I can to resolve this issue.

See also https://github.com/vitest-dev/vitest/issues/2135

jclaessens97 avatar Oct 12 '22 09:10 jclaessens97

You just need a way to detect if you are running vitest. Like a set environment variable or so. Compare with #271

Uzlopak avatar Oct 12 '22 10:10 Uzlopak

process.env.VITEST_MODE and check if it's set or not?

But even then further down it results in some issues because the use of require or that the imported ".ts" files are not recognized.

jclaessens97 avatar Oct 12 '22 10:10 jclaessens97

But even then further down it results in some issues because the use of require or that the imported ".ts" files are not recognized.

You can force to use import if it does matter by vitest.

After some investigation it also seems that @fastify/autoload is overriding the alias config of vitest.

And @fastify/autoload do nothing on the file path, it just call either import or require. It means that vitest just don't work with it somehow.

https://github.com/fastify/fastify-autoload/blob/c41e96eb70fcad58ef37620da4ee718950d091d0/index.js#L239-L241

climba03003 avatar Oct 12 '22 10:10 climba03003

Yeah so I tried that.

I added a const isVitestEnvironment = process.env.VITEST_MODE !== undefined, added it to the typescriptSupport and then on those lines you highlighted I also added the check if it's vitest to use the await import, but then I'm getting errors like Error: unknown file extension ".ts" for the plugins folder (e.g. cors.ts, env.ts, ... in my repro).

I also gave import.meta.url a shot as i've seen it being used by vite in a vue 3 context, but then it complains that it's not being used inside an ESM environment (thus package.json doesn't contain type: "module")

For now I'm just "working around" it by not using @fastify/autoload and no aliases.

It's pretty funny because at vitest they say that @fastify/autoload changes the aliases which cause the errors I'm getting, but here we can see it's the import/require that's not working 😅

jclaessens97 avatar Oct 12 '22 11:10 jclaessens97

I have a potential PR

Uzlopak avatar Oct 12 '22 11:10 Uzlopak

I quite dont understand now the issue you meant?!

see #273

Uzlopak avatar Oct 12 '22 12:10 Uzlopak

Please check the discussion in the potential solution #273

Uzlopak avatar Oct 12 '22 12:10 Uzlopak

Provided an alternative approach to set forceESM instead of ts-node #274

Uzlopak avatar Oct 12 '22 12:10 Uzlopak

Can't wait to test it 😄

jclaessens97 avatar Oct 12 '22 13:10 jclaessens97

You could test it by setting the repo and the branch for the package in package.json

{
  "dependencies": {
   ...
    "@fastify/autoload": "fastify/fastify-autoload#forceESM-for-vitest"
   ...
  }
}

Uzlopak avatar Oct 12 '22 14:10 Uzlopak

@jclaessens97

If it works, than please give feedback to have higher confidence that the PR solves the issue in a real environment.

Uzlopak avatar Oct 12 '22 15:10 Uzlopak

I didn't have the time yesterday to check, but I do have time today, if it's still needed?

jclaessens97 avatar Oct 13 '22 07:10 jclaessens97

we released today the new version ;)

Uzlopak avatar Oct 13 '22 08:10 Uzlopak

Might be a config issue on my side, but when I now try my repro again (with the updated package), I get the following:

TypeError: Unknown file extension ".ts" for /Users/jclaessens/dev/github/vitest-alias-repro/packages/api/src/plugins/cors.ts
Serialized Error: {
  "code": "ERR_UNKNOWN_FILE_EXTENSION",
}

This is the same issue I got when I tried to do the changes myself.

Again, it might be a config issue on my side, but it's unclear to me at this point.

jclaessens97 avatar Oct 14 '22 09:10 jclaessens97

ERR_UNKNOWN_FILE_EXTENSION is a node error https://github.com/nodejs/node/blob/main/lib/internal/modules/esm/get_format.js#L75-L76

Uzlopak avatar Oct 14 '22 09:10 Uzlopak