Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/vue-wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentPublicInstance, nextTick, App } from 'vue'

import { ShapeFlags } from './utils/vueShared'
import { config } from './config'

import { DOMWrapper } from './dom-wrapper'
import { FindAllComponentsSelector, FindComponentSelector } from './types'
import { createWrapperError } from './error-wrapper'
Expand Down Expand Up @@ -197,6 +197,13 @@ export class VueWrapper<T extends ComponentPublicInstance> {
return nextTick()
}

setData(data: Record<string, any>) {
// lodash.merge merges by *reference* so this will update
// any existing data with the newly passed data.
merge(this.componentVM.$data, data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we guard against setting data that is not in $data already? Not sure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's check how Vue 3 behaves. I wonder if the new reactivity API allows you to update with new properties? I think we should match whatever Vue 3 does.

return nextTick()
}

trigger(eventString: string, options?: TriggerOptions) {
const rootElementWrapper = new DOMWrapper(this.element)
return rootElementWrapper.trigger(eventString, options)
Expand Down
67 changes: 67 additions & 0 deletions tests/setData.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { mount } from '../src'

describe('setData', () => {
it('causes nested nodes to re-render', async () => {
const Comp = {
template: `<div><div v-if="show" id="show">Show</div></div>`,
data() {
return { show: false }
}
}

const wrapper = mount(Comp)
expect(wrapper.find('#show').exists()).toBe(false)

await wrapper.setData({ show: true })

expect(wrapper.find('#show').exists()).toBe(true)
})

it('runs watch function when data is updated', async () => {
const Comp = {
template: `<div>{{ sideEffect }}</div>`,
data() {
return { msg: '', sideEffect: '' }
},
watch: {
msg() {
this.sideEffect = 'side effect'
}
}
}
const wrapper = mount(Comp)
expect(wrapper.html()).not.toContain('side effect')

await wrapper.setData({ msg: 'foo' })

expect(wrapper.html()).toContain('side effect')
})

it('updates a single property of a complex object', async () => {
const Comp = {
template: `<div>Qux: {{ foo.qux }}. Baz: {{ foo.bar.baz }}</div>`,
data() {
return {
foo: {
qux: 'will not change',
bar: {
baz: 'old val'
}
}
}
}
}
const wrapper = mount(Comp)
expect(wrapper.html()).toBe('<div>Qux: will not change. Baz: old val</div>')

await wrapper.setData({
foo: {
bar: {
baz: 'new val'
}
}
})

expect(wrapper.html()).toBe('<div>Qux: will not change. Baz: new val</div>')
})
})