SpyOn doesn't work on ESM namespace object properties
Closed this issue · 4 comments
What version of Bun is running?
1.0.0
What platform is your computer?
Darwin 22.5.0 arm64 arm
What steps can reproduce the bug?
The spyOn of bun test doesn't work when the function is import from a different file of the test file. Like the example below:
Test file :
import { describe, expect, it, spyOn } from 'bun:test'
import * as fileA from './fileA'
describe('fileB', () => {
it('should spy the say toto in file A', async () => {
const spySayToto = spyOn(fileA, 'sayToto')
fileA.sayToto()
// This test failed and have 0 as value
expect(spySayToto).toHaveBeenCalledTimes(1)
})
})
File A with function to spy:
export const sayToto = () => {
console.log('toto')
}
What is the expected behavior?
The function have been called 1 times and not zero.
What do you see instead?
No response
Additional information
No response
I've found a workaround by assigning the imported function to an object created in the test file:
index.ts
export function fn() { ... }
index.test.ts
import { expect, spyOn, test } from "bun:test";
import { fn } from "./index";
test("spied fn is called", () => {
const obj = { fn };
const spy = spyOn(obj, "fn");
obj.fn();
expect(spy).toHaveBeenCalledTimes(1);
});
I've taken a few steps to look at this but I'm not familiar with C++ so I probably won't get anywhere. Documenting what I find anyway in case it'll be useful. So far:
- Created a test case for this scenario (d1d80da). The case itself is just a copy of this test case but just uses a function imported from a fixture file. It fails as expected.
- Suspect the problem is somewhere here:
bun/src/bun.js/bindings/JSMockFunction.cpp
Lines 570 to 659 in 687e31d
Yes I also look the issue few days ago, I think the problem is that the function is not in the globalContext because it's is in a different file. We need to find the right globalContext I think but I am not an expert on JavascriptCore so I am not sure about this.
This happens because the ES Module namespace object symbol table needs to be mutated to update the binding for the ESM export to the new wrapped value