* Force each plugin that extends base-components to implement a static method `NAME()`
* Remove redundant `NAME` argument from 'Utils.defineJQueryPlugin' & fix test
class Alert extends BaseComponent {
// Getters
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Alert to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Alert)
+defineJQueryPlugin(Alert)
export default Alert
dispose() {
Data.remove(this._element, this.constructor.DATA_KEY)
- EventHandler.off(this._element, `.${this.constructor.DATA_KEY}`)
+ EventHandler.off(this._element, this.constructor.EVENT_KEY)
Object.getOwnPropertyNames(this).forEach(propertyName => {
this[propertyName] = null
static get VERSION() {
return VERSION
}
+
+ static get NAME() {
+ throw new Error('You have to implement the static method "NAME", for each component!')
+ }
+
+ static get DATA_KEY() {
+ return `bs.${this.NAME}`
+ }
+
+ static get EVENT_KEY() {
+ return `.${this.DATA_KEY}`
+ }
}
export default BaseComponent
class Button extends BaseComponent {
// Getters
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Button to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Button)
+defineJQueryPlugin(Button)
export default Button
return Default
}
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Carousel to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Carousel)
+defineJQueryPlugin(Carousel)
export default Carousel
return Default
}
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Collapse to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Collapse)
+defineJQueryPlugin(Collapse)
export default Collapse
return DefaultType
}
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Dropdown to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Dropdown)
+defineJQueryPlugin(Dropdown)
export default Dropdown
return Default
}
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Modal to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Modal)
+defineJQueryPlugin(Modal)
export default Modal
// Getters
- static get Default() {
- return Default
+ static get NAME() {
+ return NAME
}
- static get DATA_KEY() {
- return DATA_KEY
+ static get Default() {
+ return Default
}
// Public
* ------------------------------------------------------------------------
*/
-defineJQueryPlugin(NAME, Offcanvas)
+defineJQueryPlugin(Offcanvas)
export default Offcanvas
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
}
* add .Popover to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Popover)
+defineJQueryPlugin(Popover)
export default Popover
return Default
}
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .ScrollSpy to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, ScrollSpy)
+defineJQueryPlugin(ScrollSpy)
export default ScrollSpy
class Tab extends BaseComponent {
// Getters
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Tab to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Tab)
+defineJQueryPlugin(Tab)
export default Tab
return Default
}
- static get DATA_KEY() {
- return DATA_KEY
+ static get NAME() {
+ return NAME
}
// Public
* add .Toast to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Toast)
+defineJQueryPlugin(Toast)
export default Toast
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
}
* add .Tooltip to jQuery only if jQuery is present
*/
-defineJQueryPlugin(NAME, Tooltip)
+defineJQueryPlugin(Tooltip)
export default Tooltip
const isRTL = () => document.documentElement.dir === 'rtl'
-const defineJQueryPlugin = (name, plugin) => {
+const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery()
/* istanbul ignore if */
if ($) {
+ const name = plugin.NAME
const JQUERY_NO_CONFLICT = $.fn[name]
$.fn[name] = plugin.jQueryInterface
$.fn[name].Constructor = plugin
--- /dev/null
+import BaseComponent from '../../src/base-component'
+import { clearFixture, getFixture } from '../helpers/fixture'
+import EventHandler from '../../src/dom/event-handler'
+import { noop } from '../../src/util'
+
+class DummyClass extends BaseComponent {
+ constructor(element) {
+ super(element)
+
+ EventHandler.on(this._element, `click${DummyClass.EVENT_KEY}`, noop)
+ }
+
+ static get NAME() {
+ return 'dummy'
+ }
+}
+
+describe('Base Component', () => {
+ let fixtureEl
+ const name = 'dummy'
+ let element
+ let instance
+ const createInstance = () => {
+ fixtureEl.innerHTML = '<div id="foo"></div>'
+ element = fixtureEl.querySelector('#foo')
+ instance = new DummyClass(element)
+ }
+
+ beforeAll(() => {
+ fixtureEl = getFixture()
+ })
+
+ afterEach(() => {
+ clearFixture()
+ })
+
+ describe('Static Methods', () => {
+ describe('VERSION', () => {
+ it('should return version', () => {
+ expect(typeof DummyClass.VERSION).toEqual('string')
+ })
+ })
+
+ describe('DATA_KEY', () => {
+ it('should return plugin data key', () => {
+ expect(DummyClass.DATA_KEY).toEqual(`bs.${name}`)
+ })
+ })
+
+ describe('NAME', () => {
+ it('should return plugin NAME', () => {
+ expect(DummyClass.NAME).toEqual(name)
+ })
+ })
+
+ describe('EVENT_KEY', () => {
+ it('should return plugin event key', () => {
+ expect(DummyClass.EVENT_KEY).toEqual(`.bs.${name}`)
+ })
+ })
+ })
+ describe('Public Methods', () => {
+ describe('constructor', () => {
+ it('should accept element, either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = [
+ '<div id="foo"></div>',
+ '<div id="bar"></div>'
+ ].join('')
+
+ const el = fixtureEl.querySelector('#foo')
+ const elInstance = new DummyClass(el)
+ const selectorInstance = new DummyClass('#bar')
+
+ expect(elInstance._element).toEqual(el)
+ expect(selectorInstance._element).toEqual(fixtureEl.querySelector('#bar'))
+ })
+ })
+ describe('dispose', () => {
+ it('should dispose an component', () => {
+ createInstance()
+ expect(DummyClass.getInstance(element)).not.toBeNull()
+
+ instance.dispose()
+
+ expect(DummyClass.getInstance(element)).toBeNull()
+ expect(instance._element).toBeNull()
+ })
+
+ it('should de-register element event listeners', () => {
+ createInstance()
+ spyOn(EventHandler, 'off')
+
+ instance.dispose()
+
+ expect(EventHandler.off).toHaveBeenCalledWith(element, DummyClass.EVENT_KEY)
+ })
+ })
+
+ describe('getInstance', () => {
+ it('should return an instance', () => {
+ createInstance()
+
+ expect(DummyClass.getInstance(element)).toEqual(instance)
+ expect(DummyClass.getInstance(element)).toBeInstanceOf(DummyClass)
+ })
+
+ it('should return null when there is no instance', () => {
+ fixtureEl.innerHTML = '<div></div>'
+
+ const div = fixtureEl.querySelector('div')
+
+ expect(DummyClass.getInstance(div)).toEqual(null)
+ })
+ })
+ })
+})
it('should define a plugin on the jQuery instance', () => {
const pluginMock = function () {}
+ pluginMock.NAME = 'test'
pluginMock.jQueryInterface = function () {}
- Util.defineJQueryPlugin('test', pluginMock)
+ Util.defineJQueryPlugin(pluginMock)
expect(fakejQuery.fn.test).toBe(pluginMock.jQueryInterface)
expect(fakejQuery.fn.test.Constructor).toBe(pluginMock)
expect(typeof fakejQuery.fn.test.noConflict).toEqual('function')