An error occurred while loading the file. Please try again.
-
Mark Otto authored045888fa
import Carousel from '../../src/carousel'
import EventHandler from '../../src/dom/event-handler'
/** Test helpers */
import { getFixture, clearFixture, createEvent, jQueryMock } from '../helpers/fixture'
describe('Carousel', () => {
const { Simulator, PointerEvent } = window
const originWinPointerEvent = PointerEvent
const supportPointerEvent = Boolean(PointerEvent)
const cssStyleCarousel = '.carousel.pointer-event { touch-action: none; }'
const stylesCarousel = document.createElement('style')
stylesCarousel.type = 'text/css'
stylesCarousel.appendChild(document.createTextNode(cssStyleCarousel))
const clearPointerEvents = () => {
window.PointerEvent = null
}
const restorePointerEvents = () => {
window.PointerEvent = originWinPointerEvent
}
let fixtureEl
beforeAll(() => {
fixtureEl = getFixture()
})
afterEach(() => {
clearFixture()
})
describe('VERSION', () => {
it('should return plugin version', () => {
expect(Carousel.VERSION).toEqual(jasmine.any(String))
})
})
describe('Default', () => {
it('should return plugin default config', () => {
expect(Carousel.Default).toEqual(jasmine.any(Object))
})
})
describe('constructor', () => {
it('should go to next item if right arrow key is pressed', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div id="item2" class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {
keyboard: true
})
spyOn(carousel, '_keydown').and.callThrough()
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item2'))
expect(carousel._keydown).toHaveBeenCalled()
done()
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
})
const keydown = createEvent('keydown')
keydown.key = 'ArrowRight'
carouselEl.dispatchEvent(keydown)
})
it('should go to previous item if left arrow key is pressed', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div id="item1" class="carousel-item">item 1</div>',
' <div class="carousel-item active">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {
keyboard: true
})
spyOn(carousel, '_keydown').and.callThrough()
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item1'))
expect(carousel._keydown).toHaveBeenCalled()
done()
})
const keydown = createEvent('keydown')
keydown.key = 'ArrowLeft'
carouselEl.dispatchEvent(keydown)
})
it('should not prevent keydown if key is not ARROW_LEFT or ARROW_RIGHT', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {
keyboard: true
})
spyOn(carousel, '_keydown').and.callThrough()
carouselEl.addEventListener('keydown', event => {
expect(carousel._keydown).toHaveBeenCalled()
expect(event.defaultPrevented).toEqual(false)
done()
})
const keydown = createEvent('keydown')
keydown.key = 'ArrowDown'
carouselEl.dispatchEvent(keydown)
})
it('should ignore keyboard events within <input>s and <textarea>s', () => {
fixtureEl.innerHTML = [
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">',
' <input type="text" />',
' <textarea></textarea>',
' </div>',
' <div class="carousel-item"></div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const input = fixtureEl.querySelector('input')
const textarea = fixtureEl.querySelector('textarea')
const carousel = new Carousel(carouselEl, {
keyboard: true
})
const spyKeydown = spyOn(carousel, '_keydown').and.callThrough()
const spyPrev = spyOn(carousel, 'prev')
const spyNext = spyOn(carousel, 'next')
const keydown = createEvent('keydown', { bubbles: true, cancelable: true })
keydown.key = 'ArrowRight'
Object.defineProperty(keydown, 'target', {
value: input,
writable: true,
configurable: true
})
input.dispatchEvent(keydown)
expect(spyKeydown).toHaveBeenCalled()
expect(spyPrev).not.toHaveBeenCalled()
expect(spyNext).not.toHaveBeenCalled()
spyKeydown.calls.reset()
spyPrev.calls.reset()
spyNext.calls.reset()
Object.defineProperty(keydown, 'target', {
value: textarea
})
textarea.dispatchEvent(keydown)
expect(spyKeydown).toHaveBeenCalled()
expect(spyPrev).not.toHaveBeenCalled()
expect(spyNext).not.toHaveBeenCalled()
})
it('should wrap around from end to start when wrap option is true', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div id="one" class="carousel-item active"></div>',
' <div id="two" class="carousel-item"></div>',
' <div id="three" class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, { wrap: true })
const getActiveId = () => {
return carouselEl.querySelector('.carousel-item.active').getAttribute('id')
}
carouselEl.addEventListener('slid.bs.carousel', e => {
const activeId = getActiveId()
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
if (activeId === 'two') {
carousel.next()
return
}
if (activeId === 'three') {
carousel.next()
return
}
if (activeId === 'one') {
// carousel wrapped around and slid from 3rd to 1st slide
expect(activeId).toEqual('one')
expect(e.from + 1).toEqual(3)
done()
}
})
carousel.next()
})
it('should stay at the start when the prev method is called and wrap is false', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div id="one" class="carousel-item active"></div>',
' <div id="two" class="carousel-item"></div>',
' <div id="three" class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const firstElement = fixtureEl.querySelector('#one')
const carousel = new Carousel(carouselEl, { wrap: false })
carouselEl.addEventListener('slid.bs.carousel', () => {
throw new Error('carousel slid when it should not have slid')
})
carousel.prev()
setTimeout(() => {
expect(firstElement.classList.contains('active')).toEqual(true)
done()
}, 10)
})
it('should not add touch event listeners if touch = false', () => {
fixtureEl.innerHTML = '<div></div>'
const carouselEl = fixtureEl.querySelector('div')
spyOn(Carousel.prototype, '_addTouchEventListeners')
const carousel = new Carousel(carouselEl, {
touch: false
})
expect(carousel._addTouchEventListeners).not.toHaveBeenCalled()
})
it('should not add touch event listeners if touch supported = false', () => {
fixtureEl.innerHTML = '<div></div>'
const carouselEl = fixtureEl.querySelector('div')
const carousel = new Carousel(carouselEl)
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
EventHandler.off(carouselEl, '.bs-carousel')
carousel._touchSupported = false
spyOn(carousel, '_addTouchEventListeners')
carousel._addEventListeners()
expect(carousel._addTouchEventListeners).not.toHaveBeenCalled()
})
it('should add touch event listeners by default', () => {
fixtureEl.innerHTML = '<div></div>'
const carouselEl = fixtureEl.querySelector('div')
spyOn(Carousel.prototype, '_addTouchEventListeners')
document.documentElement.ontouchstart = () => {}
const carousel = new Carousel(carouselEl)
expect(carousel._addTouchEventListeners).toHaveBeenCalled()
})
it('should allow swiperight and call prev with pointer events', done => {
if (!supportPointerEvent) {
expect().nothing()
done()
return
}
document.documentElement.ontouchstart = () => {}
document.head.appendChild(stylesCarousel)
Simulator.setType('pointer')
fixtureEl.innerHTML = [
'<div class="carousel" data-interval="false">',
' <div class="carousel-inner">',
' <div id="item" class="carousel-item">',
' <img alt="">',
' </div>',
' <div class="carousel-item active">',
' <img alt="">',
' </div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('.carousel')
const item = fixtureEl.querySelector('#item')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'prev').and.callThrough()
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(item.classList.contains('active')).toEqual(true)
expect(carousel.prev).toHaveBeenCalled()
document.head.removeChild(stylesCarousel)
delete document.documentElement.ontouchstart
done()
})
Simulator.gestures.swipe(carouselEl, {
deltaX: 300,
deltaY: 0
})
})
it('should allow swipeleft and call next with pointer events', done => {
if (!supportPointerEvent) {
expect().nothing()
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
done()
return
}
document.documentElement.ontouchstart = () => {}
document.head.appendChild(stylesCarousel)
Simulator.setType('pointer')
fixtureEl.innerHTML = [
'<div class="carousel" data-interval="false">',
' <div class="carousel-inner">',
' <div id="item" class="carousel-item active">',
' <img alt="">',
' </div>',
' <div class="carousel-item">',
' <img alt="">',
' </div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('.carousel')
const item = fixtureEl.querySelector('#item')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'next').and.callThrough()
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(item.classList.contains('active')).toEqual(false)
expect(carousel.next).toHaveBeenCalled()
document.head.removeChild(stylesCarousel)
delete document.documentElement.ontouchstart
done()
})
Simulator.gestures.swipe(carouselEl, {
pos: [300, 10],
deltaX: -300,
deltaY: 0
})
})
it('should allow swiperight and call prev with touch events', done => {
Simulator.setType('touch')
clearPointerEvents()
document.documentElement.ontouchstart = () => {}
fixtureEl.innerHTML = [
'<div class="carousel" data-interval="false">',
' <div class="carousel-inner">',
' <div id="item" class="carousel-item">',
' <img alt="">',
' </div>',
' <div class="carousel-item active">',
' <img alt="">',
' </div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('.carousel')
const item = fixtureEl.querySelector('#item')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'prev').and.callThrough()
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(item.classList.contains('active')).toEqual(true)
expect(carousel.prev).toHaveBeenCalled()
delete document.documentElement.ontouchstart
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
restorePointerEvents()
done()
})
Simulator.gestures.swipe(carouselEl, {
deltaX: 300,
deltaY: 0
})
})
it('should allow swipeleft and call next with touch events', done => {
Simulator.setType('touch')
clearPointerEvents()
document.documentElement.ontouchstart = () => {}
fixtureEl.innerHTML = [
'<div class="carousel" data-interval="false">',
' <div class="carousel-inner">',
' <div id="item" class="carousel-item active">',
' <img alt="">',
' </div>',
' <div class="carousel-item">',
' <img alt="">',
' </div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('.carousel')
const item = fixtureEl.querySelector('#item')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'next').and.callThrough()
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(item.classList.contains('active')).toEqual(false)
expect(carousel.next).toHaveBeenCalled()
delete document.documentElement.ontouchstart
restorePointerEvents()
done()
})
Simulator.gestures.swipe(carouselEl, {
pos: [300, 10],
deltaX: -300,
deltaY: 0
})
})
it('should not allow pinch with touch events', done => {
Simulator.setType('touch')
clearPointerEvents()
document.documentElement.ontouchstart = () => {}
fixtureEl.innerHTML = '<div class="carousel" data-interval="false"></div>'
const carouselEl = fixtureEl.querySelector('.carousel')
const carousel = new Carousel(carouselEl)
Simulator.gestures.swipe(carouselEl, {
pos: [300, 10],
deltaX: -300,
deltaY: 0,
touches: 2
}, () => {
restorePointerEvents()
delete document.documentElement.ontouchstart
expect(carousel.touchDeltaX).toEqual(0)
done()
})
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
})
it('should call pause method on mouse over with pause equal to hover', done => {
fixtureEl.innerHTML = '<div class="carousel"></div>'
const carouselEl = fixtureEl.querySelector('.carousel')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'pause')
const mouseOverEvent = createEvent('mouseover')
carouselEl.dispatchEvent(mouseOverEvent)
setTimeout(() => {
expect(carousel.pause).toHaveBeenCalled()
done()
}, 10)
})
it('should call cycle on mouse out with pause equal to hover', done => {
fixtureEl.innerHTML = '<div class="carousel"></div>'
const carouselEl = fixtureEl.querySelector('.carousel')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'cycle')
const mouseOutEvent = createEvent('mouseout')
carouselEl.dispatchEvent(mouseOutEvent)
setTimeout(() => {
expect(carousel.cycle).toHaveBeenCalled()
done()
}, 10)
})
})
describe('next', () => {
it('should not slide if the carousel is sliding', () => {
fixtureEl.innerHTML = '<div></div>'
const carouselEl = fixtureEl.querySelector('div')
const carousel = new Carousel(carouselEl, {})
spyOn(carousel, '_slide')
carousel._isSliding = true
carousel.next()
expect(carousel._slide).not.toHaveBeenCalled()
})
it('should not fire slid when slide is prevented', done => {
fixtureEl.innerHTML = '<div></div>'
const carouselEl = fixtureEl.querySelector('div')
const carousel = new Carousel(carouselEl, {})
let slidEvent = false
const doneTest = () => {
setTimeout(() => {
expect(slidEvent).toEqual(false)
done()
}, 20)
}
carouselEl.addEventListener('slide.bs.carousel', e => {
e.preventDefault()
doneTest()
})
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
carouselEl.addEventListener('slid.bs.carousel', () => {
slidEvent = true
})
carousel.next()
})
it('should fire slide event with: direction, relatedTarget, from and to', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {})
const onSlide = e => {
expect(e.direction).toEqual('left')
expect(e.relatedTarget.classList.contains('carousel-item')).toEqual(true)
expect(e.from).toEqual(0)
expect(e.to).toEqual(1)
carouselEl.removeEventListener('slide.bs.carousel', onSlide)
carouselEl.addEventListener('slide.bs.carousel', onSlide2)
carousel.prev()
}
const onSlide2 = e => {
expect(e.direction).toEqual('right')
done()
}
carouselEl.addEventListener('slide.bs.carousel', onSlide)
carousel.next()
})
it('should fire slid event with: direction, relatedTarget, from and to', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {})
const onSlid = e => {
expect(e.direction).toEqual('left')
expect(e.relatedTarget.classList.contains('carousel-item')).toEqual(true)
expect(e.from).toEqual(0)
expect(e.to).toEqual(1)
carouselEl.removeEventListener('slid.bs.carousel', onSlid)
carouselEl.addEventListener('slid.bs.carousel', onSlid2)
carousel.prev()
}
const onSlid2 = e => {
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
expect(e.direction).toEqual('right')
done()
}
carouselEl.addEventListener('slid.bs.carousel', onSlid)
carousel.next()
})
it('should get interval from data attribute in individual item', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item" data-interval="7">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {
interval: 1814
})
expect(carousel._config.interval).toEqual(1814)
carousel.next()
expect(carousel._config.interval).toEqual(7)
})
it('should update indicators if present', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <ol class="carousel-indicators">',
' <li data-target="#myCarousel" data-slide-to="0" class="active"></li>',
' <li id="secondIndicator" data-target="#myCarousel" data-slide-to="1"></li>',
' <li data-target="#myCarousel" data-slide-to="2"></li>',
' </ol>',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item" data-interval="7">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const secondIndicator = fixtureEl.querySelector('#secondIndicator')
const carousel = new Carousel(carouselEl)
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(secondIndicator.classList.contains('active')).toEqual(true)
done()
})
carousel.next()
})
})
describe('nextWhenVisible', () => {
it('should not call next when the page is not visible', () => {
fixtureEl.innerHTML = [
'<div style="display: none;">',
' <div class="carousel" data-interval="false"></div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('.carousel')
const carousel = new Carousel(carouselEl)
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
spyOn(carousel, 'next')
carousel.nextWhenVisible()
expect(carousel.next).not.toHaveBeenCalled()
})
})
describe('prev', () => {
it('should not slide if the carousel is sliding', () => {
fixtureEl.innerHTML = '<div></div>'
const carouselEl = fixtureEl.querySelector('div')
const carousel = new Carousel(carouselEl, {})
spyOn(carousel, '_slide')
carousel._isSliding = true
carousel.prev()
expect(carousel._slide).not.toHaveBeenCalled()
})
})
describe('pause', () => {
it('should call cycle if the carousel have carousel-item-next and carousel-item-prev class', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item carousel-item-next">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev"></div>',
' <div class="carousel-control-next"></div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'cycle')
spyOn(window, 'clearInterval')
carousel.pause()
expect(carousel.cycle).toHaveBeenCalledWith(true)
expect(window.clearInterval).toHaveBeenCalled()
expect(carousel._isPaused).toEqual(true)
})
it('should not call cycle if nothing is in transition', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev"></div>',
' <div class="carousel-control-next"></div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl)
spyOn(carousel, 'cycle')
spyOn(window, 'clearInterval')
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
carousel.pause()
expect(carousel.cycle).not.toHaveBeenCalled()
expect(window.clearInterval).toHaveBeenCalled()
expect(carousel._isPaused).toEqual(true)
})
it('should not set is paused at true if an event is passed', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev"></div>',
' <div class="carousel-control-next"></div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl)
const event = createEvent('mouseenter')
spyOn(window, 'clearInterval')
carousel.pause(event)
expect(window.clearInterval).toHaveBeenCalled()
expect(carousel._isPaused).toEqual(false)
})
})
describe('cycle', () => {
it('should set an interval', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev"></div>',
' <div class="carousel-control-next"></div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl)
spyOn(window, 'setInterval').and.callThrough()
carousel.cycle()
expect(window.setInterval).toHaveBeenCalled()
})
it('should not set interval if the carousel is paused', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev"></div>',
' <div class="carousel-control-next"></div>',
'</div>'
].join('')
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl)
spyOn(window, 'setInterval').and.callThrough()
carousel._isPaused = true
carousel.cycle(true)
expect(window.setInterval).not.toHaveBeenCalled()
})
it('should clear interval if there is one', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev"></div>',
' <div class="carousel-control-next"></div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl)
carousel._interval = setInterval(() => {}, 10)
spyOn(window, 'setInterval').and.callThrough()
spyOn(window, 'clearInterval').and.callThrough()
carousel.cycle()
expect(window.setInterval).toHaveBeenCalled()
expect(window.clearInterval).toHaveBeenCalled()
})
})
describe('to', () => {
it('should go directement to the provided index', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div id="item1" class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div id="item3" class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {})
expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item1'))
carousel.to(2)
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item3'))
done()
})
})
it('should return to a previous slide if the provided index is lower than the current', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item">item 1</div>',
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
' <div id="item2" class="carousel-item">item 2</div>',
' <div id="item3" class="carousel-item active">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {})
expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item3'))
carousel.to(1)
carouselEl.addEventListener('slid.bs.carousel', () => {
expect(fixtureEl.querySelector('.active')).toEqual(fixtureEl.querySelector('#item2'))
done()
})
})
it('should do nothing if a wrong index is provided', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item" data-interval="7">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {})
const spy = spyOn(carousel, '_slide')
carousel.to(25)
expect(spy).not.toHaveBeenCalled()
spy.calls.reset()
carousel.to(-5)
expect(spy).not.toHaveBeenCalled()
})
it('should call pause and cycle is the provided is the same compare to the current one', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item" data-interval="7">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {})
spyOn(carousel, '_slide')
spyOn(carousel, 'pause')
spyOn(carousel, 'cycle')
carousel.to(0)
expect(carousel._slide).not.toHaveBeenCalled()
expect(carousel.pause).toHaveBeenCalled()
expect(carousel.cycle).toHaveBeenCalled()
})
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
it('should wait before performing to if a slide is sliding', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item" data-interval="7">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl, {})
spyOn(EventHandler, 'one').and.callThrough()
spyOn(carousel, '_slide')
carousel._isSliding = true
carousel.to(1)
expect(carousel._slide).not.toHaveBeenCalled()
expect(EventHandler.one).toHaveBeenCalled()
spyOn(carousel, 'to')
EventHandler.trigger(carouselEl, 'slid.bs.carousel')
setTimeout(() => {
expect(carousel.to).toHaveBeenCalledWith(1)
done()
})
})
})
describe('dispose', () => {
it('should destroy a carousel', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item" data-interval="7">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('#myCarousel')
const carousel = new Carousel(carouselEl)
spyOn(EventHandler, 'off').and.callThrough()
carousel.dispose()
expect(EventHandler.off).toHaveBeenCalled()
})
})
describe('jQueryInterface', () => {
it('should create a carousel', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock)
expect(Carousel.getInstance(div)).toBeDefined()
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
})
it('should not re create a carousel', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const carousel = new Carousel(div)
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock)
expect(Carousel.getInstance(div)).toEqual(carousel)
})
it('should call to if the config is a number', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const carousel = new Carousel(div)
const slideTo = 2
spyOn(carousel, 'to')
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock, slideTo)
expect(carousel.to).toHaveBeenCalledWith(slideTo)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
try {
jQueryMock.fn.carousel.call(jQueryMock, action)
} catch (error) {
expect(error.message).toEqual(`No method named "${action}"`)
}
})
})
describe('data-api', () => {
it('should init carousels with data-ride="carousel" on load', () => {
fixtureEl.innerHTML = '<div data-ride="carousel"></div>'
const carouselEl = fixtureEl.querySelector('div')
const loadEvent = createEvent('load')
window.dispatchEvent(loadEvent)
expect(Carousel.getInstance(carouselEl)).toBeDefined()
})
it('should create carousel and go to the next slide on click', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div id="item2" class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
' <div class="carousel-control-prev" data-target="#myCarousel" role="button" data-slide="prev"></div>',
' <div id="next" class="carousel-control-next" data-target="#myCarousel" role="button" data-slide="next"></div>',
'</div>'
].join('')
const next = fixtureEl.querySelector('#next')
const item2 = fixtureEl.querySelector('#item2')
next.click()
setTimeout(() => {
expect(item2.classList.contains('active')).toEqual(true)
done()
}, 10)
})
it('should create carousel and go to the next slide on click with data-slide-to', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div id="item2" class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div id="next" data-target="#myCarousel" data-slide-to="1"></div>',
'</div>'
].join('')
const next = fixtureEl.querySelector('#next')
const item2 = fixtureEl.querySelector('#item2')
next.click()
setTimeout(() => {
expect(item2.classList.contains('active')).toEqual(true)
done()
}, 10)
})
it('should do nothing if no selector on click on arrows', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev" data-target="#myCarousel" role="button" data-slide="prev"></div>',
' <div id="next" class="carousel-control-next" role="button" data-slide="next"></div>',
'</div>'
].join('')
const next = fixtureEl.querySelector('#next')
next.click()
expect().nothing()
})
it('should do nothing if no carousel class on click on arrows', () => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="slide">',
' <div class="carousel-inner">',
' <div class="carousel-item active">item 1</div>',
' <div id="item2" class="carousel-item">item 2</div>',
' <div class="carousel-item">item 3</div>',
' </div>',
' <div class="carousel-control-prev" data-target="#myCarousel" role="button" data-slide="prev"></div>',
' <div id="next" class="carousel-control-next" data-target="#myCarousel" role="button" data-slide="next"></div>',
'</div>'
11911192119311941195119611971198119912001201
].join('')
const next = fixtureEl.querySelector('#next')
next.click()
expect().nothing()
})
})
})