UNPKG

bootstrap-vue

Version:

BootstrapVue, with over 40 plugins and more than 80 custom components, custom directives, and over 300 icons, provides one of the most comprehensive implementations of Bootstrap v4 components and grid system for Vue.js. With extensive and automated WAI-AR

967 lines (814 loc) 29.2 kB
import { mount } from '@vue/test-utils' import { waitNT, waitRAF } from '../../../tests/utils' import { BFormTextarea } from './form-textarea' describe('form-textarea', () => { it('root element is textarea', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.element.type).toBe('textarea') wrapper.destroy() }) it('does not have attribute disabled by default', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.attributes('disabled')).not.toBeDefined() wrapper.destroy() }) it('has attribute disabled when disabled=true', async () => { const wrapper = mount(BFormTextarea, { propsData: { disabled: true } }) expect(wrapper.attributes('disabled')).toBeDefined() wrapper.destroy() }) it('does not have attribute readonly by default', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.attributes('readonly')).not.toBeDefined() wrapper.destroy() }) it('has attribute readonly when readonly=true', async () => { const wrapper = mount(BFormTextarea, { propsData: { readonly: true } }) expect(wrapper.attributes('readonly')).toBeDefined() wrapper.destroy() }) it('inherits non-prop attributes', async () => { const wrapper = mount(BFormTextarea, { attrs: { foo: 'bar' } }) expect(wrapper.attributes('foo')).toBeDefined() expect(wrapper.attributes('foo')).toBe('bar') wrapper.destroy() }) it('has class form-control by default', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.classes()).toContain('form-control') wrapper.destroy() }) it('does not have class form-control-plaintext by default', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.classes()).not.toContain('form-control-plaintext') wrapper.destroy() }) it('does not have size classes by default', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.classes()).not.toContain('form-control-sm') expect(wrapper.classes()).not.toContain('form-control-lg') wrapper.destroy() }) it('has size class when size prop is set', async () => { const wrapper = mount(BFormTextarea, { propsData: { size: 'sm' } }) expect(wrapper.classes()).toContain('form-control-sm') wrapper.setProps({ size: 'lg' }) expect(wrapper.classes()).toContain('form-control-lg') wrapper.setProps({ size: 'foobar' }) expect(wrapper.classes()).toContain('form-control-foobar') wrapper.setProps({ size: '' }) expect(wrapper.classes()).not.toContain('form-control-') wrapper.destroy() }) it('has class form-control-plaintext when plaintext=true', async () => { const wrapper = mount(BFormTextarea, { propsData: { plaintext: true } }) expect(wrapper.classes()).toContain('form-control-plaintext') wrapper.destroy() }) it('does not have class form-control when plaintext=true', async () => { const wrapper = mount(BFormTextarea, { propsData: { plaintext: true } }) expect(wrapper.classes()).not.toContain('form-control') wrapper.destroy() }) it('has attribute readonly when plaintext=true', async () => { const wrapper = mount(BFormTextarea, { propsData: { plaintext: true } }) expect(wrapper.attributes('readonly')).toBeDefined() wrapper.destroy() }) it('has user supplied id', async () => { const wrapper = mount(BFormTextarea, { propsData: { id: 'foobar' } }) expect(wrapper.attributes('id')).toBe('foobar') wrapper.destroy() }) it('does not have is-valid or is-invalid classes by default', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.classes()).not.toContain('is-valid') expect(wrapper.classes()).not.toContain('is-invalid') wrapper.destroy() }) it('has class is-valid when state=true', async () => { const wrapper = mount(BFormTextarea, { propsData: { state: true } }) expect(wrapper.classes()).toContain('is-valid') expect(wrapper.classes()).not.toContain('is-invalid') wrapper.destroy() }) it('has class is-invalid when state=false', async () => { const wrapper = mount(BFormTextarea, { propsData: { state: false } }) expect(wrapper.classes()).toContain('is-invalid') expect(wrapper.classes()).not.toContain('is-valid') wrapper.destroy() }) it('does not have aria-invalid attribute by default', async () => { const wrapper = mount(BFormTextarea) expect(wrapper.contains('[aria-invalid]')).toBe(false) wrapper.destroy() }) it('does not have aria-invalid attribute when state=true', async () => { const wrapper = mount(BFormTextarea, { propsData: { state: true } }) expect(wrapper.contains('[aria-invalid]')).toBe(false) wrapper.destroy() }) it('has aria-invalid attribute when state=false', async () => { const input = mount(BFormTextarea, { propsData: { state: false } }) expect(input.attributes('aria-invalid')).toBe('true') input.destroy() }) it('has aria-invalid attribute when aria-invalid=true', async () => { const input = mount(BFormTextarea, { propsData: { ariaInvalid: true } }) expect(input.attributes('aria-invalid')).toBe('true') input.setProps({ ariaInvalid: 'true' }) expect(input.attributes('aria-invalid')).toBe('true') input.destroy() }) it('has aria-invalid attribute when aria-invalid="spelling"', async () => { const input = mount(BFormTextarea, { propsData: { ariaInvalid: 'spelling' } }) expect(input.attributes('aria-invalid')).toBe('spelling') input.destroy() }) it('does not emit an update event on mount when value not set', async () => { const input = mount(BFormTextarea) expect(input.emitted('update')).not.toBeDefined() input.destroy() }) it('does mot emit an update event on mount when value is set and no formatter', async () => { const input = mount(BFormTextarea, { value: 'foobar' }) expect(input.emitted('update')).not.toBeDefined() input.destroy() }) it('emits an input event with single arg of value', async () => { const input = mount(BFormTextarea) input.element.value = 'test' input.trigger('input') expect(input.emitted('input')).toBeDefined() expect(input.emitted('input')[0].length).toEqual(1) expect(input.emitted('input')[0][0]).toEqual('test') input.destroy() }) it('emits an change event with single arg of value', async () => { const input = mount(BFormTextarea) input.element.value = 'test' input.trigger('change') expect(input.emitted('change')).toBeDefined() expect(input.emitted('change')[0].length).toEqual(1) expect(input.emitted('change')[0][0]).toEqual('test') input.destroy() }) it('emits an update event with one arg on input', async () => { const input = mount(BFormTextarea) input.element.value = 'test' input.trigger('input') expect(input.emitted('update')).toBeDefined() expect(input.emitted('update')[0].length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('test') input.destroy() }) it('does not emit an update event on change when value not changed', async () => { const input = mount(BFormTextarea) input.element.value = 'test' input.trigger('input') expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('test') input.trigger('change') expect(input.emitted('update').length).toEqual(1) input.destroy() }) it('emits an update event with one arg on change when input text changed', async () => { const input = mount(BFormTextarea) input.element.value = 'test' input.trigger('input') expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('test') input.element.value = 'TEST' input.trigger('change') expect(input.emitted('update').length).toEqual(2) expect(input.emitted('update')[1][0]).toEqual('TEST') input.destroy() }) it('does not emit an update, input or change event when value prop changed', async () => { const input = mount(BFormTextarea, { value: '' }) expect(input.emitted('update')).not.toBeDefined() expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() input.setProps({ value: 'test' }) expect(input.emitted('update')).not.toBeDefined() expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() input.destroy() }) it('emits a native focus event', async () => { const spy = jest.fn() const input = mount(BFormTextarea, { listeners: { focus: spy } }) input.trigger('focus') expect(input.emitted('focus')).not.toBeDefined() expect(spy).toHaveBeenCalled() input.destroy() }) it('emits a blur event when blurred', async () => { const input = mount(BFormTextarea) input.trigger('blur') expect(input.emitted('blur')).toBeDefined() input.destroy() }) it('has attribute rows set to 2 by default', async () => { const input = mount(BFormTextarea) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('2') input.destroy() }) it('has attribute rows when rows set and max-rows not set', async () => { const input = mount(BFormTextarea, { propsData: { rows: 10 } }) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('10') // Should work with both text and number values input.setProps({ rows: '20' }) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('20') // Should use minimum value of 2 when rows is set less than 2 input.setProps({ rows: '1' }) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('2') input.setProps({ rows: -10 }) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('2') input.destroy() }) it('has attribute rows set when rows and max-rows are equal', async () => { const input = mount(BFormTextarea, { propsData: { rows: 5, maxRows: 5 } }) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('5') // Should work with both text and number values input.setProps({ rows: '10', maxRows: '10' }) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('10') input.destroy() }) it('does not have rows set when rows and max-rows set', async () => { const input = mount(BFormTextarea, { propsData: { rows: 2, maxRows: 5 } }) expect(input.attributes('rows')).not.toBeDefined() input.destroy() }) it('has attribute rows set when max-rows less than rows', async () => { const input = mount(BFormTextarea, { propsData: { rows: 10, maxRows: 5 } }) expect(input.attributes('rows')).toBeDefined() expect(input.attributes('rows')).toEqual('10') input.destroy() }) it('does not have style resize by default', async () => { const input = mount(BFormTextarea, { attachToDocument: true }) expect(input.element.style).toBeDefined() expect(input.element.style.resize).toEqual('') input.destroy() }) it('does not have style resize when no-resize is set', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { noResize: true } }) expect(input.element.style).toBeDefined() expect(input.element.style.resize).toEqual('none') input.destroy() }) it('does not have style resize when max-rows not set', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { rows: 10 } }) expect(input.element.style).toBeDefined() expect(input.element.style.resize).toEqual('') input.destroy() }) it('does not have style resize when max-rows less than rows', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { rows: 10, maxRows: 5 } }) expect(input.element.style).toBeDefined() expect(input.element.style.resize).toEqual('') input.destroy() }) it('has style resize:none when max-rows greater than rows', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { rows: 2, maxRows: 5 } }) expect(input.element.style).toBeDefined() expect(input.element.style.resize).toBeDefined() expect(input.element.style.resize).toEqual('none') input.destroy() }) it('does not have style height by default', async () => { const input = mount(BFormTextarea, { attachToDocument: true }) expect(input.element.style).toBeDefined() expect(input.element.style.height).toBeDefined() expect(input.element.style.height).toEqual('') input.destroy() }) it('does not have style height when rows and max-rows equal', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { rows: 2, maxRows: 2 } }) expect(input.element.style).toBeDefined() expect(input.element.style.height).toBeDefined() expect(input.element.style.height).toEqual('') input.destroy() }) it('does not have style height when max-rows not set', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { rows: 5 } }) expect(input.element.style).toBeDefined() expect(input.element.style.height).toBeDefined() expect(input.element.style.height).toEqual('') input.destroy() }) // The height style calculations do not work in JSDOM environment // But we do know auto height works in browser from manual testing // // it('has style height when max-rows greater than rows', async () => { // const input = mount(BFormTextarea, { // attachToDocument: true, // propsData: { // rows: 2, // maxRows: 5 // } // }) // await input.vm.$nextTick() // // expect(input.element.style).toBeDefined() // expect(input.element.style.height).toBeDefined() // expect(input.element.style.height).not.toEqual('') // // input.destroy() // }) // // it('auto height should work', async () => { // const input = mount(BFormTextarea, { // attachToDocument: true, // propsData: { // value: '', // rows: 2, // maxRows: 10 // } // }) // expect(input.element.style).toBeDefined() // expect(input.element.style.height).toBeDefined() // expect(input.element.style.height).not.toEqual('') // const firstHeight = parseFloat(input.element.style.height) // // Set content to five lines heigh // input.element.value = 'one\n two\n three\n four\n five' // input.trigger('input') // expect(input.emitted('update')).toBeDefined() // expect(input.element.style.height).not.toEqual('') // const secondHeight = parseFloat(input.element.style.height) // expect(secondHeight).toBeGreaterThan(firstHeight) // // Set content to one lines heigh // input.element.value = 'one' // input.trigger('input') // expect(input.emitted('update').length).toEqual(2) // expect(input.element.style.height).not.toEqual('') // const thirdHeight = parseFloat(input.element.style.height) // expect(thirdHeight).toBeLessThan(secondHeight) // // input.destroy() // }) it('Formats on input when not lazy', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: '', formatter(value) { return value.toLowerCase() } } }) input.element.value = 'TEST' input.trigger('input') // Update event fires first with formatted value expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('test') // Followed by an input event with formatted value expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(1) expect(input.emitted('input')[0][0]).toEqual('test') // And no change event expect(input.emitted('change')).not.toBeDefined() input.destroy() }) it('Formats on change when not lazy', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: '', formatter(value) { return value.toLowerCase() } } }) input.element.value = 'TEST' input.trigger('change') // Update event fires first with formatted value expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('test') // Followed by a change event with formatted value expect(input.emitted('change')).toBeDefined() expect(input.emitted('change').length).toEqual(1) expect(input.emitted('change')[0][0]).toEqual('test') // And no input event expect(input.emitted('input')).not.toBeDefined() input.destroy() }) it('Formats on blur when lazy', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { formatter(value) { return value.toLowerCase() }, lazyFormatter: true } }) input.element.value = 'TEST' input.trigger('input') // Update event fires first expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('TEST') // Followed by an input expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(1) expect(input.emitted('input')[0][0]).toEqual('TEST') expect(input.vm.localValue).toEqual('TEST') input.trigger('change') // Update does not fire again expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('TEST') // Event change emitted expect(input.emitted('change')).toBeDefined() expect(input.emitted('change').length).toEqual(1) expect(input.emitted('change')[0][0]).toEqual('TEST') expect(input.vm.localValue).toEqual('TEST') input.trigger('blur') // Update fires before change with formatted value expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(2) expect(input.emitted('update')[1][0]).toEqual('test') // Followed by blur event with native event expect(input.emitted('blur')).toBeDefined() expect(input.emitted('blur')[0][0] instanceof Event).toBe(true) expect(input.emitted('blur')[0][0].type).toEqual('blur') // Expected number of events from above sequence expect(input.emitted('input').length).toEqual(1) expect(input.emitted('change').length).toEqual(1) expect(input.emitted('blur').length).toEqual(1) expect(input.emitted('update').length).toEqual(2) input.destroy() }) it('Does not format value on mount when not lazy', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: 'TEST', formatter(value) { return value.toLowerCase() } } }) expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() expect(input.emitted('update')).not.toBeDefined() expect(input.vm.localValue).toEqual('TEST') input.destroy() }) it('Does not format value on mount when lazy', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: 'TEST', formatter(value) { return value.toLowerCase() }, lazyFormatter: true } }) expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() expect(input.emitted('update')).not.toBeDefined() expect(input.vm.localValue).toEqual('TEST') input.destroy() }) it('Does not format on prop "value" change when not lazy', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: '', formatter(value) { return value.toLowerCase() } } }) expect(input.emitted('update')).not.toBeDefined() expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() expect(input.vm.localValue).toEqual('') input.setProps({ value: 'TEST' }) expect(input.emitted('update')).not.toBeDefined() expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() expect(input.vm.localValue).toEqual('TEST') input.destroy() }) it('Does not format on value prop change when lazy', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: '', formatter(value) { return value.toLowerCase() }, lazyFormatter: true } }) expect(input.emitted('update')).not.toBeDefined() expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() expect(input.vm.localValue).toEqual('') input.setProps({ value: 'TEST' }) // Does not emit any events expect(input.emitted('update')).not.toBeDefined() expect(input.emitted('input')).not.toBeDefined() expect(input.emitted('change')).not.toBeDefined() expect(input.vm.localValue).toEqual('TEST') input.destroy() }) it('trim modifier prop works', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: '', trim: true } }) expect(input.vm.localValue).toEqual('') input.element.value = 'TEST' input.trigger('input') expect(input.vm.localValue).toEqual('TEST') expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('TEST') expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(1) expect(input.emitted('input')[0][0]).toEqual('TEST') input.element.value = 'TEST ' input.trigger('input') expect(input.vm.localValue).toEqual('TEST ') // `v-model` value stays the same and update event shouldn't be emitted again expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(2) expect(input.emitted('input')[1][0]).toEqual('TEST ') input.element.value = ' TEST ' input.trigger('input') expect(input.vm.localValue).toEqual(' TEST ') // `v-model` value stays the same and update event shouldn't be emitted again expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(3) expect(input.emitted('input')[2][0]).toEqual(' TEST ') input.trigger('input') expect(input.vm.localValue).toEqual(' TEST ') // `v-model` value stays the same and update event shouldn't be emitted again expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(4) expect(input.emitted('input')[3][0]).toEqual(' TEST ') input.trigger('change') expect(input.vm.localValue).toEqual(' TEST ') // `v-model` value stays the same and update event shouldn't be emitted again expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('change')).toBeDefined() expect(input.emitted('change').length).toEqual(1) expect(input.emitted('change')[0][0]).toEqual(' TEST ') input.destroy() }) it('number modifier prop works', async () => { const input = mount(BFormTextarea, { attachToDocument: true, propsData: { value: '', number: true } }) expect(input.vm.localValue).toEqual('') input.element.value = 'TEST' input.trigger('input') expect(input.vm.localValue).toEqual('TEST') expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(1) expect(input.emitted('update')[0][0]).toEqual('TEST') expect(typeof input.emitted('update')[0][0]).toEqual('string') expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(1) expect(input.emitted('input')[0][0]).toEqual('TEST') expect(typeof input.emitted('input')[0][0]).toEqual('string') input.element.value = '123.45' input.trigger('input') expect(input.vm.localValue).toEqual('123.45') expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(2) expect(input.emitted('update')[1][0]).toEqual(123.45) expect(typeof input.emitted('update')[1][0]).toEqual('number') expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(2) expect(input.emitted('input')[1][0]).toEqual('123.45') expect(typeof input.emitted('input')[1][0]).toEqual('string') input.element.value = '0123.450' input.trigger('input') expect(input.vm.localValue).toEqual('0123.450') // `v-model` value stays the same and update event shouldn't be emitted again expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(2) expect(input.emitted('update')[1][0]).toEqual(123.45) expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(3) expect(input.emitted('input')[2][0]).toEqual('0123.450') expect(typeof input.emitted('input')[2][0]).toEqual('string') input.element.value = '0123 450' input.trigger('input') expect(input.vm.localValue).toEqual('0123 450') expect(input.emitted('update')).toBeDefined() expect(input.emitted('update').length).toEqual(3) expect(input.emitted('update')[2][0]).toEqual(123) expect(typeof input.emitted('update')[2][0]).toEqual('number') expect(input.emitted('input')).toBeDefined() expect(input.emitted('input').length).toEqual(4) expect(input.emitted('input')[3][0]).toEqual('0123 450') expect(typeof input.emitted('input')[3][0]).toEqual('string') input.destroy() }) // These tests are wrapped in a new describe to limit // the scope of the `getBoundingClientRect` mock describe('prop `autofocus`', () => { const origGetBCR = Element.prototype.getBoundingClientRect beforeEach(() => { // Mock `getBoundingClientRect` so that the `isVisible(el)` test returns `true` // In our test below, all pagination buttons would normally be visible Element.prototype.getBoundingClientRect = jest.fn(() => ({ width: 24, height: 24, top: 0, left: 0, bottom: 0, right: 0 })) }) afterEach(() => { // Restore prototype Element.prototype.getBoundingClientRect = origGetBCR }) it('works when true', async () => { const wrapper = mount(BFormTextarea, { attachToDocument: true, propsData: { autofocus: true } }) expect(wrapper.vm).toBeDefined() await waitNT(wrapper.vm) await waitRAF() const input = wrapper.find('textarea') expect(input.exists()).toBe(true) expect(document).toBeDefined() expect(document.activeElement).toBe(input.element) wrapper.destroy() }) it('does not autofocus when false', async () => { const wrapper = mount(BFormTextarea, { attachToDocument: true, propsData: { autofocus: false } }) expect(wrapper.vm).toBeDefined() await waitNT(wrapper.vm) await waitRAF() const input = wrapper.find('textarea') expect(input.exists()).toBe(true) expect(document).toBeDefined() expect(document.activeElement).not.toBe(input.element) wrapper.destroy() }) }) })