testdouble.js
testdouble.js copied to clipboard
replaceEsm not working on windows
Description
ES modules are not mocked on windows. Works fine on Mac.
Environment
- [ ]
node -voutput: 14.8.2 - [ ]
yarn --versionoutput: 1.22.19 - [ ]
npm ls testdouble(oryarn list testdouble) version: 3.16.15
Example Repo
https://github.com/connorjclark/testdouble-win-example
// main.js
import * as td from 'testdouble';
td.replaceEsm('./module.js', {runMe: () => 'replaced'});
const {runMe} = await import('./module.js')
console.log(runMe());
// module.js
export function runMe() {
return 'original';
}
node --loader=testdouble main.js prints original on windows, replaced on Mac.
Paging @giltayar if he might have any insight 🙏

The key in the global modules Map duplicated C:/ for some reason. Also, the slashes are wrong.
Set here:

I believe convertUrlToPath is eating the C: portion of the module url (interprets as the protocol), and spits out the path without it.

I made the following change inside quibble, which resolved the bug:

if (process.platform === 'win32') {
fullModulePath = callerFile.replace('/C:', 'C:')
fullModulePath = path.resolve(path.dirname(fullModulePath), importPath)
fullModulePath = '/' + fullModulePath.split(path.sep).join("/")
}
Of course, I shouldn't be hardcoding the drive there. But anyway, the real fix is probably something to do with correctly juggling the format of the Error filename / module name / URLs being passed around, being mindful of Windows's differing slashes / existence of a drive suffix.
Thanks for digging into this. Ultimately, if you (or another developer that uses Windows) might consider sending a PR with a test for this that they can assert works OK on windows without breaking anything else, I'd be eager to accept it.
Cloned your repo, updated testdouble to the latest version, and added an await before td.replaceEsm. Got the correct result ("replaced"), so closing this issue.