testdouble / testdouble.js

A minimal test double library for TDD with JavaScript
MIT License
1.42k stars 142 forks source link

replaceEsm not working on windows #491

Closed connorjclark closed 1 year ago

connorjclark commented 2 years ago

Description

ES modules are not mocked on windows. Works fine on Mac.

Environment

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.

searls commented 2 years ago

Paging @giltayar if he might have any insight 🙏

connorjclark commented 2 years ago

image

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

Set here:

image

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

image

connorjclark commented 2 years ago

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

image

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.

searls commented 2 years ago

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.

giltayar commented 1 year ago

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.