|
|
@@ -1,4 +1,3 @@
|
|
|
-import { NOOP } from '@vue/shared'
|
|
|
import {
|
|
|
type Directive,
|
|
|
children,
|
|
|
@@ -6,6 +5,7 @@ import {
|
|
|
nextTick,
|
|
|
ref,
|
|
|
renderEffect,
|
|
|
+ shallowRef,
|
|
|
template,
|
|
|
withDirectives,
|
|
|
} from '../src'
|
|
|
@@ -24,17 +24,16 @@ describe('createFor', () => {
|
|
|
const { host } = define(() => {
|
|
|
const n1 = createFor(
|
|
|
() => list.value,
|
|
|
- block => {
|
|
|
+ state => {
|
|
|
const span = document.createElement('li')
|
|
|
- const update = () => {
|
|
|
- const [item, key, index] = block.s
|
|
|
+ renderEffect(() => {
|
|
|
+ const [item, key, index] = state
|
|
|
span.innerHTML = `${key}. ${item.name}`
|
|
|
|
|
|
// index should be undefined if source is not an object
|
|
|
expect(index).toBe(undefined)
|
|
|
- }
|
|
|
- renderEffect(update)
|
|
|
- return [span, update]
|
|
|
+ })
|
|
|
+ return span
|
|
|
},
|
|
|
item => item.name,
|
|
|
)
|
|
|
@@ -91,17 +90,16 @@ describe('createFor', () => {
|
|
|
const { host } = define(() => {
|
|
|
const n1 = createFor(
|
|
|
() => count.value,
|
|
|
- block => {
|
|
|
+ state => {
|
|
|
const span = document.createElement('li')
|
|
|
- const update = () => {
|
|
|
- const [item, key, index] = block.s
|
|
|
+ renderEffect(() => {
|
|
|
+ const [item, key, index] = state
|
|
|
span.innerHTML = `${key}. ${item}`
|
|
|
|
|
|
// index should be undefined if source is not an object
|
|
|
expect(index).toBe(undefined)
|
|
|
- }
|
|
|
- renderEffect(update)
|
|
|
- return [span, update]
|
|
|
+ })
|
|
|
+ return span
|
|
|
},
|
|
|
item => item.name,
|
|
|
)
|
|
|
@@ -137,15 +135,14 @@ describe('createFor', () => {
|
|
|
const { host } = define(() => {
|
|
|
const n1 = createFor(
|
|
|
() => data.value,
|
|
|
- block => {
|
|
|
+ state => {
|
|
|
const span = document.createElement('li')
|
|
|
- const update = () => {
|
|
|
- const [item, key, index] = block.s
|
|
|
+ renderEffect(() => {
|
|
|
+ const [item, key, index] = state
|
|
|
span.innerHTML = `${key}${index}. ${item}`
|
|
|
expect(index).not.toBe(undefined)
|
|
|
- }
|
|
|
- renderEffect(update)
|
|
|
- return [span, update]
|
|
|
+ })
|
|
|
+ return span
|
|
|
},
|
|
|
item => {
|
|
|
return item
|
|
|
@@ -215,11 +212,14 @@ describe('createFor', () => {
|
|
|
|
|
|
const t0 = template('<p></p>')
|
|
|
const { instance } = define(() => {
|
|
|
- const n1 = createFor(spySrcFn, block => {
|
|
|
+ const n1 = createFor(spySrcFn, ctx0 => {
|
|
|
const n2 = t0()
|
|
|
const n3 = children(n2, 0)
|
|
|
- withDirectives(n3, [[vDirective, () => block.s[0]]])
|
|
|
- return [n2, NOOP]
|
|
|
+ withDirectives(n3, [[vDirective, () => ctx0[0]]])
|
|
|
+ renderEffect(() => {
|
|
|
+ calls.push(`${ctx0[0]} effecting`)
|
|
|
+ })
|
|
|
+ return n2
|
|
|
})
|
|
|
renderEffect(() => update.value)
|
|
|
return [n1]
|
|
|
@@ -227,7 +227,12 @@ describe('createFor', () => {
|
|
|
|
|
|
await nextTick()
|
|
|
// `${item index} ${hook name}`
|
|
|
- expect(calls).toEqual(['0 created', '0 beforeMount', '0 mounted'])
|
|
|
+ expect(calls).toEqual([
|
|
|
+ '0 created',
|
|
|
+ '0 effecting',
|
|
|
+ '0 beforeMount',
|
|
|
+ '0 mounted',
|
|
|
+ ])
|
|
|
calls.length = 0
|
|
|
expect(spySrcFn).toHaveBeenCalledTimes(1)
|
|
|
|
|
|
@@ -236,6 +241,7 @@ describe('createFor', () => {
|
|
|
expect(calls).toEqual([
|
|
|
'0 beforeUpdate',
|
|
|
'1 created',
|
|
|
+ '1 effecting',
|
|
|
'1 beforeMount',
|
|
|
'0 updated',
|
|
|
'1 mounted',
|
|
|
@@ -248,6 +254,8 @@ describe('createFor', () => {
|
|
|
expect(calls).toEqual([
|
|
|
'1 beforeUpdate',
|
|
|
'0 beforeUpdate',
|
|
|
+ '1 effecting',
|
|
|
+ '0 effecting',
|
|
|
'1 updated',
|
|
|
'0 updated',
|
|
|
])
|
|
|
@@ -268,6 +276,23 @@ describe('createFor', () => {
|
|
|
calls.length = 0
|
|
|
expect(spySrcFn).toHaveBeenCalledTimes(4)
|
|
|
|
|
|
+ // change item
|
|
|
+ list.value[1] = 2
|
|
|
+ await nextTick()
|
|
|
+ expect(calls).toEqual([
|
|
|
+ '0 beforeUpdate',
|
|
|
+ '2 beforeUpdate',
|
|
|
+ '2 effecting',
|
|
|
+ '0 updated',
|
|
|
+ '2 updated',
|
|
|
+ ])
|
|
|
+ expect(spySrcFn).toHaveBeenCalledTimes(5)
|
|
|
+ list.value[1] = 1
|
|
|
+ await nextTick()
|
|
|
+ calls.length = 0
|
|
|
+ expect(spySrcFn).toHaveBeenCalledTimes(6)
|
|
|
+
|
|
|
+ // remove the last item
|
|
|
list.value.pop()
|
|
|
await nextTick()
|
|
|
expect(calls).toEqual([
|
|
|
@@ -277,10 +302,160 @@ describe('createFor', () => {
|
|
|
'1 unmounted',
|
|
|
])
|
|
|
calls.length = 0
|
|
|
- expect(spySrcFn).toHaveBeenCalledTimes(5)
|
|
|
+ expect(spySrcFn).toHaveBeenCalledTimes(7)
|
|
|
|
|
|
unmountComponent(instance)
|
|
|
expect(calls).toEqual(['0 beforeUnmount', '0 unmounted'])
|
|
|
- expect(spySrcFn).toHaveBeenCalledTimes(5)
|
|
|
+ expect(spySrcFn).toHaveBeenCalledTimes(7)
|
|
|
+ })
|
|
|
+
|
|
|
+ test('de-structured value', async () => {
|
|
|
+ const list = ref([{ name: '1' }, { name: '2' }, { name: '3' }])
|
|
|
+ function reverse() {
|
|
|
+ list.value = list.value.reverse()
|
|
|
+ }
|
|
|
+
|
|
|
+ const { host } = define(() => {
|
|
|
+ const n1 = createFor(
|
|
|
+ () => list.value,
|
|
|
+ state => {
|
|
|
+ const span = document.createElement('li')
|
|
|
+ renderEffect(() => {
|
|
|
+ const [name, key, index] = state
|
|
|
+ span.innerHTML = `${key}. ${name}`
|
|
|
+
|
|
|
+ // index should be undefined if source is not an object
|
|
|
+ expect(index).toBe(undefined)
|
|
|
+ })
|
|
|
+ return span
|
|
|
+ },
|
|
|
+ item => item.name,
|
|
|
+ undefined,
|
|
|
+ undefined,
|
|
|
+ false,
|
|
|
+ state => {
|
|
|
+ const [{ name }, key, index] = state
|
|
|
+ return [name, key, index]
|
|
|
+ },
|
|
|
+ )
|
|
|
+ return n1
|
|
|
+ }).render()
|
|
|
+
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 1</li><li>1. 2</li><li>2. 3</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // add
|
|
|
+ list.value.push({ name: '4' })
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 1</li><li>1. 2</li><li>2. 3</li><li>3. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // move
|
|
|
+ reverse()
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 4</li><li>1. 3</li><li>2. 2</li><li>3. 1</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ reverse()
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 1</li><li>1. 2</li><li>2. 3</li><li>3. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // change
|
|
|
+ list.value[0].name = 'a'
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. a</li><li>1. 2</li><li>2. 3</li><li>3. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // remove
|
|
|
+ list.value.splice(1, 1)
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. a</li><li>1. 3</li><li>2. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // clear
|
|
|
+ list.value = []
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe('<!--for-->')
|
|
|
+ })
|
|
|
+
|
|
|
+ test('shallowRef source', async () => {
|
|
|
+ const list = shallowRef([{ name: '1' }, { name: '2' }, { name: '3' }])
|
|
|
+ const setList = (update = list.value.slice()) => (list.value = update)
|
|
|
+ function reverse() {
|
|
|
+ list.value = list.value.reverse()
|
|
|
+ }
|
|
|
+
|
|
|
+ const { host } = define(() => {
|
|
|
+ const n1 = createFor(
|
|
|
+ () => list.value,
|
|
|
+ state => {
|
|
|
+ const span = document.createElement('li')
|
|
|
+ renderEffect(() => {
|
|
|
+ const [item, key, index] = state
|
|
|
+ span.innerHTML = `${key}. ${item.name}`
|
|
|
+
|
|
|
+ // index should be undefined if source is not an object
|
|
|
+ expect(index).toBe(undefined)
|
|
|
+ })
|
|
|
+ return span
|
|
|
+ },
|
|
|
+ )
|
|
|
+ return n1
|
|
|
+ }).render()
|
|
|
+
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 1</li><li>1. 2</li><li>2. 3</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // add
|
|
|
+ list.value.push({ name: '4' })
|
|
|
+ setList()
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 1</li><li>1. 2</li><li>2. 3</li><li>3. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // move
|
|
|
+ reverse()
|
|
|
+ setList()
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 4</li><li>1. 3</li><li>2. 2</li><li>3. 1</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ reverse()
|
|
|
+ setList()
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. 1</li><li>1. 2</li><li>2. 3</li><li>3. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // change
|
|
|
+ list.value[0].name = 'a'
|
|
|
+ setList()
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. a</li><li>1. 2</li><li>2. 3</li><li>3. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // remove
|
|
|
+ list.value.splice(1, 1)
|
|
|
+ setList()
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe(
|
|
|
+ '<li>0. a</li><li>1. 3</li><li>2. 4</li><!--for-->',
|
|
|
+ )
|
|
|
+
|
|
|
+ // clear
|
|
|
+ setList([])
|
|
|
+ await nextTick()
|
|
|
+ expect(host.innerHTML).toBe('<!--for-->')
|
|
|
})
|
|
|
})
|