babel-plugin-rewire-exports
babel-plugin-rewire-exports copied to clipboard
Wish: Hoisted Modules
Issue!
Currently I am in the process of using this to mock out imported dependencies for Cypress Component Testing, it works great but I am trying to get around an issue with IIFE behaviour in one of our files. Eg:
// dependency - withDateString.js
const withDateString = string => `${new Date()}: ${string}`;
export default withDateString;
// system under test - message.js
import withDateString from "./withDateString";
const message = () => "Message!";
export default withDateString(message); // <-- IIFE behaviour
// test file - message.test.js
import message from "./message.js"
import { rewire } from "./withDateString.js"
test(() => {
rewire(a => `Foo: ${a}`); // <-- too late to do this;
expect(message()).toBe("Foo: Message!"); // <-- will fail
});
The issue is, because the withDateString()
method is invoked not on execution of the SUT but on the import, as such its impossible to ever mock that dependency.
What I would like!
If there was an option in the plugin setup to hoist mocks above their declaration in the rewritten code so that they can effectively be mocked before import!
Currently my workaround is to do this in my test code, eg:
import { rewire } from "./withDateString.js"
test(async () => {
rewire(a => `Foo: ${a}`);
const { default: message } = await import("./message"); // <-- now this is guaranteed to happen after.
expect(message()).toBe("Foo: Message!");
});
But would prefer a way that allows me to use Imports as they are and simply mock where I want safe in the knowledge the plugin will ensure order of execution is sorted for me.
I think your workaround is the only way to address the issue. I don't think I can do anything in the transformation that would prevent the code in the module body from executing. Delaying the execution (by importing the module later) seems like the way to go.