import Vue from '@vue/compat' import { nextTick } from '../../runtime-core/src/scheduler' import { DeprecationTypes, deprecationData, toggleDeprecationWarning, } from '../../runtime-core/src/compat/compatConfig' import { triggerEvent } from './utils' import { h } from '@vue/runtime-core' beforeEach(() => { toggleDeprecationWarning(true) Vue.configureCompat({ MODE: 2, GLOBAL_MOUNT: 'suppress-warning', }) }) afterEach(() => { toggleDeprecationWarning(false) Vue.configureCompat({ MODE: 3 }) }) test('mode as function', () => { const Foo = { name: 'Foo', render: (h: any) => h('div', 'foo'), } const Bar = { name: 'Bar', data: () => ({ msg: 'bar' }), render: (ctx: any) => h('div', ctx.msg), } toggleDeprecationWarning(false) Vue.configureCompat({ MODE: comp => (comp && comp.name === 'Bar' ? 3 : 2), }) const vm = new Vue({ components: { Foo, Bar }, template: `
`, }).$mount() expect(vm.$el).toBeInstanceOf(HTMLDivElement) expect(vm.$el.innerHTML).toBe(`
foo
bar
`) }) test('WATCH_ARRAY', async () => { const spy = vi.fn() const vm = new Vue({ data() { return { foo: [], } }, watch: { foo: spy, }, }) as any expect( deprecationData[DeprecationTypes.WATCH_ARRAY].message, ).toHaveBeenWarned() expect(spy).not.toHaveBeenCalled() vm.foo.push(1) await nextTick() expect(spy).toHaveBeenCalledTimes(1) }) test('PROPS_DEFAULT_THIS', () => { let thisCtx: any const Child = { customOption: 1, inject: ['provided'], props: { foo: null, bar: { default(this: any) { // copy values since injection must be sync thisCtx = { foo: this.foo, $options: this.$options, provided: this.provided, } return this.foo + 1 }, }, }, template: `{{ bar }}`, } const vm = new Vue({ components: { Child }, provide: { provided: 2, }, template: ``, }).$mount() expect(vm.$el.textContent).toBe('1') // other props expect(thisCtx.foo).toBe(0) // $options expect(thisCtx.$options.customOption).toBe(1) // injections expect(thisCtx.provided).toBe(2) expect( (deprecationData[DeprecationTypes.PROPS_DEFAULT_THIS].message as Function)( 'bar', ), ).toHaveBeenWarned() }) test('V_ON_KEYCODE_MODIFIER', () => { const spy = vi.fn() const vm = new Vue({ template: ``, methods: { spy }, }).$mount() expect(vm.$el).toBeInstanceOf(HTMLInputElement) triggerEvent(vm.$el, 'keyup', e => { e.key = '_' e.keyCode = 1 }) expect(spy).toHaveBeenCalled() expect( deprecationData[DeprecationTypes.V_ON_KEYCODE_MODIFIER].message, ).toHaveBeenWarned() }) test('CUSTOM_DIR', async () => { const myDir = { bind: vi.fn(), inserted: vi.fn(), update: vi.fn(), componentUpdated: vi.fn(), unbind: vi.fn(), } as any const getCalls = () => Object.keys(myDir).map(key => myDir[key].mock.calls.length) const vm = new Vue({ data() { return { ok: true, foo: 1, } }, template: `
`, directives: { myDir, }, }).$mount() as any expect(getCalls()).toMatchObject([1, 1, 0, 0, 0]) expect( (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)( 'bind', 'beforeMount', ), ).toHaveBeenWarned() expect( (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)( 'inserted', 'mounted', ), ).toHaveBeenWarned() vm.foo++ await nextTick() expect(getCalls()).toMatchObject([1, 1, 1, 1, 0]) expect( (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)( 'update', 'updated', ), ).toHaveBeenWarned() expect( (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)( 'componentUpdated', 'updated', ), ).toHaveBeenWarned() }) test('ATTR_FALSE_VALUE', () => { const vm = new Vue({ template: `
`, }).$mount() expect(vm.$el).toBeInstanceOf(HTMLDivElement) expect(vm.$el.hasAttribute('id')).toBe(false) expect(vm.$el.hasAttribute('foo')).toBe(false) expect( (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)( 'id', ), ).toHaveBeenWarned() expect( (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)( 'foo', ), ).toHaveBeenWarned() }) test('ATTR_FALSE_VALUE with false on input value', () => { const vm = new Vue({ template: ``, }).$mount() expect(vm.$el).toBeInstanceOf(HTMLInputElement) expect(vm.$el.hasAttribute('value')).toBe(true) expect(vm.$el.getAttribute('value')).toBe('false') expect( (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)( 'value', ), ).not.toHaveBeenWarned() }) test("ATTR_FALSE_VALUE with false value shouldn't throw warning", () => { const vm = new Vue({ template: `
`, compatConfig: { ATTR_FALSE_VALUE: false, }, }).$mount() expect(vm.$el).toBeInstanceOf(HTMLDivElement) expect(vm.$el.hasAttribute('id')).toBe(true) expect(vm.$el.getAttribute('id')).toBe('false') expect(vm.$el.hasAttribute('foo')).toBe(true) expect(vm.$el.getAttribute('foo')).toBe('false') expect( (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)( 'id', ), ).not.toHaveBeenWarned() expect( (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)( 'foo', ), ).not.toHaveBeenWarned() }) test('ATTR_ENUMERATED_COERCION', () => { const vm = new Vue({ template: `
`, }).$mount() expect(vm.$el).toBeInstanceOf(HTMLDivElement) expect(vm.$el.getAttribute('draggable')).toBe('false') expect(vm.$el.getAttribute('spellcheck')).toBe('true') expect(vm.$el.getAttribute('contenteditable')).toBe('true') expect( ( deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION] .message as Function )('draggable', null, 'false'), ).toHaveBeenWarned() expect( ( deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION] .message as Function )('spellcheck', 0, 'true'), ).toHaveBeenWarned() expect( ( deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION] .message as Function )('contenteditable', 'foo', 'true'), ).toHaveBeenWarned() }) test('ATTR_ENUMERATED_COERCION, coercing "false"', () => { const vm = new Vue({ template: `
hello
`, }).$mount() expect(vm.$el.innerHTML).toBe( `
hello
`, ) expect( ( deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION] .message as Function )('draggable', 'false', 'false'), ).toHaveBeenWarned() expect( ( deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION] .message as Function )('spellcheck', 'false', 'false'), ).toHaveBeenWarned() })