From 9387b79e2a54577f23edd2641458f3e5beb95526 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Tue, 19 May 2020 03:34:10 -0300 Subject: [PATCH 1/9] feat(v-b-toggle): check for target ID via `href` if a link --- src/directives/toggle/toggle.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index 6e34a667808..dfcbc97c178 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -57,13 +57,17 @@ const RX_SPLIT_SEPARATOR = /\s+/ const isNonStandardTag = el => !arrayIncludes(['BUTTON', 'A'], el.tagName) -const getTargets = ({ modifiers, arg, value }) => { +const getTargets = ({ modifiers, arg, value }, el) => { // Any modifiers are considered target IDs const targets = keys(modifiers || {}) // If value is a string, split out individual targets (if space delimited) value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value + if (el.tagname.toLowerCase() === 'a' && el.href && /^#\[a-zA-Z]/.test(el.href)) { + targets.push(href.replace(/^#/, '')) + } + // Add ID from `arg` (if provided), and support value // as a single string ID or an array of string IDs // If `value` is not an array or string, then it gets filtered out @@ -172,7 +176,7 @@ const handleUpdate = (el, binding, vnode) => { setToggleState(el, el[BV_TOGGLE_STATE]) // Parse list of target IDs - const targets = getTargets(binding) + const targets = getTargets(binding, el) /* istanbul ignore else */ // Ensure the `aria-controls` hasn't been overwritten From 2dd783c77c0db32342e1fcbcaf8bca9a3caa536f Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Tue, 19 May 2020 03:44:54 -0300 Subject: [PATCH 2/9] Update toggle.js --- src/directives/toggle/toggle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index dfcbc97c178..b4d3c574089 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -65,7 +65,7 @@ const getTargets = ({ modifiers, arg, value }, el) => { value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value if (el.tagname.toLowerCase() === 'a' && el.href && /^#\[a-zA-Z]/.test(el.href)) { - targets.push(href.replace(/^#/, '')) + targets.push(el.href.replace(/^#/, '')) } // Add ID from `arg` (if provided), and support value From 42ba9010bdd9c464a99c28f8f641883a227769b6 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Tue, 19 May 2020 03:52:23 -0300 Subject: [PATCH 3/9] Update toggle.js --- src/directives/toggle/toggle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index b4d3c574089..b643579ce0b 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -64,7 +64,7 @@ const getTargets = ({ modifiers, arg, value }, el) => { // If value is a string, split out individual targets (if space delimited) value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value - if (el.tagname.toLowerCase() === 'a' && el.href && /^#\[a-zA-Z]/.test(el.href)) { + if (el.tagNaame.toLowerCase() === 'a' && el.href && /^#\[a-zA-Z]/.test(el.href)) { targets.push(el.href.replace(/^#/, '')) } From edba8d84cd8a8006543fe659e3d02a7c0e8bfe9e Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Tue, 19 May 2020 03:57:35 -0300 Subject: [PATCH 4/9] Update toggle.js --- src/directives/toggle/toggle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index b643579ce0b..aca7538c5b9 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -64,7 +64,7 @@ const getTargets = ({ modifiers, arg, value }, el) => { // If value is a string, split out individual targets (if space delimited) value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value - if (el.tagNaame.toLowerCase() === 'a' && el.href && /^#\[a-zA-Z]/.test(el.href)) { + if (el.tagName && el.tagName.toLowerCase() === 'a' && el.href && /^#\[a-zA-Z]/.test(el.href)) { targets.push(el.href.replace(/^#/, '')) } From 1dd49dc482fc8a0f86a2604edff28a18827da584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 19 May 2020 09:21:30 +0200 Subject: [PATCH 5/9] Update toggle.js --- src/directives/toggle/toggle.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index b643579ce0b..8300a00e820 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -1,7 +1,15 @@ import KeyCodes from '../../utils/key-codes' import looseEqual from '../../utils/loose-equal' import { arrayIncludes, concat } from '../../utils/array' -import { addClass, hasAttr, isDisabled, removeAttr, removeClass, setAttr } from '../../utils/dom' +import { + addClass, + hasAttr, + isDisabled, + isTag, + removeAttr, + removeClass, + setAttr +} from '../../utils/dom' import { isBrowser } from '../../utils/env' import { eventOn, eventOff } from '../../utils/events' import { isString } from '../../utils/inspect' @@ -51,6 +59,8 @@ export const EVENT_STATE_REQUEST = 'bv::request::collapse::state' const KEYDOWN_KEY_CODES = [ENTER, SPACE] +const RX_HASH = /^#/ +const RX_HASH_CONTENT = /^#\[a-zA-Z]/ const RX_SPLIT_SEPARATOR = /\s+/ // --- Helper methods --- @@ -64,8 +74,8 @@ const getTargets = ({ modifiers, arg, value }, el) => { // If value is a string, split out individual targets (if space delimited) value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value - if (el.tagNaame.toLowerCase() === 'a' && el.href && /^#\[a-zA-Z]/.test(el.href)) { - targets.push(el.href.replace(/^#/, '')) + if (isTag(el.tagName, 'a') && RX_HASH_CONTENT.test(el.href || '')) { + targets.push(el.href.replace(RX_HASH, '')) } // Add ID from `arg` (if provided), and support value From 1d33ab4c4d0518c9e14007e4ac9325acc9cf529f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 19 May 2020 10:24:31 +0200 Subject: [PATCH 6/9] Update toggle.js --- src/directives/toggle/toggle.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index 8300a00e820..ed5fbcc10ce 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -3,6 +3,7 @@ import looseEqual from '../../utils/loose-equal' import { arrayIncludes, concat } from '../../utils/array' import { addClass, + getAttr, hasAttr, isDisabled, isTag, @@ -60,7 +61,7 @@ export const EVENT_STATE_REQUEST = 'bv::request::collapse::state' const KEYDOWN_KEY_CODES = [ENTER, SPACE] const RX_HASH = /^#/ -const RX_HASH_CONTENT = /^#\[a-zA-Z]/ +const RX_HASH_ID = /^#[A-Za-z]+[\w\-:.]*$/ const RX_SPLIT_SEPARATOR = /\s+/ // --- Helper methods --- @@ -74,8 +75,12 @@ const getTargets = ({ modifiers, arg, value }, el) => { // If value is a string, split out individual targets (if space delimited) value = isString(value) ? value.split(RX_SPLIT_SEPARATOR) : value - if (isTag(el.tagName, 'a') && RX_HASH_CONTENT.test(el.href || '')) { - targets.push(el.href.replace(RX_HASH, '')) + // Support target ID as link href (`href="#id"`) + if (isTag(el.tagName, 'a')) { + const href = getAttr(el, 'href') || '' + if (RX_HASH_ID.test(href)) { + targets.push(href.replace(RX_HASH, '')) + } } // Add ID from `arg` (if provided), and support value From 51bcc9b51ab78b332d33f6b1be9c1d53659c5f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 19 May 2020 10:24:38 +0200 Subject: [PATCH 7/9] Update toggle.spec.js --- src/directives/toggle/toggle.spec.js | 260 ++++++++++++++++----------- 1 file changed, 152 insertions(+), 108 deletions(-) diff --git a/src/directives/toggle/toggle.spec.js b/src/directives/toggle/toggle.spec.js index 4b5e716228b..cecf1360f85 100644 --- a/src/directives/toggle/toggle.spec.js +++ b/src/directives/toggle/toggle.spec.js @@ -31,24 +31,26 @@ describe('v-b-toggle directive', () => { expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').attributes('tabindex')).not.toBeDefined() - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') expect(spy).not.toHaveBeenCalled() const $button = wrapper.find('button') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.attributes('tabindex')).not.toBeDefined() + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') + await $button.trigger('click') expect(spy).toHaveBeenCalledTimes(1) expect(spy).toBeCalledWith('test') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').attributes('tabindex')).not.toBeDefined() - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.attributes('tabindex')).not.toBeDefined() + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') wrapper.destroy() }) @@ -72,22 +74,24 @@ describe('v-b-toggle directive', () => { expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') expect(spy).not.toHaveBeenCalled() const $button = wrapper.find('button') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') + await $button.trigger('click') expect(spy).toHaveBeenCalledTimes(1) expect(spy).toBeCalledWith('test') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') wrapper.destroy() }) @@ -111,22 +115,67 @@ describe('v-b-toggle directive', () => { expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') expect(spy).not.toHaveBeenCalled() const $button = wrapper.find('button') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') + await $button.trigger('click') expect(spy).toHaveBeenCalledTimes(1) expect(spy).toBeCalledWith('test') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') + + wrapper.destroy() + }) + + it('works on passing ID as href value on links', async () => { + const spy = jest.fn() + const App = { + directives: { + bToggle: VBToggle + }, + created() { + this.$root.$on(EVENT_TOGGLE, spy) + }, + beforeDestroy() { + this.$root.$off(EVENT_TOGGLE, spy) + }, + template: 'link' + } + + const wrapper = mount(App) + + expect(wrapper.vm).toBeDefined() + expect(wrapper.element.tagName).toBe('A') + expect(spy).not.toHaveBeenCalled() + + const $link = wrapper.find('a') + expect($link.attributes('aria-controls')).toBe('test') + expect($link.attributes('aria-expanded')).toBe('false') + expect($link.attributes('tabindex')).not.toBeDefined() + expect($link.classes()).toContain('collapsed') + expect($link.classes()).not.toContain('not-collapsed') + + await $link.trigger('click') + expect(spy).toHaveBeenCalledTimes(1) + expect(spy).toBeCalledWith('test') + + // Since there is no target collapse to respond with the + // current state, the classes and attrs remain the same + expect($link.attributes('aria-controls')).toBe('test') + expect($link.attributes('aria-expanded')).toBe('false') + expect($link.attributes('tabindex')).not.toBeDefined() + expect($link.classes()).toContain('collapsed') + expect($link.classes()).not.toContain('not-collapsed') wrapper.destroy() }) @@ -160,19 +209,15 @@ describe('v-b-toggle directive', () => { expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') + expect(spy).not.toHaveBeenCalled() const $button = wrapper.find('button') - expect($button.attributes('aria-controls')).toBe('test1') expect($button.attributes('aria-expanded')).toBe('false') expect($button.classes()).toContain('collapsed') expect($button.classes()).not.toContain('not-collapsed') - expect(spy).not.toHaveBeenCalled() - - await wrapper.setProps({ - target: ['test1', 'test2'] - }) + await wrapper.setProps({ target: ['test1', 'test2'] }) expect($button.attributes('aria-controls')).toBe('test1 test2') expect($button.attributes('aria-expanded')).toBe('false') expect($button.classes()).toContain('collapsed') @@ -180,10 +225,10 @@ describe('v-b-toggle directive', () => { expect(spy).not.toHaveBeenCalled() await $button.trigger('click') - expect(spy).toHaveBeenCalledTimes(2) expect(spy).toHaveBeenNthCalledWith(1, 'test1') expect(spy).toHaveBeenNthCalledWith(2, 'test2') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same expect($button.attributes('aria-controls')).toBe('test1 test2') @@ -191,10 +236,7 @@ describe('v-b-toggle directive', () => { expect($button.classes()).toContain('collapsed') expect($button.classes()).not.toContain('not-collapsed') - await wrapper.setProps({ - target: ['test2'] - }) - + await wrapper.setProps({ target: ['test2'] }) expect($button.attributes('aria-controls')).toBe('test2') expect($button.attributes('aria-expanded')).toBe('false') expect($button.classes()).toContain('collapsed') @@ -202,9 +244,9 @@ describe('v-b-toggle directive', () => { expect(spy).toHaveBeenCalledTimes(2) await $button.trigger('click') - expect(spy).toHaveBeenCalledTimes(3) expect(spy).toHaveBeenNthCalledWith(3, 'test2') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same expect($button.attributes('aria-controls')).toBe('test2') @@ -240,66 +282,69 @@ describe('v-b-toggle directive', () => { expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('SPAN') expect(spy).not.toHaveBeenCalled() - expect(wrapper.find('span').attributes('role')).toBe('button') - expect(wrapper.find('span').attributes('tabindex')).toBe('0') - expect(wrapper.find('span').attributes('aria-controls')).toBe('test') - expect(wrapper.find('span').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('span').classes()).toContain('collapsed') - expect(wrapper.find('span').classes()).not.toContain('not-collapsed') - expect(wrapper.find('span').text()).toBe('span') const $span = wrapper.find('span') + expect($span.attributes('role')).toBe('button') + expect($span.attributes('tabindex')).toBe('0') + expect($span.attributes('aria-controls')).toBe('test') + expect($span.attributes('aria-expanded')).toBe('false') + expect($span.classes()).toContain('collapsed') + expect($span.classes()).not.toContain('not-collapsed') + expect($span.text()).toBe('span') + await $span.trigger('click') expect(spy).toHaveBeenCalledTimes(1) expect(spy).toBeCalledWith('test') - expect(wrapper.find('span').attributes('role')).toBe('button') - expect(wrapper.find('span').attributes('tabindex')).toBe('0') + expect($span.attributes('role')).toBe('button') + expect($span.attributes('tabindex')).toBe('0') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same - expect(wrapper.find('span').attributes('aria-controls')).toBe('test') - expect(wrapper.find('span').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('span').classes()).toContain('collapsed') - expect(wrapper.find('span').classes()).not.toContain('not-collapsed') + expect($span.attributes('aria-controls')).toBe('test') + expect($span.attributes('aria-expanded')).toBe('false') + expect($span.classes()).toContain('collapsed') + expect($span.classes()).not.toContain('not-collapsed') // Reacts to SPACE keypress await $span.trigger('keydown.space') expect(spy).toHaveBeenCalledTimes(2) expect(spy).toBeCalledWith('test') - expect(wrapper.find('span').attributes('role')).toBe('button') - expect(wrapper.find('span').attributes('tabindex')).toBe('0') + expect($span.attributes('role')).toBe('button') + expect($span.attributes('tabindex')).toBe('0') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same - expect(wrapper.find('span').attributes('aria-controls')).toBe('test') - expect(wrapper.find('span').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('span').classes()).toContain('collapsed') - expect(wrapper.find('span').classes()).not.toContain('not-collapsed') + expect($span.attributes('aria-controls')).toBe('test') + expect($span.attributes('aria-expanded')).toBe('false') + expect($span.classes()).toContain('collapsed') + expect($span.classes()).not.toContain('not-collapsed') // Reacts to ENTER keypress await $span.trigger('keydown.enter') expect(spy).toHaveBeenCalledTimes(3) expect(spy).toBeCalledWith('test') - expect(wrapper.find('span').attributes('role')).toBe('button') - expect(wrapper.find('span').attributes('tabindex')).toBe('0') + expect($span.attributes('role')).toBe('button') + expect($span.attributes('tabindex')).toBe('0') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same - expect(wrapper.find('span').attributes('aria-controls')).toBe('test') - expect(wrapper.find('span').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('span').classes()).toContain('collapsed') - expect(wrapper.find('span').classes()).not.toContain('not-collapsed') - - // Test updating component. should maintain role attribute - await wrapper.setData({ - text: 'foobar' - }) - expect(wrapper.find('span').text()).toBe('foobar') - expect(wrapper.find('span').attributes('role')).toBe('button') - expect(wrapper.find('span').attributes('tabindex')).toBe('0') + expect($span.attributes('aria-controls')).toBe('test') + expect($span.attributes('aria-expanded')).toBe('false') + expect($span.classes()).toContain('collapsed') + expect($span.classes()).not.toContain('not-collapsed') + + // Test updating component, should maintain role attribute + await wrapper.setData({ text: 'foobar' }) + expect($span.text()).toBe('foobar') + expect($span.attributes('role')).toBe('button') + expect($span.attributes('tabindex')).toBe('0') + // Since there is no target collapse to respond with the // current state, the classes and attrs remain the same - expect(wrapper.find('span').attributes('aria-controls')).toBe('test') - expect(wrapper.find('span').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('span').classes()).toContain('collapsed') - expect(wrapper.find('span').classes()).not.toContain('not-collapsed') + expect($span.attributes('aria-controls')).toBe('test') + expect($span.attributes('aria-expanded')).toBe('false') + expect($span.classes()).toContain('collapsed') + expect($span.classes()).not.toContain('not-collapsed') wrapper.destroy() }) @@ -316,36 +361,35 @@ describe('v-b-toggle directive', () => { expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') const $root = wrapper.vm.$root + const $button = wrapper.find('button') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') + $root.$emit(EVENT_STATE, 'test', true) await waitNT(wrapper.vm) - - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('true') - expect(wrapper.find('button').classes()).not.toContain('collapsed') - expect(wrapper.find('button').classes()).toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('true') + expect($button.classes()).not.toContain('collapsed') + expect($button.classes()).toContain('not-collapsed') $root.$emit(EVENT_STATE, 'test', false) await waitNT(wrapper.vm) - - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') $root.$emit(EVENT_STATE, 'test', true) await waitNT(wrapper.vm) - - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('true') - expect(wrapper.find('button').classes()).not.toContain('collapsed') - expect(wrapper.find('button').classes()).toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('true') + expect($button.classes()).not.toContain('collapsed') + expect($button.classes()).toContain('not-collapsed') wrapper.destroy() }) @@ -362,28 +406,28 @@ describe('v-b-toggle directive', () => { expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') const $root = wrapper.vm.$root + const $button = wrapper.find('button') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') + $root.$emit(EVENT_STATE_SYNC, 'test', true) await waitNT(wrapper.vm) - - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('true') - expect(wrapper.find('button').classes()).not.toContain('collapsed') - expect(wrapper.find('button').classes()).toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('true') + expect($button.classes()).not.toContain('collapsed') + expect($button.classes()).toContain('not-collapsed') $root.$emit(EVENT_STATE_SYNC, 'test', false) await waitNT(wrapper.vm) - - expect(wrapper.find('button').attributes('aria-controls')).toBe('test') - expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') - expect(wrapper.find('button').classes()).toContain('collapsed') - expect(wrapper.find('button').classes()).not.toContain('not-collapsed') + expect($button.attributes('aria-controls')).toBe('test') + expect($button.attributes('aria-expanded')).toBe('false') + expect($button.classes()).toContain('collapsed') + expect($button.classes()).not.toContain('not-collapsed') wrapper.destroy() }) From 0710f28fd9f9d549345fa2546e6cacdcfba8c478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Tue, 19 May 2020 10:34:10 +0200 Subject: [PATCH 8/9] Update toggle.js --- src/directives/toggle/toggle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/directives/toggle/toggle.js b/src/directives/toggle/toggle.js index ed5fbcc10ce..45a909d30d4 100644 --- a/src/directives/toggle/toggle.js +++ b/src/directives/toggle/toggle.js @@ -66,7 +66,7 @@ const RX_SPLIT_SEPARATOR = /\s+/ // --- Helper methods --- -const isNonStandardTag = el => !arrayIncludes(['BUTTON', 'A'], el.tagName) +const isNonStandardTag = el => !arrayIncludes(['button', 'a'], el.tagName.toLowerCase()) const getTargets = ({ modifiers, arg, value }, el) => { // Any modifiers are considered target IDs From 906ddf55b5b23c13d251a09e4499106e9c912b74 Mon Sep 17 00:00:00 2001 From: Troy Morehouse Date: Tue, 19 May 2020 13:55:33 -0300 Subject: [PATCH 9/9] Update README.md --- src/directives/toggle/README.md | 42 +++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/directives/toggle/README.md b/src/directives/toggle/README.md index a639933fec2..92aa0c87eac 100644 --- a/src/directives/toggle/README.md +++ b/src/directives/toggle/README.md @@ -16,7 +16,7 @@ details and caveats. ## Directive syntax and usage -The directive is applied to the element or component that triggers the visibility of hte target. The +The directive is applied to the element or component that triggers the visibility of the target. The target component can be specified (via its ID) as either a directive modifier(s), the directive argument, or as a string/array passed to as the directive value: @@ -34,7 +34,7 @@ argument, or as a string/array passed to as the directive value: Modifiers, argument, and the value can be used at the same time when targeting multiple components. -### Example usage +**Example usage:** ```html