Skip to content

Commit fa7dbaf

Browse files
authored
fix: ignore prototype methods when using setData on objects (#2265)
Fixes #2257
1 parent e16ae5a commit fa7dbaf

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/utils.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,25 @@ export function mergeGlobalProperties(
7272
export const isObject = (obj: unknown): obj is Record<string, any> =>
7373
!!obj && typeof obj === 'object'
7474

75+
function isClass(obj: unknown) {
76+
if (!(obj instanceof Object)) return
77+
78+
const isCtorClass =
79+
obj.constructor && obj.constructor.toString().substring(0, 5) === 'class'
80+
81+
if (!('prototype' in obj)) {
82+
return isCtorClass
83+
}
84+
85+
const prototype = obj.prototype as any
86+
const isPrototypeCtorClass =
87+
prototype.constructor &&
88+
prototype.constructor.toString &&
89+
prototype.constructor.toString().substring(0, 5) === 'class'
90+
91+
return isCtorClass || isPrototypeCtorClass
92+
}
93+
7594
// https://stackoverflow.com/a/48218209
7695
export const mergeDeep = (
7796
target: Record<string, unknown>,
@@ -80,8 +99,13 @@ export const mergeDeep = (
8099
if (!isObject(target) || !isObject(source)) {
81100
return source
82101
}
102+
83103
Object.keys(source)
84-
.concat(Object.getOwnPropertyNames(Object.getPrototypeOf(source) ?? {}))
104+
.concat(
105+
isClass(source)
106+
? Object.getOwnPropertyNames(Object.getPrototypeOf(source) ?? {})
107+
: Object.getOwnPropertyNames(source)
108+
)
85109
.forEach((key) => {
86110
const targetValue = target[key]
87111
const sourceValue = source[key]

tests/setData.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,4 +246,29 @@ describe('setData', () => {
246246

247247
expect(wrapper.vm.getResult()).toStrictEqual(`test2: ${expectedResult}`)
248248
})
249+
250+
// https://github.com/vuejs/test-utils/issues/2257
251+
it('should ignore prototype methods when using setData on objects', async () => {
252+
const wrapper = mount(
253+
defineComponent({
254+
template: '<div />',
255+
data() {
256+
return {
257+
firstArray: [],
258+
secondArray: []
259+
}
260+
}
261+
})
262+
)
263+
264+
await wrapper.setData({
265+
firstArray: [1, 2],
266+
secondArray: [3, 4]
267+
})
268+
269+
expect(wrapper.vm.$data).toStrictEqual({
270+
firstArray: [1, 2],
271+
secondArray: [3, 4]
272+
})
273+
})
249274
})

0 commit comments

Comments
 (0)