| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- import { ShapeFlags } from '@vue/shared'
- import Vue from '@vue/compat'
- import { createComponentInstance } from '../../runtime-core/src/component'
- import { setCurrentRenderingInstance } from '../../runtime-core/src/componentRenderContext'
- import type { DirectiveBinding } from '../../runtime-core/src/directives'
- import { createVNode } from '../../runtime-core/src/vnode'
- import {
- DeprecationTypes,
- deprecationData,
- toggleDeprecationWarning,
- } from '../../runtime-core/src/compat/compatConfig'
- import { compatH as h } from '../../runtime-core/src/compat/renderFn'
- beforeEach(() => {
- toggleDeprecationWarning(false)
- Vue.configureCompat({
- MODE: 2,
- GLOBAL_MOUNT: 'suppress-warning',
- })
- })
- afterEach(() => {
- toggleDeprecationWarning(false)
- Vue.configureCompat({ MODE: 3 })
- })
- describe('compat: render function', () => {
- const mockDir = {}
- const mockChildComp = {}
- const mockComponent = {
- directives: {
- mockDir,
- },
- components: {
- foo: mockChildComp,
- },
- }
- const mockInstance = createComponentInstance(
- createVNode(mockComponent),
- null,
- null,
- )
- beforeEach(() => {
- setCurrentRenderingInstance(mockInstance)
- })
- afterEach(() => {
- setCurrentRenderingInstance(null)
- })
- test('string component lookup', () => {
- expect(h('foo')).toMatchObject({
- type: mockChildComp,
- })
- })
- test('class / style / attrs / domProps / props', () => {
- expect(
- h('div', {
- class: 'foo',
- style: { color: 'red' },
- attrs: {
- id: 'foo',
- },
- domProps: {
- innerHTML: 'hi',
- },
- props: {
- myProp: 'foo',
- },
- }),
- ).toMatchObject({
- props: {
- class: 'foo',
- style: { color: 'red' },
- id: 'foo',
- innerHTML: 'hi',
- myProp: 'foo',
- },
- })
- })
- test('staticClass + class', () => {
- expect(
- h('div', {
- class: { foo: true },
- staticClass: 'bar',
- }),
- ).toMatchObject({
- props: {
- class: 'bar foo',
- },
- })
- })
- test('staticStyle + style', () => {
- expect(
- h('div', {
- style: { color: 'red' },
- staticStyle: { fontSize: '14px' },
- }),
- ).toMatchObject({
- props: {
- style: {
- color: 'red',
- fontSize: '14px',
- },
- },
- })
- })
- test('on / nativeOn', () => {
- const fn = () => {}
- expect(
- h('div', {
- on: {
- click: fn,
- fooBar: fn,
- },
- nativeOn: {
- click: fn,
- 'bar-baz': fn,
- },
- }),
- ).toMatchObject({
- props: {
- onClick: fn,
- onClickNative: fn,
- onFooBar: fn,
- 'onBar-bazNative': fn,
- },
- })
- })
- test('v2 legacy event prefixes', () => {
- const fn = () => {}
- expect(
- h('div', {
- on: {
- '&click': fn,
- '~keyup': fn,
- '!touchend': fn,
- },
- }),
- ).toMatchObject({
- props: {
- onClickPassive: fn,
- onKeyupOnce: fn,
- onTouchendCapture: fn,
- },
- })
- })
- test('directives', () => {
- expect(
- h('div', {
- directives: [
- {
- name: 'mock-dir',
- value: '2',
- // expression: '1 + 1',
- arg: 'foo',
- modifiers: {
- bar: true,
- },
- },
- ],
- }),
- ).toMatchObject({
- dirs: [
- {
- dir: mockDir,
- instance: mockInstance.proxy,
- value: '2',
- oldValue: void 0,
- arg: 'foo',
- modifiers: {
- bar: true,
- },
- },
- ] as DirectiveBinding[],
- })
- })
- test('scopedSlots', () => {
- const scopedSlots = {
- default() {},
- }
- const vnode = h(mockComponent, {
- scopedSlots,
- })
- expect(vnode).toMatchObject({
- children: scopedSlots,
- })
- expect('scopedSlots' in vnode.props!).toBe(false)
- expect(vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN).toBeTruthy()
- })
- test('legacy named slot', () => {
- const vnode = h(mockComponent, [
- 'text',
- h('div', { slot: 'foo' }, 'one'),
- h('div', { slot: 'bar' }, 'two'),
- h('div', { slot: 'foo' }, 'three'),
- h('div', 'four'),
- ])
- expect(vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN).toBeTruthy()
- const slots = vnode.children as any
- // default
- expect(slots.default()).toMatchObject(['text', { children: 'four' }])
- expect(slots.foo()).toMatchObject([
- { children: 'one' },
- { children: 'three' },
- ])
- expect(slots.bar()).toMatchObject([{ children: 'two' }])
- })
- test('in component usage', () => {
- toggleDeprecationWarning(true)
- const vm = new Vue({
- render(h: any) {
- return h(
- 'div',
- {
- class: 'foo',
- attrs: { id: 'bar' },
- },
- 'hello',
- )
- },
- }).$mount()
- expect(vm.$el).toBeInstanceOf(HTMLDivElement)
- expect(vm.$el.outerHTML).toBe(`<div class="foo" id="bar">hello</div>`)
- expect(
- deprecationData[DeprecationTypes.RENDER_FUNCTION].message,
- ).toHaveBeenWarned()
- })
- test('should detect v3 compiled render fn', () => {
- const vm = new Vue({
- data() {
- return {
- a: 'hello',
- }
- },
- // check is arg length based
- render(c: any, _c: any) {
- return createVNode('div', null, c.a)
- },
- }).$mount()
- expect(vm.$el).toBeInstanceOf(HTMLDivElement)
- expect(vm.$el.outerHTML).toBe(`<div>hello</div>`)
- })
- })
|