2
0
mirror of https://github.com/tenrok/bootstrap.git synced 2026-06-14 18:42:30 +03:00

rewrite popover unit tests

This commit is contained in:
Johann-S
2019-05-08 21:32:50 +02:00
parent 1ac07a66ce
commit c9e650a56f
6 changed files with 259 additions and 482 deletions
+192
View File
@@ -0,0 +1,192 @@
/**
* --------------------------------------------------------------------------
* Bootstrap (v4.3.1): popover.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/
import { jQuery as $ } from '../util/index'
import Data from '../dom/data'
import SelectorEngine from '../dom/selector-engine'
import Tooltip from '../tooltip'
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
const NAME = 'popover'
const VERSION = '4.3.1'
const DATA_KEY = 'bs.popover'
const EVENT_KEY = `.${DATA_KEY}`
const CLASS_PREFIX = 'bs-popover'
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g')
const Default = {
...Tooltip.Default,
placement: 'right',
trigger: 'click',
content: '',
template: '<div class="popover" role="tooltip">' +
'<div class="popover-arrow"></div>' +
'<h3 class="popover-header"></h3>' +
'<div class="popover-body"></div></div>'
}
const DefaultType = {
...Tooltip.DefaultType,
content: '(string|element|function)'
}
const ClassName = {
FADE: 'fade',
SHOW: 'show'
}
const Selector = {
TITLE: '.popover-header',
CONTENT: '.popover-body'
}
const Event = {
HIDE: `hide${EVENT_KEY}`,
HIDDEN: `hidden${EVENT_KEY}`,
SHOW: `show${EVENT_KEY}`,
SHOWN: `shown${EVENT_KEY}`,
INSERTED: `inserted${EVENT_KEY}`,
CLICK: `click${EVENT_KEY}`,
FOCUSIN: `focusin${EVENT_KEY}`,
FOCUSOUT: `focusout${EVENT_KEY}`,
MOUSEENTER: `mouseenter${EVENT_KEY}`,
MOUSELEAVE: `mouseleave${EVENT_KEY}`
}
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
class Popover extends Tooltip {
// Getters
static get VERSION() {
return VERSION
}
static get Default() {
return Default
}
static get NAME() {
return NAME
}
static get DATA_KEY() {
return DATA_KEY
}
static get Event() {
return Event
}
static get EVENT_KEY() {
return EVENT_KEY
}
static get DefaultType() {
return DefaultType
}
// Overrides
isWithContent() {
return this.getTitle() || this._getContent()
}
addAttachmentClass(attachment) {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${attachment}`)
}
setContent() {
const tip = this.getTipElement()
// we use append for html objects to maintain js events
this.setElementContent(SelectorEngine.findOne(Selector.TITLE, tip), this.getTitle())
let content = this._getContent()
if (typeof content === 'function') {
content = content.call(this.element)
}
this.setElementContent(SelectorEngine.findOne(Selector.CONTENT, tip), content)
tip.classList.remove(ClassName.FADE)
tip.classList.remove(ClassName.SHOW)
}
// Private
_getContent() {
return this.element.getAttribute('data-content') ||
this.config.content
}
_cleanTipClass() {
const tip = this.getTipElement()
const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX)
if (tabClass !== null && tabClass.length > 0) {
tabClass.map(token => token.trim())
.forEach(tClass => tip.classList.remove(tClass))
}
}
// Static
static _jQueryInterface(config) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
const _config = typeof config === 'object' ? config : null
if (!data && /dispose|hide/.test(config)) {
return
}
if (!data) {
data = new Popover(this, _config)
Data.setData(this, DATA_KEY, data)
}
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
}
})
}
static _getInstance(element) {
return Data.getData(element, DATA_KEY)
}
}
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/
/* istanbul ignore if */
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Popover._jQueryInterface
$.fn[NAME].Constructor = Popover
$.fn[NAME].noConflict = () => {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Popover._jQueryInterface
}
}
export default Popover
+251
View File
@@ -0,0 +1,251 @@
import Popover from './popover'
import { makeArray } from '../util/index'
/** Test helpers */
import { getFixture, clearFixture, jQueryMock } from '../../tests/helpers/fixture'
describe('Popover', () => {
let fixtureEl
beforeAll(() => {
fixtureEl = getFixture()
})
afterEach(() => {
clearFixture()
const popoverList = makeArray(document.querySelectorAll('.popover'))
popoverList.forEach(backdrop => {
document.body.removeChild(backdrop)
})
})
describe('VERSION', () => {
it('should return plugin version', () => {
expect(Popover.VERSION).toEqual(jasmine.any(String))
})
})
describe('Default', () => {
it('should return plugin default config', () => {
expect(Popover.Default).toEqual(jasmine.any(Object))
})
})
describe('NAME', () => {
it('should return plugin name', () => {
expect(Popover.NAME).toEqual(jasmine.any(String))
})
})
describe('DATA_KEY', () => {
it('should return plugin data key', () => {
expect(Popover.DATA_KEY).toEqual('bs.popover')
})
})
describe('Event', () => {
it('should return plugin events', () => {
expect(Popover.Event).toEqual(jasmine.any(Object))
})
})
describe('EVENT_KEY', () => {
it('should return plugin event key', () => {
expect(Popover.EVENT_KEY).toEqual('.bs.popover')
})
})
describe('DefaultType', () => {
it('should return plugin default type', () => {
expect(Popover.DefaultType).toEqual(jasmine.any(Object))
})
})
describe('show', () => {
it('should show a popover', done => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
popoverEl.addEventListener('shown.bs.popover', () => {
expect(document.querySelector('.popover')).toBeDefined()
done()
})
popover.show()
})
it('should set title and content from functions', done => {
fixtureEl.innerHTML = '<a href="#">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl, {
title: () => 'Bootstrap',
content: () => 'loves writing tests (╯°□°)╯︵ ┻━┻'
})
popoverEl.addEventListener('shown.bs.popover', () => {
const popoverDisplayed = document.querySelector('.popover')
expect(popoverDisplayed).toBeDefined()
expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('Bootstrap')
expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('loves writing tests (╯°□°)╯︵ ┻━┻')
done()
})
popover.show()
})
it('should show a popover with just content', done => {
fixtureEl.innerHTML = '<a href="#">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl, {
content: 'Popover content'
})
popoverEl.addEventListener('shown.bs.popover', () => {
const popoverDisplayed = document.querySelector('.popover')
expect(popoverDisplayed).toBeDefined()
expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('Popover content')
done()
})
popover.show()
})
})
describe('hide', () => {
it('should hide a popover', done => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
popoverEl.addEventListener('shown.bs.popover', () => {
popover.hide()
})
popoverEl.addEventListener('hidden.bs.popover', () => {
expect(document.querySelector('.popover')).toBeNull()
done()
})
popover.show()
})
})
describe('_jQueryInterface', () => {
it('should create a popover', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
jQueryMock.fn.popover = Popover._jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock)
expect(Popover._getInstance(popoverEl)).toBeDefined()
})
it('should create a popover with a config object', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
jQueryMock.fn.popover = Popover._jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock, {
content: 'Popover content'
})
expect(Popover._getInstance(popoverEl)).toBeDefined()
})
it('should not re create a popover', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
jQueryMock.fn.popover = Popover._jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock)
expect(Popover._getInstance(popoverEl)).toEqual(popover)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const action = 'undefinedMethod'
jQueryMock.fn.popover = Popover._jQueryInterface
jQueryMock.elements = [popoverEl]
try {
jQueryMock.fn.popover.call(jQueryMock, action)
} catch (error) {
expect(error.message).toEqual(`No method named "${action}"`)
}
})
it('should should call show method', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
jQueryMock.fn.popover = Popover._jQueryInterface
jQueryMock.elements = [popoverEl]
spyOn(popover, 'show')
jQueryMock.fn.popover.call(jQueryMock, 'show')
expect(popover.show).toHaveBeenCalled()
})
it('should do nothing if dipose is called when a popover do not exist', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
jQueryMock.fn.popover = Popover._jQueryInterface
jQueryMock.elements = [popoverEl]
spyOn(Popover.prototype, 'dispose')
jQueryMock.fn.popover.call(jQueryMock, 'dispose')
expect(Popover.prototype.dispose).not.toHaveBeenCalled()
})
})
describe('_getInstance', () => {
it('should return popover instance', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
expect(Popover._getInstance(popoverEl)).toEqual(popover)
})
it('should return null when there is no popover instance', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-content="https://twitter.com/getbootstrap">BS twitter</a>'
const popoverEl = fixtureEl.querySelector('a')
expect(Popover._getInstance(popoverEl)).toEqual(null)
})
})
})