Description
Description
I am trying to do esm mocking using testdouble
with a mixed Typescript and Javascript project, mostly following this post
Node 18.6.0 now allows for chaining of loads, and I previously needed ts-node/esm
in order to recognize my Typescript files and imports.
I realize that this new feature is less than a week old, but I would appreciate support with reconciling other loaders that I would need for my es6 project (or to find a way that only requires one loader). Due to project requirements, using commonjs
on runtime is not an option.
Issue
When running the following mocha command:
NODE_OPTIONS='--experimental-specifier-resolution=node --loader=ts-node/esm --loader=testdouble' mocha test/.js test/.spec.ts
and any permutation thereof (removing experimental-specifier-resolution
, changing the order of the --loader
params)
I get the following exception
Exception in PromiseRejectCallback:
node:internal/modules/esm/loader:178
return output;
RangeError: Maximum call stack size exceeded
Exception in PromiseRejectCallback:
/Users/repos/moRepo/node_modules/ts-node/dist/esm.js:120
const { source: rawSource } = await defaultLoad(url, {
^
RangeError: Maximum call stack size exceeded
at validateArgs (node:internal/modules/esm/loader:578:26)
These 4 lines repeat indefinitely:
at addShortCircuitFlag (/Users/repos/myRepo/node_modules/ts-node/src/esm.ts:409:21)
at load (/Users/repos/myRepo/node_modules/ts-node/src/esm.ts:239:12)
at nextLoad (node:internal/modules/esm/loader:173:28)
at /Users/repos/myRepo/node_modules/ts-node/src/esm.ts:255:45
Environment
node v18.6.0
npm v.8.13.2
testdouble v.3.16.6
Example Repo
I don't have a repo handy, but I can try to create one and add it in the future.
Code-fenced Examples
service_one.ts
export function getAllInvalidObjects(connection: Connection) {
const response: string[] = service_two.getData(someString);
... // some transformations of response
return response;
}
service_two.ts
// this is the function I'd like to mock when testing service_one.ts
export function getData(someString) {
axios.get('https://endpoint.com/path?string=' + someString).then((response: any) {
resolve(response.json);
}
}
test.ts :
import * as td from 'testdouble';
let mock_validation_rest: any;
beforeEach(async () => {
mock_rest = await td.replaceEsm('../src/services/service_two.js');
});
afterEach(function () {
sandbox.restore();
td.reset();
});
it('successfully validates with mocking, async () => {
td.when(mock_rest.prototype.getData(td.matchers.anything())).thenResolve(mockData);
// as long as the mock above works then this test will pass
return service_one.getAllInvalidObjects(connection).then((response: string[]) => {
assert.equal(3, response.length);
});
});
package.json:
{
"type": "module",
"scripts": {
"test": NODE_OPTIONS='--experimental-specifier-resolution=node --loader=ts-node/esm --loader=testdouble' mocha test/*.js test/*.spec.ts -r dotenv/config
}
}
tsconfig.json:
{
"compilerOptions": {
"target": "es2016",
"module": "es6,
"moduleResolution": "node16"
"allowJs": true,
"esModuleInterop": true
},
"ts-node": {
"esm": true
}
"include": [
"./src/**/*",
"test/**/*/.ts",
"test/**/*.js"
}
}