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

esmock fails if source maps are used #113

Closed
jakebailey opened this issue Aug 14, 2022 · 4 comments
Closed

esmock fails if source maps are used #113

jakebailey opened this issue Aug 14, 2022 · 4 comments

Comments

@jakebailey
Copy link
Contributor

jakebailey commented Aug 14, 2022

I have a TS project using ava on TS's output. I have to do this as my project calls into import.meta.resolve / import-meta-resolve, and I want to test on my project as it ships to users. I have source maps enabled so that I can debug / run coverage on my tests.

Unfortunately, esmock doesn't seem to work if source maps are enabled.

Here's a minimal repro: https://github.com/jakebailey/esmock-source-map-bug

I suspect it's due to this:

const calleePath = (err || new Error).stack.split('\n')[2]

If source maps have been loaded, the backtrace will show the mapped location (my TS src dir), not the true location (a dist dir of compiled code). Maybe esmock's API should accept a parent parameter so that the caller can pass import.meta.url, similar to import-meta-resolve or other ESM-y APIs?

@iambumblehead
Copy link
Owner

If esmock's interface is updated to support a 'parent' value defined in the fourth parameter, would that be a good solution? what do you recommend?

const indexModule = await esmock("../index.js", {
  os: {
    hostname: () => expectedHostname,
  },
}, null, {
  parent: parentURL
});

@jakebailey
Copy link
Contributor Author

It'd be an API break, but I would think this would be a required parameter, and "callePath" ceases to be automatically detected.

@jakebailey
Copy link
Contributor Author

jakebailey commented Aug 15, 2022

Just for reference for anyone finding this, my current workaround is this:

import { fileURLToPath } from "url";

export function fixESMockPath(path: string, importMetaUrl: string): string {
    const url = new URL(path, importMetaUrl);
    return fileURLToPath(url);
}

Then, when testing:

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

import { fixESMockPath } from "./testUtils.js";
import type * as myModuleType from "../myModule.js";

test("do something", async (t) => {
    const myModule: typeof myModuleType = await esmock(fixESMockPath("../myModule.js", import.meta.url), {
        fs: {
            writeFile: () => { ... }
        },
        [fixESMockPath("../localLib.js", import.meta.url)]: {
            someFunction: () => { ... }
        },
    };

    const result = await myModule.doSomething(); // Run with the above modules mocked.
    t.is(result, 1234);
});

@iambumblehead
Copy link
Owner

resolved here #122 closing

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

2 participants