diff --git a/lib/components/Button/ButtonIcon.vue b/lib/components/Button/ButtonIcon.vue index c5468225..d271c6e3 100644 --- a/lib/components/Button/ButtonIcon.vue +++ b/lib/components/Button/ButtonIcon.vue @@ -264,8 +264,7 @@ const props = withDefaults(defineProps(), { tag: 'button', type: 'button', loadingDuration: '1s', - tooltipPlacement: 'top', - tooltipDelay: () => ({ show: 0, hide: 0 }), + // Vue defaults an absent `Boolean`-typed prop to `false` unless a default // is given explicitly. Left unset, that silently forwards `pressed: false` // to BButton, which switches it into toggle-button mode: it then flips its diff --git a/tests/unit/components/Button/ButtonIconTooltip.spec.ts b/tests/unit/components/Button/ButtonIconTooltip.spec.ts new file mode 100644 index 00000000..b024cdcd --- /dev/null +++ b/tests/unit/components/Button/ButtonIconTooltip.spec.ts @@ -0,0 +1,46 @@ +import { config, mount } from '@vue/test-utils' +import { describe, expect, it } from 'vitest' +import { BPopover, BTooltip, createBootstrap } from 'bootstrap-vue-next' +import ButtonIcon from '@/components/Button/ButtonIcon.vue' +import { i18n } from '@/i18n' + +// The props ButtonIcon actually hands to its BTooltip, as seen on the vnode. +// bootstrap-vue-next only falls back to a globally configured default when a +// prop is absent from the vnode, so anything set here is a default callers +// cannot override globally. +const tooltipVNodeProps = (props: Record) => { + const wrapper = mount(ButtonIcon, { props: { label: 'Expand', hideLabel: true, ...props } }) + return wrapper.findComponent(BTooltip).vm.$.vnode.props ?? {} +} + +describe('ButtonIcon.vue tooltip', () => { + it('leaves the delay unset so a global BTooltip default applies', () => { + expect(tooltipVNodeProps({}).delay).toBeUndefined() + }) + + it('leaves the placement unset so a global BTooltip default applies', () => { + expect(tooltipVNodeProps({}).placement).toBeUndefined() + }) + + it('still forwards an explicit delay', () => { + const delay = { show: 3000, hide: 0 } + expect(tooltipVNodeProps({ tooltipDelay: delay }).delay).toStrictEqual(delay) + }) + + it('still forwards an explicit placement', () => { + expect(tooltipVNodeProps({ tooltipPlacement: 'right' }).placement).toBe('right') + }) + + it('picks up a globally configured BTooltip delay', () => { + const delay = { show: 3000, hide: 0 } + // Swap the suite-wide bootstrap plugin rather than adding a second one, + // which Vue would reject as already applied. + const plugins = config.global.plugins + config.global.plugins = [i18n, createBootstrap({ components: { BTooltip: { delay } } })] + const wrapper = mount(ButtonIcon, { props: { label: 'Expand', hideLabel: true } }) + config.global.plugins = plugins + // BTooltip resolves the global default, then spreads the outcome onto the + // BPopover it renders, which is where the delay is finally honoured. + expect(wrapper.findComponent(BPopover).vm.$.vnode.props?.delay).toStrictEqual(delay) + }) +})