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

invalid moduleId error when using tsx #209

Closed
tommy-mitchell opened this issue Jul 9, 2023 · 16 comments
Closed

invalid moduleId error when using tsx #209

tommy-mitchell opened this issue Jul 9, 2023 · 16 comments

Comments

@tommy-mitchell
Copy link
Collaborator

tommy-mitchell commented Jul 9, 2023

I'm trying to use esmock with AVA and TypeScript via transpilation with tsx (i.e. esbuild) on Node.js v18.16.1. My loader chain is effectively

node --loader=tsx --loader=esmock
AVA configuration
"files": [
	"test/*.ts"
],
"extensions": {
	"ts": "module"
},
"nodeArguments": [
	"--loader=tsx",
	"--loader=esmock",
	"--no-warnings=ExperimentalWarning"
]
Project structure
\__ src/
	\__ source-file.ts
\__ test/
    \__ test-file.ts
\__ package.json
\__ tsconfig.json

When trying to mock my source file, I get an invalid moduleId error:

// test/test-file.ts

import test from "ava";
import esmock from "esmock";

test("with mock", async t => {
	const { setExecutableBits } = await esmock("../src/source-file.js", import.meta.url, {
		// ...
	}) as typeof import("../src/source-file.js");

	// ...
});
Rejected promise returned by test. Reason:

  Error {
    message: 'invalid moduleId: "../src/source-file.js" (used by file:///.../test/test-file.ts)',
  }

  › Object.$e (node_modules/esmock/src/esmock.js:1:61)
  › wt (node_modules/esmock/src/esmock.js:2:6113)
  › <anonymous> (node_modules/esmock/src/esmock.js:3:161)

Am I missing something?

@iambumblehead
Copy link
Owner

There's not an esmock tsx test and it would be great to have one. Feel free to submit a PR, otherwise I'll respond in a week or so with a solution.

related,

@iambumblehead
Copy link
Owner

it would be awesome if you would submit a PR with a failing test

@tommy-mitchell
Copy link
Collaborator Author

Added failing tests at #210.

@iambumblehead
Copy link
Owner

@tommy-mitchell thank you for the test cases. Possibly related, ava is not fully compatible with esm --loader

Will take a look later this evening

@iambumblehead
Copy link
Owner

this seems to come from a configuration issue, such as the configurations discussed here https://stackoverflow.com/questions/62096269/cant-run-my-node-js-typescript-project-typeerror-err-unknown-file-extension

the error occurs at this line, where importing the ts file causes the error

const importedModule = await import(fileURLKey)
//   TypeError {
//     code: 'ERR_UNKNOWN_FILE_EXTENSION',
//     message: 'Unknown file extension ".ts" for /home/bumble/software/esmock/tests/local/main.ts',

I'm not great at setting up configurations for things like this but will keep trying a little bit

@iambumblehead
Copy link
Owner

PR is here #211

@iambumblehead
Copy link
Owner

this issue seems related avajs/ava#2593 (comment)

@tommy-mitchell
Copy link
Collaborator Author

Potentially related too: avajs/ava#3213 (reply in thread)

@iambumblehead
Copy link
Owner

these results indicate the problem may come from tsx,

  • if tsx is used, the tests fail if either node:test or ava are used as the test runner
  • if ts-node/esm is used, the tests pass if either node:test or ava are used as the test runner

I'll push up some changes to the PR that make it a little easier to switch between the two transpilers and test-runners

@iambumblehead
Copy link
Owner

iambumblehead commented Jul 11, 2023

At the PR, I removed the invalid moduleId test, because the moduleId was actually invalid (the file path being imported did not exist) and esmock is expected to throw an error in that situation. That is separate from the unknown-file-extension-error which seems to be a real issue.

@iambumblehead
Copy link
Owner

@tommy-mitchell I think I've narrowed down the issue to something that could be used to submit an issue at the tsx project,

test('tsx should not break when import paths include query params', async () => {
  assert.ok(await import('../local/main.ts?n=4'))
})

when query params are removed, the above test passes

@iambumblehead
Copy link
Owner

related issue is opened here privatenumber/tsx#264

@iambumblehead iambumblehead changed the title invalid moduleId error when trying to use with TypeScript and AVA invalid moduleId error when using tsx Jul 11, 2023
@tommy-mitchell
Copy link
Collaborator Author

Nice find.

@iambumblehead
Copy link
Owner

Closing with this #211

A tsx note is embedded to the README scripts example. Feel free to reopen for any reason.

@tonisives
Copy link

I get the same invalid moduleId error for node --loader=ts-node/esm src/simpletest.test.ts

import { test } from "uvu"
import esmock from "esmock"
import { myFun } from "./simpletest.js"


test("test not real", async () => {
  let mock = await esmock("./simpletest.js", {
    myFun: () => console.log("mocked")
  })
  
  myFun()
})


test.run()
export const myFun = () => {
  console.log("still real");
}
➜ node --loader=ts-node/esm src/simpletest.test.ts
(node:5062) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
✘   (0 / 1)

   FAIL  "test not real"
    invalid moduleId: "myFun" (used by file:///Users/tonis/workspace/js/audit-hero/parsers/packages/findings/src/simpletest.test.ts)

uvu runner
"ts-node": "^10.9.1",
node 20.6.1
"uvu": "^0.5.6"

@iambumblehead
Copy link
Owner

iambumblehead commented Sep 14, 2023

@tonisives respectfully, the example you gave probably does not use esmock correctly. Call esmock to mock values that are imported by the target module. See this diff, for example, which results in a passing test using the two files attached further below.

diff --git a/src/simpletest.test.ts b/src/simpletest.test.ts
index a1633c6..13a3370 100644
--- a/src/simpletest.test.ts
+++ b/src/simpletest.test.ts
@@ -1,13 +1,14 @@
 import { test } from "uvu"
 import esmock from "esmock"
-import { myFun } from "./simpletest.js"
+import simpletest from "./simpletest.js"
 
 test("test not real", async () => {
   let mock = await esmock("./simpletest.js", {
-    myFun: () => console.log("mocked")
+    "./simplefunctions.js": { myFun: () => console.log("mocked") }
   })
-  
-  myFun()
+
+  mock()
+  simpletest()
 })
 
 test.run()

src/simplefunctions.ts

export const myFun = () => {
  console.log("still real");
}

src/simpletest.ts

import { myFun } from './simplefunctions.js'

export default myFun

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

3 participants