2018-10-02 01:15:07 +08:00
|
|
|
import {
|
2019-08-24 03:27:17 +08:00
|
|
|
h,
|
2018-10-02 01:15:07 +08:00
|
|
|
render,
|
|
|
|
nodeOps,
|
|
|
|
NodeTypes,
|
|
|
|
TestElement,
|
2019-08-22 05:05:14 +08:00
|
|
|
TestText,
|
|
|
|
ref,
|
|
|
|
reactive,
|
|
|
|
dumpOps,
|
|
|
|
resetOps,
|
|
|
|
NodeOpTypes,
|
|
|
|
nextTick,
|
|
|
|
serialize,
|
2020-01-22 22:29:35 +08:00
|
|
|
triggerEvent
|
2018-10-02 01:15:07 +08:00
|
|
|
} from '../src'
|
|
|
|
|
|
|
|
describe('test renderer', () => {
|
2019-08-22 05:05:14 +08:00
|
|
|
it('should work', () => {
|
2018-10-02 01:15:07 +08:00
|
|
|
const root = nodeOps.createElement('div')
|
2019-06-20 21:28:37 +08:00
|
|
|
render(
|
|
|
|
h(
|
|
|
|
'div',
|
|
|
|
{
|
|
|
|
id: 'test'
|
|
|
|
},
|
|
|
|
'hello'
|
|
|
|
),
|
|
|
|
root
|
|
|
|
)
|
2018-10-02 01:15:07 +08:00
|
|
|
|
|
|
|
expect(root.children.length).toBe(1)
|
|
|
|
|
|
|
|
const el = root.children[0] as TestElement
|
|
|
|
expect(el.type).toBe(NodeTypes.ELEMENT)
|
|
|
|
expect(el.props.id).toBe('test')
|
|
|
|
expect(el.children.length).toBe(1)
|
|
|
|
|
|
|
|
const text = el.children[0] as TestText
|
|
|
|
expect(text.type).toBe(NodeTypes.TEXT)
|
|
|
|
expect(text.text).toBe('hello')
|
|
|
|
})
|
|
|
|
|
2019-08-22 05:05:14 +08:00
|
|
|
it('should record ops', async () => {
|
|
|
|
const state = reactive({
|
|
|
|
id: 'test',
|
|
|
|
text: 'hello'
|
|
|
|
})
|
|
|
|
|
|
|
|
const App = {
|
|
|
|
render() {
|
|
|
|
return h(
|
|
|
|
'div',
|
|
|
|
{
|
|
|
|
id: state.id
|
|
|
|
},
|
|
|
|
state.text
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const root = nodeOps.createElement('div')
|
|
|
|
|
|
|
|
resetOps()
|
|
|
|
render(h(App), root)
|
|
|
|
const ops = dumpOps()
|
|
|
|
|
|
|
|
expect(ops.length).toBe(4)
|
|
|
|
|
|
|
|
expect(ops[0]).toEqual({
|
|
|
|
type: NodeOpTypes.CREATE,
|
|
|
|
nodeType: NodeTypes.ELEMENT,
|
|
|
|
tag: 'div',
|
|
|
|
targetNode: root.children[0]
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(ops[1]).toEqual({
|
2020-06-13 00:14:39 +08:00
|
|
|
type: NodeOpTypes.SET_ELEMENT_TEXT,
|
|
|
|
text: 'hello',
|
|
|
|
targetNode: root.children[0]
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(ops[2]).toEqual({
|
2019-08-22 05:05:14 +08:00
|
|
|
type: NodeOpTypes.PATCH,
|
|
|
|
targetNode: root.children[0],
|
|
|
|
propKey: 'id',
|
|
|
|
propPrevValue: null,
|
|
|
|
propNextValue: 'test'
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(ops[3]).toEqual({
|
|
|
|
type: NodeOpTypes.INSERT,
|
|
|
|
targetNode: root.children[0],
|
|
|
|
parentNode: root,
|
|
|
|
refNode: null
|
|
|
|
})
|
|
|
|
|
|
|
|
// test update ops
|
|
|
|
state.id = 'foo'
|
|
|
|
state.text = 'bar'
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
const updateOps = dumpOps()
|
|
|
|
expect(updateOps.length).toBe(2)
|
|
|
|
|
|
|
|
expect(updateOps[0]).toEqual({
|
2021-08-17 03:46:27 +08:00
|
|
|
type: NodeOpTypes.SET_ELEMENT_TEXT,
|
2019-08-22 05:05:14 +08:00
|
|
|
targetNode: root.children[0],
|
2021-08-17 03:46:27 +08:00
|
|
|
text: 'bar'
|
2019-08-22 05:05:14 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
expect(updateOps[1]).toEqual({
|
2021-08-17 03:46:27 +08:00
|
|
|
type: NodeOpTypes.PATCH,
|
2019-08-22 05:05:14 +08:00
|
|
|
targetNode: root.children[0],
|
2021-08-17 03:46:27 +08:00
|
|
|
propKey: 'id',
|
|
|
|
propPrevValue: 'test',
|
|
|
|
propNextValue: 'foo'
|
2019-08-22 05:05:14 +08:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should be able to serialize nodes', () => {
|
|
|
|
const App = {
|
|
|
|
render() {
|
|
|
|
return h(
|
|
|
|
'div',
|
|
|
|
{
|
2019-12-18 00:50:10 +08:00
|
|
|
id: 'test',
|
|
|
|
boolean: ''
|
2019-08-22 05:05:14 +08:00
|
|
|
},
|
2019-08-24 03:27:17 +08:00
|
|
|
[h('span', 'foo'), 'hello']
|
2019-08-22 05:05:14 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const root = nodeOps.createElement('div')
|
|
|
|
render(h(App), root)
|
|
|
|
expect(serialize(root)).toEqual(
|
2019-12-18 00:50:10 +08:00
|
|
|
`<div><div id="test" boolean><span>foo</span>hello</div></div>`
|
2019-08-22 05:05:14 +08:00
|
|
|
)
|
|
|
|
// indented output
|
|
|
|
expect(serialize(root, 2)).toEqual(
|
|
|
|
`<div>
|
2019-12-18 00:50:10 +08:00
|
|
|
<div id="test" boolean>
|
2019-08-22 05:05:14 +08:00
|
|
|
<span>
|
|
|
|
foo
|
|
|
|
</span>
|
|
|
|
hello
|
|
|
|
</div>
|
|
|
|
</div>`
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should be able to trigger events', async () => {
|
|
|
|
const count = ref(0)
|
|
|
|
|
|
|
|
const App = () => {
|
|
|
|
return h(
|
|
|
|
'span',
|
|
|
|
{
|
|
|
|
onClick: () => {
|
|
|
|
count.value++
|
|
|
|
}
|
|
|
|
},
|
|
|
|
count.value
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const root = nodeOps.createElement('div')
|
|
|
|
render(h(App), root)
|
|
|
|
triggerEvent(root.children[0] as TestElement, 'click')
|
|
|
|
expect(count.value).toBe(1)
|
|
|
|
await nextTick()
|
|
|
|
expect(serialize(root)).toBe(`<div><span>1</span></div>`)
|
|
|
|
})
|
2019-10-11 09:53:15 +08:00
|
|
|
|
2019-10-18 03:01:51 +08:00
|
|
|
it('should be able to trigger events with multiple listeners', async () => {
|
2019-10-11 09:53:15 +08:00
|
|
|
const count = ref(0)
|
|
|
|
const count2 = ref(1)
|
|
|
|
|
|
|
|
const App = () => {
|
|
|
|
return h(
|
|
|
|
'span',
|
|
|
|
{
|
|
|
|
onClick: [
|
|
|
|
() => {
|
|
|
|
count.value++
|
|
|
|
},
|
|
|
|
() => {
|
|
|
|
count2.value++
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
`${count.value}, ${count2.value}`
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const root = nodeOps.createElement('div')
|
|
|
|
render(h(App), root)
|
|
|
|
triggerEvent(root.children[0] as TestElement, 'click')
|
|
|
|
expect(count.value).toBe(1)
|
|
|
|
expect(count2.value).toBe(2)
|
|
|
|
await nextTick()
|
|
|
|
expect(serialize(root)).toBe(`<div><span>1, 2</span></div>`)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should mock warn', () => {
|
|
|
|
console.warn('warn!!!')
|
|
|
|
expect('warn!!!').toHaveBeenWarned()
|
|
|
|
expect('warn!!!').toHaveBeenWarnedTimes(1)
|
|
|
|
|
|
|
|
console.warn('warn!!!')
|
|
|
|
expect('warn!!!').toHaveBeenWarnedTimes(2)
|
|
|
|
|
|
|
|
console.warn('warning')
|
|
|
|
expect('warn!!!').toHaveBeenWarnedTimes(2)
|
|
|
|
expect('warning').toHaveBeenWarnedLast()
|
|
|
|
})
|
2018-10-02 01:15:07 +08:00
|
|
|
})
|