diff --git a/e2e/spy/fixtures/util.ts b/e2e/spy/fixtures/util.ts new file mode 100644 index 00000000..eae921c8 --- /dev/null +++ b/e2e/spy/fixtures/util.ts @@ -0,0 +1 @@ +export const sayHi = () => 'hi'; diff --git a/e2e/spy/spyOn.test.ts b/e2e/spy/spyOn.test.ts index ec24841b..1378d7c2 100644 --- a/e2e/spy/spyOn.test.ts +++ b/e2e/spy/spyOn.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it, rstest } from '@rstest/core'; +import * as utils from './fixtures/util'; describe('test spyOn', () => { it('spyOn', () => { @@ -39,4 +40,42 @@ describe('test spyOn', () => { spy.mockRestore(); expect(rstest.isMockFunction(hi.sayHi)).toBeFalsy(); }); + + it('spyOn import', () => { + expect(() => { + // @ts-expect-error test + utils.sayHi = () => 'hello'; + }).toThrowError( + 'Cannot set property sayHi of # which has only a getter', + ); + + const spy = rstest.spyOn(utils, 'sayHi'); + + expect(utils.sayHi()).toBe('hi'); + + expect(utils.sayHi).toBeCalled(); + + spy.mockImplementation(() => 'hello'); + + expect(utils.sayHi()).toBe('hello'); + + spy.mockReset(); + + expect(utils.sayHi()).toBe('hi'); + }); + + it('spyOn dynamic import', async () => { + const util1 = await import('./fixtures/util'); + const spy = rstest.spyOn(util1, 'sayHi'); + + expect(util1.sayHi()).toBe('hi'); + expect(util1.sayHi).toBeCalled(); + + spy.mockImplementation(() => 'hello'); + + expect(util1.sayHi()).toBe('hello'); + + spy.mockReset(); + expect(util1.sayHi()).toBe('hi'); + }); }); diff --git a/packages/core/src/core/plugins/mockRuntime.ts b/packages/core/src/core/plugins/mockRuntime.ts index 7b1b2832..4276eb40 100644 --- a/packages/core/src/core/plugins/mockRuntime.ts +++ b/packages/core/src/core/plugins/mockRuntime.ts @@ -37,6 +37,17 @@ class MockRuntimeRspackPlugin { ); module.source!.source = Buffer.from(finalSource); } + + if (module.name === 'define_property_getters') { + const finalSource = module.source!.source.toString('utf-8').replace( + // Sets the object configurable so that imported properties can be spied + // Hard coded in EJS template https://github.com/web-infra-dev/rspack/blob/main/crates/rspack_plugin_runtime/src/runtime_module/runtime/define_property_getters.ejs + 'enumerable: true, get:', + 'enumerable: true, configurable: true, get:', + ); + + module.source!.source = Buffer.from(finalSource); + } }, ); });