Skip to content

Commit

Permalink
chore(unit testing): convert tooltip and popover tests (bootstrap-vue…
Browse files Browse the repository at this point in the history
  • Loading branch information
tmorehouse authored Apr 3, 2019
1 parent 7373464 commit 607eb9e
Show file tree
Hide file tree
Showing 13 changed files with 1,315 additions and 171 deletions.
37 changes: 0 additions & 37 deletions src/components/popover/fixtures/popover.html

This file was deleted.

38 changes: 0 additions & 38 deletions src/components/popover/fixtures/popover.js

This file was deleted.

1 change: 1 addition & 0 deletions src/components/popover/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default {
createToolpop() {
// getTarget is in toolpop mixin
const target = this.getTarget()
/* istanbul ignore else */
if (target) {
this._toolpop = new PopOver(target, this.getConfig(), this.$root)
} else {
Expand Down
222 changes: 218 additions & 4 deletions src/components/popover/popover.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,220 @@
import { loadFixture, testVM } from '../../../tests/utils'
import Popover from './popover'
import { mount, createLocalVue as CreateLocalVue } from '@vue/test-utils'

describe('popover', () => {
beforeEach(loadFixture(__dirname, 'popover'))
testVM()
const localVue = new CreateLocalVue()

const waitAF = () => new Promise(resolve => requestAnimationFrame(resolve))

// Our test application definition
const appDef = {
props: ['triggers', 'show', 'disabled', 'noFade', 'title', 'titleAttr', 'btnDisabled'],
render(h) {
return h('article', { attrs: { id: 'wrapper' } }, [
h(
'button',
{
attrs: {
id: 'foo',
type: 'button',
disabled: this.btnDisabled || null,
title: this.titleAttr || null
}
},
'text'
),
h(
Popover,
{
attrs: { id: 'bar' },
props: {
target: 'foo',
triggers: this.triggers,
show: this.show,
disabled: this.disabled,
noFade: this.noFade || false
}
},
[h('template', { slot: 'title' }, this.$slots.title), this.$slots.default || '']
)
])
}
}

// The majority of functionality has been tested in the tooltip component tests
// as popover shares a common mixin with tooltip.
// So we just test a few key differences

//
// Note:
// wrapper.destroy() **MUST** be called at the end of each test in order for
// the next test to function properly!
//
describe('tooltip', () => {
const originalCreateRange = document.createRange
const origGetBCR = Element.prototype.getBoundingClientRect

beforeEach(() => {
// 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: () => {},
commonAncestorContainer: {
nodeName: 'BODY',
ownerDocument: document
}
})
// Mock getBCR so that the isVisible(el) test returns true
// Needed for visibility checks of trigger element, etc.
Element.prototype.getBoundingClientRect = jest.fn(() => {
return {
width: 24,
height: 24,
top: 0,
left: 0,
bottom: 0,
right: 0
}
})
})

afterEach(() => {
// Reset overrides
document.createRange = originalCreateRange
Element.prototype.getBoundingClientRect = origGetBCR
})

it('has expected default structure', async () => {
const App = localVue.extend(appDef)
const wrapper = mount(App, {
attachToDocument: true,
localVue: localVue,
propsData: {
triggers: 'click'
},
slots: {
title: 'title',
default: 'content'
}
})

expect(wrapper.isVueInstance()).toBe(true)
await wrapper.vm.$nextTick()

expect(wrapper.is('article')).toBe(true)
expect(wrapper.attributes('id')).toBeDefined()
expect(wrapper.attributes('id')).toEqual('wrapper')

// The trigger button
const $button = wrapper.find('button')
expect($button.exists()).toBe(true)
expect($button.attributes('id')).toBeDefined()
expect($button.attributes('id')).toEqual('foo')
expect($button.attributes('title')).toBeDefined()
expect($button.attributes('title')).toEqual('')
expect($button.attributes('data-original-title')).toBeDefined()
expect($button.attributes('data-original-title')).toEqual('')
expect($button.attributes('aria-describedby')).not.toBeDefined()

// b-popover wrapper
const $tipholder = wrapper.find('div#bar')
expect($tipholder.exists()).toBe(true)
expect($tipholder.classes()).toContain('d-none')
expect($tipholder.attributes('aria-hidden')).toBeDefined()
expect($tipholder.attributes('aria-hidden')).toEqual('true')
expect($tipholder.element.style.display).toEqual('none')

// content placeholders
expect($tipholder.findAll('div.d-none > div').length).toBe(2)
const $holders = $tipholder.findAll('div.d-none > div')
expect($holders.at(0).text()).toEqual('title')
expect($holders.at(1).text()).toEqual('content')

wrapper.destroy()
})

it('initially open has expected structure', async () => {
jest.useFakeTimers()
const App = localVue.extend(appDef)
const wrapper = mount(App, {
attachToDocument: true,
localVue: localVue,
propsData: {
triggers: 'click',
show: true
},
slots: {
title: 'title',
default: 'content'
}
})

expect(wrapper.isVueInstance()).toBe(true)
await wrapper.vm.$nextTick()
await waitAF()
await wrapper.vm.$nextTick()
await waitAF()
jest.runOnlyPendingTimers()

expect(wrapper.is('article')).toBe(true)
expect(wrapper.attributes('id')).toBeDefined()
expect(wrapper.attributes('id')).toEqual('wrapper')

// The trigger button
const $button = wrapper.find('button')
expect($button.exists()).toBe(true)
expect($button.attributes('id')).toBeDefined()
expect($button.attributes('id')).toEqual('foo')
expect($button.attributes('title')).toBeDefined()
expect($button.attributes('title')).toEqual('')
expect($button.attributes('data-original-title')).toBeDefined()
expect($button.attributes('data-original-title')).toEqual('')
expect($button.attributes('aria-describedby')).toBeDefined()
// ID of the tooltip that will be in the body
const adb = $button.attributes('aria-describedby')

// b-popover wrapper
const $tipholder = wrapper.find('div#bar')
expect($tipholder.exists()).toBe(true)
expect($tipholder.classes()).toContain('d-none')
expect($tipholder.attributes('aria-hidden')).toBeDefined()
expect($tipholder.attributes('aria-hidden')).toEqual('true')
expect($tipholder.element.style.display).toEqual('none')

// content placeholders should be moved
expect($tipholder.findAll('div.d-none > div').length).toBe(0)
expect($tipholder.text()).toBe('')

// Find the popover element in the document
const tip = document.querySelector(`#${adb}`)
expect(tip).not.toBe(null)
expect(tip).toBeInstanceOf(HTMLElement)
expect(tip.tagName).toEqual('DIV')
expect(tip.classList.contains('popover')).toBe(true)

// Hide the tooltip
wrapper.setProps({
show: false
})
await wrapper.vm.$nextTick()
await waitAF()
await wrapper.vm.$nextTick()
await waitAF()
jest.runOnlyPendingTimers()

expect($button.attributes('aria-describedby')).not.toBeDefined()
// title placeholder (from default slot) will be back here
expect($tipholder.findAll('div.d-none > div').length).toBe(2)
const $holders = $tipholder.findAll('div.d-none > div')
expect($holders.at(0).text()).toEqual('title')
expect($holders.at(1).text()).toEqual('content')

// Popover element should not be in the document
expect(document.body.contains(tip)).toBe(false)
expect(document.querySelector(`#${adb}`)).toBe(null)

wrapper.destroy()
})
})
33 changes: 0 additions & 33 deletions src/components/tooltip/fixtures/tooltip.html

This file was deleted.

21 changes: 0 additions & 21 deletions src/components/tooltip/fixtures/tooltip.js

This file was deleted.

1 change: 1 addition & 0 deletions src/components/tooltip/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default {
createToolpop() {
// getTarget is in toolpop mixin
const target = this.getTarget()
/* istanbul ignore else */
if (target) {
this._toolpop = new ToolTip(target, this.getConfig(), this.$root)
} else {
Expand Down
Loading

0 comments on commit 607eb9e

Please sign in to comment.