Skip to content
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

ESM mode with ts-node breaks TypeScript path alias resolution in cucumber-js #2403

Closed
samydoesit opened this issue May 8, 2024 · 7 comments

Comments

@samydoesit
Copy link

👓 What did you see?

When using cucumber-js with ts-node as the loader in ESM mode, TypeScript path aliases specified in tsconfig.json fail to resolve.

Path aliases are not resolved, resulting in module resolution errors when attempting to execute tests.

Error:

Error: Cannot find package '@/index.js' imported from /cucumber-typescript-path-alias-reproduction/features/step_definitions/steps.ts
    at packageResolve (/cucumber-typescript-path-alias-reproduction/node_modules/ts-node/dist-raw/node-internal-modules-esm-resolve.js:757:9)
    at moduleResolve (/cucumber-typescript-path-alias-reproduction/node_modules/ts-node/dist-raw/node-internal-modules-esm-resolve.js:798:18)
    at Object.defaultResolve (/cucumber-typescript-path-alias-reproduction/node_modules/ts-node/dist-raw/node-internal-modules-esm-resolve.js:912:11)
    at /cucumber-typescript-path-alias-reproduction/node_modules/ts-node/src/esm.ts:218:35
    at entrypointFallback (/cucumber-typescript-path-alias-reproduction/node_modules/ts-node/src/esm.ts:168:34)
    at /cucumber-typescript-path-alias-reproduction/node_modules/ts-node/src/esm.ts:217:14
    at addShortCircuitFlag (/cucumber-typescript-path-alias-reproduction/node_modules/ts-node/src/esm.ts:409:21)
    at resolve (/cucumber-typescript-path-alias-reproduction/node_modules/ts-node/src/esm.ts:197:12)
    at nextResolve (node:internal/modules/esm/hooks:865:28)
    at Hooks.resolve (node:internal/modules/esm/hooks:303:30)

✅ What did you expect to see?

TypeScript path aliases should resolve correctly when cucumber-js is run in ESM mode using ts-node.

📦 Which tool/library version are you using?

  • Cucumber-js version: 10.6.0
  • ts-node version: 10.9.2
  • TypeScript version: 5.4.5
  • Node.js version: 20.11.1

🔬 How could we reproduce it?

Steps to Reproduce

  1. Clone the provided repository from https://github.com/samydoesit/cucumber-typescript-path-alias-reproduction
  2. Install dependencies using npm install
  3. Attempt to run the tests using npm test
  4. Notice the module resolution errors related to TypeScript path aliases

📚 Any additional context?

No response

@GRmeB
Copy link

GRmeB commented May 8, 2024

+1 Same issue here...

@davidjgoss
Copy link
Contributor

Thanks @samydoesit for raising, and taking the time to make that repro.

I've looked at the config there, but my understanding is that it would not work with or without Cucumber. From the relevant ts-node documentation:

..."paths" are intended to describe mappings that the build tool or runtime already performs, not to tell the build tool or runtime how to resolve modules. In other words, they intend us to write our imports in a way node already understands. For this reason, ts-node does not modify node's module resolution behavior to implement "paths" mappings.

ts-config-paths tends to be used for this, but from what I can see lacks ESM support for now, so unfortunately to have path mapping like this you may need to go back to CommonJS output.

@samydoesit
Copy link
Author

Thanks for your quick response. :)
I thought maybe there is another way.

We will keep the CommonJS output for now.

@dnotes
Copy link

dnotes commented Jul 22, 2024

To clarify, is there no way to import from the local files when using ts-node/esm? I can't seem to import even if I use a relative path, even if the files are in the same directory, but perhaps that's a different issue.

@dnotes
Copy link

dnotes commented Jul 28, 2024

For anyone else who finds this issue, my workaround was to use compilerOptions.moduleResolution: "node" in the tsconfig.json, and then import modules using relative paths and the .js file extension even for .ts files. So in tests/steps/search.ts:

import searchRequest from '../../src/lib/searchRequest.js'; // imports $lib/searchRequest.ts

@hynding
Copy link
Contributor

hynding commented Nov 5, 2024

Adding my two cents as I got it to work without ts-node nor tsconfig-paths despite trying everything I could think of. I did try some custom loader scripts that worked but were a bit clunky for my taste and less than ideal from a maintenance standpoint.

I came across several others pointing out they replaced their configuration with the tsx package but couldn't get it to work following the documented ESM principles. I wanted to use TypeScript for my step definitions and path aliases within those files, plus include type: module in my package.json and have the module and moduleResolution in tsconfig compilerOptions set to ES2022 and Bundler respectively. I felt obligated to use import over require in my cucumber config file when trying out tsx but I wasn't having any success.

If anyone else is having the same issue, here's what I did to get everything to run successfully:

  • Node v22
  • Cucumber v11
  • package.json includes "type": "module"
  • step definitions are all .ts files and use path aliases as defined in my tsconfig (in my case "baseUrl": "./src", "paths": {"@/*": ["*"]})
  • tsconfig file is configured to use module and moduleResolution (in my case ES2022 and Bundler respectively)
  • Do not use import in the cucumber config and instead use requireModule set to tsx/cjs (neither loader nor import set to tsx or tsx/esm did not work for me)

My cucumber.yaml file looks like this:

default:
  paths:
    - "../../features/**/*.feature"
  requireModule:
    - tsx/cjs
  require:
    - "tests/**/*.ts"

Nit: I declare my step definitions outside of my features (which rests in my repo's root directory as I intend it to target other languages in the future [hopefully with step definitions being able to be targeted outside of it, but I've read that may be wishful thinking]) and src folders in my sub-project root called tests (as I'm not using any other testing framework at the moment).

My tests also had a 4x performance improvement as well, which is always a plus.

@OctopusET
Copy link

@hynding thank you so much, this fixed my issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants