Can't use jest spies for functions in same file
If I have a file that contains
// myFile.ts
export const addOne = (x: number): string => `${x + 1}`
export const someFunc = (x: number): string => `The answer is : ${addOne(x)}`
And I want to test the two functions separately and therefore mock addOne:
import * as myFile from './myFile'
describe('someFunc', () => {
const expected = '2';
const addOneSpy = jest.spyOn(myFile, 'addOne').mockResolvedValue(expected);
it('should call addOne', () => {
expect(addOneSpy).toHaveBeenCalledWith(1);
});
});
with ts-jest, this code snippet provided works. With @swc-node/jest, it seems any jest spies from the same file cannot be spied on, and if they are, result in the error:
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: 1
Number of calls: 0
Note that I have tried the exact same scenario but exporting them as actual functions (i.e. export function someFunc(x: number): string {), but still run into the same problem.
I have same pb too. It works perfectly with ts-jest.
I'll take a look soon
It is because SWC doesn't add exports. prefix function calls in the same file.
SWC :
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.someFunc = exports.addOne = void 0;
const addOne = (x)=>`${x + 1}`
;
exports.addOne = addOne;
const someFunc = (x)=>`The answer is : ${addOne(x)}`
TypeScript:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.someFunc = exports.addOne = void 0;
const addOne = (x) => `${x + 1}`;
exports.addOne = addOne;
const someFunc = (x) => `The answer is : ${(0, exports.addOne)(x)}`;
exports.someFunc = someFunc;
/cc @kdy1
Seems like https://github.com/swc-project/swc/issues/2549 ?
Yes, thanks!
I haven't tried this lib again since this issue, did #2569 fix this, or is this still expected at the moment?
This still seems to be an error. @Brooooooklyn any idea when this will be addressed, or if ever?
This is not an error/bug. That something else makes something possible does not make it right. SWC is the one doing the right thing here, as the resolved ESM exports are supposed to be immutable. Just for reference, the output for CommonJS has changed a bit to be closer to actual ESM semantics, which should clarify what is going on (it's using getters):
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
addOne: function() {
return addOne;
},
someFunc: function() {
return someFunc;
}
});
const addOne = (x)=>`${x + 1}`;
const someFunc = (x)=>`The answer is : ${addOne(x)}`;
If you actually intend for addOne to be replaceable, make it explicit and open of for some pure DI: just make it a let and expose a export const _setAddOne(mockImpl){ addOne = mockImpl; }. Done.
Thank you! See https://github.com/swc-project/swc/issues/7435