Portal,
createStaticVNode
} from '@vue/runtime-dom'
+import { renderToString } from '@vue/server-renderer'
function mountWithHydration(html: string, render: () => any) {
const container = document.createElement('div')
})
// compile SSR + client render fn from the same template & hydrate
- test('full compiler integration', () => {})
+ test('full compiler integration', async () => {
+ const mounted: string[] = []
+ const log = jest.fn()
+ const toggle = ref(true)
+
+ const Child = {
+ data() {
+ return {
+ count: 0,
+ text: 'hello',
+ style: {
+ color: 'red'
+ }
+ }
+ },
+ mounted() {
+ mounted.push('child')
+ },
+ template: `
+ <div>
+ <span class="count" :style="style">{{ count }}</span>
+ <button class="inc" @click="count++">inc</button>
+ <button class="change" @click="style.color = 'green'" >change color</button>
+ <button class="emit" @click="$emit('foo')">emit</button>
+ <span class="text">{{ text }}</span>
+ <input v-model="text">
+ </div>
+ `
+ }
+
+ const App = {
+ setup() {
+ return { toggle }
+ },
+ mounted() {
+ mounted.push('parent')
+ },
+ template: `
+ <div>
+ <span>hello</span>
+ <template v-if="toggle">
+ <Child @foo="log('child')"/>
+ <template v-if="true">
+ <button class="parent-click" @click="log('click')">click me</button>
+ </template>
+ </template>
+ <span>hello</span>
+ </div>`,
+ components: {
+ Child
+ },
+ methods: {
+ log
+ }
+ }
+
+ const container = document.createElement('div')
+ // server render
+ container.innerHTML = await renderToString(h(App))
+ // hydrate
+ createSSRApp(App).mount(container)
+
+ // assert interactions
+ // 1. parent button click
+ triggerEvent('click', container.querySelector('.parent-click')!)
+ expect(log).toHaveBeenCalledWith('click')
+
+ // 2. child inc click + text interpolation
+ const count = container.querySelector('.count') as HTMLElement
+ expect(count.textContent).toBe(`0`)
+ triggerEvent('click', container.querySelector('.inc')!)
+ await nextTick()
+ expect(count.textContent).toBe(`1`)
+
+ // 3. child color click + style binding
+ expect(count.style.color).toBe('red')
+ triggerEvent('click', container.querySelector('.change')!)
+ await nextTick()
+ expect(count.style.color).toBe('green')
+
+ // 4. child event emit
+ triggerEvent('click', container.querySelector('.emit')!)
+ expect(log).toHaveBeenCalledWith('child')
+
+ // 5. child v-model
+ const text = container.querySelector('.text')!
+ const input = container.querySelector('input')!
+ expect(text.textContent).toBe('hello')
+ input.value = 'bye'
+ triggerEvent('input', input)
+ await nextTick()
+ expect(text.textContent).toBe('bye')
+ })
describe('mismatch handling', () => {
test('text', () => {})