test(runtime-core): add tests for componentSlots (#1940)
This commit is contained in:
		
							parent
							
								
									97bc30edad
								
							
						
					
					
						commit
						d0cc4b37d0
					
				@ -1,7 +1,201 @@
 | 
			
		||||
import { ref, render, h, nodeOps, nextTick } from '@vue/runtime-test'
 | 
			
		||||
import {
 | 
			
		||||
  ref,
 | 
			
		||||
  render,
 | 
			
		||||
  h,
 | 
			
		||||
  nodeOps,
 | 
			
		||||
  nextTick,
 | 
			
		||||
  getCurrentInstance
 | 
			
		||||
} from '@vue/runtime-test'
 | 
			
		||||
import { normalizeVNode } from '../src/vnode'
 | 
			
		||||
import { createSlots } from '../src/helpers/createSlots'
 | 
			
		||||
 | 
			
		||||
describe('component: slots', () => {
 | 
			
		||||
  // TODO more tests for slots normalization etc.
 | 
			
		||||
  function renderWithSlots(slots: any): any {
 | 
			
		||||
    let instance: any
 | 
			
		||||
    const Comp = {
 | 
			
		||||
      render() {
 | 
			
		||||
        instance = getCurrentInstance()
 | 
			
		||||
        return h('div')
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(h(Comp, null, slots), nodeOps.createElement('div'))
 | 
			
		||||
    return instance
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  test('initSlots: instance.slots should be set correctly', () => {
 | 
			
		||||
    const { slots } = renderWithSlots({ _: 1 })
 | 
			
		||||
    expect(slots).toMatchObject({ _: 1 })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('initSlots: should normalize object slots (when value is null, string, array)', () => {
 | 
			
		||||
    const { slots } = renderWithSlots({
 | 
			
		||||
      _inner: '_inner',
 | 
			
		||||
      foo: null,
 | 
			
		||||
      header: 'header',
 | 
			
		||||
      footer: ['f1', 'f2']
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      '[Vue warn]: Non-function value encountered for slot "header". Prefer function slots for better performance.'
 | 
			
		||||
    ).toHaveBeenWarned()
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      '[Vue warn]: Non-function value encountered for slot "footer". Prefer function slots for better performance.'
 | 
			
		||||
    ).toHaveBeenWarned()
 | 
			
		||||
 | 
			
		||||
    expect(slots).not.toHaveProperty('_inner')
 | 
			
		||||
    expect(slots).not.toHaveProperty('foo')
 | 
			
		||||
    expect(slots.header()).toMatchObject([normalizeVNode('header')])
 | 
			
		||||
    expect(slots.footer()).toMatchObject([
 | 
			
		||||
      normalizeVNode('f1'),
 | 
			
		||||
      normalizeVNode('f2')
 | 
			
		||||
    ])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('initSlots: should normalize object slots (when value is function)', () => {
 | 
			
		||||
    let proxy: any
 | 
			
		||||
    const Comp = {
 | 
			
		||||
      render() {
 | 
			
		||||
        proxy = getCurrentInstance()
 | 
			
		||||
        return h('div')
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(
 | 
			
		||||
      h(Comp, null, {
 | 
			
		||||
        header: () => 'header'
 | 
			
		||||
      }),
 | 
			
		||||
      nodeOps.createElement('div')
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    expect(proxy.slots.header()).toMatchObject([normalizeVNode('header')])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('initSlots: instance.slots should be set correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)', () => {
 | 
			
		||||
    const { slots } = renderWithSlots([h('span')])
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      '[Vue warn]: Non-function value encountered for default slot. Prefer function slots for better performance.'
 | 
			
		||||
    ).toHaveBeenWarned()
 | 
			
		||||
 | 
			
		||||
    expect(slots.default()).toMatchObject([normalizeVNode(h('span'))])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('updateSlots: instance.slots should be update correctly (when slotType is number)', async () => {
 | 
			
		||||
    const flag1 = ref(true)
 | 
			
		||||
 | 
			
		||||
    let instance: any
 | 
			
		||||
    const Child = () => {
 | 
			
		||||
      instance = getCurrentInstance()
 | 
			
		||||
      return 'child'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Comp = {
 | 
			
		||||
      setup() {
 | 
			
		||||
        return () => [
 | 
			
		||||
          h(
 | 
			
		||||
            Child,
 | 
			
		||||
            null,
 | 
			
		||||
            createSlots({ _: 2 as any }, [
 | 
			
		||||
              flag1.value
 | 
			
		||||
                ? {
 | 
			
		||||
                    name: 'one',
 | 
			
		||||
                    fn: () => [h('span')]
 | 
			
		||||
                  }
 | 
			
		||||
                : {
 | 
			
		||||
                    name: 'two',
 | 
			
		||||
                    fn: () => [h('div')]
 | 
			
		||||
                  }
 | 
			
		||||
            ])
 | 
			
		||||
          )
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    render(h(Comp), nodeOps.createElement('div'))
 | 
			
		||||
 | 
			
		||||
    expect(instance.slots).toHaveProperty('one')
 | 
			
		||||
    expect(instance.slots).not.toHaveProperty('two')
 | 
			
		||||
 | 
			
		||||
    flag1.value = false
 | 
			
		||||
    await nextTick()
 | 
			
		||||
 | 
			
		||||
    expect(instance.slots).not.toHaveProperty('one')
 | 
			
		||||
    expect(instance.slots).toHaveProperty('two')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('updateSlots: instance.slots should be update correctly (when slotType is null)', async () => {
 | 
			
		||||
    const flag1 = ref(true)
 | 
			
		||||
 | 
			
		||||
    let instance: any
 | 
			
		||||
    const Child = () => {
 | 
			
		||||
      instance = getCurrentInstance()
 | 
			
		||||
      return 'child'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const oldSlots = {
 | 
			
		||||
      header: 'header'
 | 
			
		||||
    }
 | 
			
		||||
    const newSlots = {
 | 
			
		||||
      footer: 'footer'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Comp = {
 | 
			
		||||
      setup() {
 | 
			
		||||
        return () => [
 | 
			
		||||
          h(Child, { n: flag1.value }, flag1.value ? oldSlots : newSlots)
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    render(h(Comp), nodeOps.createElement('div'))
 | 
			
		||||
 | 
			
		||||
    expect(instance.slots).toHaveProperty('header')
 | 
			
		||||
    expect(instance.slots).not.toHaveProperty('footer')
 | 
			
		||||
 | 
			
		||||
    flag1.value = false
 | 
			
		||||
    await nextTick()
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      '[Vue warn]: Non-function value encountered for slot "header". Prefer function slots for better performance.'
 | 
			
		||||
    ).toHaveBeenWarned()
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      '[Vue warn]: Non-function value encountered for slot "footer". Prefer function slots for better performance.'
 | 
			
		||||
    ).toHaveBeenWarned()
 | 
			
		||||
 | 
			
		||||
    expect(instance.slots).not.toHaveProperty('header')
 | 
			
		||||
    expect(instance.slots.footer()).toMatchObject([normalizeVNode('footer')])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('updateSlots: instance.slots should be update correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)', async () => {
 | 
			
		||||
    const flag1 = ref(true)
 | 
			
		||||
 | 
			
		||||
    let instance: any
 | 
			
		||||
    const Child = () => {
 | 
			
		||||
      instance = getCurrentInstance()
 | 
			
		||||
      return 'child'
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Comp = {
 | 
			
		||||
      setup() {
 | 
			
		||||
        return () => [
 | 
			
		||||
          h(Child, { n: flag1.value }, flag1.value ? ['header'] : ['footer'])
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    render(h(Comp), nodeOps.createElement('div'))
 | 
			
		||||
 | 
			
		||||
    expect(instance.slots.default()).toMatchObject([normalizeVNode('header')])
 | 
			
		||||
 | 
			
		||||
    flag1.value = false
 | 
			
		||||
    await nextTick()
 | 
			
		||||
 | 
			
		||||
    expect(
 | 
			
		||||
      '[Vue warn]: Non-function value encountered for default slot. Prefer function slots for better performance.'
 | 
			
		||||
    ).toHaveBeenWarned()
 | 
			
		||||
 | 
			
		||||
    expect(instance.slots.default()).toMatchObject([normalizeVNode('footer')])
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('should respect $stable flag', async () => {
 | 
			
		||||
    const flag1 = ref(1)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user