esmock: import('node:fs/promises') called within a library does not seem to be replaced

I’m attempting to stub a call to import('node:fs/promises') called within a library. However, esmock.p global replacement does not seem to replace the call to import(...). Is global replacements of import(...) covered in this library?

About this issue

  • Original URL
  • State: closed
  • Created 6 months ago
  • Comments: 30 (18 by maintainers)

Commits related to this issue

Most upvoted comments

@btakita this looks like an upsteam nodejs bug, my findings and a suggested work-around are given below.

When the node’s resolver hook resolves the async-imported ‘node:fs/promises’, the parent url is missing the query string that holds the mock details. Using console.log shows the resolver hook returns this resolved.url for “usesInlineBuiltinImport.js”

file:///home/bumble/software/esmock/tests/local/usesInlineBuiltinImport.js?esmkgdefs=node:fs/promises?[...]

but when node:fs/promises is async imported, the resolver hook is called with a context.parentURL that is missing the query string and without the query string esmock is unable to alter the behaviour

file:///home/bumble/software/esmock/tests/local/usesInlineBuiltinImport.js

I believe this is an upstream nodejs bug. If we want upstream nodejs to look into this, we’ll need to make a small test case for that (I could do this) and there are no guarantees we can expect any changes there.

Until a solution happens… try nesting locally mocked node:fs/promises inside globally mocked modules like this for now (the below pattern results in a passing test here)

const main = await esmock.p('../local/usesInlineBuiltinImportChild.js', {}, {
  '../local/usesInlineBuiltinImport.js': (
    await esmock.p('../local/usesInlineBuiltinImport.js', {
      'node:fs/promises': {
        readdir: () => (['mock', 'global'])
      }
    }))
})

The test is passing locally… looking into it further revealed that esmock itself was stripping the querystring from the url

A solution can probably be pushed up tonight or tomorrow.

@iambumblehead Wow, thank you! I didn’t consider tsx as the culprit. That makes sense. I’m traveling to visit family for the Christmas holidays. So I’ll take a look at this when I have a moment over the next few days.

My tests are in ts to also perform type checking, so it would be nice to keep them that way if possible. I’ll experiment with the different ts runners (or just use esbuild directly) & will let you know what solution I end up with. Thank you again!

Hi @iambumblehead…the test in question can be found in the rebuildjs package.

It uses the dependency ctx-core with the implementation.

Note that I’m stubbing out the whole file_exists_ function to get around the issue, so if you do test this, you will need to comment out or remove that stubbed module.

I dig this library, btw.