Skip to content

feat(dropdown): use provide and inject #2431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b573816
dropdown: add in provide
tmorehouse Jan 10, 2019
a89e2ee
Update dropdown-item.js
tmorehouse Jan 10, 2019
036c534
Update dropdown-item-button.js
tmorehouse Jan 10, 2019
3d58edf
Update dropdown-item.js
tmorehouse Jan 10, 2019
777c162
Update dropdown.js
tmorehouse Jan 10, 2019
94f26c5
Update dropdown.spec.js
tmorehouse Jan 10, 2019
78906c1
Update dropdown-item-button.js
tmorehouse Jan 10, 2019
662bb6c
Update dropdown-item.js
tmorehouse Jan 10, 2019
89b5190
Create dropdown-item.spec.js
tmorehouse Jan 10, 2019
7f7d110
Update dropdown-item.spec.js
tmorehouse Jan 10, 2019
8c87902
Update dropdown-item.js
tmorehouse Jan 10, 2019
9329fd6
Update dropdown-item.js
tmorehouse Jan 10, 2019
4a84176
Update dropdown-item-button.js
tmorehouse Jan 10, 2019
c4db92e
Update dropdown-item.spec.js
tmorehouse Jan 10, 2019
3e106a4
Update dropdown-item.spec.js
tmorehouse Jan 10, 2019
2ad7650
Create dropdown-item-button.spec.js
tmorehouse Jan 10, 2019
4484f90
Update dropdown-item-button.spec.js
tmorehouse Jan 10, 2019
866fc30
debug
tmorehouse Jan 10, 2019
489fe13
Update dropdown.js
tmorehouse Jan 10, 2019
3308ca4
Update dropdown-item-button.js
tmorehouse Jan 10, 2019
e9b6377
Update dropdown-item-button.spec.js
tmorehouse Jan 10, 2019
162d1df
lint
tmorehouse Jan 10, 2019
69ac21d
lint
tmorehouse Jan 10, 2019
d6557c9
Update dropdown-item-button.spec.js
tmorehouse Jan 10, 2019
c68a5c7
Update dropdown-item.js
tmorehouse Jan 10, 2019
08af530
Update dropdown-item.spec.js
tmorehouse Jan 10, 2019
f6cdd79
Update dropdown-item.js
tmorehouse Jan 10, 2019
ebaaa6f
Update dropdown-item.spec.js
tmorehouse Jan 10, 2019
ba35d53
Update dropdown.js
tmorehouse Jan 10, 2019
e22d96e
Update nav-item-dropdown.js
tmorehouse Jan 10, 2019
c96a4d8
Update dropdown.js
tmorehouse Jan 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions src/components/dropdown/dropdown-item-button.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { mergeData } from 'vue-functional-data-merge'

export const props = {
active: {
type: Boolean,
Expand All @@ -18,23 +16,30 @@ export const props = {
// @vue/component
export default {
name: 'BDropdownItemButton',
functional: true,
inject: {
dropdown: {
from: 'dropdown',
default: null
}
},
props,
render (h, { props, data, parent, children }) {
methods: {
closeDropdown () {
if (this.dropdown) {
this.dropdown.hide(true)
}
}
},
render (h) {
return h(
'button',
mergeData(data, {
props,
{
staticClass: 'dropdown-item',
class: { [props.activeClass]: props.active },
attrs: { role: 'menuitem', type: 'button', disabled: props.disabled },
on: {
click (e) {
parent.$root.$emit('clicked::link', e)
}
}
}),
children
class: { [this.activeClass]: this.active },
attrs: { role: 'menuitem', type: 'button', disabled: this.disabled },
on: { click: this.closeDropdown }
},
this.$slots.default
)
}
}
74 changes: 74 additions & 0 deletions src/components/dropdown/dropdown-item-button.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import DropdownItemBtn from './dropdown-item-button'
import { mount } from '@vue/test-utils'

describe('dropdown-item-button', async () => {
it('renders with tag "button" and type="button" by default', async () => {
const wrapper = mount(DropdownItemBtn)
expect(wrapper.is('button')).toBe(true)
expect(wrapper.attributes('type')).toBe('button')
})

it('has class "dropdown-item"', async () => {
const wrapper = mount(DropdownItemBtn)
expect(wrapper.classes()).toContain('dropdown-item')
expect(wrapper.classes()).not.toContain('active')
})

it('has class "active" when active=true', async () => {
const wrapper = mount(DropdownItemBtn, {
propsData: { active: true }
})
expect(wrapper.classes()).toContain('active')
expect(wrapper.classes()).toContain('dropdown-item')
})

it('has attribute "disabled" when disabled=true', async () => {
const wrapper = mount(DropdownItemBtn, {
propsData: { disabled: true }
})
expect(wrapper.attributes('disabled')).toBeDefined()
})

it('calls dropdown hide(true) method when clicked', async () => {
let called = false
let refocus = null
const wrapper = mount(DropdownItemBtn, {
provide: {
dropdown: {
hide (arg) {
called = true
refocus = arg
}
}
}
})
const btn = wrapper.find('button')
expect(btn).toBeDefined()
btn.trigger('click')
await wrapper.vm.$nextTick()
expect(called).toBe(true)
expect(refocus).toBe(true)
})

it('does not call dropdown hide(true) method when clicked and disabled', async () => {
let called = false
let refocus = null
const wrapper = mount(DropdownItemBtn, {
provide: {
dropdown: {
hide (arg) {
called = true
refocus = arg
}
}
},
propsData: { disabled: true }
})
const btn = wrapper.find('button')
expect(btn).toBeDefined()
btn.trigger('click')
await wrapper.vm.$nextTick()
expect(called).toBe(false)
expect(refocus).toBe(null)
})
})
28 changes: 20 additions & 8 deletions src/components/dropdown/dropdown-item.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
import { mergeData } from 'vue-functional-data-merge'
import BLink, { propsFactory as linkPropsFactory } from '../link/link'

export const props = linkPropsFactory()

// @vue/component
export default {
name: 'BDropdownItem',
functional: true,
inject: {
dropdown: {
from: 'dropdown',
default: null
}
},
props,
render (h, { props, data, children }) {
methods: {
closeDropdown () {
if (this.dropdown) {
this.dropdown.hide(true)
}
}
},
render (h) {
return h(
BLink,
mergeData(data, {
props,
{
props: this.$props,
staticClass: 'dropdown-item',
attrs: { role: 'menuitem' }
}),
children
attrs: { role: 'menuitem' },
on: { click: this.closeDropdown }
},
this.$slots.default
)
}
}
59 changes: 59 additions & 0 deletions src/components/dropdown/dropdown-item.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import DropdownItem from './dropdown-item'
import { mount } from '@vue/test-utils'

describe('dropdown-item', async () => {
it('renders with tag "a" and href="#" by default', async () => {
const wrapper = mount(DropdownItem)
expect(wrapper.is('a')).toBe(true)
expect(wrapper.attributes('href')).toBe('#')
})

it('has class "dropdown-item"', async () => {
const wrapper = mount(DropdownItem)
expect(wrapper.classes()).toContain('dropdown-item')
expect(wrapper.attributes('href')).toBe('#')
})

it('calls dropdown hide(true) method when clicked', async () => {
let called = false
let refocus = null
const wrapper = mount(DropdownItem, {
provide: {
dropdown: {
hide (arg) {
called = true
refocus = arg
}
}
}
})
const link = wrapper.find('a')
expect(link).toBeDefined()
link.trigger('click')
await wrapper.vm.$nextTick()
expect(called).toBe(true)
expect(refocus).toBe(true)
})

it('does not call dropdown hide(true) method when clicked and disabled', async () => {
let called = false
let refocus = null
const wrapper = mount(DropdownItem, {
provide: {
dropdown: {
hide (arg) {
called = true
refocus = arg
}
}
},
propsData: { disabled: true }
})
const link = wrapper.find('a')
expect(link).toBeDefined()
link.trigger('click')
await wrapper.vm.$nextTick()
expect(called).toBe(false)
expect(refocus).toBe(null)
})
})
11 changes: 6 additions & 5 deletions src/components/dropdown/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export default {
class: this.menuClasses,
attrs: {
role: this.role,
tabindex: '-1',
'aria-labelledby': this.safeId(this.split ? '_BV_button_' : '_BV_toggle_')
},
on: {
Expand All @@ -184,10 +185,10 @@ export default {
},
[this.$slots.default]
)
return h('div', { attrs: { id: this.safeId() }, class: this.dropdownClasses }, [
split,
toggle,
menu
])
return h(
'div',
{ attrs: { id: this.safeId() }, class: this.dropdownClasses },
[split, toggle, menu]
)
}
}
14 changes: 0 additions & 14 deletions src/components/dropdown/dropdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,6 @@ describe('dropdown', async () => {
expect(Array.from(dd_6.$refs.menu.children).find(node => node.innerHTML === 'button')).toBeElement('button')
})

it('dd-item-button should emit click event', async () => {
const { app: { $refs } } = window
const { dd_6 } = $refs // eslint-disable-line camelcase

const spy = jest.fn()

dd_6.$parent.$root.$on('clicked::link', spy)

const buttonItem = Array.from(dd_6.$refs.menu.children).find(node => node.innerHTML === 'button')
buttonItem.click()

expect(spy).toHaveBeenCalled()
})

it('dd-divider should render', async () => {
const { app: { $refs } } = window
const { dd_6 } = $refs // eslint-disable-line camelcase
Expand Down
14 changes: 9 additions & 5 deletions src/components/nav/nav-item-dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,21 @@ export default {
{
class: this.menuClasses,
ref: 'menu',
attrs: { 'aria-labelledby': this.safeId('_BV_button_') },
attrs: {
tabindex: '-1',
'aria-labelledby': this.safeId('_BV_button_')
},
on: {
mouseover: this.onMouseOver,
keydown: this.onKeydown // tab, up, down, esc
}
},
[this.$slots.default]
)
return h('li', { attrs: { id: this.safeId() }, class: this.dropdownClasses }, [
button,
menu
])
return h(
'li',
{ attrs: { id: this.safeId() }, class: this.dropdownClasses },
[button, menu]
)
}
}
Loading