test: add tests for rendererChildren (#52)
* test: [wip] add tests for rendererChildren * chore: use serializeInner for clearer output * fix: should remove the text node if content is empty * test: also test for appended content * test: inserting & removing * test: moving children * refactor: use a helper function * test: finish tests * test: duplicate keys tests belong to keyed children block * fix(runtime-test): fix insert when moving node in the same parent * fix: fix failing test cases for rendererChildren * test: handle rendererChildren edge case
This commit is contained in:
parent
c78d47b788
commit
b275f8697d
@ -1,37 +1,623 @@
|
||||
// reference: https://github.com/vuejs/vue/blob/dev/test/unit/modules/vdom/patch/children.spec.js
|
||||
import {
|
||||
h,
|
||||
render,
|
||||
nodeOps,
|
||||
NodeTypes,
|
||||
TestElement,
|
||||
serialize,
|
||||
serializeInner,
|
||||
mockWarn
|
||||
} from '@vue/runtime-test'
|
||||
|
||||
describe('renderer: unkeyed children', () => {
|
||||
test.todo('append')
|
||||
mockWarn()
|
||||
|
||||
test.todo('prepend')
|
||||
function toSpan(content: any) {
|
||||
if (typeof content === 'string') {
|
||||
return h('span', content.toString())
|
||||
} else {
|
||||
return h('span', { key: content }, content.toString())
|
||||
}
|
||||
}
|
||||
|
||||
test.todo('insert in middle')
|
||||
const inner = (c: TestElement) => serializeInner(c)
|
||||
|
||||
test.todo('insert at beginning and end')
|
||||
function shuffle(array: Array<any>) {
|
||||
let currentIndex = array.length
|
||||
let temporaryValue
|
||||
let randomIndex
|
||||
|
||||
test.todo('insert to empty parent')
|
||||
// while there remain elements to shuffle...
|
||||
while (currentIndex !== 0) {
|
||||
// pick a remaining element...
|
||||
randomIndex = Math.floor(Math.random() * currentIndex)
|
||||
currentIndex -= 1
|
||||
// and swap it with the current element.
|
||||
temporaryValue = array[currentIndex]
|
||||
array[currentIndex] = array[randomIndex]
|
||||
array[randomIndex] = temporaryValue
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
test.todo('shift with offset')
|
||||
it('should patch previously empty children', () => {
|
||||
const root = nodeOps.createElement('div')
|
||||
|
||||
test.todo('remove from beginning')
|
||||
render(h('div', []), root)
|
||||
expect(inner(root)).toBe('<div></div>')
|
||||
|
||||
test.todo('remove from end')
|
||||
|
||||
test.todo('remove from middle')
|
||||
|
||||
test.todo('moving single child forward')
|
||||
|
||||
test.todo('moving single child backwards')
|
||||
|
||||
test.todo('moving single child to end')
|
||||
|
||||
test.todo('swap first and last')
|
||||
|
||||
test.todo('move to left & replace')
|
||||
|
||||
test.todo('generic reorder')
|
||||
|
||||
test.todo('should not de-opt when both head and tail change')
|
||||
render(h('div', ['hello']), root)
|
||||
expect(inner(root)).toBe('<div>hello</div>')
|
||||
})
|
||||
|
||||
describe('renderer: keyed children', () => {})
|
||||
it('should patch previously null children', () => {
|
||||
const root = nodeOps.createElement('div')
|
||||
|
||||
render(h('div'), root)
|
||||
expect(inner(root)).toBe('<div></div>')
|
||||
|
||||
render(h('div', ['hello']), root)
|
||||
expect(inner(root)).toBe('<div>hello</div>')
|
||||
})
|
||||
|
||||
describe('renderer: keyed children', () => {
|
||||
let root: TestElement
|
||||
let elm: TestElement
|
||||
const renderChildren = (arr: number[]) => {
|
||||
render(h('div', arr.map(toSpan)), root)
|
||||
return root.children[0] as TestElement
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
root = nodeOps.createElement('div')
|
||||
render(h('div', { id: 1 }, 'hello'), root)
|
||||
})
|
||||
|
||||
test('append', () => {
|
||||
elm = renderChildren([1])
|
||||
expect(elm.children.length).toBe(1)
|
||||
|
||||
elm = renderChildren([1, 2, 3])
|
||||
expect(elm.children.length).toBe(3)
|
||||
expect(serialize(elm.children[1])).toBe('<span>2</span>')
|
||||
expect(serialize(elm.children[2])).toBe('<span>3</span>')
|
||||
})
|
||||
|
||||
test('prepend', () => {
|
||||
elm = renderChildren([4, 5])
|
||||
expect(elm.children.length).toBe(2)
|
||||
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5'
|
||||
])
|
||||
})
|
||||
|
||||
test('insert in middle', () => {
|
||||
elm = renderChildren([1, 2, 4, 5])
|
||||
expect(elm.children.length).toBe(4)
|
||||
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5'
|
||||
])
|
||||
})
|
||||
|
||||
test('insert at beginning and end', () => {
|
||||
elm = renderChildren([2, 3, 4])
|
||||
expect(elm.children.length).toBe(3)
|
||||
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5'
|
||||
])
|
||||
})
|
||||
|
||||
test('insert to empty parent', () => {
|
||||
elm = renderChildren([])
|
||||
expect(elm.children.length).toBe(0)
|
||||
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5'
|
||||
])
|
||||
})
|
||||
|
||||
test('remove all children from parent', () => {
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5'
|
||||
])
|
||||
|
||||
render(h('div'), root)
|
||||
expect(elm.children.length).toBe(0)
|
||||
})
|
||||
|
||||
test('remove from beginning', () => {
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
|
||||
elm = renderChildren([3, 4, 5])
|
||||
expect(elm.children.length).toBe(3)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['3', '4', '5'])
|
||||
})
|
||||
|
||||
test('remove from end', () => {
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
|
||||
elm = renderChildren([1, 2, 3])
|
||||
expect(elm.children.length).toBe(3)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['1', '2', '3'])
|
||||
})
|
||||
|
||||
test('remove from middle', () => {
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
|
||||
elm = renderChildren([1, 2, 4, 5])
|
||||
expect(elm.children.length).toBe(4)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'2',
|
||||
'4',
|
||||
'5'
|
||||
])
|
||||
})
|
||||
|
||||
test('moving single child forward', () => {
|
||||
elm = renderChildren([1, 2, 3, 4])
|
||||
expect(elm.children.length).toBe(4)
|
||||
|
||||
elm = renderChildren([2, 3, 1, 4])
|
||||
expect(elm.children.length).toBe(4)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'2',
|
||||
'3',
|
||||
'1',
|
||||
'4'
|
||||
])
|
||||
})
|
||||
|
||||
test('moving single child backwards', () => {
|
||||
elm = renderChildren([1, 2, 3, 4])
|
||||
expect(elm.children.length).toBe(4)
|
||||
|
||||
elm = renderChildren([1, 4, 2, 3])
|
||||
expect(elm.children.length).toBe(4)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'4',
|
||||
'2',
|
||||
'3'
|
||||
])
|
||||
})
|
||||
|
||||
test('moving single child to end', () => {
|
||||
elm = renderChildren([1, 2, 3])
|
||||
expect(elm.children.length).toBe(3)
|
||||
|
||||
elm = renderChildren([2, 3, 1])
|
||||
expect(elm.children.length).toBe(3)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['2', '3', '1'])
|
||||
})
|
||||
|
||||
test('swap first and last', () => {
|
||||
elm = renderChildren([1, 2, 3, 4])
|
||||
expect(elm.children.length).toBe(4)
|
||||
|
||||
elm = renderChildren([4, 2, 3, 1])
|
||||
expect(elm.children.length).toBe(4)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'4',
|
||||
'2',
|
||||
'3',
|
||||
'1'
|
||||
])
|
||||
})
|
||||
|
||||
test('move to left & replace', () => {
|
||||
elm = renderChildren([1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(5)
|
||||
|
||||
elm = renderChildren([4, 1, 2, 3, 6])
|
||||
expect(elm.children.length).toBe(5)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'4',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'6'
|
||||
])
|
||||
})
|
||||
|
||||
test('move to left and leaves hold', () => {
|
||||
elm = renderChildren([1, 4, 5])
|
||||
expect(elm.children.length).toBe(3)
|
||||
|
||||
elm = renderChildren([4, 6])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['4', '6'])
|
||||
})
|
||||
|
||||
test('moved and set to undefined element ending at the end', () => {
|
||||
elm = renderChildren([2, 4, 5])
|
||||
expect(elm.children.length).toBe(3)
|
||||
|
||||
elm = renderChildren([4, 5, 3])
|
||||
expect(elm.children.length).toBe(3)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['4', '5', '3'])
|
||||
})
|
||||
|
||||
test('reverse element', () => {
|
||||
elm = renderChildren([1, 2, 3, 4, 5, 6, 7, 8])
|
||||
expect(elm.children.length).toBe(8)
|
||||
|
||||
elm = renderChildren([8, 7, 6, 5, 4, 3, 2, 1])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'8',
|
||||
'7',
|
||||
'6',
|
||||
'5',
|
||||
'4',
|
||||
'3',
|
||||
'2',
|
||||
'1'
|
||||
])
|
||||
})
|
||||
|
||||
test('something', () => {
|
||||
elm = renderChildren([0, 1, 2, 3, 4, 5])
|
||||
expect(elm.children.length).toBe(6)
|
||||
|
||||
elm = renderChildren([4, 3, 2, 1, 5, 0])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'4',
|
||||
'3',
|
||||
'2',
|
||||
'1',
|
||||
'5',
|
||||
'0'
|
||||
])
|
||||
})
|
||||
|
||||
test('random shuffle', () => {
|
||||
const elms = 14
|
||||
const samples = 5
|
||||
const arr = [...Array(elms).keys()]
|
||||
const opacities: string[] = []
|
||||
|
||||
function spanNumWithOpacity(n: number, o: string) {
|
||||
return h('span', { key: n, style: { opacity: o } }, n.toString())
|
||||
}
|
||||
|
||||
for (let n = 0; n < samples; ++n) {
|
||||
render(h('span', arr.map(n => spanNumWithOpacity(n, '1'))), root)
|
||||
elm = root.children[0] as TestElement
|
||||
|
||||
for (let i = 0; i < elms; ++i) {
|
||||
expect(serializeInner(elm.children[i] as TestElement)).toBe(
|
||||
i.toString()
|
||||
)
|
||||
opacities[i] = Math.random()
|
||||
.toFixed(5)
|
||||
.toString()
|
||||
}
|
||||
|
||||
const shufArr = shuffle(arr.slice(0))
|
||||
render(
|
||||
h('span', arr.map(n => spanNumWithOpacity(shufArr[n], opacities[n]))),
|
||||
root
|
||||
)
|
||||
elm = root.children[0] as TestElement
|
||||
for (let i = 0; i < elms; ++i) {
|
||||
expect(serializeInner(elm.children[i] as TestElement)).toBe(
|
||||
shufArr[i].toString()
|
||||
)
|
||||
expect(elm.children[i]).toMatchObject({
|
||||
props: {
|
||||
style: {
|
||||
opacity: opacities[i]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('children with the same key but with different tag', () => {
|
||||
render(
|
||||
h('div', [
|
||||
h('div', { key: 1 }, 'one'),
|
||||
h('div', { key: 2 }, 'two'),
|
||||
h('div', { key: 3 }, 'three'),
|
||||
h('div', { key: 4 }, 'four')
|
||||
]),
|
||||
root
|
||||
)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(c => c.tag)).toEqual([
|
||||
'div',
|
||||
'div',
|
||||
'div',
|
||||
'div'
|
||||
])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
'four'
|
||||
])
|
||||
|
||||
render(
|
||||
h('div', [
|
||||
h('div', { key: 4 }, 'four'),
|
||||
h('span', { key: 3 }, 'three'),
|
||||
h('span', { key: 2 }, 'two'),
|
||||
h('div', { key: 1 }, 'one')
|
||||
]),
|
||||
root
|
||||
)
|
||||
expect((elm.children as TestElement[]).map(c => c.tag)).toEqual([
|
||||
'div',
|
||||
'span',
|
||||
'span',
|
||||
'div'
|
||||
])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'four',
|
||||
'three',
|
||||
'two',
|
||||
'one'
|
||||
])
|
||||
})
|
||||
|
||||
test('children with the same tag, same key, but one with data and one without data', () => {
|
||||
render(h('div', [h('div', { class: 'hi' }, 'one')]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect(elm.children[0]).toMatchObject({
|
||||
props: {
|
||||
class: 'hi'
|
||||
}
|
||||
})
|
||||
|
||||
render(h('div', [h('div', 'four')]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect(elm.children[0] as TestElement).toMatchObject({
|
||||
props: {
|
||||
// in the DOM renderer this will be ''
|
||||
// but the test renderer simply sets whatever value it receives.
|
||||
class: null
|
||||
}
|
||||
})
|
||||
expect(serialize(elm.children[0])).toBe(`<div>four</div>`)
|
||||
})
|
||||
|
||||
test('should warn with duplicate keys', () => {
|
||||
renderChildren([1, 2, 3, 4, 5])
|
||||
renderChildren([1, 6, 6, 3, 5])
|
||||
expect(`Duplicate keys`).toHaveBeenWarned()
|
||||
})
|
||||
})
|
||||
|
||||
describe('renderer: unkeyed children', () => {
|
||||
let root: TestElement
|
||||
let elm: TestElement
|
||||
const renderChildren = (arr: Array<number | string>) => {
|
||||
render(h('div', arr.map(toSpan)), root)
|
||||
return root.children[0] as TestElement
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
root = nodeOps.createElement('div')
|
||||
render(h('div', { id: 1 }, 'hello'), root)
|
||||
})
|
||||
|
||||
test('move a key in non-keyed nodes with a size up', () => {
|
||||
elm = renderChildren([1, 'a', 'b', 'c'])
|
||||
expect(elm.children.length).toBe(4)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'1',
|
||||
'a',
|
||||
'b',
|
||||
'c'
|
||||
])
|
||||
|
||||
elm = renderChildren(['d', 'a', 'b', 'c', 1, 'e'])
|
||||
expect(elm.children.length).toBe(6)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'd',
|
||||
'a',
|
||||
'b',
|
||||
'c',
|
||||
'1',
|
||||
'e'
|
||||
])
|
||||
})
|
||||
|
||||
test('append elements with updating children without keys', () => {
|
||||
elm = renderChildren(['hello'])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['hello'])
|
||||
|
||||
elm = renderChildren(['hello', 'world'])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'hello',
|
||||
'world'
|
||||
])
|
||||
})
|
||||
|
||||
test('unmoved text nodes with updating children without keys', () => {
|
||||
render(h('div', ['text', h('span', ['hello'])]), root)
|
||||
|
||||
elm = root.children[0] as TestElement
|
||||
expect(elm.children[0]).toMatchObject({
|
||||
type: NodeTypes.TEXT,
|
||||
text: 'text'
|
||||
})
|
||||
|
||||
render(h('div', ['text', h('span', ['hello'])]), root)
|
||||
|
||||
elm = root.children[0] as TestElement
|
||||
expect(elm.children[0]).toMatchObject({
|
||||
type: NodeTypes.TEXT,
|
||||
text: 'text'
|
||||
})
|
||||
})
|
||||
|
||||
test('changing text children with updating children without keys', () => {
|
||||
render(h('div', ['text', h('span', ['hello'])]), root)
|
||||
|
||||
elm = root.children[0] as TestElement
|
||||
expect(elm.children[0]).toMatchObject({
|
||||
type: NodeTypes.TEXT,
|
||||
text: 'text'
|
||||
})
|
||||
|
||||
render(h('div', ['text2', h('span', ['hello'])]), root)
|
||||
|
||||
elm = root.children[0] as TestElement
|
||||
expect(elm.children[0]).toMatchObject({
|
||||
type: NodeTypes.TEXT,
|
||||
text: 'text2'
|
||||
})
|
||||
})
|
||||
|
||||
test('prepend element with updating children without keys', () => {
|
||||
render(h('div', [h('span', ['world'])]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['world'])
|
||||
|
||||
render(h('div', [h('span', ['hello']), h('span', ['world'])]), root)
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'hello',
|
||||
'world'
|
||||
])
|
||||
})
|
||||
|
||||
test('prepend element of different tag type with updating children without keys', () => {
|
||||
render(h('div', [h('span', ['world'])]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['world'])
|
||||
|
||||
render(h('div', [h('div', ['hello']), h('span', ['world'])]), root)
|
||||
expect((elm.children as TestElement[]).map(c => c.tag)).toEqual([
|
||||
'div',
|
||||
'span'
|
||||
])
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'hello',
|
||||
'world'
|
||||
])
|
||||
})
|
||||
|
||||
test('remove elements with updating children without keys', () => {
|
||||
render(
|
||||
h('div', [h('span', ['one']), h('span', ['two']), h('span', ['three'])]),
|
||||
root
|
||||
)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'one',
|
||||
'two',
|
||||
'three'
|
||||
])
|
||||
|
||||
render(h('div', [h('span', ['one']), h('span', ['three'])]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['one', 'three'])
|
||||
})
|
||||
|
||||
test('remove a single text node with updating children without keys', () => {
|
||||
render(h('div', ['one']), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect(serializeInner(elm)).toBe('one')
|
||||
|
||||
render(h('div'), root)
|
||||
expect(serializeInner(elm)).toBe('')
|
||||
})
|
||||
|
||||
test('remove a single text node when children are updated', () => {
|
||||
render(h('div', ['one']), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect(serializeInner(elm)).toBe('one')
|
||||
|
||||
render(h('div', [h('div', ['two']), h('span', ['three'])]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual(['two', 'three'])
|
||||
})
|
||||
|
||||
test('remove a text node among other elements', () => {
|
||||
render(h('div', ['one', h('span', ['two'])]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(c => serialize(c))).toEqual([
|
||||
'one',
|
||||
'<span>two</span>'
|
||||
])
|
||||
|
||||
render(h('div', [h('div', ['three'])]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
expect(elm.children.length).toBe(1)
|
||||
expect(serialize(elm.children[0])).toBe('<div>three</div>')
|
||||
})
|
||||
|
||||
test('reorder elements', () => {
|
||||
render(
|
||||
h('div', [h('span', ['one']), h('div', ['two']), h('b', ['three'])]),
|
||||
root
|
||||
)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'one',
|
||||
'two',
|
||||
'three'
|
||||
])
|
||||
|
||||
render(
|
||||
h('div', [h('b', ['three']), h('div', ['two']), h('span', ['one'])]),
|
||||
root
|
||||
)
|
||||
elm = root.children[0] as TestElement
|
||||
expect((elm.children as TestElement[]).map(inner)).toEqual([
|
||||
'three',
|
||||
'two',
|
||||
'one'
|
||||
])
|
||||
})
|
||||
|
||||
// #6502
|
||||
test('should not de-opt when both head and tail change', () => {
|
||||
render(h('div', [null, h('div'), null]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
const original = elm.children[1]
|
||||
|
||||
render(h('div', [h('p'), h('div'), h('p')]), root)
|
||||
elm = root.children[0] as TestElement
|
||||
const postPatch = elm.children[1]
|
||||
|
||||
expect(postPatch).toBe(original)
|
||||
})
|
||||
})
|
||||
|
@ -1512,7 +1512,10 @@ export function createRenderer<
|
||||
} else {
|
||||
// key-less node, try to locate a key-less node of the same type
|
||||
for (j = s2; j <= e2; j++) {
|
||||
if (isSameType(prevChild, c2[j] as HostVNode)) {
|
||||
if (
|
||||
newIndexToOldIndexMap[j - s2] === 0 &&
|
||||
isSameType(prevChild, c2[j] as HostVNode)
|
||||
) {
|
||||
newIndex = j
|
||||
break
|
||||
}
|
||||
|
@ -155,7 +155,9 @@ function insert(child: TestNode, parent: TestElement, ref?: TestNode | null) {
|
||||
})
|
||||
// remove the node first, but don't log it as a REMOVE op
|
||||
remove(child, false)
|
||||
if (refIndex === undefined) {
|
||||
// re-calculate the ref index because the child's removal may have affected it
|
||||
refIndex = ref ? parent.children.indexOf(ref) : -1
|
||||
if (refIndex === -1) {
|
||||
parent.children.push(child)
|
||||
child.parentNode = parent
|
||||
} else {
|
||||
@ -195,14 +197,18 @@ function setElementText(el: TestElement, text: string) {
|
||||
el.children.forEach(c => {
|
||||
c.parentNode = null
|
||||
})
|
||||
el.children = [
|
||||
{
|
||||
id: nodeId++,
|
||||
type: NodeTypes.TEXT,
|
||||
text,
|
||||
parentNode: el
|
||||
}
|
||||
]
|
||||
if (!text) {
|
||||
el.children = []
|
||||
} else {
|
||||
el.children = [
|
||||
{
|
||||
id: nodeId++,
|
||||
type: NodeTypes.TEXT,
|
||||
text,
|
||||
parentNode: el
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function parentNode(node: TestNode): TestElement | null {
|
||||
|
Loading…
Reference in New Issue
Block a user