From 6d90471b00902bcf37d27fa495252ddbe6d09408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 18:01:42 +0200 Subject: [PATCH 01/17] chore: tests cleanup --- src/components/avatar/avatar.spec.js | 6 +- src/components/carousel/carousel.spec.js | 48 ++++--------- src/components/collapse/collapse.spec.js | 23 ++---- src/components/dropdown/dropdown-item.spec.js | 16 ++--- src/components/dropdown/dropdown.spec.js | 12 ++-- src/components/link/link.spec.js | 30 ++++---- src/components/modal/helpers/bv-modal.spec.js | 23 +++--- src/components/modal/modal.spec.js | 39 +++++----- .../pagination-nav/pagination-nav.spec.js | 2 +- src/components/popover/popover.spec.js | 10 +-- src/components/toast/helpers/bv-toast.spec.js | 19 +++-- src/components/tooltip/tooltip.spec.js | 42 +---------- src/directives/hover/hover.spec.js | 7 +- src/directives/modal/modal.spec.js | 52 +++++--------- src/directives/popover/popover.spec.js | 14 ++-- src/directives/toggle/toggle.spec.js | 71 ++++++------------- src/directives/tooltip/tooltip.spec.js | 32 ++++----- src/icons/icons.spec.js | 53 +++++--------- src/mixins/listen-on-document.spec.js | 12 ++-- src/mixins/listen-on-root.spec.js | 16 ++--- src/mixins/listen-on-window.spec.js | 12 ++-- src/utils/config.spec.js | 6 +- src/utils/transporter.spec.js | 18 ++--- 23 files changed, 189 insertions(+), 374 deletions(-) diff --git a/src/components/avatar/avatar.spec.js b/src/components/avatar/avatar.spec.js index 86f66917a3b..cc0b45d9662 100644 --- a/src/components/avatar/avatar.spec.js +++ b/src/components/avatar/avatar.spec.js @@ -1,4 +1,4 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { createLocalVue, mount } from '@vue/test-utils' import { BIconPerson } from '../../icons/icons' import { BAvatar } from './avatar' @@ -154,14 +154,16 @@ describe('avatar', () => { }) it('should have expected structure when prop `icon` set', async () => { - const localVue = new CreateLocalVue() + const localVue = createLocalVue() localVue.component('BIconPerson', BIconPerson) + const wrapper = mount(BAvatar, { localVue, propsData: { icon: 'person' } }) + expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('SPAN') expect(wrapper.classes()).toContain('b-avatar') diff --git a/src/components/carousel/carousel.spec.js b/src/components/carousel/carousel.spec.js index 37dee23f91a..5097b9071f8 100644 --- a/src/components/carousel/carousel.spec.js +++ b/src/components/carousel/carousel.spec.js @@ -1,13 +1,11 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BCarousel } from './carousel' import { BCarouselSlide } from './carousel-slide' -const localVue = new CreateLocalVue() - jest.useFakeTimers() -const appDef = { +const App = { props: { interval: 0, indicators: false, @@ -44,7 +42,6 @@ const appDef = { describe('carousel', () => { it('has expected default structure', async () => { const wrapper = mount(BCarousel, { - localVue, attachTo: createContainer() }) @@ -112,7 +109,6 @@ describe('carousel', () => { it('has prev/next controls when prop controls is set', async () => { const wrapper = mount(BCarousel, { - localVue, attachTo: createContainer(), propsData: { controls: true @@ -176,7 +172,6 @@ describe('carousel', () => { it('has indicators showing when prop indicators is set', async () => { const wrapper = mount(BCarousel, { - localVue, attachTo: createContainer(), propsData: { indicators: true @@ -224,7 +219,6 @@ describe('carousel', () => { it('should have class carousel-fade when prop fade=true', async () => { const wrapper = mount(BCarousel, { - localVue, attachTo: createContainer(), propsData: { fade: true @@ -244,7 +238,6 @@ describe('carousel', () => { it('should not have class fade or slide when prop no-animation=true', async () => { const wrapper = mount(BCarousel, { - localVue, attachTo: createContainer(), propsData: { noAnimation: true @@ -264,7 +257,6 @@ describe('carousel', () => { it('should not have class fade or slide when prop no-animation=true and fade=true', async () => { const wrapper = mount(BCarousel, { - localVue, attachTo: createContainer(), propsData: { fade: true, @@ -284,8 +276,7 @@ describe('carousel', () => { }) it('should not automatically scroll to next slide when interval=0', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -316,8 +307,7 @@ describe('carousel', () => { }) it('should scroll to next/prev slide when next/prev clicked', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -383,8 +373,7 @@ describe('carousel', () => { }) it('should scroll to next/prev slide when next/prev space keypress', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -450,8 +439,7 @@ describe('carousel', () => { }) it('should scroll to specified slide when indicator clicked', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -517,8 +505,7 @@ describe('carousel', () => { }) it('should scroll to specified slide when indicator keypress space/enter', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -584,8 +571,7 @@ describe('carousel', () => { }) it('should scroll to next/prev slide when key next/prev pressed', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -648,8 +634,7 @@ describe('carousel', () => { }) it('should emit paused and unpaused events when interval changed to 0', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -733,8 +718,7 @@ describe('carousel', () => { }) it('should scroll to specified slide when value (v-model) changed', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -817,8 +801,7 @@ describe('carousel', () => { }) it('changing slides works when no-animation set', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -886,8 +869,7 @@ describe('carousel', () => { }) it('setting new slide when sliding is active, schedules the new slide to happen after finished', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -969,8 +951,7 @@ describe('carousel', () => { }) it('Next/Prev slide wraps to end/start when no-wrap is false', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, @@ -1038,8 +1019,7 @@ describe('carousel', () => { }) it('Next/Prev slide does not wrap to end/start when no-wrap is true', async () => { - const wrapper = mount(localVue.extend(appDef), { - localVue, + const wrapper = mount(App, { attachTo: createContainer(), propsData: { interval: 0, diff --git a/src/components/collapse/collapse.spec.js b/src/components/collapse/collapse.spec.js index 8e4c0c98fcd..64aefbd39b6 100644 --- a/src/components/collapse/collapse.spec.js +++ b/src/components/collapse/collapse.spec.js @@ -1,9 +1,4 @@ -import { - config as vtuConfig, - createLocalVue as CreateLocalVue, - createWrapper, - mount -} from '@vue/test-utils' +import { config as vtuConfig, createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BCollapse } from './collapse' @@ -381,8 +376,7 @@ describe('collapse', () => { }) it('should close when clicking on contained nav-link prop is-nav is set', async () => { - const localVue = CreateLocalVue() - const App = localVue.extend({ + const App = { render(h) { return h('div', [ // JSDOM supports `getComputedStyle()` when using stylesheets (non responsive) @@ -401,10 +395,9 @@ describe('collapse', () => { ) ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() @@ -433,8 +426,7 @@ describe('collapse', () => { }) it('should not close when clicking on nav-link prop is-nav is set & collapse is display block important', async () => { - const localVue = CreateLocalVue() - const App = localVue.extend({ + const App = { render(h) { return h('div', [ // JSDOM supports `getComputedStyle()` when using stylesheets (non responsive) @@ -459,10 +451,9 @@ describe('collapse', () => { ) ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() diff --git a/src/components/dropdown/dropdown-item.spec.js b/src/components/dropdown/dropdown-item.spec.js index c6eaf13b837..797fc303399 100644 --- a/src/components/dropdown/dropdown-item.spec.js +++ b/src/components/dropdown/dropdown-item.spec.js @@ -1,5 +1,5 @@ import VueRouter from 'vue-router' -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { createLocalVue, mount } from '@vue/test-utils' import { createContainer, waitRAF } from '../../../tests/utils' import { BDropdownItem } from './dropdown-item' @@ -94,7 +94,7 @@ describe('dropdown-item', () => { describe('router-link support', () => { it('works', async () => { - const localVue = new CreateLocalVue() + const localVue = createLocalVue() localVue.use(VueRouter) const router = new VueRouter({ @@ -106,22 +106,22 @@ describe('dropdown-item', () => { ] }) - const App = localVue.extend({ + const App = { router, render(h) { return h('ul', [ - // router-link + // h(BDropdownItem, { props: { to: '/a' } }, ['to-a']), - // regular link + // Regular link h(BDropdownItem, { props: { href: '/a' } }, ['href-a']), - // router-link + // h(BDropdownItem, { props: { to: { path: '/b' } } }, ['to-path-b']), - // regular link + // Regular link h(BDropdownItem, { props: { href: '/b' } }, ['href-a']), h('router-view') ]) } - }) + } const wrapper = mount(App, { localVue, diff --git a/src/components/dropdown/dropdown.spec.js b/src/components/dropdown/dropdown.spec.js index 43c133b3cb2..651199f70e3 100644 --- a/src/components/dropdown/dropdown.spec.js +++ b/src/components/dropdown/dropdown.spec.js @@ -1,4 +1,4 @@ -import { mount, createLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BDropdown } from './dropdown' import { BDropdownItem } from './dropdown-item' @@ -429,15 +429,14 @@ describe('dropdown', () => { }) it('dropdown opens and closes', async () => { - const localVue = createLocalVue() - const App = localVue.extend({ + const App = { render(h) { return h('div', { attrs: { id: 'container' } }, [ h(BDropdown, { props: { id: 'test' } }, [h(BDropdownItem, 'item')]), h('input', { attrs: { id: 'input' } }) ]) } - }) + } const wrapper = mount(App, { attachTo: createContainer() @@ -695,8 +694,7 @@ describe('dropdown', () => { }) it('Keyboard navigation works when open', async () => { - const localVue = createLocalVue() - const App = localVue.extend({ + const App = { render(h) { return h('div', [ h(BDropdown, { props: { id: 'test' } }, [ @@ -707,7 +705,7 @@ describe('dropdown', () => { ]) ]) } - }) + } const wrapper = mount(App, { attachTo: createContainer() diff --git a/src/components/link/link.spec.js b/src/components/link/link.spec.js index 3a8830a6d8c..7f3913abb5e 100644 --- a/src/components/link/link.spec.js +++ b/src/components/link/link.spec.js @@ -1,5 +1,5 @@ import VueRouter from 'vue-router' -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { createLocalVue, mount } from '@vue/test-utils' import { createContainer } from '../../../tests/utils' import { BLink } from './link' @@ -200,8 +200,6 @@ describe('b-link', () => { }) describe('click handling', () => { - const localVue = new CreateLocalVue() - it('should invoke click handler bound by Vue when clicked on', async () => { let called = 0 let evt = null @@ -281,15 +279,13 @@ describe('b-link', () => { }) it('should emit "clicked::link" on $root when clicked on', async () => { - const App = localVue.extend({ + const spy = jest.fn() + const App = { render(h) { return h('div', [h(BLink, { props: { href: '/foo' } }, 'link')]) } - }) - const spy = jest.fn() - const wrapper = mount(App, { - localVue - }) + } + const wrapper = mount(App) wrapper.vm.$root.$on('clicked::link', spy) await wrapper.find('a').trigger('click') expect(spy).toHaveBeenCalled() @@ -298,15 +294,13 @@ describe('b-link', () => { }) it('should NOT emit "clicked::link" on $root when clicked on when disabled', async () => { - const App = localVue.extend({ + const spy = jest.fn() + const App = { render(h) { return h('div', [h(BLink, { props: { href: '/foo', disabled: true } }, 'link')]) } - }) - const spy = jest.fn() - const wrapper = mount(App, { - localVue - }) + } + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() @@ -320,7 +314,7 @@ describe('b-link', () => { describe('router-link support', () => { it('works', async () => { - const localVue = new CreateLocalVue() + const localVue = createLocalVue() localVue.use(VueRouter) const router = new VueRouter({ @@ -332,7 +326,7 @@ describe('b-link', () => { ] }) - const App = localVue.extend({ + const App = { router, components: { BLink }, render(h) { @@ -348,7 +342,7 @@ describe('b-link', () => { h('router-view') ]) } - }) + } const wrapper = mount(App, { localVue, diff --git a/src/components/modal/helpers/bv-modal.spec.js b/src/components/modal/helpers/bv-modal.spec.js index e6f0dc43119..ab2419d8f72 100644 --- a/src/components/modal/helpers/bv-modal.spec.js +++ b/src/components/modal/helpers/bv-modal.spec.js @@ -1,20 +1,17 @@ -import { mount, createWrapper, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount, createLocalVue, createWrapper } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../../tests/utils' import { ModalPlugin } from '../index' -describe('$bvModal', () => { - const localVue = new CreateLocalVue() - - beforeAll(() => { - localVue.use(ModalPlugin) - }) +const localVue = createLocalVue() +localVue.use(ModalPlugin) +describe('$bvModal', () => { it('$bvModal.show() and $bvModal.hide() works', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('b-modal', { props: { static: true, id: 'test1' } }, 'content') } - }) + } const wrapper = mount(App, { attachTo: createContainer(), localVue @@ -58,11 +55,11 @@ describe('$bvModal', () => { }) it('$bvModal.msgBoxOk() works', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', 'app') } - }) + } const wrapper = mount(App, { attachTo: createContainer(), localVue @@ -120,11 +117,11 @@ describe('$bvModal', () => { }) it('$bvModal.msgBoxConfirm() works', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', 'app') } - }) + } const wrapper = mount(App, { attachTo: createContainer(), localVue diff --git a/src/components/modal/modal.spec.js b/src/components/modal/modal.spec.js index 75567e91530..14f36abde07 100644 --- a/src/components/modal/modal.spec.js +++ b/src/components/modal/modal.spec.js @@ -1,4 +1,4 @@ -import { config as vtuConfig, createLocalVue, createWrapper, mount } from '@vue/test-utils' +import { config as vtuConfig, createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BModal } from './modal' import { BvModalEvent } from './helpers/bv-modal-event.class' @@ -963,20 +963,17 @@ describe('modal', () => { }) describe('focus management', () => { - const localVue = createLocalVue() - it('returns focus to previous active element when return focus not set and not using v-b-toggle', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', [ h('button', { class: 'trigger', attrs: { id: 'trigger', type: 'button' } }, 'trigger'), h(BModal, { props: { static: true, id: 'test', visible: false } }, 'modal content') ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() @@ -1040,7 +1037,7 @@ describe('modal', () => { }) it('returns focus to element specified in toggle() method', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', [ h('button', { class: 'trigger', attrs: { id: 'trigger', type: 'button' } }, 'trigger'), @@ -1052,10 +1049,9 @@ describe('modal', () => { h(BModal, { props: { static: true, id: 'test', visible: false } }, 'modal content') ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() @@ -1126,17 +1122,16 @@ describe('modal', () => { }) it('if focus leaves modal it returns to modal', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', [ h('button', { attrs: { id: 'button', type: 'button' } }, 'Button'), h(BModal, { props: { static: true, id: 'test', visible: true } }, 'Modal content') ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() @@ -1208,7 +1203,7 @@ describe('modal', () => { }) it('it allows focus for elements when "no-enforce-focus" enabled', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', [ h('button', { attrs: { id: 'button1', type: 'button' } }, 'Button 1'), @@ -1227,10 +1222,9 @@ describe('modal', () => { ) ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() @@ -1277,7 +1271,7 @@ describe('modal', () => { }) it('it allows focus for elements in "ignore-enforce-focus-selector" prop', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', [ h('button', { attrs: { id: 'button1', type: 'button' } }, 'Button 1'), @@ -1296,10 +1290,9 @@ describe('modal', () => { ) ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() diff --git a/src/components/pagination-nav/pagination-nav.spec.js b/src/components/pagination-nav/pagination-nav.spec.js index d3b8a10bb24..3cd48357a9e 100644 --- a/src/components/pagination-nav/pagination-nav.spec.js +++ b/src/components/pagination-nav/pagination-nav.spec.js @@ -1,5 +1,5 @@ import VueRouter from 'vue-router' -import { mount, createLocalVue } from '@vue/test-utils' +import { createLocalVue, mount } from '@vue/test-utils' import { waitNT, waitRAF } from '../../../tests/utils' import { BPaginationNav } from './pagination-nav' diff --git a/src/components/popover/popover.spec.js b/src/components/popover/popover.spec.js index 487105722e3..b34c1ae71ee 100644 --- a/src/components/popover/popover.spec.js +++ b/src/components/popover/popover.spec.js @@ -1,11 +1,9 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BPopover } from './popover' -const localVue = new CreateLocalVue() - // Our test application definition -const appDef = { +const App = { props: [ 'triggers', 'show', @@ -93,10 +91,8 @@ describe('b-popover', () => { }) it('has expected default structure', async () => { - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click' }, @@ -130,10 +126,8 @@ describe('b-popover', () => { it('initially open has expected structure', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true diff --git a/src/components/toast/helpers/bv-toast.spec.js b/src/components/toast/helpers/bv-toast.spec.js index 360849ba4ee..08a9647281a 100644 --- a/src/components/toast/helpers/bv-toast.spec.js +++ b/src/components/toast/helpers/bv-toast.spec.js @@ -1,16 +1,13 @@ -import { mount, createWrapper, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount, createWrapper, createLocalVue } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../../tests/utils' import { ToastPlugin } from '../index' -describe('$bvToast', () => { - const localVue = new CreateLocalVue() - - beforeAll(() => { - localVue.use(ToastPlugin) - }) +const localVue = createLocalVue() +localVue.use(ToastPlugin) +describe('$bvToast', () => { it('$bvToast.show() and $bvToast.hide() works', async () => { - const App = localVue.extend({ + const App = { render(h) { return h( 'b-toast', @@ -25,7 +22,7 @@ describe('$bvToast', () => { 'content' ) } - }) + } const wrapper = mount(App, { attachTo: createContainer(), localVue @@ -72,11 +69,11 @@ describe('$bvToast', () => { }) it('$bvModal.toast() works', async () => { - const App = localVue.extend({ + const App = { render(h) { return h('div', 'app') } - }) + } const wrapper = mount(App, { attachTo: createContainer(), localVue diff --git a/src/components/tooltip/tooltip.spec.js b/src/components/tooltip/tooltip.spec.js index fcd0d544fca..5543680dfea 100644 --- a/src/components/tooltip/tooltip.spec.js +++ b/src/components/tooltip/tooltip.spec.js @@ -1,13 +1,11 @@ -import { mount, createLocalVue as CreateLocalVue, createWrapper } from '@vue/test-utils' +import { mount, createWrapper } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BTooltip } from './tooltip' -const localVue = new CreateLocalVue() - const MODAL_CLOSE_EVENT = 'bv::modal::hidden' -// Our test application definition -const appDef = { +// Our test application +const App = { props: [ 'triggers', 'show', @@ -98,10 +96,8 @@ describe('b-tooltip', () => { }) it('has expected default structure', async () => { - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click' }, @@ -137,10 +133,8 @@ describe('b-tooltip', () => { it('initially open has expected structure', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true @@ -223,10 +217,8 @@ describe('b-tooltip', () => { it('title prop is reactive', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -293,10 +285,8 @@ describe('b-tooltip', () => { it('activating trigger element (click) opens tooltip', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: false @@ -355,10 +345,8 @@ describe('b-tooltip', () => { it('activating trigger element (focus) opens tooltip', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'focus', show: false, @@ -435,10 +423,8 @@ describe('b-tooltip', () => { it('activating trigger element (hover) opens tooltip', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'hover', show: false, @@ -516,10 +502,8 @@ describe('b-tooltip', () => { it('disabled tooltip does not open on trigger', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: false, @@ -620,10 +604,8 @@ describe('b-tooltip', () => { it('closes/opens on instance events', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -703,10 +685,8 @@ describe('b-tooltip', () => { it('closes on $root close specific ID event', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -777,10 +757,8 @@ describe('b-tooltip', () => { it('does not close on $root close specific other ID event', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -850,10 +828,8 @@ describe('b-tooltip', () => { it('closes on $root close all event', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -925,10 +901,8 @@ describe('b-tooltip', () => { it('does not close on $root modal hidden event by default', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -999,10 +973,8 @@ describe('b-tooltip', () => { it('closes on $root modal hidden event when inside a modal', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -1075,10 +1047,8 @@ describe('b-tooltip', () => { // Prevent warns from appearing in the test logs jest.spyOn(console, 'warn').mockImplementation(() => {}) - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { triggers: 'click', show: true, @@ -1189,10 +1159,8 @@ describe('b-tooltip', () => { it('applies noninteractive class based on noninteractive prop', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { show: true }, @@ -1245,10 +1213,8 @@ describe('b-tooltip', () => { it('applies variant class', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { show: true, variant: 'danger' @@ -1299,10 +1265,8 @@ describe('b-tooltip', () => { it('applies custom class', async () => { jest.useFakeTimers() - const App = localVue.extend(appDef) const wrapper = mount(App, { attachTo: createContainer(), - localVue, propsData: { show: true, customClass: 'foobar-class' diff --git a/src/directives/hover/hover.spec.js b/src/directives/hover/hover.spec.js index dc35e2974fc..5d12c1931d2 100644 --- a/src/directives/hover/hover.spec.js +++ b/src/directives/hover/hover.spec.js @@ -1,12 +1,11 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { VBHover } from './hover' describe('v-b-hover directive', () => { it('works', async () => { - const localVue = new CreateLocalVue() let hovered1 = false let hovered2 = false - const App = localVue.extend({ + const App = { data() { return { text: 'FOO', @@ -25,7 +24,7 @@ describe('v-b-hover directive', () => { } }, template: `
{{ text }}
` - }) + } const wrapper = mount(App) expect(wrapper.vm).toBeDefined() diff --git a/src/directives/modal/modal.spec.js b/src/directives/modal/modal.spec.js index a73c4bfb234..24faf17c99b 100644 --- a/src/directives/modal/modal.spec.js +++ b/src/directives/modal/modal.spec.js @@ -1,14 +1,12 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { VBModal } from './modal' const EVENT_SHOW = 'bv::show::modal' describe('v-b-modal directive', () => { it('works on buttons', async () => { - const localVue = new CreateLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bModal: VBModal }, @@ -19,10 +17,8 @@ describe('v-b-modal directive', () => { this.$root.$off(EVENT_SHOW, spy) }, template: '' - }) - const wrapper = mount(App, { - localVue - }) + } + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') @@ -39,10 +35,8 @@ describe('v-b-modal directive', () => { }) it('works on links', async () => { - const localVue = new CreateLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bModal: VBModal }, @@ -58,10 +52,8 @@ describe('v-b-modal directive', () => { this.$root.$off(EVENT_SHOW, spy) }, template: '{{ text }}' - }) - const wrapper = mount(App, { - localVue - }) + } + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('A') @@ -81,10 +73,8 @@ describe('v-b-modal directive', () => { }) it('works on non-buttons', async () => { - const localVue = new CreateLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bModal: VBModal }, @@ -100,10 +90,8 @@ describe('v-b-modal directive', () => { this.$root.$off(EVENT_SHOW, spy) }, template: '{{ text }}' - }) - const wrapper = mount(App, { - localVue - }) + } + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('SPAN') @@ -129,10 +117,8 @@ describe('v-b-modal directive', () => { }) it('works on non-buttons using keydown space', async () => { - const localVue = new CreateLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bModal: VBModal }, @@ -148,10 +134,8 @@ describe('v-b-modal directive', () => { this.$root.$off(EVENT_SHOW, spy) }, template: '{{ text }}' - }) - const wrapper = mount(App, { - localVue - }) + } + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('SPAN') @@ -170,10 +154,8 @@ describe('v-b-modal directive', () => { }) it('works on non-buttons using keydown enter', async () => { - const localVue = new CreateLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bModal: VBModal }, @@ -189,10 +171,8 @@ describe('v-b-modal directive', () => { this.$root.$off(EVENT_SHOW, spy) }, template: '{{ text }}' - }) - const wrapper = mount(App, { - localVue - }) + } + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('SPAN') diff --git a/src/directives/popover/popover.spec.js b/src/directives/popover/popover.spec.js index d534e0c3fbe..9e22a494acc 100644 --- a/src/directives/popover/popover.spec.js +++ b/src/directives/popover/popover.spec.js @@ -1,4 +1,4 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { VBPopover } from './popover' import { BVPopover } from '../../components/popover/helpers/bv-popover' @@ -43,17 +43,15 @@ describe('v-b-popover directive', () => { it('should have BVPopover Vue instance', async () => { jest.useFakeTimers() - const localVue = new CreateLocalVue() - const App = localVue.extend({ + const App = { directives: { bPopover: VBPopover }, template: `` - }) + } const wrapper = mount(App, { - localVue, attachTo: createContainer() }) @@ -80,17 +78,15 @@ describe('v-b-popover directive', () => { it('should work', async () => { jest.useFakeTimers() - const localVue = new CreateLocalVue() - const App = localVue.extend({ + const App = { directives: { bPopover: VBPopover }, template: `` - }) + } const wrapper = mount(App, { - localVue, attachTo: createContainer() }) diff --git a/src/directives/toggle/toggle.spec.js b/src/directives/toggle/toggle.spec.js index 6aafa17b7f8..4b5e716228b 100644 --- a/src/directives/toggle/toggle.spec.js +++ b/src/directives/toggle/toggle.spec.js @@ -1,4 +1,4 @@ -import { mount, createLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { waitNT } from '../../../tests/utils' import { VBToggle } from './toggle' @@ -13,10 +13,8 @@ const EVENT_STATE_SYNC = 'bv::collapse::sync::state' describe('v-b-toggle directive', () => { it('works on buttons', async () => { - const localVue = createLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bToggle: VBToggle }, @@ -27,11 +25,9 @@ describe('v-b-toggle directive', () => { this.$root.$off(EVENT_TOGGLE, spy) }, template: '' - }) + } - const wrapper = mount(App, { - localVue - }) + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') @@ -58,10 +54,8 @@ describe('v-b-toggle directive', () => { }) it('works on passing ID as directive value', async () => { - const localVue = createLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bToggle: VBToggle }, @@ -72,11 +66,9 @@ describe('v-b-toggle directive', () => { this.$root.$off(EVENT_TOGGLE, spy) }, template: `` - }) + } - const wrapper = mount(App, { - localVue - }) + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') @@ -101,10 +93,8 @@ describe('v-b-toggle directive', () => { }) it('works on passing ID as directive argument', async () => { - const localVue = createLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bToggle: VBToggle }, @@ -115,11 +105,9 @@ describe('v-b-toggle directive', () => { this.$root.$off(EVENT_TOGGLE, spy) }, template: `` - }) + } - const wrapper = mount(App, { - localVue - }) + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') @@ -144,10 +132,8 @@ describe('v-b-toggle directive', () => { }) it('works with multiple targets, and updates when targets change', async () => { - const localVue = createLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bToggle: VBToggle }, @@ -164,13 +150,12 @@ describe('v-b-toggle directive', () => { this.$root.$off(EVENT_TOGGLE, spy) }, template: `` - }) + } const wrapper = mount(App, { propsData: { target: 'test1' - }, - localVue + } }) expect(wrapper.vm).toBeDefined() @@ -231,10 +216,8 @@ describe('v-b-toggle directive', () => { }) it('works on non-buttons', async () => { - const localVue = createLocalVue() const spy = jest.fn() - - const App = localVue.extend({ + const App = { directives: { bToggle: VBToggle }, @@ -250,11 +233,9 @@ describe('v-b-toggle directive', () => { this.$root.$off(EVENT_TOGGLE, spy) }, template: '{{ text }}' - }) + } - const wrapper = mount(App, { - localVue - }) + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('SPAN') @@ -324,18 +305,14 @@ describe('v-b-toggle directive', () => { }) it('responds to state update events', async () => { - const localVue = createLocalVue() - - const App = localVue.extend({ + const App = { directives: { bToggle: VBToggle }, template: '' - }) + } - const wrapper = mount(App, { - localVue - }) + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') @@ -374,18 +351,14 @@ describe('v-b-toggle directive', () => { }) it('responds to private sync state update events', async () => { - const localVue = createLocalVue() - - const App = localVue.extend({ + const App = { directives: { bToggle: VBToggle }, template: '' - }) + } - const wrapper = mount(App, { - localVue - }) + const wrapper = mount(App) expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') diff --git a/src/directives/tooltip/tooltip.spec.js b/src/directives/tooltip/tooltip.spec.js index 28193a31bbc..4a6a9b381dc 100644 --- a/src/directives/tooltip/tooltip.spec.js +++ b/src/directives/tooltip/tooltip.spec.js @@ -1,4 +1,4 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { VBTooltip } from './tooltip' import { BVTooltip } from '../../components/tooltip/helpers/bv-tooltip' @@ -11,10 +11,10 @@ describe('v-b-tooltip directive', () => { const origGetBCR = Element.prototype.getBoundingClientRect beforeEach(() => { + // Hack to make Popper not bork out during tests + // Note: Popper still does not do any positioning calculation in JSDOM though + // So we cannot test actual positioning - just detect when it is open // https://github.com/FezVrasta/popper.js/issues/478#issuecomment-407422016 - // Hack to make Popper not bork out during tests. - // Note popper still does not do any positioning calculation in JSDOM though. - // So we cannot test actual positioning... just detect when it is open. document.createRange = () => ({ setStart: () => {}, setEnd: () => {}, @@ -43,17 +43,15 @@ describe('v-b-tooltip directive', () => { it('should have BVTooltip Vue class instance', async () => { jest.useFakeTimers() - const localVue = new CreateLocalVue() - const App = localVue.extend({ + const App = { directives: { bTooltip: VBTooltip }, template: '' - }) + } const wrapper = mount(App, { - localVue, attachTo: createContainer() }) @@ -80,17 +78,15 @@ describe('v-b-tooltip directive', () => { it('should work', async () => { jest.useFakeTimers() - const localVue = new CreateLocalVue() - const App = localVue.extend({ + const App = { directives: { bTooltip: VBTooltip }, template: '' - }) + } const wrapper = mount(App, { - localVue, attachTo: createContainer() }) @@ -134,17 +130,15 @@ describe('v-b-tooltip directive', () => { it('should not show tooltip when title is empty', async () => { jest.useFakeTimers() - const localVue = new CreateLocalVue() - const App = localVue.extend({ + const App = { directives: { bTooltip: VBTooltip }, template: '' - }) + } const wrapper = mount(App, { - localVue, attachTo: createContainer() }) @@ -183,17 +177,15 @@ describe('v-b-tooltip directive', () => { it('variant and customClass should work', async () => { jest.useFakeTimers() - const localVue = new CreateLocalVue() - const App = localVue.extend({ + const App = { directives: { bTooltip: VBTooltip }, template: `` - }) + } const wrapper = mount(App, { - localVue, attachTo: createContainer() }) diff --git a/src/icons/icons.spec.js b/src/icons/icons.spec.js index e2af4f7d4fb..a1e75328cfa 100644 --- a/src/icons/icons.spec.js +++ b/src/icons/icons.spec.js @@ -1,31 +1,15 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { createLocalVue, mount } from '@vue/test-utils' import { IconsPlugin } from './index' import { BIcon } from './icon' import { makeIcon } from './helpers/make-icon' -describe('icons', () => { - const localVue = new CreateLocalVue() - - const parentComponent = { - name: 'ParentComponent', - components: { - // For testing user defined Icons - BIconFakeIconTest: makeIcon('FakeIconTest', '') - }, - render(h) { - return h(this.$slots.default) - } - } - - beforeAll(() => { - // We install all icon components so that BIcon will work - localVue.use(IconsPlugin) - }) +const localVue = createLocalVue() +localVue.use(IconsPlugin) +describe('icons', () => { it('b-icon has expected structure', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill' } @@ -57,7 +41,6 @@ describe('icons', () => { it('b-icon has expected structure when `stacked` prop is true', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', stacked: true @@ -117,7 +100,6 @@ describe('icons', () => { // As we currently do not check the validity of icon names const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: undefined } @@ -136,7 +118,6 @@ describe('icons', () => { it('b-icon with unknown icon name renders BIconBlank', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'unknown-icon-name' } @@ -158,7 +139,6 @@ describe('icons', () => { it('b-icon variant works', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', variant: 'danger' @@ -185,7 +165,6 @@ describe('icons', () => { it('b-icon font-scale prop works', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', fontScale: '1.25' @@ -211,10 +190,21 @@ describe('icons', () => { }) it('b-icon with custom icon works', async () => { + const ParentComponent = { + name: 'ParentComponent', + components: { + // For testing user defined Icons + BIconFakeIconTest: makeIcon('FakeIconTest', '') + }, + render(h) { + return h(this.$slots.default) + } + } + const wrapper = mount(BIcon, { localVue, // Parent component has a custom icon registered - parentComponent: parentComponent, + parentComponent: ParentComponent, propsData: { icon: 'fake-icon-test' } @@ -236,7 +226,6 @@ describe('icons', () => { it('b-icon rotate prop works', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', rotate: '45' @@ -262,7 +251,6 @@ describe('icons', () => { it('b-icon scale prop works', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', scale: '1.5' @@ -288,7 +276,6 @@ describe('icons', () => { it('b-icon flip-h prop works', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', flipH: true @@ -314,7 +301,6 @@ describe('icons', () => { it('b-icon flip-v prop works', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', flipV: true @@ -340,7 +326,6 @@ describe('icons', () => { it('b-icon flip-h prop works with flip-v prop', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', flipH: true, @@ -367,7 +352,6 @@ describe('icons', () => { it('b-icon scale prop works with flip-h prop', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', scale: '1.5', @@ -394,7 +378,6 @@ describe('icons', () => { it('b-icon scale prop works with flip-v prop', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', scale: '1.5', @@ -421,7 +404,6 @@ describe('icons', () => { it('b-icon scale prop works with flip-h and flip-v prop', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', scale: '1.5', @@ -449,7 +431,6 @@ describe('icons', () => { it('b-icon shift-h and shift-v props work', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', shiftH: 8, @@ -476,7 +457,6 @@ describe('icons', () => { it('b-icon shift-h and shift-v props work with rotate prop', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'alarm-fill', rotate: 45, @@ -507,7 +487,6 @@ describe('icons', () => { it('b-icon animation prop works', async () => { const wrapper = mount(BIcon, { localVue, - parentComponent: parentComponent, propsData: { icon: 'circle-fill', animation: 'spin' diff --git a/src/mixins/listen-on-document.spec.js b/src/mixins/listen-on-document.spec.js index cbd8eb07916..6e7c2e322ea 100644 --- a/src/mixins/listen-on-document.spec.js +++ b/src/mixins/listen-on-document.spec.js @@ -1,16 +1,14 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer } from '../../tests/utils' import listenOnDocumentMixin from './listen-on-document' describe('mixins/listen-on-document', () => { - const localVue = new CreateLocalVue() - it('works', async () => { const spyClick1 = jest.fn() const spyClick2 = jest.fn() const spyFocusin = jest.fn() - const TestComponent = localVue.extend({ + const TestComponent = { mixins: [listenOnDocumentMixin], props: { offClickOne: { @@ -33,9 +31,9 @@ describe('mixins/listen-on-document', () => { render(h) { return h('div', this.$slots.default) } - }) + } - const App = localVue.extend({ + const App = { components: { TestComponent }, props: { offClickOne: { @@ -57,7 +55,7 @@ describe('mixins/listen-on-document', () => { this.destroy ? h() : h(TestComponent, { props }, 'test-component') ]) } - }) + } const wrapper = mount(App, { attachTo: createContainer(), diff --git a/src/mixins/listen-on-root.spec.js b/src/mixins/listen-on-root.spec.js index af366c870a4..f5f149edc3e 100644 --- a/src/mixins/listen-on-root.spec.js +++ b/src/mixins/listen-on-root.spec.js @@ -1,13 +1,12 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import listenOnRootMixin from './listen-on-root' describe('mixins/listen-on-root', () => { - const localVue = new CreateLocalVue() it('works', async () => { const spyOn = jest.fn() const spyOnce = jest.fn() - const TestComponent = localVue.extend({ + const TestComponent = { mixins: [listenOnRootMixin], created() { this.listenOnRoot('root-on', spyOn) @@ -16,9 +15,9 @@ describe('mixins/listen-on-root', () => { render(h) { return h('div', this.$slots.default) } - }) + } - const App = localVue.extend({ + const App = { components: { TestComponent }, props: { destroy: { @@ -29,10 +28,9 @@ describe('mixins/listen-on-root', () => { render(h) { return h('div', [this.destroy ? h() : h(TestComponent, 'test-component')]) } - }) + } const wrapper = mount(App, { - localVue, propsData: { destroy: false } @@ -47,22 +45,18 @@ describe('mixins/listen-on-root', () => { const $root = wrapper.vm.$root $root.$emit('root-on') - expect(spyOn).toHaveBeenCalledTimes(1) expect(spyOnce).not.toHaveBeenCalled() await wrapper.setProps({ destroy: true }) - expect(spyOn).toHaveBeenCalledTimes(1) expect(spyOnce).not.toHaveBeenCalled() $root.$emit('root-on') - expect(spyOn).toHaveBeenCalledTimes(1) expect(spyOnce).not.toHaveBeenCalled() $root.$emit('root-once') - expect(spyOn).toHaveBeenCalledTimes(1) expect(spyOnce).not.toHaveBeenCalled() diff --git a/src/mixins/listen-on-window.spec.js b/src/mixins/listen-on-window.spec.js index 4461abbb8c5..4289a296c9a 100644 --- a/src/mixins/listen-on-window.spec.js +++ b/src/mixins/listen-on-window.spec.js @@ -1,16 +1,14 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer } from '../../tests/utils' import listenOnWindowMixin from './listen-on-window' describe('mixins/listen-on-window', () => { - const localVue = new CreateLocalVue() - it('works', async () => { const spyResize1 = jest.fn() const spyResize2 = jest.fn() const spyScroll = jest.fn() - const TestComponent = localVue.extend({ + const TestComponent = { mixins: [listenOnWindowMixin], props: { offResizeOne: { @@ -33,9 +31,9 @@ describe('mixins/listen-on-window', () => { render(h) { return h('div', this.$slots.default) } - }) + } - const App = localVue.extend({ + const App = { components: { TestComponent }, props: { offResizeOne: { @@ -53,7 +51,7 @@ describe('mixins/listen-on-window', () => { } return h('div', [this.destroy ? h() : h(TestComponent, { props }, 'test-component')]) } - }) + } const wrapper = mount(App, { attachTo: createContainer(), diff --git a/src/utils/config.spec.js b/src/utils/config.spec.js index 420179ea58d..ff096338848 100644 --- a/src/utils/config.spec.js +++ b/src/utils/config.spec.js @@ -104,10 +104,10 @@ describe('utils/config', () => { }) it('config via Vue.use(BootstrapVue) works', async () => { + const localVue = createLocalVue() const testConfig = { BAlert: { variant: 'foobar' } } - const localVue = createLocalVue() expect(getConfig()).toEqual({}) @@ -120,10 +120,10 @@ describe('utils/config', () => { }) it('config via Vue.use(ComponentPlugin) works', async () => { + const localVue = createLocalVue() const testConfig = { BAlert: { variant: 'foobar' } } - const localVue = createLocalVue() expect(getConfig()).toEqual({}) @@ -136,10 +136,10 @@ describe('utils/config', () => { }) it('config via Vue.use(BVConfig) works', async () => { + const localVue = createLocalVue() const testConfig = { BAlert: { variant: 'foobar' } } - const localVue = createLocalVue() expect(getConfig()).toEqual({}) diff --git a/src/utils/transporter.spec.js b/src/utils/transporter.spec.js index 475586d6cf7..9a7b8809913 100644 --- a/src/utils/transporter.spec.js +++ b/src/utils/transporter.spec.js @@ -1,20 +1,17 @@ -import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT } from '../../tests/utils' import { BTransporterSingle } from './transporter' describe('utils/transporter component', () => { - const localVue = new CreateLocalVue() - it('renders in-pace when disabled=true', async () => { - const App = localVue.extend({ + const App = { render(h) { return h(BTransporterSingle, { props: { disabled: true } }, [h('div', 'content')]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() @@ -25,17 +22,16 @@ describe('utils/transporter component', () => { }) it('does not render in-pace when disabled=false', async () => { - const App = localVue.extend({ + const App = { render(h) { return h(BTransporterSingle, { props: { disabled: false } }, [ h('div', { attrs: { id: 'foobar' } }, 'content') ]) } - }) + } const wrapper = mount(App, { - attachTo: createContainer(), - localVue + attachTo: createContainer() }) expect(wrapper.vm).toBeDefined() From c544be7a50c7b505857c3173124cb7ce3ebb36c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 18:22:00 +0200 Subject: [PATCH 02/17] Only stub components when really needed --- src/components/alert/alert.spec.js | 6 +----- src/components/collapse/collapse.spec.js | 6 +----- src/components/modal/helpers/bv-modal.spec.js | 6 +++++- src/components/modal/modal.spec.js | 6 +----- src/components/overlay/overlay.spec.js | 6 +----- src/components/sidebar/sidebar.spec.js | 6 +----- src/components/table/table-tbody-transition.spec.js | 10 +++++++--- src/components/tabs/tab.spec.js | 6 +----- src/components/toast/helpers/bv-toast.spec.js | 2 +- src/components/toast/toast.spec.js | 6 +----- src/components/toast/toaster.spec.js | 7 +------ src/components/tooltip/tooltip.spec.js | 2 +- tests/setup.js | 6 +++--- 13 files changed, 25 insertions(+), 50 deletions(-) diff --git a/src/components/alert/alert.spec.js b/src/components/alert/alert.spec.js index 5c864fd003f..9f30a3dc78f 100644 --- a/src/components/alert/alert.spec.js +++ b/src/components/alert/alert.spec.js @@ -1,11 +1,7 @@ -import { config as vtuConfig, mount } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { waitNT, waitRAF } from '../../../tests/utils' import { BAlert } from './alert' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs.transition = false - describe('alert', () => { it('hidden alert renders comment node', async () => { const wrapper = mount(BAlert) diff --git a/src/components/collapse/collapse.spec.js b/src/components/collapse/collapse.spec.js index 64aefbd39b6..902ae6b7961 100644 --- a/src/components/collapse/collapse.spec.js +++ b/src/components/collapse/collapse.spec.js @@ -1,11 +1,7 @@ -import { config as vtuConfig, createWrapper, mount } from '@vue/test-utils' +import { createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BCollapse } from './collapse' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs.transition = false - // Events collapse emits on $root const EVENT_STATE = 'bv::collapse::state' const EVENT_ACCORDION = 'bv::collapse::accordion' diff --git a/src/components/modal/helpers/bv-modal.spec.js b/src/components/modal/helpers/bv-modal.spec.js index ab2419d8f72..6c5ede4ec62 100644 --- a/src/components/modal/helpers/bv-modal.spec.js +++ b/src/components/modal/helpers/bv-modal.spec.js @@ -1,7 +1,11 @@ -import { mount, createLocalVue, createWrapper } from '@vue/test-utils' +import { config as vtuConfig, createLocalVue, createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../../tests/utils' +import { TransitionStub } from '../../../../tests/components' import { ModalPlugin } from '../index' +// Stub `` component +vtuConfig.stubs.transition = TransitionStub + const localVue = createLocalVue() localVue.use(ModalPlugin) diff --git a/src/components/modal/modal.spec.js b/src/components/modal/modal.spec.js index 14f36abde07..1a3019d7cee 100644 --- a/src/components/modal/modal.spec.js +++ b/src/components/modal/modal.spec.js @@ -1,12 +1,8 @@ -import { config as vtuConfig, createWrapper, mount } from '@vue/test-utils' +import { createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BModal } from './modal' import { BvModalEvent } from './helpers/bv-modal-event.class' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs.transition = false - // The default Z-INDEX for modal backdrop const DEFAULT_ZINDEX = 1040 diff --git a/src/components/overlay/overlay.spec.js b/src/components/overlay/overlay.spec.js index 017bc4be943..edb2be4e88d 100644 --- a/src/components/overlay/overlay.spec.js +++ b/src/components/overlay/overlay.spec.js @@ -1,11 +1,7 @@ -import { config as vtuConfig, mount } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BOverlay } from './overlay' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs.transition = false - describe('overlay', () => { it('has expected default structure', async () => { const wrapper = mount(BOverlay, { diff --git a/src/components/sidebar/sidebar.spec.js b/src/components/sidebar/sidebar.spec.js index 8228782bfb9..448872c6463 100644 --- a/src/components/sidebar/sidebar.spec.js +++ b/src/components/sidebar/sidebar.spec.js @@ -1,11 +1,7 @@ -import { config as vtuConfig, createWrapper, mount } from '@vue/test-utils' +import { createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BSidebar } from './sidebar' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs.transition = false - const EVENT_TOGGLE = 'bv::toggle::collapse' const EVENT_STATE = 'bv::collapse::state' const EVENT_STATE_SYNC = 'bv::collapse::sync::state' diff --git a/src/components/table/table-tbody-transition.spec.js b/src/components/table/table-tbody-transition.spec.js index c02a2f5f75d..7ca3c4a01d5 100644 --- a/src/components/table/table-tbody-transition.spec.js +++ b/src/components/table/table-tbody-transition.spec.js @@ -1,8 +1,11 @@ -import { mount } from '@vue/test-utils' +import { config as vtuConfig, mount } from '@vue/test-utils' import { createContainer } from '../../../tests/utils' import { TransitionGroupStub } from '../../../tests/components' import { BTable } from './table' +// Stub `` component +vtuConfig.stubs['transition-group'] = TransitionGroupStub + const testItems = [{ a: 1, b: 2, c: 3 }, { a: 5, b: 5, c: 6 }, { a: 7, b: 8, c: 9 }] const testFields = ['a', 'b', 'c'] @@ -19,6 +22,7 @@ describe('table > tbody transition', () => { expect(wrapper.element.tagName).toBe('TABLE') expect(wrapper.find('tbody').exists()).toBe(true) expect(wrapper.find('tbody').element.tagName).toBe('TBODY') + // `` stub doesn't render itself with the specified tag expect(wrapper.findComponent(TransitionGroupStub).exists()).toBe(false) wrapper.destroy() @@ -37,8 +41,8 @@ describe('table > tbody transition', () => { }) expect(wrapper).toBeDefined() expect(wrapper.element.tagName).toBe('TABLE') + // `` stub doesn't render itself with the specified tag expect(wrapper.findComponent(TransitionGroupStub).exists()).toBe(true) - // Transition-group stub doesn't render itself with the specified tag expect(wrapper.find('tbody').exists()).toBe(false) wrapper.destroy() @@ -60,8 +64,8 @@ describe('table > tbody transition', () => { }) expect(wrapper).toBeDefined() expect(wrapper.element.tagName).toBe('TABLE') + // `` stub doesn't render itself with the specified tag expect(wrapper.findComponent(TransitionGroupStub).exists()).toBe(true) - // Transition-group stub doesn't render itself with the specified tag expect(wrapper.find('tbody').exists()).toBe(false) wrapper.destroy() diff --git a/src/components/tabs/tab.spec.js b/src/components/tabs/tab.spec.js index 9d62c7a0bd8..f256b20a818 100644 --- a/src/components/tabs/tab.spec.js +++ b/src/components/tabs/tab.spec.js @@ -1,11 +1,7 @@ -import { config as vtuConfig, mount } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { waitNT, waitRAF } from '../../../tests/utils' import { BTab } from './tab' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs.transition = false - describe('tab', () => { it('default has expected classes, attributes and structure', async () => { const wrapper = mount(BTab) diff --git a/src/components/toast/helpers/bv-toast.spec.js b/src/components/toast/helpers/bv-toast.spec.js index 08a9647281a..d0a44b23cd5 100644 --- a/src/components/toast/helpers/bv-toast.spec.js +++ b/src/components/toast/helpers/bv-toast.spec.js @@ -1,4 +1,4 @@ -import { mount, createWrapper, createLocalVue } from '@vue/test-utils' +import { createLocalVue, createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../../tests/utils' import { ToastPlugin } from '../index' diff --git a/src/components/toast/toast.spec.js b/src/components/toast/toast.spec.js index 13a0733a61f..7b0c7e72f3f 100644 --- a/src/components/toast/toast.spec.js +++ b/src/components/toast/toast.spec.js @@ -1,11 +1,7 @@ -import { config as vtuConfig, mount } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BToast } from './toast' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs.transition = false - describe('b-toast', () => { beforeAll(() => { // Prevent multiple Vue warnings in tests diff --git a/src/components/toast/toaster.spec.js b/src/components/toast/toaster.spec.js index 188ffea451b..e03bf78e010 100644 --- a/src/components/toast/toaster.spec.js +++ b/src/components/toast/toaster.spec.js @@ -1,13 +1,8 @@ -import { config as vtuConfig, mount } from '@vue/test-utils' +import { mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { PortalTarget } from 'portal-vue' import { BToaster } from './toaster' -// Disable the use of the TransitionStub component -// since it doesn't run transition hooks -vtuConfig.stubs['transition-group'] = false -vtuConfig.stubs.transition = false - describe('b-toaster', () => { it('has expected structure', async () => { const wrapper = mount(BToaster, { diff --git a/src/components/tooltip/tooltip.spec.js b/src/components/tooltip/tooltip.spec.js index 5543680dfea..5f8c3e4995e 100644 --- a/src/components/tooltip/tooltip.spec.js +++ b/src/components/tooltip/tooltip.spec.js @@ -1,4 +1,4 @@ -import { mount, createWrapper } from '@vue/test-utils' +import { createWrapper, mount } from '@vue/test-utils' import { createContainer, waitNT, waitRAF } from '../../../tests/utils' import { BTooltip } from './tooltip' diff --git a/tests/setup.js b/tests/setup.js index a526836d70c..f7810e142c4 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -1,6 +1,6 @@ import '@testing-library/jest-dom' import { config as vtuConfig } from '@vue/test-utils' -import { TransitionGroupStub, TransitionStub } from './components' -vtuConfig.stubs['transition-group'] = TransitionGroupStub -vtuConfig.stubs.transition = TransitionStub +// Don't stub `` and `` components +vtuConfig.stubs.transition = false +vtuConfig.stubs['transition-group'] = false From d02997983e0a5b27222e3fd99251c1af7740c781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:53:49 +0200 Subject: [PATCH 03/17] Update button-toolbar.spec.js --- src/components/button-toolbar/button-toolbar.spec.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/button-toolbar/button-toolbar.spec.js b/src/components/button-toolbar/button-toolbar.spec.js index 9f2d1138be4..3ca7ea55598 100644 --- a/src/components/button-toolbar/button-toolbar.spec.js +++ b/src/components/button-toolbar/button-toolbar.spec.js @@ -1,4 +1,3 @@ -import Vue from 'vue' import { mount } from '@vue/test-utils' import { createContainer, waitNT } from '../../../tests/utils' import { BButton } from '../button/button' @@ -82,7 +81,7 @@ describe('button-toolbar', () => { }) // Test App for keynav - const App = Vue.extend({ + const App = { render(h) { return h(BButtonToolbar, { props: { keyNav: true } }, [ h(BButtonGroup, [h(BButton, 'a'), h(BButton, 'b')]), @@ -90,7 +89,7 @@ describe('button-toolbar', () => { h(BButtonGroup, [h(BButton, 'e'), h(BButton, 'f')]) ]) } - }) + } it('has correct structure', async () => { const wrapper = mount(App, { From 363dfd39b081898ca0f74d952f5b04f7ea8773e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:53:57 +0200 Subject: [PATCH 04/17] Update carousel-slide.spec.js --- .../carousel/carousel-slide.spec.js | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/components/carousel/carousel-slide.spec.js b/src/components/carousel/carousel-slide.spec.js index cbb10abf7a8..b419b0a9be0 100644 --- a/src/components/carousel/carousel-slide.spec.js +++ b/src/components/carousel/carousel-slide.spec.js @@ -2,75 +2,68 @@ import { mount } from '@vue/test-utils' import { BCarouselSlide } from './carousel-slide' describe('carousel-slide', () => { - it('has root element "div"', async () => { + it('has expected default structure', async () => { const wrapper = mount(BCarouselSlide) - expect(wrapper.element.tagName).toBe('DIV') - - wrapper.destroy() - }) - it('has class carousel-item', async () => { - const wrapper = mount(BCarouselSlide) - expect(wrapper.classes()).toContain('carousel-item') + expect(wrapper.element.tagName).toBe('DIV') expect(wrapper.classes().length).toBe(1) - - wrapper.destroy() - }) - - it('has role=listitem', async () => { - const wrapper = mount(BCarouselSlide) + expect(wrapper.classes()).toContain('carousel-item') expect(wrapper.attributes('role')).toBeDefined() expect(wrapper.attributes('role')).toBe('listitem') wrapper.destroy() }) - it('does not have child div.carousel-caption by default', async () => { + it('does not have child "carousel-caption" by default', async () => { const wrapper = mount(BCarouselSlide) + expect(wrapper.find('.carousel-caption').exists()).toBe(false) wrapper.destroy() }) - it('does not have image by default', async () => { + it('does not have "img" by default', async () => { const wrapper = mount(BCarouselSlide) expect(wrapper.find('img').exists()).toBe(false) wrapper.destroy() }) - it('does not have caption tag h3 by default', async () => { + it('does not have caption tag "h3" by default', async () => { const wrapper = mount(BCarouselSlide) expect(wrapper.find('h3').exists()).toBe(false) wrapper.destroy() }) - it('does not have text tag p by default', async () => { + it('does not have text tag "p" by default', async () => { const wrapper = mount(BCarouselSlide) + expect(wrapper.find('p').exists()).toBe(false) wrapper.destroy() }) - it('renders default slot inside carousel-caption', async () => { + it('renders default slot inside "carousel-caption"', async () => { const wrapper = mount(BCarouselSlide, { slots: { default: 'foobar' } }) + expect(wrapper.find('.carousel-caption').exists()).toBe(true) expect(wrapper.find('.carousel-caption').text()).toContain('foobar') wrapper.destroy() }) - it('has caption tag h3 when prop caption is set', async () => { + it('has caption tag "h3" when prop "caption" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { caption: 'foobar' } }) + const content = wrapper.find('.carousel-caption') expect(content.find('h3').exists()).toBe(true) expect(content.find('h3').text()).toBe('foobar') @@ -78,12 +71,13 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has text tag p when prop text is set', async () => { + it('has text tag "p" when prop "text" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { text: 'foobar' } }) + const content = wrapper.find('.carousel-caption') expect(content.find('p').exists()).toBe(true) expect(content.find('p').text()).toBe('foobar') @@ -91,7 +85,7 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has custom content tag when prop contentTag is set', async () => { + it('has custom content tag when prop "content-tag" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { contentTag: 'span' @@ -100,13 +94,14 @@ describe('carousel-slide', () => { default: 'foobar' } }) + expect(wrapper.find('.carousel-caption').exists()).toBe(true) expect(wrapper.find('.carousel-caption').element.tagName).toBe('SPAN') wrapper.destroy() }) - it('has display classes on .carousel-caption when prop contentVisibleUp is set', async () => { + it('has display classes on "carousel-caption" when prop "content-visible-up" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { contentVisibleUp: 'lg' @@ -115,6 +110,7 @@ describe('carousel-slide', () => { default: 'foobar' } }) + expect(wrapper.find('.carousel-caption').exists()).toBe(true) expect(wrapper.find('.carousel-caption').classes()).toContain('d-none') expect(wrapper.find('.carousel-caption').classes()).toContain('d-lg-block') @@ -123,25 +119,21 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('does not have style background when prop background not set', async () => { + it('does not have style "background" when prop "background" not set', async () => { const wrapper = mount(BCarouselSlide) - if (wrapper.attributes('style')) { - // Vue always includes a style attr when passed an empty style object - expect(wrapper.attributes('style')).not.toContain('background:') - } else { - // But just in case that changes in the future - expect(true).toBe(true) - } + + expect(wrapper.attributes('style')).not.toBeDefined() wrapper.destroy() }) - it('has style background when prop background is set', async () => { + it('has style "background" when prop "background" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { background: 'rgb(1, 2, 3)' } }) + expect(wrapper.attributes('style')).toBeDefined() expect(wrapper.attributes('style')).toContain('background:') expect(wrapper.attributes('style')).toContain('rgb(') @@ -157,6 +149,7 @@ describe('carousel-slide', () => { } } }) + expect(wrapper.attributes('style')).toBeDefined() expect(wrapper.attributes('style')).toContain('background:') expect(wrapper.attributes('style')).toContain('rgb(') @@ -164,13 +157,14 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has custom caption tag when prop captionTag is set', async () => { + it('has custom caption tag when prop "caption-tag" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { captionTag: 'h1', caption: 'foobar' } }) + const content = wrapper.find('.carousel-caption') expect(content.find('h1').exists()).toBe(true) expect(content.find('h1').text()).toBe('foobar') @@ -178,13 +172,14 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has custom text tag when prop textTag is set', async () => { + it('has custom text tag when prop "text-tag is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { textTag: 'span', text: 'foobar' } }) + const content = wrapper.find('.carousel-caption') expect(content.find('span').exists()).toBe(true) expect(content.find('span').text()).toBe('foobar') @@ -192,12 +187,13 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has image when prop img-src is set', async () => { + it('has image when prop "img-src" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { imgSrc: 'https://picsum.photos/1024/480/?image=52' } }) + expect(wrapper.find('img').exists()).toBe(true) expect(wrapper.find('img').attributes('src')).toBeDefined() expect(wrapper.find('img').attributes('src')).toBe('https://picsum.photos/1024/480/?image=52') @@ -205,12 +201,13 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has image when prop img-blank is set', async () => { + it('has image when prop "img-blank" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { imgBlank: true } }) + expect(wrapper.find('img').exists()).toBe(true) expect(wrapper.find('img').attributes('src')).toBeDefined() expect(wrapper.find('img').attributes('src')).toContain('data:') @@ -218,13 +215,14 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has image with alt attribute when prop img-alt is set', async () => { + it('has image with "alt" attr when prop "img-alt" is set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { imgSrc: 'https://picsum.photos/1024/480/?image=52', imgAlt: 'foobar' } }) + expect(wrapper.find('img').exists()).toBe(true) expect(wrapper.find('img').attributes('src')).toBeDefined() expect(wrapper.find('img').attributes('alt')).toBeDefined() @@ -233,7 +231,7 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has image with width and height attrs when props img-width and img-height are set', async () => { + it('has image with "width" and "height" attrs when props "img-width" and "img-height" are set', async () => { const wrapper = mount(BCarouselSlide, { propsData: { imgSrc: 'https://picsum.photos/1024/480/?image=52', @@ -241,6 +239,7 @@ describe('carousel-slide', () => { imgHeight: '480' } }) + expect(wrapper.find('img').exists()).toBe(true) expect(wrapper.find('img').attributes('src')).toBeDefined() expect(wrapper.find('img').attributes('width')).toBeDefined() @@ -251,7 +250,7 @@ describe('carousel-slide', () => { wrapper.destroy() }) - it('has image with width and height attrs inherited from carousel parent', async () => { + it('has image with "width" and "height" attrs inherited from carousel parent', async () => { const wrapper = mount(BCarouselSlide, { provide: { // Mock carousel injection @@ -264,6 +263,7 @@ describe('carousel-slide', () => { imgSrc: 'https://picsum.photos/1024/480/?image=52' } }) + expect(wrapper.find('img').exists()).toBe(true) expect(wrapper.find('img').attributes('src')).toBeDefined() expect(wrapper.find('img').attributes('width')).toBeDefined() From 101438002ac83f6b0459332f6cd5075ebceb2d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:54:06 +0200 Subject: [PATCH 05/17] Update form-checkbox-group.spec.js --- src/components/form-checkbox/form-checkbox-group.spec.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/form-checkbox/form-checkbox-group.spec.js b/src/components/form-checkbox/form-checkbox-group.spec.js index 99cfcb18dff..f9e12de616b 100644 --- a/src/components/form-checkbox/form-checkbox-group.spec.js +++ b/src/components/form-checkbox/form-checkbox-group.spec.js @@ -1,4 +1,3 @@ -import Vue from 'vue' import { mount } from '@vue/test-utils' import { createContainer, waitNT } from '../../../tests/utils' import { BFormCheckboxGroup } from './form-checkbox-group' @@ -241,7 +240,7 @@ describe('form-checkbox-group', () => { }) it('button mode button variant works', async () => { - const App = Vue.extend({ + const App = { render(h) { return h( BFormCheckboxGroup, @@ -259,7 +258,7 @@ describe('form-checkbox-group', () => { ] ) } - }) + } const wrapper = mount(App, { attachTo: createContainer() From 0b6f5bc00201bf92e8afcdd2dba41acf76ab2eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:54:13 +0200 Subject: [PATCH 06/17] Update form-radio-group.spec.js --- src/components/form-radio/form-radio-group.spec.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/form-radio/form-radio-group.spec.js b/src/components/form-radio/form-radio-group.spec.js index 107102e4755..1b504ea752e 100644 --- a/src/components/form-radio/form-radio-group.spec.js +++ b/src/components/form-radio/form-radio-group.spec.js @@ -1,4 +1,3 @@ -import Vue from 'vue' import { mount } from '@vue/test-utils' import { createContainer, waitNT } from '../../../tests/utils' import { BFormRadioGroup } from './form-radio-group' @@ -241,7 +240,7 @@ describe('form-radio-group', () => { }) it('button mode button-variant works', async () => { - const App = Vue.extend({ + const App = { render(h) { return h( BFormRadioGroup, @@ -259,7 +258,7 @@ describe('form-radio-group', () => { ] ) } - }) + } const wrapper = mount(App, { attachTo: createContainer() From 5c9fe87e6030dce4d90f3a7e790f67f53799032e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:54:21 +0200 Subject: [PATCH 07/17] Update tabs.spec.js --- src/components/tabs/tabs.spec.js | 53 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/components/tabs/tabs.spec.js b/src/components/tabs/tabs.spec.js index 3746bb316db..5ce934af82e 100644 --- a/src/components/tabs/tabs.spec.js +++ b/src/components/tabs/tabs.spec.js @@ -1,4 +1,3 @@ -import Vue from 'vue' import { mount } from '@vue/test-utils' import { waitNT, waitRAF } from '../../../tests/utils' import { BLink } from '../link/link' @@ -102,7 +101,7 @@ describe('tabs', () => { }) it('sets correct tab active when first tab is disabled', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, [ h(BTab, { props: { disabled: true } }, 'tab 0'), @@ -110,7 +109,7 @@ describe('tabs', () => { h(BTab, { props: {} }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -134,7 +133,7 @@ describe('tabs', () => { }) it('sets current index based on active prop of b-tab', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, [ h(BTab, { props: { active: false } }, 'tab 0'), @@ -142,7 +141,7 @@ describe('tabs', () => { h(BTab, { props: { active: false } }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -166,7 +165,7 @@ describe('tabs', () => { }) it('selects first non-disabled tab when active tab disabled', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, [ h(BTab, { props: { active: false, disabled: true } }, 'tab 0'), @@ -174,7 +173,7 @@ describe('tabs', () => { h(BTab, { props: { active: false } }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -213,7 +212,7 @@ describe('tabs', () => { }) it('v-model works', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 0 } }, [ h(BTab, { props: {} }, 'tab 0'), @@ -221,7 +220,7 @@ describe('tabs', () => { h(BTab, { props: {} }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -257,7 +256,7 @@ describe('tabs', () => { }) it('v-model works when trying to activate a disabled tab', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 0 } }, [ h(BTab, { props: {} }, 'tab 0'), @@ -265,7 +264,7 @@ describe('tabs', () => { h(BTab, { props: {} }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -305,7 +304,7 @@ describe('tabs', () => { }) it('`activate-tab` event works', async () => { - const App = Vue.extend({ + const App = { methods: { preventTab(next, prev, bvEvt) { // Prevent 3rd tab (index === 2) from activating @@ -321,7 +320,7 @@ describe('tabs', () => { h(BTab, { props: {} }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -369,7 +368,7 @@ describe('tabs', () => { }) it('clicking on tab activates the tab, and tab emits click event', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 0 } }, [ h(BTab, { props: { title: 'one' } }, 'tab 0'), @@ -377,7 +376,7 @@ describe('tabs', () => { h(BTab, { props: { title: 'three' } }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -443,7 +442,7 @@ describe('tabs', () => { }) it('pressing space on tab activates the tab, and tab emits click event', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 0, noKeyNav: true } }, [ h(BTab, { props: { title: 'one' } }, 'tab 0'), @@ -451,7 +450,7 @@ describe('tabs', () => { h(BTab, { props: { title: 'three' } }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -517,7 +516,7 @@ describe('tabs', () => { }) it('key nav works', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 0 } }, [ h(BTab, { props: { title: 'one' } }, 'tab 0'), @@ -525,7 +524,7 @@ describe('tabs', () => { h(BTab, { props: { title: 'three' } }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -596,7 +595,7 @@ describe('tabs', () => { }) it('disabling active tab selects first non-disabled tab', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 2 } }, [ h(BTab, { props: { title: 'one' } }, 'tab 0'), @@ -604,7 +603,7 @@ describe('tabs', () => { h(BTab, { props: { title: 'three', disabled: false } }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -649,13 +648,13 @@ describe('tabs', () => { }) it('tab title slots are reactive', async () => { - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 2 } }, [ h(BTab, { props: { title: 'original' } }, 'tab content') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -686,7 +685,7 @@ describe('tabs', () => { it('"active-nav-item-class" is applied to active nav item', async () => { const activeNavItemClass = 'text-success' - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 0, activeNavItemClass } }, [ h(BTab, { props: {} }, 'tab 0'), @@ -694,7 +693,7 @@ describe('tabs', () => { h(BTab, { props: {} }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() @@ -727,7 +726,7 @@ describe('tabs', () => { it('"active-tab-class" is applied to active tab', async () => { const activeTabClass = 'text-success' - const App = Vue.extend({ + const App = { render(h) { return h(BTabs, { props: { value: 0, activeTabClass } }, [ h(BTab, { props: {} }, 'tab 0'), @@ -735,7 +734,7 @@ describe('tabs', () => { h(BTab, { props: {} }, 'tab 2') ]) } - }) + } const wrapper = mount(App) expect(wrapper).toBeDefined() From 4c067867b921b2bb377ef0c396f9be04c490c0c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:54:27 +0200 Subject: [PATCH 08/17] Update click-out.spec.js --- src/mixins/click-out.spec.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mixins/click-out.spec.js b/src/mixins/click-out.spec.js index 4dab3faa9f6..6c1fe677c20 100644 --- a/src/mixins/click-out.spec.js +++ b/src/mixins/click-out.spec.js @@ -1,12 +1,12 @@ -import Vue from 'vue' -import { mount } from '@vue/test-utils' +import { createLocalVue, mount } from '@vue/test-utils' import { createContainer, waitNT } from '../../tests/utils' import clickOutMixin from './click-out' describe('utils/click-out', () => { it('works', async () => { let count = 0 - const App = Vue.extend({ + const localVue = createLocalVue() + const App = localVue.extend({ mixins: [clickOutMixin], // `listenForClickOut` comes from the mixin data created() { @@ -23,7 +23,8 @@ describe('utils/click-out', () => { }) const wrapper = mount(App, { - attachTo: createContainer() + attachTo: createContainer(), + localVue }) const clickEvt = new MouseEvent('click') From 1a9bab147ef299d4350d34c89d602468750a824c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:54:33 +0200 Subject: [PATCH 09/17] Update focus-in.spec.js --- src/mixins/focus-in.spec.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mixins/focus-in.spec.js b/src/mixins/focus-in.spec.js index 2599232492b..267f45da35b 100644 --- a/src/mixins/focus-in.spec.js +++ b/src/mixins/focus-in.spec.js @@ -1,12 +1,12 @@ -import Vue from 'vue' -import { mount } from '@vue/test-utils' +import { createLocalVue, mount } from '@vue/test-utils' import { createContainer, waitNT } from '../../tests/utils' import focusInMixin from './focus-in' describe('utils/focus-in', () => { it('works', async () => { let count = 0 - const App = Vue.extend({ + const localVue = createLocalVue() + const App = localVue.extend({ mixins: [focusInMixin], // listenForFocusIn comes from the mixin created() { @@ -23,7 +23,8 @@ describe('utils/focus-in', () => { }) const wrapper = mount(App, { - attachTo: createContainer() + attachTo: createContainer(), + localVue }) const focusinEvt = new FocusEvent('focusin') From af260729d09e302a694fcb0724beab1594b9dbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 20:54:37 +0200 Subject: [PATCH 10/17] Update dom.spec.js --- src/utils/dom.spec.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/utils/dom.spec.js b/src/utils/dom.spec.js index 08ebc01884e..34397d6ec97 100644 --- a/src/utils/dom.spec.js +++ b/src/utils/dom.spec.js @@ -1,4 +1,3 @@ -import Vue from 'vue' import { mount } from '@vue/test-utils' import { createContainer } from '../../tests/utils' import { @@ -26,8 +25,7 @@ const template = ` ` - -const App = Vue.extend({ template }) +const App = { template } describe('utils/dom', () => { it('isElement() works', async () => { From 3d40929a0397164c33ee17f8845c36446b5fc7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 12 May 2020 23:13:23 +0200 Subject: [PATCH 11/17] fix: ensure all intervals/timeouts/observers are cleared --- src/components/carousel/carousel.js | 78 ++++++++++++++++++----------- src/components/modal/modal.js | 33 ++++++------ src/components/tabs/tabs.js | 17 +++---- 3 files changed, 73 insertions(+), 55 deletions(-) diff --git a/src/components/carousel/carousel.js b/src/components/carousel/carousel.js index 775456cc7a6..f5b98b7ce8c 100644 --- a/src/components/carousel/carousel.js +++ b/src/components/carousel/carousel.js @@ -205,9 +205,10 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ }, created() { // Create private non-reactive props - this._intervalId = null - this._animationTimeout = null - this._touchTimeout = null + this._bvInterval = null + this._bvAnimationTimeout = null + this._bvTouchTimeout = null + this._bvObserver = null // Set initial paused state this.isPaused = !(toInteger(this.interval, 0) > 0) }, @@ -217,22 +218,47 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ // Get all slides this.updateSlides() // Observe child changes so we can update slide list - observeDom(this.$refs.inner, this.updateSlides.bind(this), { - subtree: false, - childList: true, - attributes: true, - attributeFilter: ['id'] - }) + this.setObserver() }, beforeDestroy() { - clearTimeout(this._animationTimeout) - clearTimeout(this._touchTimeout) - clearInterval(this._intervalId) - this._intervalId = null - this._animationTimeout = null - this._touchTimeout = null + this.clearInterval() + this.clearAnimationTimeout() + this.clearTouchTimeout() + this.setObserver(false) }, methods: { + clearInterval() { + if (this._bvInterval) { + clearInterval(this._bvInterval) + this._bvInterval = null + } + }, + clearAnimationTimeout() { + if (this._bvAnimationTimeout) { + clearTimeout(this._bvAnimationTimeout) + this._bvAnimationTimeout = null + } + }, + clearTouchTimeout() { + if (this._bvTouchTimeout) { + clearTimeout(this._bvTouchTimeout) + this._bvTouchTimeout = null + } + }, + setObserver(on = false) { + if (this._bvObserver) { + this._bvObserver.disconnect() + this._bvObserver = null + } + if (on) { + this._bvObserver = observeDom(this.$refs.inner, this.updateSlides.bind(this), { + subtree: false, + childList: true, + attributes: true, + attributeFilter: ['id'] + }) + } + }, // Set slide setSlide(slide, direction = null) { // Don't animate when page is not visible @@ -286,10 +312,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ if (!evt) { this.isPaused = true } - if (this._intervalId) { - clearInterval(this._intervalId) - this._intervalId = null - } + this.clearInterval() }, // Start auto rotate slides start(evt) { @@ -297,13 +320,10 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ this.isPaused = false } /* istanbul ignore next: most likely will never happen, but just in case */ - if (this._intervalId) { - clearInterval(this._intervalId) - this._intervalId = null - } + this.clearInterval() // Don't start if no interval, or less than 2 slides if (this.interval && this.numSlides > 1) { - this._intervalId = setInterval(this.next, mathMax(1000, this.interval)) + this._bvInterval = setInterval(this.next, mathMax(1000, this.interval)) } }, // Restart auto rotate slides when focus/hover leaves the carousel @@ -362,7 +382,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ eventOff(currentSlide, evt, onceTransEnd, EVENT_OPTIONS_NO_CAPTURE) ) } - this._animationTimeout = null + this.clearAnimationTimeout() removeClass(nextSlide, dirClass) removeClass(nextSlide, overlayClass) addClass(nextSlide, 'active') @@ -387,7 +407,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ ) } // Fallback to setTimeout() - this._animationTimeout = setTimeout(onceTransEnd, TRANS_DURATION) + this._bvAnimationTimeout = setTimeout(onceTransEnd, TRANS_DURATION) } if (isCycling) { this.start(false) @@ -480,10 +500,8 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ // is NOT fired) and after a timeout (to allow for mouse compatibility // events to fire) we explicitly restart cycling this.pause(false) - if (this._touchTimeout) { - clearTimeout(this._touchTimeout) - } - this._touchTimeout = setTimeout( + this.clearTouchTimeout() + this._bvTouchTimeout = setTimeout( this.start, TOUCH_EVENT_COMPAT_WAIT + mathMax(1000, this.interval) ) diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js index a2363652ec4..e5cbddf1202 100644 --- a/src/components/modal/modal.js +++ b/src/components/modal/modal.js @@ -450,7 +450,7 @@ export const BModal = /*#__PURE__*/ Vue.extend({ }, created() { // Define non-reactive properties - this._observer = null + this._bvObserver = null }, mounted() { // Set initial z-index as queried from the DOM @@ -470,10 +470,7 @@ export const BModal = /*#__PURE__*/ Vue.extend({ }, beforeDestroy() { // Ensure everything is back to normal - if (this._observer) { - this._observer.disconnect() - this._observer = null - } + this.setObserver(false) if (this.isVisible) { this.isVisible = false this.isShow = false @@ -481,6 +478,19 @@ export const BModal = /*#__PURE__*/ Vue.extend({ } }, methods: { + setObserver(on = false) { + if (this._bvObserver) { + this._bvObserver.disconnect() + this._bvObserver = null + } + if (on) { + this._bvObserver = observeDom( + this.$refs.content, + this.checkModalOverflow.bind(this), + OBSERVER_CONFIG + ) + } + }, // Private method to update the v-model updateModel(val) { if (val !== this.visible) { @@ -562,10 +572,7 @@ export const BModal = /*#__PURE__*/ Vue.extend({ return } // Stop observing for content changes - if (this._observer) { - this._observer.disconnect() - this._observer = null - } + this.setObserver(false) // Trigger the hide transition this.isVisible = false // Update the v-model @@ -615,13 +622,9 @@ export const BModal = /*#__PURE__*/ Vue.extend({ // Update the v-model this.updateModel(true) this.$nextTick(() => { - // In a nextTick in case modal content is lazy // Observe changes in modal content and adjust if necessary - this._observer = observeDom( - this.$refs.content, - this.checkModalOverflow.bind(this), - OBSERVER_CONFIG - ) + // In a `$nextTick()` in case modal content is lazy + this.setObserver() }) }) }, diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index eb53b56c435..3c0c2660e47 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -312,8 +312,9 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ } }, created() { - this.currentTab = toInteger(this.value, -1) + // Create private non-reactive props this._bvObserver = null + this.currentTab = toInteger(this.value, -1) // For SSR and to make sure only a single tab is shown on mount // We wrap this in a `$nextTick()` to ensure the child tabs have been created this.$nextTick(() => { @@ -362,11 +363,13 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ unregisterTab(tab) { this.registeredTabs = this.registeredTabs.slice().filter(t => t !== tab) }, + // DOM observer is needed to detect changes in order of tabs setObserver(on) { - // DOM observer is needed to detect changes in order of tabs + if (this._bvObserver) { + this._bvObserver.disconnect() + this._bvObserver = null + } if (on) { - // Make sure no existing observer running - this.setObserver(false) const self = this /* istanbul ignore next: difficult to test mutation observer in JSDOM */ const handler = () => { @@ -385,12 +388,6 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ attributes: true, attributeFilter: ['id'] }) - } else { - /* istanbul ignore next */ - if (this._bvObserver && this._bvObserver.disconnect) { - this._bvObserver.disconnect() - } - this._bvObserver = null } }, getTabs() { From d7f239aff981bc49026dca3d96a6edad4cb89a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Wed, 13 May 2020 02:17:33 +0200 Subject: [PATCH 12/17] Unify variable name for non-reactive properties --- src/components/carousel/carousel.js | 40 +++++++++---------- src/components/modal/modal.js | 10 ++--- .../table/helpers/mixin-filtering.js | 2 +- src/components/tabs/tabs.js | 10 ++--- src/components/tooltip/tooltip.js | 30 +++++++------- src/mixins/dropdown.js | 2 +- src/mixins/form-text.js | 3 +- src/utils/transporter.js | 27 +++++++------ 8 files changed, 63 insertions(+), 61 deletions(-) diff --git a/src/components/carousel/carousel.js b/src/components/carousel/carousel.js index f5b98b7ce8c..d9e6ea98437 100644 --- a/src/components/carousel/carousel.js +++ b/src/components/carousel/carousel.js @@ -205,10 +205,10 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ }, created() { // Create private non-reactive props - this._bvInterval = null - this._bvAnimationTimeout = null - this._bvTouchTimeout = null - this._bvObserver = null + this.$_interval = null + this.$_animationTimeout = null + this.$_touchTimeout = null + this.$_observer = null // Set initial paused state this.isPaused = !(toInteger(this.interval, 0) > 0) }, @@ -228,30 +228,30 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ }, methods: { clearInterval() { - if (this._bvInterval) { - clearInterval(this._bvInterval) - this._bvInterval = null + if (this.$_interval) { + clearInterval(this.$_interval) + this.$_interval = null } }, clearAnimationTimeout() { - if (this._bvAnimationTimeout) { - clearTimeout(this._bvAnimationTimeout) - this._bvAnimationTimeout = null + if (this.$_animationTimeout) { + clearTimeout(this.$_animationTimeout) + this.$_animationTimeout = null } }, clearTouchTimeout() { - if (this._bvTouchTimeout) { - clearTimeout(this._bvTouchTimeout) - this._bvTouchTimeout = null + if (this.$_touchTimeout) { + clearTimeout(this.$_touchTimeout) + this.$_touchTimeout = null } }, setObserver(on = false) { - if (this._bvObserver) { - this._bvObserver.disconnect() - this._bvObserver = null + if (this.$_observer) { + this.$_observer.disconnect() + this.$_observer = null } if (on) { - this._bvObserver = observeDom(this.$refs.inner, this.updateSlides.bind(this), { + this.$_observer = observeDom(this.$refs.inner, this.updateSlides.bind(this), { subtree: false, childList: true, attributes: true, @@ -323,7 +323,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ this.clearInterval() // Don't start if no interval, or less than 2 slides if (this.interval && this.numSlides > 1) { - this._bvInterval = setInterval(this.next, mathMax(1000, this.interval)) + this.$_interval = setInterval(this.next, mathMax(1000, this.interval)) } }, // Restart auto rotate slides when focus/hover leaves the carousel @@ -407,7 +407,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ ) } // Fallback to setTimeout() - this._bvAnimationTimeout = setTimeout(onceTransEnd, TRANS_DURATION) + this.$_animationTimeout = setTimeout(onceTransEnd, TRANS_DURATION) } if (isCycling) { this.start(false) @@ -501,7 +501,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ // events to fire) we explicitly restart cycling this.pause(false) this.clearTouchTimeout() - this._bvTouchTimeout = setTimeout( + this.$_touchTimeout = setTimeout( this.start, TOUCH_EVENT_COMPAT_WAIT + mathMax(1000, this.interval) ) diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js index e5cbddf1202..88c31a6ef63 100644 --- a/src/components/modal/modal.js +++ b/src/components/modal/modal.js @@ -450,7 +450,7 @@ export const BModal = /*#__PURE__*/ Vue.extend({ }, created() { // Define non-reactive properties - this._bvObserver = null + this.$_observer = null }, mounted() { // Set initial z-index as queried from the DOM @@ -479,12 +479,12 @@ export const BModal = /*#__PURE__*/ Vue.extend({ }, methods: { setObserver(on = false) { - if (this._bvObserver) { - this._bvObserver.disconnect() - this._bvObserver = null + if (this.$_observer) { + this.$_observer.disconnect() + this.$_observer = null } if (on) { - this._bvObserver = observeDom( + this.$_observer = observeDom( this.$refs.content, this.checkModalOverflow.bind(this), OBSERVER_CONFIG diff --git a/src/components/table/helpers/mixin-filtering.js b/src/components/table/helpers/mixin-filtering.js index 2e1d5b36195..0032b098e42 100644 --- a/src/components/table/helpers/mixin-filtering.js +++ b/src/components/table/helpers/mixin-filtering.js @@ -155,7 +155,7 @@ export default { } }, created() { - // Create non-reactive prop where we store the debounce timer id + // Create private non-reactive props this.$_filterTimer = null // If filter is "pre-set", set the criteria // This will trigger any watchers/dependents diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index 3c0c2660e47..818fc117f07 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -313,7 +313,7 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ }, created() { // Create private non-reactive props - this._bvObserver = null + this.$_observer = null this.currentTab = toInteger(this.value, -1) // For SSR and to make sure only a single tab is shown on mount // We wrap this in a `$nextTick()` to ensure the child tabs have been created @@ -365,9 +365,9 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ }, // DOM observer is needed to detect changes in order of tabs setObserver(on) { - if (this._bvObserver) { - this._bvObserver.disconnect() - this._bvObserver = null + if (this.$_observer) { + this.$_observer.disconnect() + this.$_observer = null } if (on) { const self = this @@ -382,7 +382,7 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ }) } // Watch for changes to sub components - this._bvObserver = observeDom(this.$refs.tabsContainer, handler, { + this.$_observer = observeDom(this.$refs.tabsContainer, handler, { childList: true, subtree: false, attributes: true, diff --git a/src/components/tooltip/tooltip.js b/src/components/tooltip/tooltip.js index 512b38625d1..a6d4d441f0b 100644 --- a/src/components/tooltip/tooltip.js +++ b/src/components/tooltip/tooltip.js @@ -144,12 +144,12 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ }, watch: { show(show, oldVal) { - if (show !== oldVal && show !== this.localShow && this.$_bv_toolpop) { + if (show !== oldVal && show !== this.localShow && this.$_toolpop) { if (show) { - this.$_bv_toolpop.show() + this.$_toolpop.show() } else { // We use `forceHide()` to override any active triggers - this.$_bv_toolpop.forceHide() + this.$_toolpop.forceHide() } } }, @@ -166,8 +166,8 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ }, templateData() { this.$nextTick(() => { - if (this.$_bv_toolpop) { - this.$_bv_toolpop.updateData(this.templateData) + if (this.$_toolpop) { + this.$_toolpop.updateData(this.templateData) } }) }, @@ -177,8 +177,8 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ } }, created() { - // Non reactive properties - this.$_bv_toolpop = null + // Create private non-reactive props + this.$_toolpop = null }, updated() { // Update the `propData` object @@ -192,8 +192,8 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ this.$off('disable', this.doDisable) this.$off('enable', this.doEnable) // Destroy the tip instance - this.$_bv_toolpop && this.$_bv_toolpop.$destroy() - this.$_bv_toolpop = null + this.$_toolpop && this.$_toolpop.$destroy() + this.$_toolpop = null }, mounted() { // Instantiate a new BVTooltip instance @@ -207,7 +207,7 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ // Pass down the scoped style attribute if available const scopeId = getScopId(this) || getScopId(this.$parent) // Create the instance - const $toolpop = (this.$_bv_toolpop = new Component({ + const $toolpop = (this.$_toolpop = new Component({ parent: this, // Pass down the scoped style ID _scopeId: scopeId || undefined @@ -236,7 +236,7 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ this.$on('enable', this.doEnable) // Initially show tooltip? if (this.localShow) { - this.$_bv_toolpop && this.$_bv_toolpop.show() + this.$_toolpop && this.$_toolpop.show() } }) }, @@ -307,16 +307,16 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ }, // --- Local event listeners --- doOpen() { - !this.localShow && this.$_bv_toolpop && this.$_bv_toolpop.show() + !this.localShow && this.$_toolpop && this.$_toolpop.show() }, doClose() { - this.localShow && this.$_bv_toolpop && this.$_bv_toolpop.hide() + this.localShow && this.$_toolpop && this.$_toolpop.hide() }, doDisable() { - this.$_bv_toolpop && this.$_bv_toolpop.disable() + this.$_toolpop && this.$_toolpop.disable() }, doEnable() { - this.$_bv_toolpop && this.$_bv_toolpop.enable() + this.$_toolpop && this.$_toolpop.enable() } }, render(h) { diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js index cc92f840b6c..a73fc202631 100644 --- a/src/mixins/dropdown.js +++ b/src/mixins/dropdown.js @@ -169,7 +169,7 @@ export default { } }, created() { - // Create non-reactive property + // Create private non-reactive props this.$_popper = null }, /* istanbul ignore next */ diff --git a/src/mixins/form-text.js b/src/mixins/form-text.js index cc30ea4cdac..387ffed7aaa 100644 --- a/src/mixins/form-text.js +++ b/src/mixins/form-text.js @@ -118,8 +118,9 @@ export default { } }, mounted() { - // Create non-reactive property and set up destroy handler + // Create private non-reactive props this.$_inputDebounceTimer = null + // Set up destroy handler this.$on('hook:beforeDestroy', this.clearDebounce) // Preset the internal state const value = this.value diff --git a/src/utils/transporter.js b/src/utils/transporter.js index cfabaed40cd..d5e6352041a 100644 --- a/src/utils/transporter.js +++ b/src/utils/transporter.js @@ -88,8 +88,9 @@ export const BTransporterSingle = /*#__PURE__*/ Vue.extend({ } }, created() { - this._bv_defaultFn = null - this._bv_target = null + // Create private non-reactive props + this.$_defaultFn = null + this.$_target = null }, beforeMount() { this.mountTarget() @@ -105,7 +106,7 @@ export const BTransporterSingle = /*#__PURE__*/ Vue.extend({ }, beforeDestroy() { this.unmountTarget() - this._bv_defaultFn = null + this.$_defaultFn = null }, methods: { // Get the element which the target should be appended to @@ -120,12 +121,12 @@ export const BTransporterSingle = /*#__PURE__*/ Vue.extend({ }, // Mount the target mountTarget() { - if (!this._bv_target) { + if (!this.$_target) { const container = this.getContainer() if (container) { const el = document.createElement('div') container.appendChild(el) - this._bv_target = new BTransporterTargetSingle({ + this.$_target = new BTransporterTargetSingle({ el, parent: this, propsData: { @@ -138,29 +139,29 @@ export const BTransporterSingle = /*#__PURE__*/ Vue.extend({ }, // Update the content of the target updateTarget() { - if (isBrowser && this._bv_target) { + if (isBrowser && this.$_target) { const defaultFn = this.$scopedSlots.default if (!this.disabled) { /* istanbul ignore else: only applicable in Vue 2.5.x */ - if (defaultFn && this._bv_defaultFn !== defaultFn) { + if (defaultFn && this.$_defaultFn !== defaultFn) { // We only update the target component if the scoped slot // function is a fresh one. The new slot syntax (since Vue 2.6) // can cache unchanged slot functions and we want to respect that here - this._bv_target.updatedNodes = defaultFn + this.$_target.updatedNodes = defaultFn } else if (!defaultFn) { // We also need to be back compatible with non-scoped default slot (i.e. 2.5.x) - this._bv_target.updatedNodes = this.$slots.default + this.$_target.updatedNodes = this.$slots.default } } // Update the scoped slot function cache - this._bv_defaultFn = defaultFn + this.$_defaultFn = defaultFn } }, // Unmount the target unmountTarget() { - if (this._bv_target) { - this._bv_target.$destroy() - this._bv_target = null + if (this.$_target) { + this.$_target.$destroy() + this.$_target = null } } }, From 917662d1d6338c44ae2c13f2704539eb3fc2e81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Wed, 13 May 2020 12:11:17 +0200 Subject: [PATCH 13/17] Shave off some bytes --- src/components/carousel/carousel.js | 24 +++++++------------ .../form-spinbutton/form-spinbutton.js | 2 ++ src/components/modal/modal.js | 6 ++--- .../table/helpers/mixin-filtering.js | 13 +++++----- src/components/tabs/tabs.js | 6 ++--- src/components/tooltip/helpers/bv-popper.js | 10 ++++---- src/components/tooltip/helpers/bv-tooltip.js | 14 ++++------- src/components/tooltip/tooltip.js | 8 ++++--- src/directives/scrollspy/scrollspy.class.js | 22 +++++++---------- src/directives/visible/visible.js | 10 +++----- src/mixins/dropdown.js | 10 ++++---- src/mixins/form-text.js | 4 +++- src/utils/transporter.js | 6 ++--- 13 files changed, 57 insertions(+), 78 deletions(-) diff --git a/src/components/carousel/carousel.js b/src/components/carousel/carousel.js index d9e6ea98437..6bc5a6badbe 100644 --- a/src/components/carousel/carousel.js +++ b/src/components/carousel/carousel.js @@ -228,28 +228,20 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ }, methods: { clearInterval() { - if (this.$_interval) { - clearInterval(this.$_interval) - this.$_interval = null - } + clearInterval(this.$_interval) + this.$_interval = null }, clearAnimationTimeout() { - if (this.$_animationTimeout) { - clearTimeout(this.$_animationTimeout) - this.$_animationTimeout = null - } + clearTimeout(this.$_animationTimeout) + this.$_animationTimeout = null }, clearTouchTimeout() { - if (this.$_touchTimeout) { - clearTimeout(this.$_touchTimeout) - this.$_touchTimeout = null - } + clearTimeout(this.$_touchTimeout) + this.$_touchTimeout = null }, setObserver(on = false) { - if (this.$_observer) { - this.$_observer.disconnect() - this.$_observer = null - } + this.$_observer && this.$_observer.disconnect() + this.$_observer = null if (on) { this.$_observer = observeDom(this.$refs.inner, this.updateSlides.bind(this), { subtree: false, diff --git a/src/components/form-spinbutton/form-spinbutton.js b/src/components/form-spinbutton/form-spinbutton.js index 47ba175c8f0..54ccbd3a209 100644 --- a/src/components/form-spinbutton/form-spinbutton.js +++ b/src/components/form-spinbutton/form-spinbutton.js @@ -466,6 +466,8 @@ export const BFormSpinbutton = /*#__PURE__*/ Vue.extend({ resetTimers() { clearTimeout(this.$_autoDelayTimer) clearInterval(this.$_autoRepeatTimer) + this.$_autoDelayTimer = null + this.$_autoRepeatTimer = null }, clearRepeat() { this.resetTimers() diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js index 88c31a6ef63..06dcd4b44e3 100644 --- a/src/components/modal/modal.js +++ b/src/components/modal/modal.js @@ -479,10 +479,8 @@ export const BModal = /*#__PURE__*/ Vue.extend({ }, methods: { setObserver(on = false) { - if (this.$_observer) { - this.$_observer.disconnect() - this.$_observer = null - } + this.$_observer && this.$_observer.disconnect() + this.$_observer = null if (on) { this.$_observer = observeDom( this.$refs.content, diff --git a/src/components/table/helpers/mixin-filtering.js b/src/components/table/helpers/mixin-filtering.js index 0032b098e42..deb4646bec6 100644 --- a/src/components/table/helpers/mixin-filtering.js +++ b/src/components/table/helpers/mixin-filtering.js @@ -101,8 +101,7 @@ export default { // Watch for debounce being set to 0 computedFilterDebounce(newVal) { if (!newVal && this.$_filterTimer) { - clearTimeout(this.$_filterTimer) - this.$_filterTimer = null + this.clearFilterTimer() this.localFilter = this.filterSanitize(this.filter) } }, @@ -113,8 +112,7 @@ export default { deep: true, handler(newCriteria) { const timeout = this.computedFilterDebounce - clearTimeout(this.$_filterTimer) - this.$_filterTimer = null + this.clearFilterTimer() if (timeout && timeout > 0) { // If we have a debounce time, delay the update of `localFilter` this.$_filterTimer = setTimeout(() => { @@ -167,10 +165,13 @@ export default { }) }, beforeDestroy() /* istanbul ignore next */ { - clearTimeout(this.$_filterTimer) - this.$_filterTimer = null + this.clearFilterTimer() }, methods: { + clearFilterTimer() { + clearTimeout(this.$_filterTimer) + this.$_filterTimer = null + }, filterSanitize(criteria) { // Sanitizes filter criteria based on internal or external filtering if ( diff --git a/src/components/tabs/tabs.js b/src/components/tabs/tabs.js index 818fc117f07..75008b57eab 100644 --- a/src/components/tabs/tabs.js +++ b/src/components/tabs/tabs.js @@ -365,10 +365,8 @@ export const BTabs = /*#__PURE__*/ Vue.extend({ }, // DOM observer is needed to detect changes in order of tabs setObserver(on) { - if (this.$_observer) { - this.$_observer.disconnect() - this.$_observer = null - } + this.$_observer && this.$_observer.disconnect() + this.$_observer = null if (on) { const self = this /* istanbul ignore next: difficult to test mutation observer in JSDOM */ diff --git a/src/components/tooltip/helpers/bv-popper.js b/src/components/tooltip/helpers/bv-popper.js index a1360184c50..2cace4baa7b 100644 --- a/src/components/tooltip/helpers/bv-popper.js +++ b/src/components/tooltip/helpers/bv-popper.js @@ -157,10 +157,10 @@ export const BVPopper = /*#__PURE__*/ Vue.extend({ updated() { // Update popper if needed // TODO: Should this be a watcher on `this.popperConfig` instead? - this.popperUpdate() + this.updatePopper() }, beforeDestroy() { - this.popperDestroy() + this.destroyPopper() }, destroyed() { // Make sure template is removed from DOM @@ -198,16 +198,16 @@ export const BVPopper = /*#__PURE__*/ Vue.extend({ return this.offset }, popperCreate(el) { - this.popperDestroy() + this.destroyPopper() // We use `el` rather than `this.$el` just in case the original // mountpoint root element type was changed by the template this.$_popper = new Popper(this.target, el, this.popperConfig) }, - popperDestroy() { + destroyPopper() { this.$_popper && this.$_popper.destroy() this.$_popper = null }, - popperUpdate() { + updatePopper() { this.$_popper && this.$_popper.scheduleUpdate() }, popperPlacementChange(data) { diff --git a/src/components/tooltip/helpers/bv-tooltip.js b/src/components/tooltip/helpers/bv-tooltip.js index c7800d74b60..656dbfca221 100644 --- a/src/components/tooltip/helpers/bv-tooltip.js +++ b/src/components/tooltip/helpers/bv-tooltip.js @@ -343,7 +343,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ this.clearActiveTriggers() this.localPlacementTarget = null try { - this.$_tip && this.$_tip.$destroy() + this.$_tip.$destroy() } catch {} this.$_tip = null this.removeAriaDescribedby() @@ -552,16 +552,12 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ return this.isDropdown() && target && select(DROPDOWN_OPEN_SELECTOR, target) }, clearHoverTimeout() { - if (this.$_hoverTimeout) { - clearTimeout(this.$_hoverTimeout) - this.$_hoverTimeout = null - } + clearTimeout(this.$_hoverTimeout) + this.$_hoverTimeout = null }, clearVisibilityInterval() { - if (this.$_visibleInterval) { - clearInterval(this.$_visibleInterval) - this.$_visibleInterval = null - } + clearInterval(this.$_visibleInterval) + this.$_visibleInterval = null }, clearActiveTriggers() { for (const trigger in this.activeTrigger) { diff --git a/src/components/tooltip/tooltip.js b/src/components/tooltip/tooltip.js index a6d4d441f0b..31ccc1c926a 100644 --- a/src/components/tooltip/tooltip.js +++ b/src/components/tooltip/tooltip.js @@ -192,8 +192,10 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ this.$off('disable', this.doDisable) this.$off('enable', this.doEnable) // Destroy the tip instance - this.$_toolpop && this.$_toolpop.$destroy() - this.$_toolpop = null + if (this.$_toolpop) { + this.$_toolpop.$destroy() + this.$_toolpop = null + } }, mounted() { // Instantiate a new BVTooltip instance @@ -236,7 +238,7 @@ export const BTooltip = /*#__PURE__*/ Vue.extend({ this.$on('enable', this.doEnable) // Initially show tooltip? if (this.localShow) { - this.$_toolpop && this.$_toolpop.show() + $toolpop.show() } }) }, diff --git a/src/directives/scrollspy/scrollspy.class.js b/src/directives/scrollspy/scrollspy.class.js index 65c82b382ad..4522789b4c1 100644 --- a/src/directives/scrollspy/scrollspy.class.js +++ b/src/directives/scrollspy/scrollspy.class.js @@ -134,8 +134,8 @@ class ScrollSpy /* istanbul ignore next: not easy to test */ { this.$activeTarget = null this.$scrollHeight = 0 this.$resizeTimeout = null - this.$obs_scroller = null - this.$obs_targets = null + this.$scrollerObserver = null + this.$targetsObserver = null this.$root = $root || null this.$config = null @@ -223,16 +223,12 @@ class ScrollSpy /* istanbul ignore next: not easy to test */ { setObservers(on) { // We observe both the scroller for content changes, and the target links - if (this.$obs_scroller) { - this.$obs_scroller.disconnect() - this.$obs_scroller = null - } - if (this.$obs_targets) { - this.$obs_targets.disconnect() - this.$obs_targets = null - } + this.$scrollerObserver && this.$scrollerObserver.disconnect() + this.$targetsObserver && this.$targetsObserver.disconnect() + this.$scrollerObserver = null + this.$targetsObserver = null if (on) { - this.$obs_targets = observeDom( + this.$targetsObserver = observeDom( this.$el, () => { this.handleEvent('mutation') @@ -244,7 +240,7 @@ class ScrollSpy /* istanbul ignore next: not easy to test */ { attributeFilter: ['href'] } ) - this.$obs_scroller = observeDom( + this.$scrollerObserver = observeDom( this.getScroller(), () => { this.handleEvent('mutation') @@ -276,7 +272,7 @@ class ScrollSpy /* istanbul ignore next: not easy to test */ { } if (type === 'scroll') { - if (!this.$obs_scroller) { + if (!this.$scrollerObserver) { // Just in case we are added to the DOM before the scroll target is // We re-instantiate our listeners, just in case this.listen() diff --git a/src/directives/visible/visible.js b/src/directives/visible/visible.js index ec7889f945e..68f477650b5 100644 --- a/src/directives/visible/visible.js +++ b/src/directives/visible/visible.js @@ -38,7 +38,7 @@ import { clone, keys } from '../../utils/object' const OBSERVER_PROP_NAME = '__bv__visibility_observer' -const onlyDgitsRE = /^\d+$/ +const RX_ONLY_DIGITS = /^\d+$/ class VisibilityObserver { constructor(el, options, vnode) { @@ -114,11 +114,7 @@ class VisibilityObserver { } stop() { - const observer = this.observer - /* istanbul ignore next */ - if (observer && observer.disconnect) { - observer.disconnect() - } + this.observer && this.observer.disconnect() this.observer = null } } @@ -141,7 +137,7 @@ const bind = (el, { value, modifiers }, vnode) => { // Parse modifiers keys(modifiers).forEach(mod => { /* istanbul ignore else: Until is switched to use this directive */ - if (onlyDgitsRE.test(mod)) { + if (RX_ONLY_DIGITS.test(mod)) { options.margin = `${mod}px` } else if (mod.toLowerCase() === 'once') { options.once = true diff --git a/src/mixins/dropdown.js b/src/mixins/dropdown.js index a73fc202631..2068babd9ca 100644 --- a/src/mixins/dropdown.js +++ b/src/mixins/dropdown.js @@ -236,16 +236,14 @@ export default { this.destroyPopper() this.$_popper = new Popper(element, this.$refs.menu, this.getPopperConfig()) }, + // Ensure popper event listeners are removed cleanly destroyPopper() { - // Ensure popper event listeners are removed cleanly - if (this.$_popper) { - this.$_popper.destroy() - } + this.$_popper && this.$_popper.destroy() this.$_popper = null }, + // Instructs popper to re-computes the dropdown position + // useful if the content changes size updatePopper() /* istanbul ignore next: not easy to test */ { - // Instructs popper to re-computes the dropdown position - // useful if the content changes size try { this.$_popper.scheduleUpdate() } catch {} diff --git a/src/mixins/form-text.js b/src/mixins/form-text.js index 387ffed7aaa..321dd5ef73b 100644 --- a/src/mixins/form-text.js +++ b/src/mixins/form-text.js @@ -117,9 +117,11 @@ export default { } } }, - mounted() { + created() { // Create private non-reactive props this.$_inputDebounceTimer = null + }, + mounted() { // Set up destroy handler this.$on('hook:beforeDestroy', this.clearDebounce) // Preset the internal state diff --git a/src/utils/transporter.js b/src/utils/transporter.js index d5e6352041a..c0ea07d15b9 100644 --- a/src/utils/transporter.js +++ b/src/utils/transporter.js @@ -159,10 +159,8 @@ export const BTransporterSingle = /*#__PURE__*/ Vue.extend({ }, // Unmount the target unmountTarget() { - if (this.$_target) { - this.$_target.$destroy() - this.$_target = null - } + this.$_target && this.$_target.$destroy() + this.$_target = null } }, render(h) { From 7af09ad1088b34443b8a482c7bfd5aa0066d7f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Wed, 13 May 2020 12:20:02 +0200 Subject: [PATCH 14/17] Update visible.js --- src/directives/visible/visible.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/directives/visible/visible.js b/src/directives/visible/visible.js index 68f477650b5..f17d1cc0465 100644 --- a/src/directives/visible/visible.js +++ b/src/directives/visible/visible.js @@ -114,6 +114,7 @@ class VisibilityObserver { } stop() { + /* istanbul ignore next */ this.observer && this.observer.disconnect() this.observer = null } From 1e89bc03223d6a629930ed8dafc8009f48924684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Wed, 13 May 2020 12:36:25 +0200 Subject: [PATCH 15/17] Update mixin-tbody.js --- src/components/table/helpers/mixin-tbody.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/table/helpers/mixin-tbody.js b/src/components/table/helpers/mixin-tbody.js index 6518aaf9985..2a5d4c38647 100644 --- a/src/components/table/helpers/mixin-tbody.js +++ b/src/components/table/helpers/mixin-tbody.js @@ -17,6 +17,9 @@ const props = { export default { mixins: [tbodyRowMixin], props, + beforeDestroy() { + this.$_bodyFieldSlotNameCache = null + }, methods: { // Helper methods getTbodyTrs() { From 4c0a6a0d5a6f9c90bae3e6c3185aa72b245f22e8 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Wed, 13 May 2020 22:02:04 -0300 Subject: [PATCH 16/17] Update modal.js --- src/components/modal/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js index 06dcd4b44e3..36ce83a9e2b 100644 --- a/src/components/modal/modal.js +++ b/src/components/modal/modal.js @@ -622,7 +622,7 @@ export const BModal = /*#__PURE__*/ Vue.extend({ this.$nextTick(() => { // Observe changes in modal content and adjust if necessary // In a `$nextTick()` in case modal content is lazy - this.setObserver() + this.setObserver(true) }) }) }, From 45ee85649744f6dfe72e96d2629c08491fd12066 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Wed, 13 May 2020 22:04:13 -0300 Subject: [PATCH 17/17] Update carousel.js --- src/components/carousel/carousel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/carousel/carousel.js b/src/components/carousel/carousel.js index 6bc5a6badbe..67a7ca5e534 100644 --- a/src/components/carousel/carousel.js +++ b/src/components/carousel/carousel.js @@ -218,7 +218,7 @@ export const BCarousel = /*#__PURE__*/ Vue.extend({ // Get all slides this.updateSlides() // Observe child changes so we can update slide list - this.setObserver() + this.setObserver(true) }, beforeDestroy() { this.clearInterval()