mirror of
https://github.com/twbs/bootstrap.git
synced 2025-02-17 14:54:30 +01:00
rewrite tab unit tests
This commit is contained in:
parent
e1b5d8471a
commit
233f3fb1ce
@ -40,7 +40,7 @@ const bsPlugins = {
|
|||||||
Modal: path.resolve(__dirname, '../js/src/modal/modal.js'),
|
Modal: path.resolve(__dirname, '../js/src/modal/modal.js'),
|
||||||
Popover: path.resolve(__dirname, '../js/src/popover/popover.js'),
|
Popover: path.resolve(__dirname, '../js/src/popover/popover.js'),
|
||||||
ScrollSpy: path.resolve(__dirname, '../js/src/scrollspy/scrollspy.js'),
|
ScrollSpy: path.resolve(__dirname, '../js/src/scrollspy/scrollspy.js'),
|
||||||
Tab: path.resolve(__dirname, '../js/src/tab.js'),
|
Tab: path.resolve(__dirname, '../js/src/tab/tab.js'),
|
||||||
Toast: path.resolve(__dirname, '../js/src/toast/toast.js'),
|
Toast: path.resolve(__dirname, '../js/src/toast/toast.js'),
|
||||||
Tooltip: path.resolve(__dirname, '../js/src/tooltip/tooltip.js')
|
Tooltip: path.resolve(__dirname, '../js/src/tooltip/tooltip.js')
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import Dropdown from './src/dropdown/dropdown'
|
|||||||
import Modal from './src/modal/modal'
|
import Modal from './src/modal/modal'
|
||||||
import Popover from './src/popover/popover'
|
import Popover from './src/popover/popover'
|
||||||
import ScrollSpy from './src/scrollspy/scrollspy'
|
import ScrollSpy from './src/scrollspy/scrollspy'
|
||||||
import Tab from './src/tab'
|
import Tab from './src/tab/tab'
|
||||||
import Toast from './src/toast/toast'
|
import Toast from './src/toast/toast'
|
||||||
import Tooltip from './src/tooltip/tooltip'
|
import Tooltip from './src/tooltip/tooltip'
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import Dropdown from './src/dropdown/dropdown'
|
|||||||
import Modal from './src/modal/modal'
|
import Modal from './src/modal/modal'
|
||||||
import Popover from './src/popover/popover'
|
import Popover from './src/popover/popover'
|
||||||
import ScrollSpy from './src/scrollspy/scrollspy'
|
import ScrollSpy from './src/scrollspy/scrollspy'
|
||||||
import Tab from './src/tab'
|
import Tab from './src/tab/tab'
|
||||||
import Toast from './src/toast/toast'
|
import Toast from './src/toast/toast'
|
||||||
import Tooltip from './src/tooltip/tooltip'
|
import Tooltip from './src/tooltip/tooltip'
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ import {
|
|||||||
getTransitionDurationFromElement,
|
getTransitionDurationFromElement,
|
||||||
makeArray,
|
makeArray,
|
||||||
reflow
|
reflow
|
||||||
} from './util/index'
|
} from '../util/index'
|
||||||
import Data from './dom/data'
|
import Data from '../dom/data'
|
||||||
import EventHandler from './dom/event-handler'
|
import EventHandler from '../dom/event-handler'
|
||||||
import SelectorEngine from './dom/selector-engine'
|
import SelectorEngine from '../dom/selector-engine'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
@ -253,7 +253,7 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (
|
|||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
* add .tab to jQuery only if jQuery is present
|
* add .tab to jQuery only if jQuery is present
|
||||||
*/
|
*/
|
||||||
|
/* istanbul ignore if */
|
||||||
if (typeof $ !== 'undefined') {
|
if (typeof $ !== 'undefined') {
|
||||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||||
$.fn[NAME] = Tab._jQueryInterface
|
$.fn[NAME] = Tab._jQueryInterface
|
593
js/src/tab/tab.spec.js
Normal file
593
js/src/tab/tab.spec.js
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
import Tab from './tab'
|
||||||
|
|
||||||
|
/** Test helpers */
|
||||||
|
import { getFixture, clearFixture, jQueryMock } from '../../tests/helpers/fixture'
|
||||||
|
|
||||||
|
describe('Tab', () => {
|
||||||
|
let fixtureEl
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
fixtureEl = getFixture()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clearFixture()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('VERSION', () => {
|
||||||
|
it('should return plugin version', () => {
|
||||||
|
expect(Tab.VERSION).toEqual(jasmine.any(String))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('show', () => {
|
||||||
|
it('should activate element by tab id', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav">',
|
||||||
|
' <li><a href="#home" role="tab">Home</a></li>',
|
||||||
|
' <li><a id="triggerProfile" role="tab" href="#profile">Profile</a></li>',
|
||||||
|
'</ul>',
|
||||||
|
'<ul><li id="home"/><li id="profile"/></ul>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const profileTriggerEl = fixtureEl.querySelector('#triggerProfile')
|
||||||
|
const tab = new Tab(profileTriggerEl)
|
||||||
|
|
||||||
|
profileTriggerEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(fixtureEl.querySelector('#profile').classList.contains('active')).toEqual(true)
|
||||||
|
expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
tab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should activate element by tab id in ordered list', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ol class="nav nav-pills">',
|
||||||
|
' <li><a href="#home">Home</a></li>',
|
||||||
|
' <li><a id="triggerProfile" href="#profile">Profile</a></li>',
|
||||||
|
'</ol>',
|
||||||
|
'<ol><li id="home"/><li id="profile"/></ol>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const profileTriggerEl = fixtureEl.querySelector('#triggerProfile')
|
||||||
|
const tab = new Tab(profileTriggerEl)
|
||||||
|
|
||||||
|
profileTriggerEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(fixtureEl.querySelector('#profile').classList.contains('active')).toEqual(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
tab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should activate element by tab id in nav list', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<nav class="nav">',
|
||||||
|
' <a href="#home">Home</a>',
|
||||||
|
' <a id="triggerProfile" href="#profile">Profile</a>',
|
||||||
|
'</nav>',
|
||||||
|
'<nav><div id="home"></div><div id="profile"></div></nav>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const profileTriggerEl = fixtureEl.querySelector('#triggerProfile')
|
||||||
|
const tab = new Tab(profileTriggerEl)
|
||||||
|
|
||||||
|
profileTriggerEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(fixtureEl.querySelector('#profile').classList.contains('active')).toEqual(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
tab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should activate element by tab id in list group', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<div class="list-group">',
|
||||||
|
' <a href="#home">Home</a>',
|
||||||
|
' <a id="triggerProfile" href="#profile">Profile</a>',
|
||||||
|
'</div>',
|
||||||
|
'<nav><div id="home"></div><div id="profile"></div></nav>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const profileTriggerEl = fixtureEl.querySelector('#triggerProfile')
|
||||||
|
const tab = new Tab(profileTriggerEl)
|
||||||
|
|
||||||
|
profileTriggerEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(fixtureEl.querySelector('#profile').classList.contains('active')).toEqual(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
tab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not fire shown when show is prevented', done => {
|
||||||
|
fixtureEl.innerHTML = '<div class="nav"></div>'
|
||||||
|
|
||||||
|
const navEl = fixtureEl.querySelector('div')
|
||||||
|
const tab = new Tab(navEl)
|
||||||
|
const expectDone = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
expect().nothing()
|
||||||
|
done()
|
||||||
|
}, 30)
|
||||||
|
}
|
||||||
|
|
||||||
|
navEl.addEventListener('show.bs.tab', ev => {
|
||||||
|
ev.preventDefault()
|
||||||
|
expectDone()
|
||||||
|
})
|
||||||
|
|
||||||
|
navEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
throw new Error('should not trigger shown event')
|
||||||
|
})
|
||||||
|
|
||||||
|
tab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not fire shown when tab is already active', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
|
||||||
|
' <li class="nav-item"><a href="#profile" class="nav-link" role="tab">Profile</a></li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
|
||||||
|
' <div class="tab-pane" id="profile" role="tabpanel"></div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const triggerActive = fixtureEl.querySelector('a.active')
|
||||||
|
const tab = new Tab(triggerActive)
|
||||||
|
|
||||||
|
triggerActive.addEventListener('shown.bs.tab', () => {
|
||||||
|
throw new Error('should not trigger shown event')
|
||||||
|
})
|
||||||
|
|
||||||
|
tab.show()
|
||||||
|
setTimeout(() => {
|
||||||
|
expect().nothing()
|
||||||
|
done()
|
||||||
|
}, 30)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not fire shown when tab is disabled', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
|
||||||
|
' <li class="nav-item"><a href="#profile" class="nav-link disabled" role="tab">Profile</a></li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
|
||||||
|
' <div class="tab-pane" id="profile" role="tabpanel"></div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const triggerDisabled = fixtureEl.querySelector('a.disabled')
|
||||||
|
const tab = new Tab(triggerDisabled)
|
||||||
|
|
||||||
|
triggerDisabled.addEventListener('shown.bs.tab', () => {
|
||||||
|
throw new Error('should not trigger shown event')
|
||||||
|
})
|
||||||
|
|
||||||
|
tab.show()
|
||||||
|
setTimeout(() => {
|
||||||
|
expect().nothing()
|
||||||
|
done()
|
||||||
|
}, 30)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('show and shown events should reference correct relatedTarget', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
|
||||||
|
' <li class="nav-item"><a id="triggerProfile" href="#profile" class="nav-link" role="tab">Profile</a></li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
|
||||||
|
' <div class="tab-pane" id="profile" role="tabpanel"></div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const secondTabTrigger = fixtureEl.querySelector('#triggerProfile')
|
||||||
|
const secondTab = new Tab(secondTabTrigger)
|
||||||
|
|
||||||
|
secondTabTrigger.addEventListener('show.bs.tab', ev => {
|
||||||
|
expect(ev.relatedTarget.hash).toEqual('#home')
|
||||||
|
})
|
||||||
|
|
||||||
|
secondTabTrigger.addEventListener('shown.bs.tab', ev => {
|
||||||
|
expect(ev.relatedTarget.hash).toEqual('#home')
|
||||||
|
expect(secondTabTrigger.getAttribute('aria-selected')).toEqual('true')
|
||||||
|
expect(fixtureEl.querySelector('a:not(.active)').getAttribute('aria-selected')).toEqual('false')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
secondTab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fire hide and hidden events', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav">',
|
||||||
|
' <li><a href="#home">Home</a></li>',
|
||||||
|
' <li><a href="#profile">Profile</a></li>',
|
||||||
|
'</ul>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const triggerList = fixtureEl.querySelectorAll('a')
|
||||||
|
const firstTab = new Tab(triggerList[0])
|
||||||
|
const secondTab = new Tab(triggerList[1])
|
||||||
|
|
||||||
|
let hideCalled = false
|
||||||
|
triggerList[0].addEventListener('shown.bs.tab', () => {
|
||||||
|
secondTab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
triggerList[0].addEventListener('hide.bs.tab', ev => {
|
||||||
|
hideCalled = true
|
||||||
|
expect(ev.relatedTarget.hash).toEqual('#profile')
|
||||||
|
})
|
||||||
|
|
||||||
|
triggerList[0].addEventListener('hidden.bs.tab', ev => {
|
||||||
|
expect(hideCalled).toEqual(true)
|
||||||
|
expect(ev.relatedTarget.hash).toEqual('#profile')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
firstTab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not fire hidden when hide is prevented', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav">',
|
||||||
|
' <li><a href="#home">Home</a></li>',
|
||||||
|
' <li><a href="#profile">Profile</a></li>',
|
||||||
|
'</ul>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const triggerList = fixtureEl.querySelectorAll('a')
|
||||||
|
const firstTab = new Tab(triggerList[0])
|
||||||
|
const secondTab = new Tab(triggerList[1])
|
||||||
|
const expectDone = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
expect().nothing()
|
||||||
|
done()
|
||||||
|
}, 30)
|
||||||
|
}
|
||||||
|
|
||||||
|
triggerList[0].addEventListener('shown.bs.tab', () => {
|
||||||
|
secondTab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
triggerList[0].addEventListener('hide.bs.tab', ev => {
|
||||||
|
ev.preventDefault()
|
||||||
|
expectDone()
|
||||||
|
})
|
||||||
|
|
||||||
|
triggerList[0].addEventListener('hidden.bs.tab', () => {
|
||||||
|
throw new Error('should not trigger hidden')
|
||||||
|
})
|
||||||
|
|
||||||
|
firstTab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle removed tabs', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item">',
|
||||||
|
' <a class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">',
|
||||||
|
' <button class="close"><span aria-hidden="true">×</span></button>',
|
||||||
|
' </a>',
|
||||||
|
' </li>',
|
||||||
|
' <li class="nav-item">',
|
||||||
|
' <a id="secondNav" class="nav-link nav-tab" href="#buzz" role="tab" data-toggle="tab">',
|
||||||
|
' <button class="close"><span aria-hidden="true">×</span></button>',
|
||||||
|
' </a>',
|
||||||
|
' </li>',
|
||||||
|
' <li class="nav-item">',
|
||||||
|
' <a class="nav-link nav-tab" href="#references" role="tab" data-toggle="tab">',
|
||||||
|
' <button id="btnClose" class="close"><span aria-hidden="true">×</span></button>',
|
||||||
|
' </a>',
|
||||||
|
' </li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div role="tabpanel" class="tab-pane fade show active" id="profile">test 1</div>',
|
||||||
|
' <div role="tabpanel" class="tab-pane fade" id="buzz">test 2</div>',
|
||||||
|
' <div role="tabpanel" class="tab-pane fade" id="references">test 3</div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const secondNavEl = fixtureEl.querySelector('#secondNav')
|
||||||
|
const btnCloseEl = fixtureEl.querySelector('#btnClose')
|
||||||
|
const secondNavTab = new Tab(secondNavEl)
|
||||||
|
|
||||||
|
secondNavEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(fixtureEl.querySelectorAll('.nav-tab').length).toEqual(2)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
btnCloseEl.addEventListener('click', () => {
|
||||||
|
const linkEl = btnCloseEl.parentNode
|
||||||
|
const liEl = linkEl.parentNode
|
||||||
|
const tabId = linkEl.getAttribute('href')
|
||||||
|
const tabIdEl = fixtureEl.querySelector(tabId)
|
||||||
|
|
||||||
|
liEl.parentNode.removeChild(liEl)
|
||||||
|
tabIdEl.parentNode.removeChild(tabIdEl)
|
||||||
|
secondNavTab.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
btnCloseEl.click()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('dispose', () => {
|
||||||
|
it('should dispose a tab', () => {
|
||||||
|
fixtureEl.innerHTML = '<div></div>'
|
||||||
|
|
||||||
|
const el = fixtureEl.querySelector('div')
|
||||||
|
const tab = new Tab(fixtureEl.querySelector('div'))
|
||||||
|
|
||||||
|
expect(Tab._getInstance(el)).not.toBeNull()
|
||||||
|
|
||||||
|
tab.dispose()
|
||||||
|
|
||||||
|
expect(Tab._getInstance(el)).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('_jQueryInterface', () => {
|
||||||
|
it('should create a tab', () => {
|
||||||
|
fixtureEl.innerHTML = '<div></div>'
|
||||||
|
|
||||||
|
const div = fixtureEl.querySelector('div')
|
||||||
|
|
||||||
|
jQueryMock.fn.tab = Tab._jQueryInterface
|
||||||
|
jQueryMock.elements = [div]
|
||||||
|
|
||||||
|
jQueryMock.fn.tab.call(jQueryMock)
|
||||||
|
|
||||||
|
expect(Tab._getInstance(div)).toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not re create a tab', () => {
|
||||||
|
fixtureEl.innerHTML = '<div></div>'
|
||||||
|
|
||||||
|
const div = fixtureEl.querySelector('div')
|
||||||
|
const tab = new Tab(div)
|
||||||
|
|
||||||
|
jQueryMock.fn.tab = Tab._jQueryInterface
|
||||||
|
jQueryMock.elements = [div]
|
||||||
|
|
||||||
|
jQueryMock.fn.tab.call(jQueryMock)
|
||||||
|
|
||||||
|
expect(Tab._getInstance(div)).toEqual(tab)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call a tab method', () => {
|
||||||
|
fixtureEl.innerHTML = '<div></div>'
|
||||||
|
|
||||||
|
const div = fixtureEl.querySelector('div')
|
||||||
|
const tab = new Tab(div)
|
||||||
|
|
||||||
|
spyOn(tab, 'show')
|
||||||
|
|
||||||
|
jQueryMock.fn.tab = Tab._jQueryInterface
|
||||||
|
jQueryMock.elements = [div]
|
||||||
|
|
||||||
|
jQueryMock.fn.tab.call(jQueryMock, 'show')
|
||||||
|
|
||||||
|
expect(Tab._getInstance(div)).toEqual(tab)
|
||||||
|
expect(tab.show).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw error on undefined method', () => {
|
||||||
|
fixtureEl.innerHTML = '<div></div>'
|
||||||
|
|
||||||
|
const div = fixtureEl.querySelector('div')
|
||||||
|
const action = 'undefinedMethod'
|
||||||
|
|
||||||
|
jQueryMock.fn.tab = Tab._jQueryInterface
|
||||||
|
jQueryMock.elements = [div]
|
||||||
|
|
||||||
|
try {
|
||||||
|
jQueryMock.fn.tab.call(jQueryMock, action)
|
||||||
|
} catch (error) {
|
||||||
|
expect(error.message).toEqual(`No method named "${action}"`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('_getInstance', () => {
|
||||||
|
it('should return null if there is no instance', () => {
|
||||||
|
expect(Tab._getInstance(fixtureEl)).toEqual(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return this instance', () => {
|
||||||
|
fixtureEl.innerHTML = '<div></div>'
|
||||||
|
|
||||||
|
const divEl = fixtureEl.querySelector('div')
|
||||||
|
const tab = new Tab(divEl)
|
||||||
|
|
||||||
|
expect(Tab._getInstance(divEl)).toEqual(tab)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('data-api', () => {
|
||||||
|
it('should create dynamicaly a tab', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
|
||||||
|
' <li class="nav-item"><a id="triggerProfile" data-toggle="tab" href="#profile" class="nav-link" role="tab">Profile</a></li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
|
||||||
|
' <div class="tab-pane" id="profile" role="tabpanel"></div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const secondTabTrigger = fixtureEl.querySelector('#triggerProfile')
|
||||||
|
|
||||||
|
secondTabTrigger.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(secondTabTrigger.classList.contains('active')).toEqual(true)
|
||||||
|
expect(fixtureEl.querySelector('#profile').classList.contains('active')).toEqual(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
secondTabTrigger.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('selected tab should deactivate previous selected link in dropdown', () => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs">',
|
||||||
|
' <li class="nav-item"><a class="nav-link" href="#home" data-toggle="tab">Home</a></li>',
|
||||||
|
' <li class="nav-item"><a class="nav-link" href="#profile" data-toggle="tab">Profile</a></li>',
|
||||||
|
' <li class="nav-item dropdown">',
|
||||||
|
' <a class="nav-link dropdown-toggle active" data-toggle="dropdown" href="#">Dropdown</>',
|
||||||
|
' <div class="dropdown-menu">',
|
||||||
|
' <a class="dropdown-item active" href="#dropdown1" id="dropdown1-tab" data-toggle="tab">@fat</a>',
|
||||||
|
' <a class="dropdown-item" href="#dropdown2" id="dropdown2-tab" data-toggle="tab">@mdo</a>',
|
||||||
|
' </div>',
|
||||||
|
' </li>',
|
||||||
|
'</ul>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const firstLiLinkEl = fixtureEl.querySelector('li:first-child a')
|
||||||
|
|
||||||
|
firstLiLinkEl.click()
|
||||||
|
expect(firstLiLinkEl.classList.contains('active')).toEqual(true)
|
||||||
|
expect(fixtureEl.querySelector('li:last-child a').classList.contains('active')).toEqual(false)
|
||||||
|
expect(fixtureEl.querySelector('li:last-child .dropdown-menu a:first-child').classList.contains('active')).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle nested tabs', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<nav class="nav nav-tabs" role="tablist">',
|
||||||
|
' <a id="tab1" href="#x-tab1" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</a>',
|
||||||
|
' <a href="#x-tab2" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</a>',
|
||||||
|
' <a href="#x-tab3" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</a>',
|
||||||
|
'</nav>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div class="tab-pane" id="x-tab1" role="tabpanel">',
|
||||||
|
' <nav class="nav nav-tabs" role="tablist">',
|
||||||
|
' <a href="#nested-tab1" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</a>',
|
||||||
|
' <a id="tabNested2" href="#nested-tab2" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</a>',
|
||||||
|
' </nav>',
|
||||||
|
' <div class="tab-content">',
|
||||||
|
' <div class="tab-pane active" id="nested-tab1" role="tabpanel">Nested Tab1 Content</div>',
|
||||||
|
' <div class="tab-pane" id="nested-tab2" role="tabpanel">Nested Tab2 Content</div>',
|
||||||
|
' </div>',
|
||||||
|
' </div>',
|
||||||
|
' <div class="tab-pane active" id="x-tab2" role="tabpanel">Tab2 Content</div>',
|
||||||
|
' <div class="tab-pane" id="x-tab3" role="tabpanel">Tab3 Content</div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const tab1El = fixtureEl.querySelector('#tab1')
|
||||||
|
const tabNested2El = fixtureEl.querySelector('#tabNested2')
|
||||||
|
const xTab1El = fixtureEl.querySelector('#x-tab1')
|
||||||
|
|
||||||
|
tabNested2El.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(xTab1El.classList.contains('active')).toEqual(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
tab1El.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(xTab1El.classList.contains('active')).toEqual(true)
|
||||||
|
tabNested2El.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
tab1El.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not remove fade class if no active pane is present', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item"><a id="tab-home" href="#home" class="nav-link" data-toggle="tab" role="tab">Home</a></li>',
|
||||||
|
' <li class="nav-item"><a id="tab-profile" href="#profile" class="nav-link" data-toggle="tab" role="tab">Profile</a></li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div class="tab-pane fade" id="home" role="tabpanel"></div>',
|
||||||
|
' <div class="tab-pane fade" id="profile" role="tabpanel"></div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const triggerTabProfileEl = fixtureEl.querySelector('#tab-profile')
|
||||||
|
const triggerTabHomeEl = fixtureEl.querySelector('#tab-home')
|
||||||
|
const tabProfileEl = fixtureEl.querySelector('#profile')
|
||||||
|
const tabHomeEl = fixtureEl.querySelector('#home')
|
||||||
|
|
||||||
|
triggerTabProfileEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(tabProfileEl.classList.contains('fade')).toEqual(true)
|
||||||
|
expect(tabProfileEl.classList.contains('show')).toEqual(true)
|
||||||
|
|
||||||
|
triggerTabHomeEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(tabProfileEl.classList.contains('fade')).toEqual(true)
|
||||||
|
expect(tabProfileEl.classList.contains('show')).toEqual(false)
|
||||||
|
|
||||||
|
expect(tabHomeEl.classList.contains('fade')).toEqual(true)
|
||||||
|
expect(tabHomeEl.classList.contains('show')).toEqual(true)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
triggerTabHomeEl.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
triggerTabProfileEl.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not add show class to tab panes if there is no `.fade` class', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item">',
|
||||||
|
' <a class="nav-link nav-tab" href="#home" role="tab" data-toggle="tab">Home</a>',
|
||||||
|
' </li>',
|
||||||
|
' <li class="nav-item">',
|
||||||
|
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">Profile</a>',
|
||||||
|
' </li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div role="tabpanel" class="tab-pane" id="home">test 1</div>',
|
||||||
|
' <div role="tabpanel" class="tab-pane" id="profile">test 2</div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const secondNavEl = fixtureEl.querySelector('#secondNav')
|
||||||
|
|
||||||
|
secondNavEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(fixtureEl.querySelectorAll('.show').length).toEqual(0)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
secondNavEl.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should add show class to tab panes if there is a `.fade` class', done => {
|
||||||
|
fixtureEl.innerHTML = [
|
||||||
|
'<ul class="nav nav-tabs" role="tablist">',
|
||||||
|
' <li class="nav-item">',
|
||||||
|
' <a class="nav-link nav-tab" href="#home" role="tab" data-toggle="tab">Home</a>',
|
||||||
|
' </li>',
|
||||||
|
' <li class="nav-item">',
|
||||||
|
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">Profile</a>',
|
||||||
|
' </li>',
|
||||||
|
'</ul>',
|
||||||
|
'<div class="tab-content">',
|
||||||
|
' <div role="tabpanel" class="tab-pane fade" id="home">test 1</div>',
|
||||||
|
' <div role="tabpanel" class="tab-pane fade" id="profile">test 2</div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const secondNavEl = fixtureEl.querySelector('#secondNav')
|
||||||
|
|
||||||
|
secondNavEl.addEventListener('shown.bs.tab', () => {
|
||||||
|
expect(fixtureEl.querySelectorAll('.show').length).toEqual(1)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
secondNavEl.click()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -1,62 +0,0 @@
|
|||||||
{
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"jquery": true,
|
|
||||||
"qunit": true
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"bootstrap": false,
|
|
||||||
"sinon": false,
|
|
||||||
"Util": false,
|
|
||||||
"Sanitizer": false,
|
|
||||||
"Data": false,
|
|
||||||
"Alert": false,
|
|
||||||
"Button": false,
|
|
||||||
"Carousel": false,
|
|
||||||
"Simulator": false,
|
|
||||||
"Toast": false,
|
|
||||||
"EventHandler": false,
|
|
||||||
"Manipulator": false,
|
|
||||||
"SelectorEngine": false
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 5,
|
|
||||||
"sourceType": "script"
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"plugin:unicorn/recommended",
|
|
||||||
"xo",
|
|
||||||
"xo/browser"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"capitalized-comments": "off",
|
|
||||||
"indent": [
|
|
||||||
"error",
|
|
||||||
2,
|
|
||||||
{
|
|
||||||
"MemberExpression": "off",
|
|
||||||
"SwitchCase": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"multiline-ternary": [
|
|
||||||
"error",
|
|
||||||
"always-multiline"
|
|
||||||
],
|
|
||||||
"new-cap": "off",
|
|
||||||
"object-curly-spacing": [
|
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
],
|
|
||||||
"semi": [
|
|
||||||
"error",
|
|
||||||
"never"
|
|
||||||
],
|
|
||||||
"strict": "error",
|
|
||||||
"unicorn/no-unused-properties": "error",
|
|
||||||
"unicorn/prefer-includes": "off",
|
|
||||||
"unicorn/prefer-node-append": "off",
|
|
||||||
"unicorn/prefer-node-remove": "off",
|
|
||||||
"unicorn/prefer-query-selector": "off",
|
|
||||||
"unicorn/prevent-abbreviations": "off"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,530 +0,0 @@
|
|||||||
$(function () {
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
var Tab = typeof window.bootstrap === 'undefined' ? window.Tab : window.bootstrap.Tab
|
|
||||||
|
|
||||||
QUnit.module('tabs plugin')
|
|
||||||
|
|
||||||
QUnit.test('should be defined on jquery object', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
assert.ok($(document.body).tab, 'tabs method is defined')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.module('tabs', {
|
|
||||||
beforeEach: function () {
|
|
||||||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
|
||||||
$.fn.bootstrapTab = $.fn.tab.noConflict()
|
|
||||||
},
|
|
||||||
afterEach: function () {
|
|
||||||
$.fn.tab = $.fn.bootstrapTab
|
|
||||||
delete $.fn.bootstrapTab
|
|
||||||
$('#qunit-fixture').html('')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should provide no conflict', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
assert.strictEqual(typeof $.fn.tab, 'undefined', 'tab was set back to undefined (org value)')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should throw explicit error on undefined method', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
var $el = $('<div/>')
|
|
||||||
$el.bootstrapTab()
|
|
||||||
try {
|
|
||||||
$el.bootstrapTab('noMethod')
|
|
||||||
} catch (error) {
|
|
||||||
assert.strictEqual(error.message, 'No method named "noMethod"')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should return jquery collection containing the element', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var $el = $('<div/>')
|
|
||||||
var $tab = $el.bootstrapTab()
|
|
||||||
assert.ok($tab instanceof $, 'returns jquery collection')
|
|
||||||
assert.strictEqual($tab[0], $el[0], 'collection contains element')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should activate element by tab id', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var tabsHTML = '<ul class="nav">' +
|
|
||||||
'<li><a href="#home">Home</a></li>' +
|
|
||||||
'<li><a href="#profile">Profile</a></li>' +
|
|
||||||
'</ul>'
|
|
||||||
|
|
||||||
$('<ul><li id="home"/><li id="profile"/></ul>').appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$(tabsHTML).find('li:last-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile')
|
|
||||||
|
|
||||||
$(tabsHTML).find('li:first-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should activate element by tab id', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var pillsHTML = '<ul class="nav nav-pills">' +
|
|
||||||
'<li><a href="#home">Home</a></li>' +
|
|
||||||
'<li><a href="#profile">Profile</a></li>' +
|
|
||||||
'</ul>'
|
|
||||||
|
|
||||||
$('<ul><li id="home"/><li id="profile"/></ul>').appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$(pillsHTML).find('li:last-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile')
|
|
||||||
|
|
||||||
$(pillsHTML).find('li:first-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should activate element by tab id in ordered list', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var pillsHTML = '<ol class="nav nav-pills">' +
|
|
||||||
'<li><a href="#home">Home</a></li>' +
|
|
||||||
'<li><a href="#profile">Profile</a></li>' +
|
|
||||||
'</ol>'
|
|
||||||
|
|
||||||
$('<ol><li id="home"/><li id="profile"/></ol>').appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$(pillsHTML).find('li:last-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile')
|
|
||||||
|
|
||||||
$(pillsHTML).find('li:first-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should activate element by tab id in nav list', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var tabsHTML = '<nav class="nav">' +
|
|
||||||
'<a href="#home">Home</a>' +
|
|
||||||
'<a href="#profile">Profile</a>' +
|
|
||||||
'</nav>'
|
|
||||||
|
|
||||||
$('<nav><div id="home"></div><div id="profile"></div></nav>').appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$(tabsHTML).find('a:last-child').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile')
|
|
||||||
|
|
||||||
$(tabsHTML).find('a:first-child').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should activate element by tab id in list group', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var tabsHTML = '<div class="list-group">' +
|
|
||||||
'<a href="#home">Home</a>' +
|
|
||||||
'<a href="#profile">Profile</a>' +
|
|
||||||
'</div>'
|
|
||||||
|
|
||||||
$('<nav><div id="home"></div><div id="profile"></div></nav>').appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$(tabsHTML).find('a:last-child').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile')
|
|
||||||
|
|
||||||
$(tabsHTML).find('a:first-child').bootstrapTab('show')
|
|
||||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should not fire shown when show is prevented', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
$('<div class="nav"/>')
|
|
||||||
.on('show.bs.tab', function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
assert.ok(true, 'show event fired')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.on('shown.bs.tab', function () {
|
|
||||||
assert.ok(false, 'shown event fired')
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should not fire shown when tab is already active', function (assert) {
|
|
||||||
assert.expect(0)
|
|
||||||
var tabsHTML = '<ul class="nav nav-tabs" role="tablist">' +
|
|
||||||
'<li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>' +
|
|
||||||
'<li class="nav-item"><a href="#profile" class="nav-link" role="tab">Profile</a></li>' +
|
|
||||||
'</ul>' +
|
|
||||||
'<div class="tab-content">' +
|
|
||||||
'<div class="tab-pane active" id="home" role="tabpanel"></div>' +
|
|
||||||
'<div class="tab-pane" id="profile" role="tabpanel"></div>' +
|
|
||||||
'</div>'
|
|
||||||
|
|
||||||
$(tabsHTML)
|
|
||||||
.find('a.active')
|
|
||||||
.on('shown.bs.tab', function () {
|
|
||||||
assert.ok(true, 'shown event fired')
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should not fire shown when tab is disabled', function (assert) {
|
|
||||||
assert.expect(0)
|
|
||||||
var tabsHTML = '<ul class="nav nav-tabs" role="tablist">' +
|
|
||||||
'<li class="nav-item"><a href="#home" class="nav-link active" role="tab">Home</a></li>' +
|
|
||||||
'<li class="nav-item"><a href="#profile" class="nav-link disabled" role="tab">Profile</a></li>' +
|
|
||||||
'</ul>' +
|
|
||||||
'<div class="tab-content">' +
|
|
||||||
'<div class="tab-pane active" id="home" role="tabpanel"></div>' +
|
|
||||||
'<div class="tab-pane" id="profile" role="tabpanel"></div>' +
|
|
||||||
'</div>'
|
|
||||||
|
|
||||||
$(tabsHTML)
|
|
||||||
.find('a.disabled')
|
|
||||||
.on('shown.bs.tab', function () {
|
|
||||||
assert.ok(true, 'shown event fired')
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('show and shown events should reference correct relatedTarget', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
var dropHTML =
|
|
||||||
'<ul class="drop nav">' +
|
|
||||||
' <li class="dropdown"><a data-toggle="dropdown" href="#">1</a>' +
|
|
||||||
' <ul class="dropdown-menu nav">' +
|
|
||||||
' <li><a href="#a1-1" data-toggle="tab">1-1</a></li>' +
|
|
||||||
' <li><a href="#a1-2" data-toggle="tab">1-2</a></li>' +
|
|
||||||
' </ul>' +
|
|
||||||
' </li>' +
|
|
||||||
'</ul>'
|
|
||||||
|
|
||||||
$(dropHTML)
|
|
||||||
.find('ul > li:first-child a')
|
|
||||||
.bootstrapTab('show')
|
|
||||||
.end()
|
|
||||||
.find('ul > li:last-child a')
|
|
||||||
.on('show.bs.tab', function (e) {
|
|
||||||
assert.strictEqual(e.relatedTarget.hash, '#a1-1', 'references correct element as relatedTarget')
|
|
||||||
})
|
|
||||||
.on('shown.bs.tab', function (e) {
|
|
||||||
assert.strictEqual(e.relatedTarget.hash, '#a1-1', 'references correct element as relatedTarget')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should fire hide and hidden events', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
var tabsHTML = '<ul class="nav">' +
|
|
||||||
'<li><a href="#home">Home</a></li>' +
|
|
||||||
'<li><a href="#profile">Profile</a></li>' +
|
|
||||||
'</ul>'
|
|
||||||
|
|
||||||
$(tabsHTML)
|
|
||||||
.find('li:first-child a')
|
|
||||||
.on('hide.bs.tab', function () {
|
|
||||||
assert.ok(true, 'hide event fired')
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
.end()
|
|
||||||
.find('li:last-child a')
|
|
||||||
.bootstrapTab('show')
|
|
||||||
|
|
||||||
$(tabsHTML)
|
|
||||||
.find('li:first-child a')
|
|
||||||
.on('hidden.bs.tab', function () {
|
|
||||||
assert.ok(true, 'hidden event fired')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
.end()
|
|
||||||
.find('li:last-child a')
|
|
||||||
.bootstrapTab('show')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should not fire hidden when hide is prevented', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
var tabsHTML = '<ul class="nav">' +
|
|
||||||
'<li><a href="#home">Home</a></li>' +
|
|
||||||
'<li><a href="#profile">Profile</a></li>' +
|
|
||||||
'</ul>'
|
|
||||||
|
|
||||||
$(tabsHTML)
|
|
||||||
.find('li:first-child a')
|
|
||||||
.on('hide.bs.tab', function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
assert.ok(true, 'hide event fired')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.on('hidden.bs.tab', function () {
|
|
||||||
assert.ok(false, 'hidden event fired')
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
.end()
|
|
||||||
.find('li:last-child a')
|
|
||||||
.bootstrapTab('show')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('hide and hidden events contain correct relatedTarget', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
var tabsHTML = '<ul class="nav">' +
|
|
||||||
'<li><a href="#home">Home</a></li>' +
|
|
||||||
'<li><a href="#profile">Profile</a></li>' +
|
|
||||||
'</ul>'
|
|
||||||
|
|
||||||
$(tabsHTML)
|
|
||||||
.find('li:first-child a')
|
|
||||||
.on('hide.bs.tab', function (e) {
|
|
||||||
assert.strictEqual(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget')
|
|
||||||
})
|
|
||||||
.on('hidden.bs.tab', function (e) {
|
|
||||||
assert.strictEqual(e.relatedTarget.hash, '#profile', 'references correct element as relatedTarget')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
.bootstrapTab('show')
|
|
||||||
.end()
|
|
||||||
.find('li:last-child a')
|
|
||||||
.bootstrapTab('show')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('selected tab should have aria-selected', function (assert) {
|
|
||||||
assert.expect(8)
|
|
||||||
var tabsHTML = '<ul class="nav nav-tabs">' +
|
|
||||||
'<li><a class="nav-item active" href="#home" toggle="tab" aria-selected="true">Home</a></li>' +
|
|
||||||
'<li><a class="nav-item" href="#profile" toggle="tab" aria-selected="false">Profile</a></li>' +
|
|
||||||
'</ul>'
|
|
||||||
var $tabs = $(tabsHTML).appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$tabs.find('li:first-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'shown tab has aria-selected = true')
|
|
||||||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'hidden tab has aria-selected = false')
|
|
||||||
|
|
||||||
$tabs.find('li:last-child a').trigger('click')
|
|
||||||
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'after click, shown tab has aria-selected = true')
|
|
||||||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'after click, hidden tab has aria-selected = false')
|
|
||||||
|
|
||||||
$tabs.find('li:first-child a').bootstrapTab('show')
|
|
||||||
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'shown tab has aria-selected = true')
|
|
||||||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'hidden tab has aria-selected = false')
|
|
||||||
|
|
||||||
$tabs.find('li:first-child a').trigger('click')
|
|
||||||
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'after second show event, shown tab still has aria-selected = true')
|
|
||||||
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'after second show event, hidden tab has aria-selected = false')
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('selected tab should deactivate previous selected tab', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var tabsHTML = '<ul class="nav nav-tabs">' +
|
|
||||||
'<li class="nav-item"><a class="nav-link active" href="#home" data-toggle="tab">Home</a></li>' +
|
|
||||||
'<li class="nav-item"><a class="nav-link" href="#profile" data-toggle="tab">Profile</a></li>' +
|
|
||||||
'</ul>'
|
|
||||||
var $tabs = $(tabsHTML).appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$tabs.find('li:last-child a')[0].click()
|
|
||||||
assert.notOk($tabs.find('li:first-child a').hasClass('active'))
|
|
||||||
assert.ok($tabs.find('li:last-child a').hasClass('active'))
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('selected tab should deactivate previous selected link in dropdown', function (assert) {
|
|
||||||
assert.expect(3)
|
|
||||||
var tabsHTML = '<ul class="nav nav-tabs">' +
|
|
||||||
'<li class="nav-item"><a class="nav-link" href="#home" data-toggle="tab">Home</a></li>' +
|
|
||||||
'<li class="nav-item"><a class="nav-link" href="#profile" data-toggle="tab">Profile</a></li>' +
|
|
||||||
'<li class="nav-item dropdown"><a class="nav-link dropdown-toggle active" data-toggle="dropdown" href="#">Dropdown</a>' +
|
|
||||||
'<div class="dropdown-menu">' +
|
|
||||||
'<a class="dropdown-item active" href="#dropdown1" id="dropdown1-tab" data-toggle="tab">@fat</a>' +
|
|
||||||
'<a class="dropdown-item" href="#dropdown2" id="dropdown2-tab" data-toggle="tab">@mdo</a>' +
|
|
||||||
'</div>' +
|
|
||||||
'</li>' +
|
|
||||||
'</ul>'
|
|
||||||
var $tabs = $(tabsHTML).appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$tabs.find('li:first-child a')[0].click()
|
|
||||||
assert.ok($tabs.find('li:first-child a').hasClass('active'))
|
|
||||||
assert.notOk($tabs.find('li:last-child a').hasClass('active'))
|
|
||||||
assert.notOk($tabs.find('li:last-child .dropdown-menu a:first-child').hasClass('active'))
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('Nested tabs', function (assert) {
|
|
||||||
assert.expect(2)
|
|
||||||
var done = assert.async()
|
|
||||||
var tabsHTML =
|
|
||||||
'<nav class="nav nav-tabs" role="tablist">' +
|
|
||||||
' <a id="tab1" href="#x-tab1" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</a>' +
|
|
||||||
' <a href="#x-tab2" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</a>' +
|
|
||||||
' <a href="#x-tab3" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</a>' +
|
|
||||||
'</nav>' +
|
|
||||||
'<div class="tab-content">' +
|
|
||||||
' <div class="tab-pane" id="x-tab1" role="tabpanel">' +
|
|
||||||
' <nav class="nav nav-tabs" role="tablist">' +
|
|
||||||
' <a href="#nested-tab1" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</a>' +
|
|
||||||
' <a id="tabNested2" href="#nested-tab2" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</a>' +
|
|
||||||
' </nav>' +
|
|
||||||
' <div class="tab-content">' +
|
|
||||||
' <div class="tab-pane active" id="nested-tab1" role="tabpanel">Nested Tab1 Content</div>' +
|
|
||||||
' <div class="tab-pane" id="nested-tab2" role="tabpanel">Nested Tab2 Content</div>' +
|
|
||||||
' </div>' +
|
|
||||||
' </div>' +
|
|
||||||
' <div class="tab-pane active" id="x-tab2" role="tabpanel">Tab2 Content</div>' +
|
|
||||||
' <div class="tab-pane" id="x-tab3" role="tabpanel">Tab3 Content</div>' +
|
|
||||||
'</div>'
|
|
||||||
|
|
||||||
$(tabsHTML).appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$('#tabNested2').on('shown.bs.tab', function () {
|
|
||||||
assert.ok($('#x-tab1').hasClass('active'))
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#tab1').on('shown.bs.tab', function () {
|
|
||||||
assert.ok($('#x-tab1').hasClass('active'))
|
|
||||||
$('#tabNested2')[0].click()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#tab1')[0].click()
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should not remove fade class if no active pane is present', function (assert) {
|
|
||||||
assert.expect(6)
|
|
||||||
var done = assert.async()
|
|
||||||
var tabsHTML = '<ul class="nav nav-tabs" role="tablist">' +
|
|
||||||
'<li class="nav-item"><a id="tab-home" href="#home" class="nav-link" data-toggle="tab" role="tab">Home</a></li>' +
|
|
||||||
'<li class="nav-item"><a id="tab-profile" href="#profile" class="nav-link" data-toggle="tab" role="tab">Profile</a></li>' +
|
|
||||||
'</ul>' +
|
|
||||||
'<div class="tab-content">' +
|
|
||||||
'<div class="tab-pane fade" id="home" role="tabpanel"></div>' +
|
|
||||||
'<div class="tab-pane fade" id="profile" role="tabpanel"></div>' +
|
|
||||||
'</div>'
|
|
||||||
|
|
||||||
$(tabsHTML).appendTo('#qunit-fixture')
|
|
||||||
$('#tab-profile')
|
|
||||||
.on('shown.bs.tab', function () {
|
|
||||||
assert.ok($('#profile').hasClass('fade'))
|
|
||||||
assert.ok($('#profile').hasClass('show'))
|
|
||||||
|
|
||||||
$('#tab-home')
|
|
||||||
.on('shown.bs.tab', function () {
|
|
||||||
assert.ok($('#profile').hasClass('fade'))
|
|
||||||
assert.notOk($('#profile').hasClass('show'))
|
|
||||||
assert.ok($('#home').hasClass('fade'))
|
|
||||||
assert.ok($('#home').hasClass('show'))
|
|
||||||
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#tab-home')[0].click()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#tab-profile')[0].click()
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should handle removed tabs', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
var html = [
|
|
||||||
'<ul class="nav nav-tabs" role="tablist">',
|
|
||||||
' <li class="nav-item">',
|
|
||||||
' <a class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">',
|
|
||||||
' <button class="close"><span aria-hidden="true">×</span></button>',
|
|
||||||
' </a>',
|
|
||||||
' </li>',
|
|
||||||
' <li class="nav-item">',
|
|
||||||
' <a id="secondNav" class="nav-link nav-tab" href="#buzz" role="tab" data-toggle="tab">',
|
|
||||||
' <button class="close"><span aria-hidden="true">×</span></button>',
|
|
||||||
' </a>',
|
|
||||||
' </li>',
|
|
||||||
' <li class="nav-item">',
|
|
||||||
' <a class="nav-link nav-tab" href="#references" role="tab" data-toggle="tab">',
|
|
||||||
' <button id="btnClose" class="close"><span aria-hidden="true">×</span></button>',
|
|
||||||
' </a>',
|
|
||||||
' </li>',
|
|
||||||
'</ul>',
|
|
||||||
'<div class="tab-content">',
|
|
||||||
' <div role="tabpanel" class="tab-pane fade show active" id="profile">test 1</div>',
|
|
||||||
' <div role="tabpanel" class="tab-pane fade" id="buzz">test 2</div>',
|
|
||||||
' <div role="tabpanel" class="tab-pane fade" id="references">test 3</div>',
|
|
||||||
'</div>'
|
|
||||||
].join('')
|
|
||||||
|
|
||||||
$(html).appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$('#secondNav').on('shown.bs.tab', function () {
|
|
||||||
assert.strictEqual($('.nav-tab').length, 2)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#btnClose').one('click', function () {
|
|
||||||
var tabId = $(this).parents('a').attr('href')
|
|
||||||
$(this).parents('li').remove()
|
|
||||||
$(tabId).remove()
|
|
||||||
$('.nav-tabs a:last').bootstrapTab('show')
|
|
||||||
})
|
|
||||||
.trigger($.Event('click'))
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should not add show class to tab panes if there is no `.fade` class', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
var html = [
|
|
||||||
'<ul class="nav nav-tabs" role="tablist">',
|
|
||||||
' <li class="nav-item">',
|
|
||||||
' <a class="nav-link nav-tab" href="#home" role="tab" data-toggle="tab">Home</a>',
|
|
||||||
' </li>',
|
|
||||||
' <li class="nav-item">',
|
|
||||||
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">Profile</a>',
|
|
||||||
' </li>',
|
|
||||||
'</ul>',
|
|
||||||
'<div class="tab-content">',
|
|
||||||
' <div role="tabpanel" class="tab-pane" id="home">test 1</div>',
|
|
||||||
' <div role="tabpanel" class="tab-pane" id="profile">test 2</div>',
|
|
||||||
'</div>'
|
|
||||||
].join('')
|
|
||||||
|
|
||||||
$(html).appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$('#secondNav').on('shown.bs.tab', function () {
|
|
||||||
assert.strictEqual($('.show').length, 0)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#secondNav')[0].click()
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should add show class to tab panes if there is a `.fade` class', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
var done = assert.async()
|
|
||||||
|
|
||||||
var html = [
|
|
||||||
'<ul class="nav nav-tabs" role="tablist">',
|
|
||||||
' <li class="nav-item">',
|
|
||||||
' <a class="nav-link nav-tab" href="#home" role="tab" data-toggle="tab">Home</a>',
|
|
||||||
' </li>',
|
|
||||||
' <li class="nav-item">',
|
|
||||||
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-toggle="tab">Profile</a>',
|
|
||||||
' </li>',
|
|
||||||
'</ul>',
|
|
||||||
'<div class="tab-content">',
|
|
||||||
' <div role="tabpanel" class="tab-pane fade" id="home">test 1</div>',
|
|
||||||
' <div role="tabpanel" class="tab-pane fade" id="profile">test 2</div>',
|
|
||||||
'</div>'
|
|
||||||
].join('')
|
|
||||||
|
|
||||||
$(html).appendTo('#qunit-fixture')
|
|
||||||
|
|
||||||
$('#secondNav').on('shown.bs.tab', function () {
|
|
||||||
assert.strictEqual($('.show').length, 1)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#secondNav')[0].click()
|
|
||||||
})
|
|
||||||
|
|
||||||
QUnit.test('should return the version', function (assert) {
|
|
||||||
assert.expect(1)
|
|
||||||
assert.strictEqual(typeof Tab.VERSION, 'string')
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,28 +0,0 @@
|
|||||||
// Polyfills for our unit tests
|
|
||||||
(function () {
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
// Event constructor shim
|
|
||||||
if (!window.Event || typeof window.Event !== 'function') {
|
|
||||||
var origEvent = window.Event
|
|
||||||
window.Event = function (inType, params) {
|
|
||||||
params = params || {}
|
|
||||||
var e = document.createEvent('Event')
|
|
||||||
e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
window.Event.prototype = origEvent.prototype
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof window.CustomEvent !== 'function') {
|
|
||||||
window.CustomEvent = function (event, params) {
|
|
||||||
params = params || { bubbles: false, cancelable: false, detail: null }
|
|
||||||
var evt = document.createEvent('CustomEvent')
|
|
||||||
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomEvent.prototype = window.Event.prototype
|
|
||||||
}
|
|
||||||
})()
|
|
Loading…
x
Reference in New Issue
Block a user