Skip to content

Commit b263547

Browse files
committed
fix: correctly restore getter
1 parent 746d855 commit b263547

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

src/spyOn.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ export function internalSpyOn<T, K extends string & keyof T>(
5858
let objDescriptor = getDescriptor(obj, accessName)
5959
let proto = Object.getPrototypeOf(obj)
6060
let protoDescriptor = proto && getDescriptor(proto, accessName)
61-
let descriptor = objDescriptor || protoDescriptor
61+
let originalDescriptor = objDescriptor || protoDescriptor
6262

6363
assert(
64-
descriptor || accessName in obj,
64+
originalDescriptor || accessName in obj,
6565
`${String(accessName)} does not exist`
6666
)
6767

@@ -70,19 +70,19 @@ export function internalSpyOn<T, K extends string & keyof T>(
7070
// vite ssr support - actual function is stored inside a getter
7171
if (
7272
accessType === 'value' &&
73-
descriptor &&
74-
!descriptor.value &&
75-
descriptor.get
73+
originalDescriptor &&
74+
!originalDescriptor.value &&
75+
originalDescriptor.get
7676
) {
7777
accessType = 'get'
7878
ssr = true
79-
mock = descriptor.get!()
79+
mock = originalDescriptor.get!()
8080
}
8181

8282
let origin: Procedure
8383

84-
if (descriptor) {
85-
origin = descriptor[accessType]
84+
if (originalDescriptor) {
85+
origin = originalDescriptor[accessType]
8686
} else if (accessType !== 'value') {
8787
origin = () => obj[accessName as keyof T]
8888
} else {
@@ -93,7 +93,7 @@ export function internalSpyOn<T, K extends string & keyof T>(
9393

9494
let fn = createInternalSpy(mock)
9595
let reassign = (cb: any) => {
96-
let { value, ...desc } = descriptor || {
96+
let { value, ...desc } = originalDescriptor || {
9797
configurable: true,
9898
writable: true,
9999
}
@@ -103,7 +103,9 @@ export function internalSpyOn<T, K extends string & keyof T>(
103103
;(desc as PropertyDescriptor)[accessType] = cb
104104
define(obj, accessName, desc)
105105
}
106-
let restore = () => reassign(origin)
106+
let restore = () => originalDescriptor
107+
? define(obj, accessName, originalDescriptor)
108+
: reassign(origin)
107109
const state = fn[S]
108110
defineValue(state, 'restore', restore)
109111
defineValue(state, 'getOriginal', () => (ssr ? origin() : origin))

test/index.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ test('can spy on method', () => {
3131
},
3232
}
3333

34+
const original = obj.method
35+
3436
let method = spyOn(obj, 'method')
37+
38+
expect(original).not.toBe(obj.method)
3539
expect(method.called).toBe(false)
3640
expect(method.callCount).toBe(0)
3741
expect(method.calls).toEqual([])
@@ -70,6 +74,7 @@ test('can spy on method', () => {
7074
expect(method.results).toEqual([ok('a!'), ok('b!'), ok('C!'), error(err)])
7175

7276
method.restore()
77+
expect(original).toBe(obj.method)
7378
expect(obj.method('e')).toBe('e!')
7479
expect(calls).toEqual(['a', 'b', 'e'])
7580
expect(method.callCount).toBe(4)
@@ -585,6 +590,10 @@ test('no descriptor', () => {
585590
expect(count).toBe(42)
586591
expect(getter.called).toBe(true)
587592
expect(getter.returns[0]).toBe(42)
593+
594+
spy.restore()
595+
596+
expect(head.appendChild).toBeTruthy()
588597
})
589598

590599
test('throw error', () => {
@@ -685,3 +694,14 @@ test('does not await on non-promise values that contain .then', async () => {
685694
const spiedResult = spied().addValue('Hello').addValue('World')
686695
expect(spiedResult).toStrictEqual(originalResult)
687696
})
697+
698+
test('.restore correctly restores primitive property', () => {
699+
const obj = {
700+
test: 42
701+
}
702+
const spy = spyOn(obj, { getter: 'test' })
703+
spy.willCall(() => 10)
704+
expect(obj.test).toBe(10)
705+
spy.restore()
706+
expect(obj.test).toBe(42)
707+
})

0 commit comments

Comments
 (0)