mirror of
https://github.com/twbs/bootstrap.git
synced 2025-01-17 09:52:29 +01:00
Switch from QUnit to Jasmine.
This commit is contained in:
parent
08d81c8437
commit
c8c2074650
@ -11,10 +11,5 @@ module.exports = {
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-object-rest-spread'
|
||||
],
|
||||
env: {
|
||||
test: {
|
||||
plugins: [ 'istanbul' ]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -12,7 +12,6 @@ const rollup = require('rollup')
|
||||
const babel = require('rollup-plugin-babel')
|
||||
const banner = require('./banner.js')
|
||||
|
||||
const TEST = process.env.NODE_ENV === 'test'
|
||||
const plugins = [
|
||||
babel({
|
||||
// Only transpile our source code
|
||||
@ -33,7 +32,7 @@ const bsPlugins = {
|
||||
Manipulator: path.resolve(__dirname, '../js/src/dom/manipulator.js'),
|
||||
Polyfill: path.resolve(__dirname, '../js/src/dom/polyfill.js'),
|
||||
SelectorEngine: path.resolve(__dirname, '../js/src/dom/selector-engine.js'),
|
||||
Alert: path.resolve(__dirname, '../js/src/alert.js'),
|
||||
Alert: path.resolve(__dirname, '../js/src/alert/alert.js'),
|
||||
Button: path.resolve(__dirname, '../js/src/button.js'),
|
||||
Carousel: path.resolve(__dirname, '../js/src/carousel.js'),
|
||||
Collapse: path.resolve(__dirname, '../js/src/collapse.js'),
|
||||
@ -45,12 +44,7 @@ const bsPlugins = {
|
||||
Toast: path.resolve(__dirname, '../js/src/toast.js'),
|
||||
Tooltip: path.resolve(__dirname, '../js/src/tooltip.js')
|
||||
}
|
||||
const rootPath = TEST ? '../js/coverage/dist/' : '../js/dist/'
|
||||
|
||||
if (TEST) {
|
||||
bsPlugins.Util = path.resolve(__dirname, '../js/src/util/index.js')
|
||||
bsPlugins.Sanitizer = path.resolve(__dirname, '../js/src/util/sanitizer.js')
|
||||
}
|
||||
const rootPath = '../js/dist/'
|
||||
|
||||
const defaultPluginConfig = {
|
||||
external: [
|
||||
|
@ -5,7 +5,7 @@
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Alert from './src/alert'
|
||||
import Alert from './src/alert/alert'
|
||||
import Button from './src/button'
|
||||
import Carousel from './src/carousel'
|
||||
import Collapse from './src/collapse'
|
||||
|
@ -5,7 +5,7 @@
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Alert from './src/alert'
|
||||
import Alert from './src/alert/alert'
|
||||
import Button from './src/button'
|
||||
import Carousel from './src/carousel'
|
||||
import Collapse from './src/collapse'
|
||||
|
14
js/src/.eslintrc.json
Normal file
14
js/src/.eslintrc.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"../../.eslintrc.json"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/*.spec.js"],
|
||||
"env": {
|
||||
"jasmine": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -11,10 +11,10 @@ import {
|
||||
emulateTransitionEnd,
|
||||
getSelectorFromElement,
|
||||
getTransitionDurationFromElement
|
||||
} from './util/index'
|
||||
import Data from './dom/data'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
} from '../util/index'
|
||||
import Data from '../dom/data'
|
||||
import EventHandler from '../dom/event-handler'
|
||||
import SelectorEngine from '../dom/selector-engine'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
@ -53,6 +53,7 @@ const ClassName = {
|
||||
class Alert {
|
||||
constructor(element) {
|
||||
this._element = element
|
||||
|
||||
if (this._element) {
|
||||
Data.setData(element, DATA_KEY, this)
|
||||
}
|
||||
@ -118,7 +119,7 @@ class Alert {
|
||||
const transitionDuration = getTransitionDurationFromElement(element)
|
||||
|
||||
EventHandler
|
||||
.one(element, TRANSITION_END, event => this._destroyElement(element, event))
|
||||
.one(element, TRANSITION_END, () => this._destroyElement(element))
|
||||
emulateTransitionEnd(element, transitionDuration)
|
||||
}
|
||||
|
||||
@ -176,6 +177,7 @@ EventHandler
|
||||
* add .alert to jQuery only if jQuery is present
|
||||
*/
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (typeof $ !== 'undefined') {
|
||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||
$.fn[NAME] = Alert._jQueryInterface
|
127
js/src/alert/alert.spec.js
Normal file
127
js/src/alert/alert.spec.js
Normal file
@ -0,0 +1,127 @@
|
||||
import Alert from './alert'
|
||||
import { makeArray, getTransitionDurationFromElement } from '../util/index'
|
||||
|
||||
/** Test helpers */
|
||||
import { getFixture, clearFixture } from '../../tests/helpers/fixture'
|
||||
|
||||
describe('Alert', () => {
|
||||
let fixtureEl
|
||||
|
||||
beforeAll(() => {
|
||||
fixtureEl = getFixture()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
clearFixture()
|
||||
})
|
||||
|
||||
it('should return version', () => {
|
||||
expect(typeof Alert.VERSION).toEqual('string')
|
||||
})
|
||||
|
||||
describe('data-api', () => {
|
||||
it('should close an alert without instanciate it manually', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div class="alert">',
|
||||
' <button type="button" data-dismiss="alert">x</button>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const button = document.querySelector('button')
|
||||
|
||||
button.click()
|
||||
expect(makeArray(document.querySelectorAll('.alert')).length).toEqual(0)
|
||||
})
|
||||
|
||||
it('should close an alert without instanciate it manually with the parent selector', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div class="alert">',
|
||||
' <button type="button" data-target=".alert" data-dismiss="alert">x</button>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const button = document.querySelector('button')
|
||||
|
||||
button.click()
|
||||
expect(makeArray(document.querySelectorAll('.alert')).length).toEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('close', () => {
|
||||
it('should close an alert', done => {
|
||||
const spy = jasmine.createSpy('spy', getTransitionDurationFromElement)
|
||||
fixtureEl.innerHTML = '<div class="alert"></div>'
|
||||
|
||||
const alertEl = document.querySelector('.alert')
|
||||
const alert = new Alert(alertEl)
|
||||
|
||||
alertEl.addEventListener('closed.bs.alert', () => {
|
||||
expect(makeArray(document.querySelectorAll('.alert')).length).toEqual(0)
|
||||
expect(spy).not.toHaveBeenCalled()
|
||||
done()
|
||||
})
|
||||
|
||||
alert.close()
|
||||
})
|
||||
|
||||
it('should close alert with fade class', done => {
|
||||
fixtureEl.innerHTML = '<div class="alert fade"></div>'
|
||||
|
||||
const alertEl = document.querySelector('.alert')
|
||||
const alert = new Alert(alertEl)
|
||||
|
||||
alertEl.addEventListener('transitionend', () => {
|
||||
expect().nothing()
|
||||
})
|
||||
|
||||
alertEl.addEventListener('closed.bs.alert', () => {
|
||||
expect(makeArray(document.querySelectorAll('.alert')).length).toEqual(0)
|
||||
done()
|
||||
})
|
||||
|
||||
alert.close()
|
||||
})
|
||||
|
||||
it('should not remove alert if close event is prevented', done => {
|
||||
fixtureEl.innerHTML = '<div class="alert"></div>'
|
||||
|
||||
const alertEl = document.querySelector('.alert')
|
||||
const alert = new Alert(alertEl)
|
||||
|
||||
const endTest = () => {
|
||||
setTimeout(() => {
|
||||
expect(alert._removeElement).not.toHaveBeenCalled()
|
||||
done()
|
||||
}, 10)
|
||||
}
|
||||
|
||||
spyOn(alert, '_removeElement')
|
||||
|
||||
alertEl.addEventListener('close.bs.alert', event => {
|
||||
event.preventDefault()
|
||||
endTest()
|
||||
})
|
||||
|
||||
alertEl.addEventListener('closed.bs.alert', () => {
|
||||
endTest()
|
||||
})
|
||||
|
||||
alert.close()
|
||||
})
|
||||
})
|
||||
|
||||
describe('dispose', () => {
|
||||
it('should dispose an alert', () => {
|
||||
fixtureEl.innerHTML = '<div class="alert"></div>'
|
||||
|
||||
const alertEl = document.querySelector('.alert')
|
||||
const alert = new Alert(alertEl)
|
||||
|
||||
expect(Alert._getInstance(alertEl)).toBeDefined()
|
||||
|
||||
alert.dispose()
|
||||
|
||||
expect(Alert._getInstance(alertEl)).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
131
js/src/dom/data.spec.js
Normal file
131
js/src/dom/data.spec.js
Normal file
@ -0,0 +1,131 @@
|
||||
import Data from './data'
|
||||
|
||||
/** Test helpers */
|
||||
import { getFixture, clearFixture } from '../../tests/helpers/fixture'
|
||||
|
||||
describe('Data', () => {
|
||||
let fixtureEl
|
||||
|
||||
beforeAll(() => {
|
||||
fixtureEl = getFixture()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
clearFixture()
|
||||
})
|
||||
|
||||
describe('setData', () => {
|
||||
it('should set data in an element by adding a key attribute', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
|
||||
Data.setData(div, 'test', data)
|
||||
expect(div.key).toBeDefined()
|
||||
})
|
||||
|
||||
it('should change data if something is already stored', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
|
||||
Data.setData(div, 'test', data)
|
||||
|
||||
data.test = 'bsData2'
|
||||
Data.setData(div, 'test', data)
|
||||
|
||||
expect(div.key).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getData', () => {
|
||||
it('should return stored data', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
|
||||
Data.setData(div, 'test', data)
|
||||
expect(Data.getData(div, 'test')).toEqual(data)
|
||||
})
|
||||
|
||||
it('should return null on undefined element', () => {
|
||||
expect(Data.getData(null)).toEqual(null)
|
||||
expect(Data.getData(undefined)).toEqual(null)
|
||||
})
|
||||
|
||||
it('should return null when an element have nothing stored', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
expect(Data.getData(div, 'test')).toEqual(null)
|
||||
})
|
||||
|
||||
it('should return null when an element have nothing stored with the provided key', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
|
||||
Data.setData(div, 'test', data)
|
||||
|
||||
expect(Data.getData(div, 'test2')).toEqual(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeData', () => {
|
||||
it('should do nothing when an element have nothing stored', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
Data.removeData(div, 'test')
|
||||
expect().nothing()
|
||||
})
|
||||
|
||||
it('should should do nothing if it\'s not a valid key provided', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
|
||||
Data.setData(div, 'test', data)
|
||||
|
||||
expect(div.key).toBeDefined()
|
||||
|
||||
Data.removeData(div, 'test2')
|
||||
|
||||
expect(div.key).toBeDefined()
|
||||
})
|
||||
|
||||
it('should remove data if something is stored', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
|
||||
Data.setData(div, 'test', data)
|
||||
|
||||
expect(div.key).toBeDefined()
|
||||
|
||||
Data.removeData(div, 'test')
|
||||
|
||||
expect(div.key).toBeUndefined()
|
||||
})
|
||||
})
|
||||
})
|
@ -192,7 +192,9 @@ function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {
|
||||
}
|
||||
|
||||
const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''))
|
||||
const fn = delegation ? bootstrapDelegationHandler(element, handler, delegationFn) : bootstrapHandler(element, handler)
|
||||
const fn = delegation ?
|
||||
bootstrapDelegationHandler(element, handler, delegationFn) :
|
||||
bootstrapHandler(element, handler)
|
||||
|
||||
fn.delegationSelector = delegation ? handler : null
|
||||
fn.originalHandler = originalHandler
|
||||
|
327
js/src/dom/event-handler.spec.js
Normal file
327
js/src/dom/event-handler.spec.js
Normal file
@ -0,0 +1,327 @@
|
||||
import EventHandler from './event-handler'
|
||||
|
||||
/** Test helpers */
|
||||
import { getFixture, clearFixture } from '../../tests/helpers/fixture'
|
||||
|
||||
describe('EventHandler', () => {
|
||||
let fixtureEl
|
||||
|
||||
beforeAll(() => {
|
||||
fixtureEl = getFixture()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
clearFixture()
|
||||
})
|
||||
|
||||
describe('on', () => {
|
||||
it('should not add event listener if the event is not a string', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.on(div, null, () => {})
|
||||
EventHandler.on(null, 'click', () => {})
|
||||
|
||||
expect().nothing()
|
||||
})
|
||||
|
||||
it('should add event listener', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.on(div, 'click', () => {
|
||||
expect().nothing()
|
||||
done()
|
||||
})
|
||||
|
||||
div.click()
|
||||
})
|
||||
|
||||
it('should add namespaced event listener', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.on(div, 'bs.namespace', () => {
|
||||
expect().nothing()
|
||||
done()
|
||||
})
|
||||
|
||||
EventHandler.trigger(div, 'bs.namespace')
|
||||
})
|
||||
|
||||
it('should add native namespaced event listener', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.on(div, 'click.namespace', () => {
|
||||
expect().nothing()
|
||||
done()
|
||||
})
|
||||
|
||||
EventHandler.trigger(div, 'click')
|
||||
})
|
||||
|
||||
it('should handle event delegation', done => {
|
||||
EventHandler.on(document, 'click', '.test', () => {
|
||||
expect().nothing()
|
||||
done()
|
||||
})
|
||||
|
||||
fixtureEl.innerHTML = '<div class="test"></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
div.click()
|
||||
})
|
||||
})
|
||||
|
||||
describe('one', () => {
|
||||
it('should call listener just one', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
let called = 0
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const obj = {
|
||||
oneListener() {
|
||||
called++
|
||||
}
|
||||
}
|
||||
|
||||
EventHandler.one(div, 'bootstrap', obj.oneListener)
|
||||
|
||||
EventHandler.trigger(div, 'bootstrap')
|
||||
EventHandler.trigger(div, 'bootstrap')
|
||||
|
||||
setTimeout(() => {
|
||||
expect(called).toEqual(1)
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
describe('off', () => {
|
||||
it('should not remove a listener', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.off(div, null, () => {})
|
||||
EventHandler.off(null, 'click', () => {})
|
||||
expect().nothing()
|
||||
})
|
||||
|
||||
it('should remove a listener', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
let called = 0
|
||||
const handler = () => {
|
||||
called++
|
||||
}
|
||||
|
||||
EventHandler.on(div, 'foobar', handler)
|
||||
EventHandler.trigger(div, 'foobar')
|
||||
|
||||
EventHandler.off(div, 'foobar', handler)
|
||||
EventHandler.trigger(div, 'foobar')
|
||||
|
||||
setTimeout(() => {
|
||||
expect(called).toEqual(1)
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
it('should remove all the events', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
let called = 0
|
||||
|
||||
EventHandler.on(div, 'foobar', () => {
|
||||
called++
|
||||
})
|
||||
EventHandler.on(div, 'foobar', () => {
|
||||
called++
|
||||
})
|
||||
EventHandler.trigger(div, 'foobar')
|
||||
|
||||
EventHandler.off(div, 'foobar')
|
||||
EventHandler.trigger(div, 'foobar')
|
||||
|
||||
setTimeout(() => {
|
||||
expect(called).toEqual(2)
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
it('should remove all the namespaced listeners if namespace is passed', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
let called = 0
|
||||
|
||||
EventHandler.on(div, 'foobar.namespace', () => {
|
||||
called++
|
||||
})
|
||||
EventHandler.on(div, 'foofoo.namespace', () => {
|
||||
called++
|
||||
})
|
||||
EventHandler.trigger(div, 'foobar.namespace')
|
||||
EventHandler.trigger(div, 'foofoo.namespace')
|
||||
|
||||
EventHandler.off(div, '.namespace')
|
||||
EventHandler.trigger(div, 'foobar.namespace')
|
||||
EventHandler.trigger(div, 'foofoo.namespace')
|
||||
|
||||
setTimeout(() => {
|
||||
expect(called).toEqual(2)
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
it('should remove the namespaced listeners', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
let calledCallback1 = 0
|
||||
let calledCallback2 = 0
|
||||
|
||||
EventHandler.on(div, 'foobar.namespace', () => {
|
||||
calledCallback1++
|
||||
})
|
||||
EventHandler.on(div, 'foofoo.namespace', () => {
|
||||
calledCallback2++
|
||||
})
|
||||
|
||||
EventHandler.trigger(div, 'foobar.namespace')
|
||||
EventHandler.off(div, 'foobar.namespace')
|
||||
EventHandler.trigger(div, 'foobar.namespace')
|
||||
|
||||
EventHandler.trigger(div, 'foofoo.namespace')
|
||||
|
||||
setTimeout(() => {
|
||||
expect(calledCallback1).toEqual(1)
|
||||
expect(calledCallback2).toEqual(1)
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
it('should remove the all the namespaced listeners for native events', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
let called = 0
|
||||
|
||||
EventHandler.on(div, 'click.namespace', () => {
|
||||
called++
|
||||
})
|
||||
EventHandler.on(div, 'click.namespace2', () => {
|
||||
called++
|
||||
})
|
||||
|
||||
EventHandler.trigger(div, 'click')
|
||||
EventHandler.off(div, 'click')
|
||||
EventHandler.trigger(div, 'click')
|
||||
|
||||
setTimeout(() => {
|
||||
expect(called).toEqual(2)
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
it('should remove the specified namespaced listeners for native events', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
let called1 = 0
|
||||
let called2 = 0
|
||||
|
||||
EventHandler.on(div, 'click.namespace', () => {
|
||||
called1++
|
||||
})
|
||||
EventHandler.on(div, 'click.namespace2', () => {
|
||||
called2++
|
||||
})
|
||||
EventHandler.trigger(div, 'click')
|
||||
|
||||
EventHandler.off(div, 'click.namespace')
|
||||
EventHandler.trigger(div, 'click')
|
||||
|
||||
setTimeout(() => {
|
||||
expect(called1).toEqual(1)
|
||||
expect(called2).toEqual(2)
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
it('should remove a listener registered by .one', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const handler = () => {
|
||||
throw new Error('called')
|
||||
}
|
||||
|
||||
EventHandler.one(div, 'foobar', handler)
|
||||
EventHandler.off(div, 'foobar', handler)
|
||||
|
||||
EventHandler.trigger(div, 'foobar')
|
||||
setTimeout(() => {
|
||||
expect().nothing()
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
|
||||
it('should remove the correct delegated event listener', () => {
|
||||
const element = document.createElement('div')
|
||||
const subelement = document.createElement('span')
|
||||
element.appendChild(subelement)
|
||||
|
||||
const anchor = document.createElement('a')
|
||||
element.appendChild(anchor)
|
||||
|
||||
let i = 0
|
||||
const handler = () => {
|
||||
i++
|
||||
}
|
||||
|
||||
EventHandler.on(element, 'click', 'a', handler)
|
||||
EventHandler.on(element, 'click', 'span', handler)
|
||||
|
||||
fixtureEl.appendChild(element)
|
||||
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
|
||||
// first listeners called
|
||||
expect(i === 2).toEqual(true)
|
||||
|
||||
EventHandler.off(element, 'click', 'span', handler)
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
|
||||
// removed listener not called
|
||||
expect(i === 2).toEqual(true)
|
||||
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
|
||||
// not removed listener called
|
||||
expect(i === 3).toEqual(true)
|
||||
|
||||
EventHandler.on(element, 'click', 'span', handler)
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
|
||||
// listener re-registered
|
||||
expect(i === 5).toEqual(true)
|
||||
|
||||
EventHandler.off(element, 'click', 'span')
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
|
||||
// listener removed again
|
||||
expect(i === 5).toEqual(true)
|
||||
})
|
||||
})
|
||||
})
|
297
js/src/util/index.spec.js
Normal file
297
js/src/util/index.spec.js
Normal file
@ -0,0 +1,297 @@
|
||||
import * as Util from './index'
|
||||
|
||||
/** Test helpers */
|
||||
import { getFixture, clearFixture } from '../../tests/helpers/fixture'
|
||||
|
||||
describe('Util', () => {
|
||||
let fixtureEl
|
||||
|
||||
beforeAll(() => {
|
||||
fixtureEl = getFixture()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
clearFixture()
|
||||
})
|
||||
|
||||
describe('getUID', () => {
|
||||
it('should generate uid', () => {
|
||||
const uid = Util.getUID('bs')
|
||||
const uid2 = Util.getUID('bs')
|
||||
|
||||
expect(uid).not.toEqual(uid2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getSelectorFromElement', () => {
|
||||
it('should get selector from data-target', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="test" data-target=".target"></div>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should get selector from href if no data-target set', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should get selector from href if data-target equal to #', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<a id="test" data-target="#" href=".target"></a>',
|
||||
'<div class="target"></div>'
|
||||
].join('')
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
|
||||
})
|
||||
|
||||
it('should return null if selector not found', () => {
|
||||
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'
|
||||
|
||||
const testEl = fixtureEl.querySelector('#test')
|
||||
|
||||
expect(Util.getSelectorFromElement(testEl)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getTransitionDurationFromElement', () => {
|
||||
it('should get transition from element', () => {
|
||||
fixtureEl.innerHTML = '<div style="transition: all 300ms ease-out;"></div>'
|
||||
|
||||
expect(Util.getTransitionDurationFromElement(fixtureEl.querySelector('div'))).toEqual(300)
|
||||
})
|
||||
|
||||
it('should return 0 if the element is undefined or null', () => {
|
||||
expect(Util.getTransitionDurationFromElement(null)).toEqual(0)
|
||||
expect(Util.getTransitionDurationFromElement(undefined)).toEqual(0)
|
||||
})
|
||||
|
||||
it('should return 0 if the element do not possess transition', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
expect(Util.getTransitionDurationFromElement(fixtureEl.querySelector('div'))).toEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('triggerTransitionEnd', () => {
|
||||
it('should trigger transitionend event', done => {
|
||||
fixtureEl.innerHTML = '<div style="transition: all 300ms ease-out;"></div>'
|
||||
|
||||
const el = fixtureEl.querySelector('div')
|
||||
|
||||
el.addEventListener('transitionend', () => {
|
||||
expect().nothing()
|
||||
done()
|
||||
})
|
||||
|
||||
Util.triggerTransitionEnd(el)
|
||||
})
|
||||
})
|
||||
|
||||
describe('isElement', () => {
|
||||
it('should detect if the parameter is an element or not', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const el = document.querySelector('div')
|
||||
|
||||
expect(Util.isElement(el)).toEqual(el.nodeType)
|
||||
expect(Util.isElement({})).toEqual(undefined)
|
||||
})
|
||||
|
||||
it('should detect jQuery element', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const el = document.querySelector('div')
|
||||
const fakejQuery = {
|
||||
0: el
|
||||
}
|
||||
|
||||
expect(Util.isElement(fakejQuery)).toEqual(el.nodeType)
|
||||
})
|
||||
})
|
||||
|
||||
describe('emulateTransitionEnd', () => {
|
||||
it('should emulate transition end', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const el = document.querySelector('div')
|
||||
const spy = spyOn(window, 'setTimeout')
|
||||
|
||||
Util.emulateTransitionEnd(el, 10)
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not emulate transition end if already triggered', done => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const el = fixtureEl.querySelector('div')
|
||||
const spy = spyOn(el, 'removeEventListener')
|
||||
|
||||
Util.emulateTransitionEnd(el, 10)
|
||||
Util.triggerTransitionEnd(el)
|
||||
|
||||
setTimeout(() => {
|
||||
expect(spy).toHaveBeenCalled()
|
||||
done()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
describe('typeCheckConfig', () => {
|
||||
it('should check type of the config object', () => {
|
||||
const namePlugin = 'collapse'
|
||||
const defaultType = {
|
||||
toggle: 'boolean',
|
||||
parent: '(string|element)'
|
||||
}
|
||||
const config = {
|
||||
toggle: true,
|
||||
parent: 777
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
Util.typeCheckConfig(namePlugin, config, defaultType)
|
||||
}).toThrow(new Error('COLLAPSE: Option "parent" provided type "number" but expected type "(string|element)".'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('makeArray', () => {
|
||||
it('should convert node list to array', () => {
|
||||
const nodeList = document.querySelectorAll('div')
|
||||
|
||||
expect(Array.isArray(nodeList)).toEqual(false)
|
||||
expect(Array.isArray(Util.makeArray(nodeList))).toEqual(true)
|
||||
})
|
||||
|
||||
it('should return an empty array if the nodeList is undefined', () => {
|
||||
expect(Util.makeArray(null)).toEqual([])
|
||||
expect(Util.makeArray(undefined)).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('isVisible', () => {
|
||||
it('should return false if the element is not defined', () => {
|
||||
expect(Util.isVisible(null)).toEqual(false)
|
||||
expect(Util.isVisible(undefined)).toEqual(false)
|
||||
})
|
||||
|
||||
it('should return false if the element provided is not a dom element', () => {
|
||||
expect(Util.isVisible({})).toEqual(false)
|
||||
})
|
||||
|
||||
it('should return false if the element is not visible with display none', () => {
|
||||
fixtureEl.innerHTML = '<div style="display: none;"></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
expect(Util.isVisible(div)).toEqual(false)
|
||||
})
|
||||
|
||||
it('should return false if the element is not visible with visibility hidden', () => {
|
||||
fixtureEl.innerHTML = '<div style="visibility: hidden;"></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
expect(Util.isVisible(div)).toEqual(false)
|
||||
})
|
||||
|
||||
it('should return false if the parent element is not visible', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
expect(Util.isVisible(div)).toEqual(false)
|
||||
})
|
||||
|
||||
it('should return true if the element is visible', () => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div>',
|
||||
' <div id="element"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const div = fixtureEl.querySelector('#element')
|
||||
|
||||
expect(Util.isVisible(div)).toEqual(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('findShadowRoot', () => {
|
||||
it('should return null if shadow dom is not available', () => {
|
||||
// Only for newer browsers
|
||||
if (!document.documentElement.attachShadow) {
|
||||
expect().nothing()
|
||||
return
|
||||
}
|
||||
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
spyOn(document.documentElement, 'attachShadow').and.returnValue(null)
|
||||
|
||||
expect(Util.findShadowRoot(div)).toEqual(null)
|
||||
})
|
||||
|
||||
it('should return null when we do not find a shadow root', () => {
|
||||
// Only for newer browsers
|
||||
if (!document.documentElement.attachShadow) {
|
||||
expect().nothing()
|
||||
return
|
||||
}
|
||||
|
||||
spyOn(document, 'getRootNode').and.returnValue(undefined)
|
||||
|
||||
expect(Util.findShadowRoot(document)).toEqual(null)
|
||||
})
|
||||
|
||||
it('should return the shadow root when found', () => {
|
||||
// Only for newer browsers
|
||||
if (!document.documentElement.attachShadow) {
|
||||
expect().nothing()
|
||||
return
|
||||
}
|
||||
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const shadowRoot = div.attachShadow({
|
||||
mode: 'open'
|
||||
})
|
||||
|
||||
expect(Util.findShadowRoot(shadowRoot)).toEqual(shadowRoot)
|
||||
|
||||
shadowRoot.innerHTML = '<button>Shadow Button</button>'
|
||||
|
||||
expect(Util.findShadowRoot(shadowRoot.firstChild)).toEqual(shadowRoot)
|
||||
})
|
||||
})
|
||||
|
||||
describe('noop', () => {
|
||||
it('should return a function', () => {
|
||||
expect(typeof Util.noop()).toEqual('function')
|
||||
})
|
||||
})
|
||||
|
||||
describe('reflow', () => {
|
||||
it('should return element offset height to force the reflow', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
expect(Util.reflow(div)).toEqual(0)
|
||||
})
|
||||
})
|
||||
})
|
70
js/src/util/sanitizer.spec.js
Normal file
70
js/src/util/sanitizer.spec.js
Normal file
@ -0,0 +1,70 @@
|
||||
import { DefaultWhitelist, sanitizeHtml } from './sanitizer'
|
||||
|
||||
describe('Sanitizer', () => {
|
||||
describe('sanitizeHtml', () => {
|
||||
it('should return the same on empty string', () => {
|
||||
const empty = ''
|
||||
|
||||
const result = sanitizeHtml(empty, DefaultWhitelist, null)
|
||||
|
||||
expect(result).toEqual(empty)
|
||||
})
|
||||
|
||||
it('should sanitize template by removing tags with XSS', () => {
|
||||
const template = [
|
||||
'<div>',
|
||||
' <a href="javascript:alert(7)">Click me</a>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const result = sanitizeHtml(template, DefaultWhitelist, null)
|
||||
|
||||
expect(result.indexOf('script') === -1).toEqual(true)
|
||||
})
|
||||
|
||||
it('should allow aria attributes and safe attributes', () => {
|
||||
const template = [
|
||||
'<div aria-pressed="true">',
|
||||
' <span class="test">Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const result = sanitizeHtml(template, DefaultWhitelist, null)
|
||||
|
||||
expect(result.indexOf('aria-pressed') !== -1).toEqual(true)
|
||||
expect(result.indexOf('class="test"') !== -1).toEqual(true)
|
||||
})
|
||||
|
||||
it('should remove not whitelist tags', () => {
|
||||
const template = [
|
||||
'<div>',
|
||||
' <script>alert(7)</script>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const result = sanitizeHtml(template, DefaultWhitelist, null)
|
||||
|
||||
expect(result.indexOf('<script>') === -1).toEqual(true)
|
||||
})
|
||||
|
||||
it('should not use native api to sanitize if a custom function passed', () => {
|
||||
const template = [
|
||||
'<div>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
function mySanitize(htmlUnsafe) {
|
||||
return htmlUnsafe
|
||||
}
|
||||
|
||||
spyOn(DOMParser.prototype, 'parseFromString')
|
||||
|
||||
const result = sanitizeHtml(template, DefaultWhitelist, mySanitize)
|
||||
|
||||
expect(result).toEqual(template)
|
||||
expect(DOMParser.prototype.parseFromString).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
@ -1,20 +1,16 @@
|
||||
## How does Bootstrap's test suite work?
|
||||
|
||||
Bootstrap uses [QUnit](https://qunitjs.com/) and [Sinon](https://sinonjs.org/). Each plugin has a file dedicated to its tests in `unit/<plugin-name>.js`.
|
||||
Bootstrap uses [Jasmine](https://jasmine.github.io/). Each plugin has a file dedicated to its tests in `src/<plugin-name>/<plugin-name>.spec.js`.
|
||||
|
||||
* `unit/` contains the unit test files for each Bootstrap plugin.
|
||||
* `vendor/` contains third-party testing-related code (QUnit, jQuery and Sinon).
|
||||
* `visual/` contains "visual" tests which are run interactively in real browsers and require manual verification by humans.
|
||||
|
||||
To run the unit test suite via [Karma](https://karma-runner.github.io/), run `npm run js-test`.
|
||||
|
||||
To run the unit test suite via a real web browser, open `index.html` in the browser.
|
||||
|
||||
To run the unit test suite via [Karma](https://karma-runner.github.io/) and debug, run `npm run js-debug`.
|
||||
|
||||
## How do I add a new unit test?
|
||||
|
||||
1. Locate and open the file dedicated to the plugin which you need to add tests to (`unit/<plugin-name>.js`).
|
||||
2. Review the [QUnit API Documentation](https://api.qunitjs.com/) and use the existing tests as references for how to structure your new tests.
|
||||
1. Locate and open the file dedicated to the plugin which you need to add tests to (`src/<plugin-name>/<plugin-name>.spec.js`).
|
||||
2. Review the [Jasmine API Documentation](https://jasmine.github.io/pages/docs_home.html) and use the existing tests as references for how to structure your new tests.
|
||||
3. Write the necessary unit test(s) for the new or revised functionality.
|
||||
4. Run `npm run js-test` to see the results of your newly-added test(s).
|
||||
|
||||
@ -23,47 +19,53 @@ To run the unit test suite via a real web browser, open `index.html` in the brow
|
||||
## What should a unit test look like?
|
||||
|
||||
* Each test should have a unique name clearly stating what unit is being tested.
|
||||
* Each test should be in the corresponding `describe`.
|
||||
* Each test should test only one unit per test, although one test can include several assertions. Create multiple tests for multiple units of functionality.
|
||||
* Each test should begin with [`assert.expect`](https://api.qunitjs.com/assert/expect/) to ensure that the expected assertions are run.
|
||||
* Each test should use [`expect`](https://jasmine.github.io/api/edge/matchers.html) to ensure something is expected.
|
||||
* Each test should follow the project's [JavaScript Code Guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#js)
|
||||
|
||||
## Code coverage
|
||||
|
||||
Currently we're aiming for at least 80% test coverage for our code. To ensure your changes meet or exceed this limit, run `npm run js-compile && npm run js-test` and open the file in `js/coverage/lcov-report/index.html` to see the code coverage for each plugin. See more details when you select a plugin and ensure your change is fully covered by unit tests.
|
||||
Currently we're aiming for at least 90% test coverage for our code. To ensure your changes meet or exceed this limit, run `npm run js-compile && npm run js-test` and open the file in `js/coverage/lcov-report/index.html` to see the code coverage for each plugin. See more details when you select a plugin and ensure your change is fully covered by unit tests.
|
||||
|
||||
### Example tests
|
||||
|
||||
```js
|
||||
// Synchronous test
|
||||
QUnit.test('should describe the unit being tested', function (assert) {
|
||||
assert.expect(1)
|
||||
var templateHTML = '<div class="alert alert-danger fade show">' +
|
||||
'<a class="close" href="#" data-dismiss="alert">×</a>' +
|
||||
'<p><strong>Template necessary for the test.</p>' +
|
||||
'</div>'
|
||||
var $alert = $(templateHTML).appendTo('#qunit-fixture').bootstrapAlert()
|
||||
describe('_getInstance', () => {
|
||||
it('should return null if there is no instance', () => {
|
||||
// Make assertion
|
||||
expect(Tab._getInstance(fixtureEl)).toEqual(null)
|
||||
})
|
||||
|
||||
$alert.find('.close').trigger('click')
|
||||
it('should return this instance', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
// Make assertion
|
||||
assert.strictEqual($alert.hasClass('show'), false, 'remove .show class on .close click')
|
||||
const divEl = fixtureEl.querySelector('div')
|
||||
const tab = new Tab(divEl)
|
||||
|
||||
// Make assertion
|
||||
expect(Tab._getInstance(divEl)).toEqual(tab)
|
||||
})
|
||||
})
|
||||
|
||||
// Asynchronous test
|
||||
QUnit.test('should describe the unit being tested', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
it('should show a tooltip without the animation', done => {
|
||||
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"/>'
|
||||
|
||||
var $tooltip = $('<div title="tooltip title"></div>').bootstrapTooltip()
|
||||
var tooltipInstance = $tooltip.data('bs.tooltip')
|
||||
var spyShow = sinon.spy(tooltipInstance, 'show')
|
||||
const tooltipEl = fixtureEl.querySelector('a')
|
||||
const tooltip = new Tooltip(tooltipEl, {
|
||||
animation: false
|
||||
})
|
||||
|
||||
$tooltip.appendTo('#qunit-fixture')
|
||||
.on('shown.bs.tooltip', function () {
|
||||
assert.ok(true, '"shown" event was fired after calling "show"')
|
||||
assert.ok(spyShow.called, 'show called')
|
||||
done()
|
||||
})
|
||||
.bootstrapTooltip('show')
|
||||
tooltipEl.addEventListener('shown.bs.tooltip', () => {
|
||||
const tip = document.querySelector('.tooltip')
|
||||
|
||||
expect(tip).toBeDefined()
|
||||
expect(tip.classList.contains('fade')).toEqual(false)
|
||||
done()
|
||||
})
|
||||
|
||||
tooltip.show()
|
||||
})
|
||||
```
|
||||
|
20
js/tests/helpers/fixture.js
Normal file
20
js/tests/helpers/fixture.js
Normal file
@ -0,0 +1,20 @@
|
||||
const fixtureId = 'fixture'
|
||||
|
||||
export const getFixture = () => {
|
||||
let fixtureEl = document.getElementById(fixtureId)
|
||||
|
||||
if (!fixtureEl) {
|
||||
fixtureEl = document.createElement('div')
|
||||
fixtureEl.setAttribute('id', fixtureId)
|
||||
fixtureEl.style.display = 'none'
|
||||
document.body.appendChild(fixtureEl)
|
||||
}
|
||||
|
||||
return fixtureEl
|
||||
}
|
||||
|
||||
export const clearFixture = () => {
|
||||
const fixtureEl = getFixture()
|
||||
|
||||
fixtureEl.innerHTML = ''
|
||||
}
|
@ -7,22 +7,19 @@ const {
|
||||
browsers,
|
||||
browsersKeys
|
||||
} = require('./browsers')
|
||||
const babel = require('rollup-plugin-babel')
|
||||
const istanbul = require('rollup-plugin-istanbul')
|
||||
|
||||
const { env } = process
|
||||
const bundle = env.BUNDLE === 'true'
|
||||
const browserStack = env.BROWSER === 'true'
|
||||
const debug = env.DEBUG === 'true'
|
||||
|
||||
const jqueryFile = 'node_modules/jquery/dist/jquery.slim.min.js'
|
||||
|
||||
const frameworks = [
|
||||
'qunit',
|
||||
'sinon'
|
||||
'jasmine'
|
||||
]
|
||||
|
||||
const plugins = [
|
||||
'karma-qunit',
|
||||
'karma-sinon'
|
||||
'karma-jasmine',
|
||||
'karma-rollup-preprocessor'
|
||||
]
|
||||
|
||||
const reporters = ['dots']
|
||||
@ -49,10 +46,35 @@ const customLaunchers = {
|
||||
}
|
||||
}
|
||||
|
||||
let files = [
|
||||
'node_modules/popper.js/dist/umd/popper.min.js',
|
||||
'node_modules/hammer-simulator/index.js'
|
||||
]
|
||||
const rollupPreprocessor = {
|
||||
plugins: [
|
||||
istanbul({
|
||||
exclude: ['js/src/**/*.spec.js']
|
||||
}),
|
||||
babel({
|
||||
// Only transpile our source code
|
||||
exclude: 'node_modules/**',
|
||||
// Include only required helpers
|
||||
externalHelpersWhitelist: [
|
||||
'defineProperties',
|
||||
'createClass',
|
||||
'inheritsLoose',
|
||||
'defineProperty',
|
||||
'objectSpread2'
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-object-rest-spread'
|
||||
]
|
||||
})
|
||||
],
|
||||
output: {
|
||||
format: 'iife',
|
||||
name: 'bootstrapTest',
|
||||
sourcemap: 'inline'
|
||||
}
|
||||
}
|
||||
|
||||
let files = []
|
||||
|
||||
const conf = {
|
||||
basePath: '../..',
|
||||
@ -62,28 +84,11 @@ const conf = {
|
||||
singleRun: true,
|
||||
concurrency: Infinity,
|
||||
client: {
|
||||
qunit: {
|
||||
showUI: true
|
||||
}
|
||||
clearContext: false
|
||||
}
|
||||
}
|
||||
|
||||
if (bundle) {
|
||||
frameworks.push('detectBrowsers')
|
||||
plugins.push(
|
||||
'karma-chrome-launcher',
|
||||
'karma-firefox-launcher',
|
||||
'karma-detect-browsers'
|
||||
)
|
||||
conf.customLaunchers = customLaunchers
|
||||
conf.detectBrowsers = detectBrowsers
|
||||
files = files.concat([
|
||||
jqueryFile,
|
||||
'js/tests/unit/tests-polyfills.js',
|
||||
'dist/js/bootstrap.js',
|
||||
'js/tests/unit/!(tests-polyfills).js'
|
||||
])
|
||||
} else if (browserStack) {
|
||||
if (browserStack) {
|
||||
conf.hostname = ip.address()
|
||||
conf.browserStack = {
|
||||
username: env.BROWSER_STACK_USERNAME,
|
||||
@ -92,27 +97,17 @@ if (bundle) {
|
||||
project: 'Bootstrap',
|
||||
retryLimit: 2
|
||||
}
|
||||
plugins.push('karma-browserstack-launcher')
|
||||
plugins.push('karma-browserstack-launcher', 'karma-jasmine-html-reporter')
|
||||
conf.customLaunchers = browsers
|
||||
conf.browsers = browsersKeys
|
||||
reporters.push('BrowserStack')
|
||||
reporters.push('BrowserStack', 'kjhtml')
|
||||
files = files.concat([
|
||||
jqueryFile,
|
||||
'js/tests/unit/tests-polyfills.js',
|
||||
'js/coverage/dist/util/index.js',
|
||||
'js/coverage/dist/util/sanitizer.js',
|
||||
'js/coverage/dist/dom/polyfill.js',
|
||||
'js/coverage/dist/dom/event-handler.js',
|
||||
'js/coverage/dist/dom/selector-engine.js',
|
||||
'js/coverage/dist/dom/data.js',
|
||||
'js/coverage/dist/dom/manipulator.js',
|
||||
'js/coverage/dist/dom/!(polyfill).js',
|
||||
'js/coverage/dist/tooltip.js',
|
||||
'js/coverage/dist/!(util|index|tooltip).js', // include all of our js/dist files except util.js, index.js and tooltip.js
|
||||
'js/tests/unit/!(tests-polyfills).js',
|
||||
'js/tests/unit/dom/*.js',
|
||||
'js/tests/unit/util/*.js'
|
||||
{ pattern: 'js/src/**/*.spec.js', watched: false }
|
||||
])
|
||||
conf.preprocessors = {
|
||||
'js/src/**/*.spec.js': ['rollup']
|
||||
}
|
||||
conf.rollupPreprocessor = rollupPreprocessor
|
||||
} else {
|
||||
frameworks.push('detectBrowsers')
|
||||
plugins.push(
|
||||
@ -122,23 +117,13 @@ if (bundle) {
|
||||
'karma-coverage-istanbul-reporter'
|
||||
)
|
||||
files = files.concat([
|
||||
jqueryFile,
|
||||
'js/tests/unit/tests-polyfills.js',
|
||||
'js/coverage/dist/util/index.js',
|
||||
'js/coverage/dist/util/sanitizer.js',
|
||||
'js/coverage/dist/dom/polyfill.js',
|
||||
'js/coverage/dist/dom/event-handler.js',
|
||||
'js/coverage/dist/dom/selector-engine.js',
|
||||
'js/coverage/dist/dom/data.js',
|
||||
'js/coverage/dist/dom/manipulator.js',
|
||||
'js/coverage/dist/dom/!(polyfill).js',
|
||||
'js/coverage/dist/tooltip.js',
|
||||
'js/coverage/dist/!(util|index|tooltip).js', // include all of our js/dist files except util.js, index.js and tooltip.js
|
||||
'js/tests/unit/!(tests-polyfills).js',
|
||||
'js/tests/unit/dom/*.js',
|
||||
'js/tests/unit/util/*.js'
|
||||
{ pattern: 'js/src/**/*.spec.js', watched: true }
|
||||
])
|
||||
reporters.push('coverage-istanbul')
|
||||
conf.preprocessors = {
|
||||
'js/src/**/*.spec.js': ['rollup']
|
||||
}
|
||||
conf.rollupPreprocessor = rollupPreprocessor
|
||||
conf.customLaunchers = customLaunchers
|
||||
conf.detectBrowsers = detectBrowsers
|
||||
conf.coverageIstanbulReporter = {
|
||||
@ -148,8 +133,8 @@ if (bundle) {
|
||||
emitWarning: false,
|
||||
global: {
|
||||
statements: 90,
|
||||
branches: 86,
|
||||
functions: 89,
|
||||
branches: 90,
|
||||
functions: 90,
|
||||
lines: 90
|
||||
},
|
||||
each: {
|
||||
@ -166,6 +151,9 @@ if (bundle) {
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
conf.hostname = ip.address()
|
||||
plugins.push('karma-jasmine-html-reporter')
|
||||
reporters.push('kjhtml')
|
||||
conf.singleRun = false
|
||||
conf.autoWatch = true
|
||||
}
|
||||
|
@ -1,123 +0,0 @@
|
||||
$(function () {
|
||||
'use strict'
|
||||
|
||||
var Alert = typeof window.bootstrap === 'undefined' ? window.Alert : window.bootstrap.Alert
|
||||
|
||||
QUnit.module('alert plugin')
|
||||
|
||||
QUnit.test('should be defined on jquery object', function (assert) {
|
||||
assert.expect(1)
|
||||
assert.ok($(document.body).alert, 'alert method is defined')
|
||||
})
|
||||
|
||||
QUnit.module('alert', {
|
||||
beforeEach: function () {
|
||||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
||||
$.fn.bootstrapAlert = $.fn.alert.noConflict()
|
||||
},
|
||||
afterEach: function () {
|
||||
$.fn.alert = $.fn.bootstrapAlert
|
||||
delete $.fn.bootstrapAlert
|
||||
$('#qunit-fixture').html('')
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('should provide no conflict', function (assert) {
|
||||
assert.expect(1)
|
||||
assert.strictEqual(typeof $.fn.alert, 'undefined', 'alert was set back to undefined (org value)')
|
||||
})
|
||||
|
||||
QUnit.test('should return jquery collection containing the element', function (assert) {
|
||||
assert.expect(2)
|
||||
var $el = $('<div/>')
|
||||
var $alert = $el.bootstrapAlert()
|
||||
assert.ok($alert instanceof $, 'returns jquery collection')
|
||||
assert.strictEqual($alert[0], $el[0], 'collection contains element')
|
||||
})
|
||||
|
||||
QUnit.test('should fade element out on clicking .close', function (assert) {
|
||||
assert.expect(1)
|
||||
var alertHTML = '<div class="alert alert-danger fade show">' +
|
||||
'<a class="close" href="#" data-dismiss="alert">×</a>' +
|
||||
'<p><strong>Holy guacamole!</strong> Best check yo self, you\'re not looking too good.</p>' +
|
||||
'</div>'
|
||||
|
||||
var $alert = $(alertHTML).bootstrapAlert().appendTo($('#qunit-fixture'))
|
||||
|
||||
var closeBtn = $alert.find('.close')[0]
|
||||
closeBtn.dispatchEvent(new Event('click'))
|
||||
assert.strictEqual($alert.hasClass('show'), false, 'remove .show class on .close click')
|
||||
})
|
||||
|
||||
QUnit.test('should remove element when clicking .close', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var alertHTML = '<div class="alert alert-danger fade show">' +
|
||||
'<a class="close" href="#" data-dismiss="alert">×</a>' +
|
||||
'<p><strong>Holy guacamole!</strong> Best check yo self, you\'re not looking too good.</p>' +
|
||||
'</div>'
|
||||
var $alert = $(alertHTML).appendTo('#qunit-fixture').bootstrapAlert()
|
||||
|
||||
assert.notEqual($('#qunit-fixture').find('.alert').length, 0, 'element added to dom')
|
||||
|
||||
$alert[0].addEventListener('closed.bs.alert', function () {
|
||||
assert.strictEqual($('#qunit-fixture').find('.alert').length, 0, 'element removed from dom')
|
||||
done()
|
||||
})
|
||||
|
||||
var closeBtn = $alert.find('.close')[0]
|
||||
closeBtn.dispatchEvent(new Event('click'))
|
||||
})
|
||||
|
||||
QUnit.test('should not fire closed when close is prevented', function (assert) {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
var $alert = $('<div class="alert"/>')
|
||||
$alert.appendTo('#qunit-fixture')
|
||||
|
||||
$alert[0].addEventListener('close.bs.alert', function (e) {
|
||||
e.preventDefault()
|
||||
assert.ok(true, 'close event fired')
|
||||
done()
|
||||
})
|
||||
$alert[0].addEventListener('closed.bs.alert', function () {
|
||||
assert.ok(false, 'closed event fired')
|
||||
})
|
||||
|
||||
$alert.bootstrapAlert('close')
|
||||
})
|
||||
|
||||
QUnit.test('close should use internal _element if no element provided', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var done = assert.async()
|
||||
var $el = $('<div/>')
|
||||
var $alert = $el.bootstrapAlert()
|
||||
var alertInstance = Alert._getInstance($alert[0])
|
||||
|
||||
$alert[0].addEventListener('closed.bs.alert', function () {
|
||||
assert.ok('alert closed')
|
||||
done()
|
||||
})
|
||||
|
||||
alertInstance.close()
|
||||
})
|
||||
|
||||
QUnit.test('dispose should remove data and the element', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var $el = $('<div/>')
|
||||
var $alert = $el.bootstrapAlert()
|
||||
|
||||
assert.ok(typeof Alert._getInstance($alert[0]) !== 'undefined')
|
||||
|
||||
Alert._getInstance($alert[0]).dispose()
|
||||
|
||||
assert.ok(Alert._getInstance($alert[0]) === null)
|
||||
})
|
||||
|
||||
QUnit.test('should return the version', function (assert) {
|
||||
assert.expect(1)
|
||||
assert.strictEqual(typeof Alert.VERSION, 'string')
|
||||
})
|
||||
})
|
@ -1,83 +0,0 @@
|
||||
$(function () {
|
||||
'use strict'
|
||||
|
||||
QUnit.module('data')
|
||||
|
||||
QUnit.test('should be defined', function (assert) {
|
||||
assert.expect(1)
|
||||
assert.ok(Data, 'Data is defined')
|
||||
})
|
||||
|
||||
QUnit.test('should set data in a element', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var $div = $('<div />').appendTo('#qunit-fixture')
|
||||
var data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
Data.setData($div[0], 'test', data)
|
||||
|
||||
assert.ok($div[0].key, 'element have a data key')
|
||||
})
|
||||
|
||||
QUnit.test('should get data from an element', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var $div = $('<div />').appendTo('#qunit-fixture')
|
||||
var data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
Data.setData($div[0], 'test', data)
|
||||
|
||||
assert.strictEqual(Data.getData($div[0], 'test'), data)
|
||||
})
|
||||
|
||||
QUnit.test('should return null if nothing is stored', function (assert) {
|
||||
assert.expect(1)
|
||||
assert.ok(Data.getData(document.body, 'test') === null)
|
||||
})
|
||||
|
||||
QUnit.test('should return null if nothing is stored with an existing key', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var $div = $('<div />').appendTo('#qunit-fixture')
|
||||
$div[0].key = {
|
||||
key: 'test2',
|
||||
data: 'woot woot'
|
||||
}
|
||||
|
||||
assert.ok(Data.getData($div[0], 'test') === null)
|
||||
})
|
||||
|
||||
QUnit.test('should delete data', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var $div = $('<div />').appendTo('#qunit-fixture')
|
||||
var data = {
|
||||
test: 'bsData'
|
||||
}
|
||||
Data.setData($div[0], 'test', data)
|
||||
assert.ok(Data.getData($div[0], 'test') !== null)
|
||||
|
||||
Data.removeData($div[0], 'test')
|
||||
assert.ok(Data.getData($div[0], 'test') === null)
|
||||
})
|
||||
|
||||
QUnit.test('should delete nothing if there are nothing', function (assert) {
|
||||
assert.expect(0)
|
||||
|
||||
Data.removeData(document.body, 'test')
|
||||
})
|
||||
|
||||
QUnit.test('should delete nothing if not the good key', function (assert) {
|
||||
assert.expect(0)
|
||||
|
||||
var $div = $('<div />').appendTo('#qunit-fixture')
|
||||
$div[0].key = {
|
||||
key: 'test2',
|
||||
data: 'woot woot'
|
||||
}
|
||||
|
||||
Data.removeData($div[0], 'test')
|
||||
})
|
||||
})
|
@ -1,340 +0,0 @@
|
||||
$(function () {
|
||||
'use strict'
|
||||
|
||||
QUnit.module('eventHandler')
|
||||
|
||||
QUnit.test('should be defined', function (assert) {
|
||||
assert.expect(1)
|
||||
assert.ok(EventHandler, 'EventHandler is defined')
|
||||
})
|
||||
|
||||
QUnit.test('should trigger event correctly', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
element.addEventListener('foobar', function () {
|
||||
assert.ok(true, 'listener called')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
})
|
||||
|
||||
QUnit.test('should trigger event through jQuery event system', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
$(element).on('foobar', function () {
|
||||
assert.ok(true, 'listener called')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
})
|
||||
|
||||
QUnit.test('should trigger namespaced event through jQuery event system', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var element = document.createElement('div')
|
||||
$(element).on('foobar.namespace', function () {
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
element.addEventListener('foobar.namespace', function () {
|
||||
assert.ok(true, 'second listener called')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'foobar.namespace')
|
||||
})
|
||||
|
||||
QUnit.test('should mirror preventDefault', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var element = document.createElement('div')
|
||||
$(element).on('foobar.namespace', function (event) {
|
||||
event.preventDefault()
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
element.addEventListener('foobar.namespace', function (event) {
|
||||
assert.ok(event.defaultPrevented, 'defaultPrevented is true in second listener')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'foobar.namespace')
|
||||
})
|
||||
|
||||
QUnit.test('should mirror preventDefault for native events', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var element = document.createElement('div')
|
||||
document.body.appendChild(element)
|
||||
|
||||
$(element).on('click', function (event) {
|
||||
event.preventDefault()
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
element.addEventListener('click', function (event) {
|
||||
assert.ok(event.defaultPrevented, 'defaultPrevented is true in second listener')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'click')
|
||||
document.body.removeChild(element)
|
||||
})
|
||||
|
||||
QUnit.test('on should add event listener', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
EventHandler.on(element, 'foobar', function () {
|
||||
assert.ok(true, 'listener called')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
})
|
||||
|
||||
QUnit.test('on should add namespaced event listener', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
EventHandler.on(element, 'foobar.namespace', function () {
|
||||
assert.ok(true, 'listener called')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'foobar.namespace')
|
||||
})
|
||||
|
||||
QUnit.test('on should add native namespaced event listener', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
document.body.appendChild(element)
|
||||
EventHandler.on(element, 'click.namespace', function () {
|
||||
assert.ok(true, 'listener called')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'click')
|
||||
document.body.removeChild(element)
|
||||
})
|
||||
|
||||
QUnit.test('on should add delegated event listener', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
var subelement = document.createElement('span')
|
||||
element.appendChild(subelement)
|
||||
|
||||
var anchor = document.createElement('a')
|
||||
element.appendChild(anchor)
|
||||
|
||||
EventHandler.on(element, 'click.namespace', 'a', function () {
|
||||
assert.ok(true, 'listener called')
|
||||
})
|
||||
|
||||
EventHandler.on(element, 'click', 'span', function () {
|
||||
assert.notOk(true, 'listener should not be called')
|
||||
})
|
||||
|
||||
document.body.appendChild(element)
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
document.body.removeChild(element)
|
||||
})
|
||||
|
||||
QUnit.test('on should add delegated event listener if delegated selector differs', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
var subelement = document.createElement('span')
|
||||
element.appendChild(subelement)
|
||||
|
||||
var anchor = document.createElement('a')
|
||||
element.appendChild(anchor)
|
||||
|
||||
var i = 0
|
||||
var handler = function () {
|
||||
i++
|
||||
}
|
||||
|
||||
EventHandler.on(element, 'click', 'a', handler)
|
||||
EventHandler.on(element, 'click', 'span', handler)
|
||||
|
||||
document.body.appendChild(element)
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
document.body.removeChild(element)
|
||||
|
||||
assert.ok(i === 2, 'listeners called')
|
||||
})
|
||||
|
||||
QUnit.test('one should remove the listener after the event', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
EventHandler.one(element, 'foobar', function () {
|
||||
assert.ok(true, 'listener called')
|
||||
})
|
||||
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
})
|
||||
|
||||
QUnit.test('off should remove a listener', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var element = document.createElement('div')
|
||||
var handler = function () {
|
||||
assert.ok(true, 'listener called')
|
||||
}
|
||||
|
||||
EventHandler.on(element, 'foobar', handler)
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
|
||||
EventHandler.off(element, 'foobar', handler)
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
})
|
||||
|
||||
QUnit.test('off should remove all the listeners', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var element = document.createElement('div')
|
||||
|
||||
EventHandler.on(element, 'foobar', function () {
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
EventHandler.on(element, 'foobar', function () {
|
||||
assert.ok(true, 'second listener called')
|
||||
})
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
|
||||
EventHandler.off(element, 'foobar')
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
})
|
||||
|
||||
QUnit.test('off should remove all the namespaced listeners if namespace is passed', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var element = document.createElement('div')
|
||||
|
||||
EventHandler.on(element, 'foobar.namespace', function () {
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
EventHandler.on(element, 'foofoo.namespace', function () {
|
||||
assert.ok(true, 'second listener called')
|
||||
})
|
||||
EventHandler.trigger(element, 'foobar.namespace')
|
||||
EventHandler.trigger(element, 'foofoo.namespace')
|
||||
|
||||
EventHandler.off(element, '.namespace')
|
||||
EventHandler.trigger(element, 'foobar.namespace')
|
||||
EventHandler.trigger(element, 'foofoo.namespace')
|
||||
})
|
||||
|
||||
QUnit.test('off should remove the namespaced listeners', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var element = document.createElement('div')
|
||||
|
||||
EventHandler.on(element, 'foobar.namespace', function () {
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
EventHandler.on(element, 'foofoo.namespace', function () {
|
||||
assert.ok(true, 'second listener called')
|
||||
})
|
||||
EventHandler.trigger(element, 'foobar.namespace')
|
||||
|
||||
EventHandler.off(element, 'foobar.namespace')
|
||||
EventHandler.trigger(element, 'foobar.namespace')
|
||||
|
||||
EventHandler.trigger(element, 'foofoo.namespace')
|
||||
})
|
||||
|
||||
QUnit.test('off should remove the all the namespaced listeners for native events', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var element = document.createElement('div')
|
||||
document.body.appendChild(element)
|
||||
|
||||
EventHandler.on(element, 'click.namespace', function () {
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
EventHandler.on(element, 'click.namespace2', function () {
|
||||
assert.ok(true, 'second listener called')
|
||||
})
|
||||
EventHandler.trigger(element, 'click')
|
||||
|
||||
EventHandler.off(element, 'click')
|
||||
EventHandler.trigger(element, 'click')
|
||||
document.body.removeChild(element)
|
||||
})
|
||||
|
||||
QUnit.test('off should remove the specified namespaced listeners for native events', function (assert) {
|
||||
assert.expect(3)
|
||||
|
||||
var element = document.createElement('div')
|
||||
document.body.appendChild(element)
|
||||
|
||||
EventHandler.on(element, 'click.namespace', function () {
|
||||
assert.ok(true, 'first listener called')
|
||||
})
|
||||
EventHandler.on(element, 'click.namespace2', function () {
|
||||
assert.ok(true, 'second listener called')
|
||||
})
|
||||
EventHandler.trigger(element, 'click')
|
||||
|
||||
EventHandler.off(element, 'click.namespace')
|
||||
EventHandler.trigger(element, 'click')
|
||||
document.body.removeChild(element)
|
||||
})
|
||||
|
||||
QUnit.test('off should remove a listener registered by .one', function (assert) {
|
||||
assert.expect(0)
|
||||
|
||||
var element = document.createElement('div')
|
||||
var handler = function () {
|
||||
assert.notOk(true, 'listener called')
|
||||
}
|
||||
|
||||
EventHandler.one(element, 'foobar', handler)
|
||||
EventHandler.off(element, 'foobar', handler)
|
||||
|
||||
EventHandler.trigger(element, 'foobar')
|
||||
})
|
||||
|
||||
QUnit.test('off should remove the correct delegated event listener', function (assert) {
|
||||
assert.expect(5)
|
||||
|
||||
var element = document.createElement('div')
|
||||
var subelement = document.createElement('span')
|
||||
element.appendChild(subelement)
|
||||
|
||||
var anchor = document.createElement('a')
|
||||
element.appendChild(anchor)
|
||||
|
||||
var i = 0
|
||||
var handler = function () {
|
||||
i++
|
||||
}
|
||||
|
||||
EventHandler.on(element, 'click', 'a', handler)
|
||||
EventHandler.on(element, 'click', 'span', handler)
|
||||
|
||||
document.body.appendChild(element)
|
||||
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
assert.ok(i === 2, 'first listeners called')
|
||||
|
||||
EventHandler.off(element, 'click', 'span', handler)
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
assert.ok(i === 2, 'removed listener not called')
|
||||
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
assert.ok(i === 3, 'not removed listener called')
|
||||
|
||||
EventHandler.on(element, 'click', 'span', handler)
|
||||
EventHandler.trigger(anchor, 'click')
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
assert.ok(i === 5, 'listener re-registered')
|
||||
|
||||
EventHandler.off(element, 'click', 'span')
|
||||
EventHandler.trigger(subelement, 'click')
|
||||
assert.ok(i === 5, 'listener removed again')
|
||||
|
||||
document.body.removeChild(element)
|
||||
})
|
||||
})
|
@ -1,191 +0,0 @@
|
||||
$(function () {
|
||||
'use strict'
|
||||
|
||||
QUnit.module('util', {
|
||||
afterEach: function () {
|
||||
$('#qunit-fixture').html('')
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('Util.getSelectorFromElement should return the correct element', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var $el = $('<div data-target="body"></div>').appendTo($('#qunit-fixture'))
|
||||
assert.strictEqual(Util.getSelectorFromElement($el[0]), 'body')
|
||||
|
||||
// Not found element
|
||||
var $el2 = $('<div data-target="#fakeDiv"></div>').appendTo($('#qunit-fixture'))
|
||||
assert.strictEqual(Util.getSelectorFromElement($el2[0]), null)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getSelectorFromElement should return null when there is a bad selector', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var $el = $('<div data-target="#1"></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
assert.strictEqual(Util.getSelectorFromElement($el[0]), null)
|
||||
|
||||
var $el2 = $('<a href="/posts"></a>').appendTo($('#qunit-fixture'))
|
||||
|
||||
assert.strictEqual(Util.getSelectorFromElement($el2[0]), null)
|
||||
})
|
||||
|
||||
QUnit.test('Util.typeCheckConfig should thrown an error when a bad config is passed', function (assert) {
|
||||
assert.expect(1)
|
||||
var namePlugin = 'collapse'
|
||||
var defaultType = {
|
||||
toggle: 'boolean',
|
||||
parent: '(string|element)'
|
||||
}
|
||||
var config = {
|
||||
toggle: true,
|
||||
parent: 777
|
||||
}
|
||||
|
||||
try {
|
||||
Util.typeCheckConfig(namePlugin, config, defaultType)
|
||||
} catch (error) {
|
||||
assert.strictEqual(error.message, 'COLLAPSE: Option "parent" provided type "number" but expected type "(string|element)".')
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('Util.isElement should check if we passed an element or not', function (assert) {
|
||||
assert.expect(3)
|
||||
var $div = $('<div id="test"></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
assert.strictEqual(Util.isElement($div), 1)
|
||||
assert.strictEqual(Util.isElement($div[0]), 1)
|
||||
assert.strictEqual(typeof Util.isElement({}) === 'undefined', true)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getTransitionDurationFromElement should accept transition durations in milliseconds', function (assert) {
|
||||
assert.expect(1)
|
||||
var $div = $('<div style="transition: all 300ms ease-out;"></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
assert.strictEqual(Util.getTransitionDurationFromElement($div[0]), 300)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getTransitionDurationFromElement should accept transition durations in seconds', function (assert) {
|
||||
assert.expect(1)
|
||||
var $div = $('<div style="transition: all .4s ease-out;"></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
assert.strictEqual(Util.getTransitionDurationFromElement($div[0]), 400)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getTransitionDurationFromElement should return the addition of transition-delay and transition-duration', function (assert) {
|
||||
assert.expect(2)
|
||||
var $fixture = $('#qunit-fixture')
|
||||
var $div = $('<div style="transition: all 0s 150ms ease-out;"></div>').appendTo($fixture)
|
||||
var $div2 = $('<div style="transition: all .25s 30ms ease-out;"></div>').appendTo($fixture)
|
||||
|
||||
assert.strictEqual(Util.getTransitionDurationFromElement($div[0]), 150)
|
||||
assert.strictEqual(Util.getTransitionDurationFromElement($div2[0]), 280)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getTransitionDurationFromElement should get the first transition duration if multiple transition durations are defined', function (assert) {
|
||||
assert.expect(1)
|
||||
var $div = $('<div style="transition: transform .3s ease-out, opacity .2s;"></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
assert.strictEqual(Util.getTransitionDurationFromElement($div[0]), 300)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getTransitionDurationFromElement should return 0 if transition duration is not defined', function (assert) {
|
||||
assert.expect(1)
|
||||
var $div = $('<div></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
assert.strictEqual(Util.getTransitionDurationFromElement($div[0]), 0)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getTransitionDurationFromElement should return 0 if element is not found in DOM', function (assert) {
|
||||
assert.expect(1)
|
||||
var $div = $('#fake-id')
|
||||
|
||||
assert.strictEqual(Util.getTransitionDurationFromElement($div[0]), 0)
|
||||
})
|
||||
|
||||
QUnit.test('Util.getUID should generate a new id uniq', function (assert) {
|
||||
assert.expect(2)
|
||||
var id = Util.getUID('test')
|
||||
var id2 = Util.getUID('test')
|
||||
|
||||
assert.ok(id !== id2, id + ' !== ' + id2)
|
||||
|
||||
id = Util.getUID('test')
|
||||
$('<div id="' + id + '"></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
id2 = Util.getUID('test')
|
||||
assert.ok(id !== id2, id + ' !== ' + id2)
|
||||
})
|
||||
|
||||
QUnit.test('Util.findShadowRoot should find the shadow DOM root', function (assert) {
|
||||
// Only for newer browsers
|
||||
if (!document.documentElement.attachShadow) {
|
||||
assert.expect(0)
|
||||
return
|
||||
}
|
||||
|
||||
assert.expect(2)
|
||||
var $div = $('<div id="test"></div>').appendTo($('#qunit-fixture'))
|
||||
var shadowRoot = $div[0].attachShadow({
|
||||
mode: 'open'
|
||||
})
|
||||
|
||||
assert.equal(shadowRoot, Util.findShadowRoot(shadowRoot))
|
||||
shadowRoot.innerHTML = '<button>Shadow Button</button>'
|
||||
assert.equal(shadowRoot, Util.findShadowRoot(shadowRoot.firstChild))
|
||||
})
|
||||
|
||||
QUnit.test('Util.findShadowRoot should return null when attachShadow is not available', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var $div = $('<div id="test"></div>').appendTo($('#qunit-fixture'))
|
||||
if (document.documentElement.attachShadow) {
|
||||
var sandbox = sinon.createSandbox()
|
||||
|
||||
sandbox.replace(document.documentElement, 'attachShadow', function () {
|
||||
// to avoid empty function
|
||||
return $div
|
||||
})
|
||||
|
||||
assert.equal(null, Util.findShadowRoot($div[0]))
|
||||
sandbox.restore()
|
||||
} else {
|
||||
assert.equal(null, Util.findShadowRoot($div[0]))
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('noop should return an empty function', function (assert) {
|
||||
assert.expect(1)
|
||||
Util.noop().call()
|
||||
assert.ok(typeof Util.noop() === 'function')
|
||||
})
|
||||
|
||||
QUnit.test('should return jQuery if present', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
assert.equal(Util.jQuery, $)
|
||||
|
||||
$.noConflict()
|
||||
|
||||
assert.equal(Util.jQuery, jQuery)
|
||||
|
||||
window.$ = jQuery
|
||||
})
|
||||
|
||||
QUnit.test('Util.emulateTransitionEnd should emulate transition end', function (assert) {
|
||||
assert.expect(1)
|
||||
var $div = $('<div></div>').appendTo($('#qunit-fixture'))
|
||||
|
||||
var spy = sinon.spy($div[0], 'removeEventListener')
|
||||
|
||||
Util.emulateTransitionEnd($div[0], 7)
|
||||
|
||||
assert.ok(spy.notCalled)
|
||||
})
|
||||
|
||||
QUnit.test('Util.makeArray should return empty array on null', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
assert.ok(Util.makeArray(null).length === 0)
|
||||
})
|
||||
})
|
@ -1,51 +0,0 @@
|
||||
$(function () {
|
||||
'use strict'
|
||||
|
||||
QUnit.module('sanitizer', {
|
||||
afterEach: function () {
|
||||
$('#qunit-fixture').html('')
|
||||
}
|
||||
})
|
||||
|
||||
QUnit.test('should export a default white list', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
assert.ok(Sanitizer.DefaultWhitelist)
|
||||
})
|
||||
|
||||
QUnit.test('should sanitize template by removing tags with XSS', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var template = [
|
||||
'<div>',
|
||||
' <a href="javascript:alert(7)">Click me</a>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
var result = Sanitizer.sanitizeHtml(template, Sanitizer.DefaultWhitelist, null)
|
||||
|
||||
assert.strictEqual(result.indexOf('script'), -1)
|
||||
})
|
||||
|
||||
QUnit.test('should not use native api to sanitize if a custom function passed', function (assert) {
|
||||
assert.expect(2)
|
||||
|
||||
var template = [
|
||||
'<div>',
|
||||
' <span>Some content</span>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
function mySanitize(htmlUnsafe) {
|
||||
return htmlUnsafe
|
||||
}
|
||||
|
||||
var spy = sinon.spy(DOMParser.prototype, 'parseFromString')
|
||||
var result = Sanitizer.sanitizeHtml(template, Sanitizer.DefaultWhitelist, mySanitize)
|
||||
|
||||
assert.strictEqual(result, template)
|
||||
assert.strictEqual(spy.called, false)
|
||||
spy.restore()
|
||||
})
|
||||
})
|
516
package-lock.json
generated
516
package-lock.json
generated
@ -854,42 +854,6 @@
|
||||
"integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==",
|
||||
"dev": true
|
||||
},
|
||||
"@sinonjs/commons": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz",
|
||||
"integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-detect": "4.0.8"
|
||||
}
|
||||
},
|
||||
"@sinonjs/formatio": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz",
|
||||
"integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/commons": "^1",
|
||||
"@sinonjs/samsam": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"@sinonjs/samsam": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz",
|
||||
"integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/commons": "^1.0.2",
|
||||
"array-from": "^2.1.1",
|
||||
"lodash": "^4.17.11"
|
||||
}
|
||||
},
|
||||
"@sinonjs/text-encoding": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz",
|
||||
"integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@szmarczak/http-timer": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
|
||||
@ -1224,12 +1188,6 @@
|
||||
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
|
||||
"dev": true
|
||||
},
|
||||
"array-from": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz",
|
||||
"integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=",
|
||||
"dev": true
|
||||
},
|
||||
"array-includes": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
|
||||
@ -1395,6 +1353,50 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-code-frame": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^1.1.3",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "10.0.2",
|
||||
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.2.tgz",
|
||||
@ -1409,6 +1411,39 @@
|
||||
"eslint-visitor-keys": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"babel-generator": {
|
||||
"version": "6.26.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
|
||||
"integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"detect-indent": "^4.0.0",
|
||||
"jsesc": "^1.3.0",
|
||||
"lodash": "^4.17.4",
|
||||
"source-map": "^0.5.7",
|
||||
"trim-right": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsesc": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
|
||||
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-messages": {
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
|
||||
"integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.22.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-dynamic-import-node": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz",
|
||||
@ -1430,6 +1465,88 @@
|
||||
"test-exclude": "^5.2.3"
|
||||
}
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
|
||||
"integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-template": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
|
||||
"integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"lodash": "^4.17.4"
|
||||
}
|
||||
},
|
||||
"babel-traverse": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
|
||||
"integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.26.0",
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"debug": "^2.6.8",
|
||||
"globals": "^9.18.0",
|
||||
"invariant": "^2.2.2",
|
||||
"lodash": "^4.17.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"globals": {
|
||||
"version": "9.18.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
|
||||
"integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-types": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
|
||||
"integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.4",
|
||||
"to-fast-properties": "^1.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"to-fast-properties": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
|
||||
"integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"babylon": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
|
||||
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
|
||||
"dev": true
|
||||
},
|
||||
"backo2": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||
@ -2686,6 +2803,12 @@
|
||||
"integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==",
|
||||
"dev": true
|
||||
},
|
||||
"debounce": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz",
|
||||
"integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@ -2969,6 +3092,15 @@
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
|
||||
"dev": true
|
||||
},
|
||||
"detect-indent": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
|
||||
"integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"repeating": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
@ -2981,12 +3113,6 @@
|
||||
"integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
|
||||
"dev": true
|
||||
},
|
||||
"diff": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"dev": true
|
||||
},
|
||||
"dir-glob": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
|
||||
@ -6185,10 +6311,10 @@
|
||||
"is-object": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
|
||||
"integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==",
|
||||
"jasmine-core": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz",
|
||||
"integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==",
|
||||
"dev": true
|
||||
},
|
||||
"js-base64": {
|
||||
@ -6203,12 +6329,6 @@
|
||||
"integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
|
||||
"dev": true
|
||||
},
|
||||
"js-reporters": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/js-reporters/-/js-reporters-1.2.1.tgz",
|
||||
"integrity": "sha1-+IxgjjJKM3OpW8xFrTBeXJecRZs=",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@ -6323,12 +6443,6 @@
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"just-extend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz",
|
||||
"integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==",
|
||||
"dev": true
|
||||
},
|
||||
"karma": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz",
|
||||
@ -6528,17 +6642,131 @@
|
||||
"integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==",
|
||||
"dev": true
|
||||
},
|
||||
"karma-qunit": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/karma-qunit/-/karma-qunit-4.0.0.tgz",
|
||||
"integrity": "sha512-sGuMyTMbiA2zq/aV43uduwf58mMiMDiG6YH3dvaarQnwFLmyRD1i8356TndX8lFeVSOtykowtBtpcdGxyuezTA==",
|
||||
"karma-jasmine": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz",
|
||||
"integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jasmine-core": "^3.3"
|
||||
}
|
||||
},
|
||||
"karma-jasmine-html-reporter": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.4.2.tgz",
|
||||
"integrity": "sha512-7g0gPj8+9JepCNJR9WjDyQ2RkZ375jpdurYQyAYv8PorUCadepl8vrD6LmMqOGcM17cnrynBawQYZHaumgDjBw==",
|
||||
"dev": true
|
||||
},
|
||||
"karma-sinon": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/karma-sinon/-/karma-sinon-1.0.5.tgz",
|
||||
"integrity": "sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo=",
|
||||
"dev": true
|
||||
"karma-rollup-preprocessor": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.2.tgz",
|
||||
"integrity": "sha512-A+kr5FoiMr/S8dIPij/nuzB9PLhkrh3umFowjumAOKBDVQRhPYs3kKmQ82hP3+2MB6CICqeB4MmiIE4iTwUmDQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": "^3.0.2",
|
||||
"debounce": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.3.tgz",
|
||||
"integrity": "sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
||||
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
|
||||
"dev": true
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz",
|
||||
"integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"anymatch": "^3.0.1",
|
||||
"braces": "^3.0.2",
|
||||
"fsevents": "^2.0.6",
|
||||
"glob-parent": "^5.0.0",
|
||||
"is-binary-path": "^2.1.0",
|
||||
"is-glob": "^4.0.1",
|
||||
"normalize-path": "^3.0.0",
|
||||
"readdirp": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz",
|
||||
"integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz",
|
||||
"integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.1.tgz",
|
||||
"integrity": "sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"keyv": {
|
||||
"version": "3.0.0",
|
||||
@ -7143,27 +7371,6 @@
|
||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"nise": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz",
|
||||
"integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/formatio": "^3.1.0",
|
||||
"@sinonjs/text-encoding": "^0.7.1",
|
||||
"just-extend": "^4.0.2",
|
||||
"lolex": "^4.1.0",
|
||||
"path-to-regexp": "^1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lolex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz",
|
||||
"integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-abi": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.9.0.tgz",
|
||||
@ -7446,12 +7653,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-watch": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.6.0.tgz",
|
||||
"integrity": "sha512-XAgTL05z75ptd7JSVejH1a2Dm1zmXYhuDr9l230Qk6Z7/7GPcnAs/UyJJ4ggsXSvWil8iOzwQLW0zuGUvHpG8g==",
|
||||
"dev": true
|
||||
},
|
||||
"nodemon": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.1.tgz",
|
||||
@ -8357,23 +8558,6 @@
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
|
||||
"integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isarray": "0.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"path-type": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||
@ -9043,36 +9227,6 @@
|
||||
"integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=",
|
||||
"dev": true
|
||||
},
|
||||
"qunit": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/qunit/-/qunit-2.9.2.tgz",
|
||||
"integrity": "sha512-wTOYHnioWHcx5wa85Wl15IE7D6zTZe2CQlsodS14yj7s2FZ3MviRnQluspBZsueIDEO7doiuzKlv05yfky1R7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "2.12.2",
|
||||
"js-reporters": "1.2.1",
|
||||
"minimatch": "3.0.4",
|
||||
"node-watch": "0.6.0",
|
||||
"resolve": "1.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.12.2",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz",
|
||||
"integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
|
||||
"integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
@ -9209,6 +9363,12 @@
|
||||
"regenerate": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
|
||||
"dev": true
|
||||
},
|
||||
"regenerator-transform": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz",
|
||||
@ -9519,6 +9679,39 @@
|
||||
"rollup-pluginutils": "^2.8.1"
|
||||
}
|
||||
},
|
||||
"rollup-plugin-istanbul": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-istanbul/-/rollup-plugin-istanbul-2.0.1.tgz",
|
||||
"integrity": "sha512-5X1ExH74moFY/pHqCrAZQ0V8RyEMCmrUSuo1t1bDzv9UHTd54s79ALDaK8N87PgNzA6UuKtBVAP/tsaSYzIUVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"istanbul-lib-instrument": "^1.9.1",
|
||||
"rollup-pluginutils": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"istanbul-lib-coverage": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz",
|
||||
"integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==",
|
||||
"dev": true
|
||||
},
|
||||
"istanbul-lib-instrument": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz",
|
||||
"integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-generator": "^6.18.0",
|
||||
"babel-template": "^6.16.0",
|
||||
"babel-traverse": "^6.18.0",
|
||||
"babel-types": "^6.18.0",
|
||||
"babylon": "^6.18.0",
|
||||
"istanbul-lib-coverage": "^1.2.1",
|
||||
"semver": "^5.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rollup-plugin-node-resolve": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz",
|
||||
@ -10057,29 +10250,6 @@
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"sinon": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-7.3.2.tgz",
|
||||
"integrity": "sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/commons": "^1.4.0",
|
||||
"@sinonjs/formatio": "^3.2.1",
|
||||
"@sinonjs/samsam": "^3.3.1",
|
||||
"diff": "^3.5.0",
|
||||
"lolex": "^4.0.1",
|
||||
"nise": "^1.4.10",
|
||||
"supports-color": "^5.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lolex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz",
|
||||
"integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"slash": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
|
||||
@ -11293,12 +11463,6 @@
|
||||
"prelude-ls": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"type-detect": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
|
||||
"dev": true
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
|
||||
|
14
package.json
14
package.json
@ -47,7 +47,6 @@
|
||||
"js-compile-standalone-esm": "rollup --environment ESM:true,BUNDLE:false --config build/rollup.config.js --sourcemap",
|
||||
"js-compile-bundle": "rollup --environment BUNDLE:true --config build/rollup.config.js --sourcemap",
|
||||
"js-compile-plugins": "node build/build-plugins.js",
|
||||
"js-compile-plugins-coverage": "cross-env NODE_ENV=test node build/build-plugins.js",
|
||||
"js-lint": "npm-run-all --continue-on-error --parallel js-lint-*",
|
||||
"js-lint-main": "eslint --cache --cache-location .cache/.eslintcache js/src js/tests build/",
|
||||
"js-lint-docs": "eslint --cache --cache-location .cache/.eslintcache site/",
|
||||
@ -57,10 +56,9 @@
|
||||
"js-minify-standalone-esm": "terser --compress --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.esm.js.map,includeSources,url=bootstrap.esm.min.js.map\" --output dist/js/bootstrap.esm.min.js dist/js/bootstrap.esm.js",
|
||||
"js-minify-bundle": "terser --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.bundle.js.map,includeSources,url=bootstrap.bundle.min.js.map\" --output dist/js/bootstrap.bundle.min.js dist/js/bootstrap.bundle.js",
|
||||
"js-minify-docs": "cross-env-shell terser --mangle --comments \\\"/^!/\\\" --output site/static/docs/$npm_package_version_short/assets/js/docs.min.js site/static/docs/$npm_package_version_short/assets/js/vendor/anchor.min.js site/static/docs/$npm_package_version_short/assets/js/vendor/clipboard.min.js site/static/docs/$npm_package_version_short/assets/js/vendor/bs-custom-file-input.min.js \"site/static/docs/$npm_package_version_short/assets/js/src/*.js\"",
|
||||
"js-test": "npm-run-all js-test-karma* js-test-integration",
|
||||
"js-test": "npm-run-all js-test-karma js-test-integration",
|
||||
"js-debug": "cross-env DEBUG=true karma start js/tests/karma.conf.js",
|
||||
"js-test-karma": "karma start js/tests/karma.conf.js",
|
||||
"js-test-karma-bundle": "cross-env BUNDLE=true npm run js-test-karma",
|
||||
"js-test-integration": "rollup --config js/tests/integration/rollup.bundle.js",
|
||||
"js-test-cloud": "cross-env BROWSER=true npm run js-test-karma",
|
||||
"lint": "npm-run-all --parallel js-lint css-lint",
|
||||
@ -127,29 +125,29 @@
|
||||
"hammer-simulator": "0.0.1",
|
||||
"hugo-bin": "^0.43.6",
|
||||
"ip": "^1.1.5",
|
||||
"jquery": "^3.4.1",
|
||||
"jasmine-core": "^3.4.0",
|
||||
"karma": "^4.2.0",
|
||||
"karma-browserstack-launcher": "1.4.0",
|
||||
"karma-chrome-launcher": "^3.0.0",
|
||||
"karma-coverage-istanbul-reporter": "^2.0.6",
|
||||
"karma-detect-browsers": "^2.3.3",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-qunit": "^4.0.0",
|
||||
"karma-sinon": "^1.0.5",
|
||||
"karma-jasmine": "^2.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"karma-rollup-preprocessor": "^7.0.0",
|
||||
"linkinator": "^1.5.0",
|
||||
"node-sass": "^4.12.0",
|
||||
"nodemon": "^1.19.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"popper.js": "^1.15.0",
|
||||
"postcss-cli": "^6.1.3",
|
||||
"qunit": "^2.9.2",
|
||||
"rollup": "^1.17.0",
|
||||
"rollup-plugin-babel": "^4.3.3",
|
||||
"rollup-plugin-istanbul": "^2.0.1",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"serve": "^11.1.0",
|
||||
"shelljs": "^0.8.3",
|
||||
"shx": "^0.3.2",
|
||||
"sinon": "^7.3.2",
|
||||
"stylelint": "^10.1.0",
|
||||
"stylelint-config-twbs-bootstrap": "^0.3.1",
|
||||
"terser": "^4.1.2",
|
||||
|
Loading…
x
Reference in New Issue
Block a user