mirror of
https://github.com/twbs/bootstrap.git
synced 2025-08-10 07:37:27 +02:00
tests: replace 'done' callback with 'Promise' to fix deprecation errors (#35659)
Reference: https://jasmine.github.io/tutorials/async 'DEPRECATION: An asynchronous function called its 'done' callback more than once. This is a bug in the spec, beforeAll, beforeEach, afterAll, or afterEach function in question. This will be treated as an error in a future version. See<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> for more information.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import ScrollSpy from '../../src/scrollspy'
|
||||
import Manipulator from '../../src/dom/manipulator'
|
||||
import { getFixture, clearFixture, createEvent, jQueryMock } from '../helpers/fixture'
|
||||
import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
|
||||
|
||||
describe('ScrollSpy', () => {
|
||||
let fixtureEl
|
||||
@@ -85,418 +85,436 @@ describe('ScrollSpy', () => {
|
||||
expect(scrollSpy._targets).toHaveSize(2)
|
||||
})
|
||||
|
||||
it('should only switch "active" class on current target', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="root" class="active" style="display: block">',
|
||||
' <div class="topbar">',
|
||||
' <div class="topbar-inner">',
|
||||
' <div class="container" id="ss-target">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a href="#masthead">Overview</a></li>',
|
||||
' <li class="nav-item"><a href="#detail">Detail</a></li>',
|
||||
' </ul>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div id="scrollspy-example" style="height: 100px; overflow: auto;">',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="masthead">Overview</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="detail">Detail</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
it('should only switch "active" class on current target', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="root" class="active" style="display: block">',
|
||||
' <div class="topbar">',
|
||||
' <div class="topbar-inner">',
|
||||
' <div class="container" id="ss-target">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a href="#masthead">Overview</a></li>',
|
||||
' <li class="nav-item"><a href="#detail">Detail</a></li>',
|
||||
' </ul>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div id="scrollspy-example" style="height: 100px; overflow: auto;">',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="masthead">Overview</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="detail">Detail</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const scrollSpyEl = fixtureEl.querySelector('#scrollspy-example')
|
||||
const rootEl = fixtureEl.querySelector('#root')
|
||||
const scrollSpy = new ScrollSpy(scrollSpyEl, {
|
||||
target: 'ss-target'
|
||||
})
|
||||
const scrollSpyEl = fixtureEl.querySelector('#scrollspy-example')
|
||||
const rootEl = fixtureEl.querySelector('#root')
|
||||
const scrollSpy = new ScrollSpy(scrollSpyEl, {
|
||||
target: 'ss-target'
|
||||
})
|
||||
|
||||
spyOn(scrollSpy, '_process').and.callThrough()
|
||||
spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
scrollSpyEl.addEventListener('scroll', () => {
|
||||
expect(rootEl).toHaveClass('active')
|
||||
expect(scrollSpy._process).toHaveBeenCalled()
|
||||
done()
|
||||
})
|
||||
scrollSpyEl.addEventListener('scroll', () => {
|
||||
expect(rootEl).toHaveClass('active')
|
||||
expect(scrollSpy._process).toHaveBeenCalled()
|
||||
resolve()
|
||||
})
|
||||
|
||||
scrollSpyEl.scrollTop = 350
|
||||
})
|
||||
|
||||
it('should only switch "active" class on current target specified w element', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="root" class="active" style="display: block">',
|
||||
' <div class="topbar">',
|
||||
' <div class="topbar-inner">',
|
||||
' <div class="container" id="ss-target">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a href="#masthead">Overview</a></li>',
|
||||
' <li class="nav-item"><a href="#detail">Detail</a></li>',
|
||||
' </ul>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div id="scrollspy-example" style="height: 100px; overflow: auto;">',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="masthead">Overview</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="detail">Detail</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const scrollSpyEl = fixtureEl.querySelector('#scrollspy-example')
|
||||
const rootEl = fixtureEl.querySelector('#root')
|
||||
const scrollSpy = new ScrollSpy(scrollSpyEl, {
|
||||
target: fixtureEl.querySelector('#ss-target')
|
||||
})
|
||||
|
||||
spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
scrollSpyEl.addEventListener('scroll', () => {
|
||||
expect(rootEl).toHaveClass('active')
|
||||
expect(scrollSpy._process).toHaveBeenCalled()
|
||||
done()
|
||||
})
|
||||
|
||||
scrollSpyEl.scrollTop = 350
|
||||
})
|
||||
|
||||
it('should correctly select middle navigation option when large offset is used', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="header" style="height: 500px;"></div>',
|
||||
'<nav id="navigation" class="navbar">',
|
||||
' <ul class="navbar-nav">',
|
||||
' <li class="nav-item"><a class="nav-link active" id="one-link" href="#one">One</a></li>',
|
||||
' <li class="nav-item"><a class="nav-link" id="two-link" href="#two">Two</a></li>',
|
||||
' <li class="nav-item"><a class="nav-link" id="three-link" href="#three">Three</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div id="content" style="height: 200px; overflow-y: auto;">',
|
||||
' <div id="one" style="height: 500px;"></div>',
|
||||
' <div id="two" style="height: 300px;"></div>',
|
||||
' <div id="three" style="height: 10px;"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('#content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
target: '#navigation',
|
||||
offset: Manipulator.position(contentEl).top
|
||||
})
|
||||
|
||||
spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
contentEl.addEventListener('scroll', () => {
|
||||
expect(fixtureEl.querySelector('#one-link')).not.toHaveClass('active')
|
||||
expect(fixtureEl.querySelector('#two-link')).toHaveClass('active')
|
||||
expect(fixtureEl.querySelector('#three-link')).not.toHaveClass('active')
|
||||
expect(scrollSpy._process).toHaveBeenCalled()
|
||||
done()
|
||||
})
|
||||
|
||||
contentEl.scrollTop = 550
|
||||
})
|
||||
|
||||
it('should add the active class to the correct element', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a class="nav-link" id="a-1" href="#div-1">div 1</a></li>',
|
||||
' <li class="nav-item"><a class="nav-link" id="a-2" href="#div-2">div 2</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div class="content" style="overflow: auto; height: 50px">',
|
||||
' <div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-1',
|
||||
targetSelector: '#div-1',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => {
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-2',
|
||||
targetSelector: '#div-2',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => done()
|
||||
})
|
||||
}
|
||||
scrollSpyEl.scrollTop = 350
|
||||
})
|
||||
})
|
||||
|
||||
it('should add the active class to the correct element (nav markup)', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <nav class="nav">',
|
||||
' <a class="nav-link" id="a-1" href="#div-1">div 1</a>',
|
||||
' <a class="nav-link" id="a-2" href="#div-2">div 2</a>',
|
||||
' </nav>',
|
||||
'</nav>',
|
||||
'<div class="content" style="overflow: auto; height: 50px">',
|
||||
' <div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
it('should only switch "active" class on current target specified w element', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="root" class="active" style="display: block">',
|
||||
' <div class="topbar">',
|
||||
' <div class="topbar-inner">',
|
||||
' <div class="container" id="ss-target">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a href="#masthead">Overview</a></li>',
|
||||
' <li class="nav-item"><a href="#detail">Detail</a></li>',
|
||||
' </ul>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div id="scrollspy-example" style="height: 100px; overflow: auto;">',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="masthead">Overview</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' <div style="height: 200px;">',
|
||||
' <h4 id="detail">Detail</h4>',
|
||||
' <p style="height: 200px;"></p>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
const scrollSpyEl = fixtureEl.querySelector('#scrollspy-example')
|
||||
const rootEl = fixtureEl.querySelector('#root')
|
||||
const scrollSpy = new ScrollSpy(scrollSpyEl, {
|
||||
target: fixtureEl.querySelector('#ss-target')
|
||||
})
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-1',
|
||||
targetSelector: '#div-1',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => {
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-2',
|
||||
targetSelector: '#div-2',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => done()
|
||||
})
|
||||
}
|
||||
spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
scrollSpyEl.addEventListener('scroll', () => {
|
||||
expect(rootEl).toHaveClass('active')
|
||||
expect(scrollSpy._process).toHaveBeenCalled()
|
||||
resolve()
|
||||
})
|
||||
|
||||
scrollSpyEl.scrollTop = 350
|
||||
})
|
||||
})
|
||||
|
||||
it('should add the active class to the correct element (list-group markup)', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <div class="list-group">',
|
||||
' <a class="list-group-item" id="a-1" href="#div-1">div 1</a>',
|
||||
' <a class="list-group-item" id="a-2" href="#div-2">div 2</a>',
|
||||
' </div>',
|
||||
'</nav>',
|
||||
'<div class="content" style="overflow: auto; height: 50px">',
|
||||
' <div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
it('should correctly select middle navigation option when large offset is used', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="header" style="height: 500px;"></div>',
|
||||
'<nav id="navigation" class="navbar">',
|
||||
' <ul class="navbar-nav">',
|
||||
' <li class="nav-item"><a class="nav-link active" id="one-link" href="#one">One</a></li>',
|
||||
' <li class="nav-item"><a class="nav-link" id="two-link" href="#two">Two</a></li>',
|
||||
' <li class="nav-item"><a class="nav-link" id="three-link" href="#three">Three</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div id="content" style="height: 200px; overflow-y: auto;">',
|
||||
' <div id="one" style="height: 500px;"></div>',
|
||||
' <div id="two" style="height: 300px;"></div>',
|
||||
' <div id="three" style="height: 10px;"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
const contentEl = fixtureEl.querySelector('#content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
target: '#navigation',
|
||||
offset: Manipulator.position(contentEl).top
|
||||
})
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-1',
|
||||
targetSelector: '#div-1',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => {
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-2',
|
||||
targetSelector: '#div-2',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => done()
|
||||
})
|
||||
}
|
||||
spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
contentEl.addEventListener('scroll', () => {
|
||||
expect(fixtureEl.querySelector('#one-link')).not.toHaveClass('active')
|
||||
expect(fixtureEl.querySelector('#two-link')).toHaveClass('active')
|
||||
expect(fixtureEl.querySelector('#three-link')).not.toHaveClass('active')
|
||||
expect(scrollSpy._process).toHaveBeenCalled()
|
||||
resolve()
|
||||
})
|
||||
|
||||
contentEl.scrollTop = 550
|
||||
})
|
||||
})
|
||||
|
||||
it('should clear selection if above the first section', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="header" style="height: 500px;"></div>',
|
||||
'<nav id="navigation" class="navbar">',
|
||||
' <ul class="navbar-nav">',
|
||||
' <li class="nav-item"><a id="one-link" class="nav-link active" href="#one">One</a></li>',
|
||||
' <li class="nav-item"><a id="two-link" class="nav-link" href="#two">Two</a></li>',
|
||||
' <li class="nav-item"><a id="three-link" class="nav-link" href="#three">Three</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div id="content" style="height: 200px; overflow-y: auto;">',
|
||||
' <div id="spacer" style="height: 100px;"></div>',
|
||||
' <div id="one" style="height: 100px;"></div>',
|
||||
' <div id="two" style="height: 100px;"></div>',
|
||||
' <div id="three" style="height: 100px;"></div>',
|
||||
' <div id="spacer" style="height: 100px;"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
it('should add the active class to the correct element', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a class="nav-link" id="a-1" href="#div-1">div 1</a></li>',
|
||||
' <li class="nav-item"><a class="nav-link" id="a-2" href="#div-2">div 2</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div class="content" style="overflow: auto; height: 50px">',
|
||||
' <div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('#content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
target: '#navigation',
|
||||
offset: Manipulator.position(contentEl).top
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-1',
|
||||
targetSelector: '#div-1',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => {
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-2',
|
||||
targetSelector: '#div-2',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: resolve
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
let firstTime = true
|
||||
|
||||
contentEl.addEventListener('scroll', () => {
|
||||
const active = fixtureEl.querySelector('.active')
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
spy.calls.reset()
|
||||
if (firstTime) {
|
||||
expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1)
|
||||
expect(active.getAttribute('id')).toEqual('two-link')
|
||||
firstTime = false
|
||||
contentEl.scrollTop = 0
|
||||
} else {
|
||||
expect(active).toBeNull()
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
contentEl.scrollTop = 201
|
||||
})
|
||||
|
||||
it('should not clear selection if above the first section and first section is at the top', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="header" style="height: 500px;"></div>',
|
||||
'<nav id="navigation" class="navbar">',
|
||||
' <ul class="navbar-nav">',
|
||||
' <li class="nav-item"><a id="one-link" class="nav-link active" href="#one">One</a></li>',
|
||||
' <li class="nav-item"><a id="two-link" class="nav-link" href="#two">Two</a></li>',
|
||||
' <li class="nav-item"><a id="three-link" class="nav-link" href="#three">Three</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div id="content" style="height: 200px; overflow-y: auto;">',
|
||||
' <div id="one" style="height: 100px;"></div>',
|
||||
' <div id="two" style="height: 100px;"></div>',
|
||||
' <div id="three" style="height: 100px;"></div>',
|
||||
' <div id="spacer" style="height: 100px;"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
it('should add the active class to the correct element (nav markup)', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <nav class="nav">',
|
||||
' <a class="nav-link" id="a-1" href="#div-1">div 1</a>',
|
||||
' <a class="nav-link" id="a-2" href="#div-2">div 2</a>',
|
||||
' </nav>',
|
||||
'</nav>',
|
||||
'<div class="content" style="overflow: auto; height: 50px">',
|
||||
' <div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const negativeHeight = -10
|
||||
const startOfSectionTwo = 101
|
||||
const contentEl = fixtureEl.querySelector('#content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
target: '#navigation',
|
||||
offset: contentEl.offsetTop
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-1',
|
||||
targetSelector: '#div-1',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => {
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-2',
|
||||
targetSelector: '#div-2',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: resolve
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
let firstTime = true
|
||||
|
||||
contentEl.addEventListener('scroll', () => {
|
||||
const active = fixtureEl.querySelector('.active')
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
spy.calls.reset()
|
||||
if (firstTime) {
|
||||
expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1)
|
||||
expect(active.getAttribute('id')).toEqual('two-link')
|
||||
firstTime = false
|
||||
contentEl.scrollTop = negativeHeight
|
||||
} else {
|
||||
expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1)
|
||||
expect(active.getAttribute('id')).toEqual('one-link')
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
contentEl.scrollTop = startOfSectionTwo
|
||||
})
|
||||
|
||||
it('should correctly select navigation element on backward scrolling when each target section height is 100%', done => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a id="li-100-1" class="nav-link" href="#div-100-1">div 1</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-2" class="nav-link" href="#div-100-2">div 2</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-3" class="nav-link" href="#div-100-3">div 3</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-4" class="nav-link" href="#div-100-4">div 4</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-5" class="nav-link" href="#div-100-5">div 5</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div class="content" style="position: relative; overflow: auto; height: 100px">',
|
||||
' <div id="div-100-1" style="position: relative; height: 100%; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-100-2" style="position: relative; height: 100%; padding: 0; margin: 0">div 2</div>',
|
||||
' <div id="div-100-3" style="position: relative; height: 100%; padding: 0; margin: 0">div 3</div>',
|
||||
' <div id="div-100-4" style="position: relative; height: 100%; padding: 0; margin: 0">div 4</div>',
|
||||
' <div id="div-100-5" style="position: relative; height: 100%; padding: 0; margin: 0">div 5</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
it('should add the active class to the correct element (list-group markup)', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <div class="list-group">',
|
||||
' <a class="list-group-item" id="a-1" href="#div-1">div 1</a>',
|
||||
' <a class="list-group-item" id="a-2" href="#div-2">div 2</a>',
|
||||
' </div>',
|
||||
'</nav>',
|
||||
'<div class="content" style="overflow: auto; height: 50px">',
|
||||
' <div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-1',
|
||||
targetSelector: '#div-1',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: () => {
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#a-2',
|
||||
targetSelector: '#div-2',
|
||||
contentEl,
|
||||
scrollSpy,
|
||||
spy,
|
||||
cb: resolve
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
})
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-5',
|
||||
targetSelector: '#div-100-5',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-4',
|
||||
targetSelector: '#div-100-4',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-3',
|
||||
targetSelector: '#div-100-3',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-2',
|
||||
targetSelector: '#div-100-2',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-1',
|
||||
targetSelector: '#div-100-1',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb: done
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
it('should clear selection if above the first section', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="header" style="height: 500px;"></div>',
|
||||
'<nav id="navigation" class="navbar">',
|
||||
' <ul class="navbar-nav">',
|
||||
' <li class="nav-item"><a id="one-link" class="nav-link active" href="#one">One</a></li>',
|
||||
' <li class="nav-item"><a id="two-link" class="nav-link" href="#two">Two</a></li>',
|
||||
' <li class="nav-item"><a id="three-link" class="nav-link" href="#three">Three</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div id="content" style="height: 200px; overflow-y: auto;">',
|
||||
' <div id="spacer" style="height: 100px;"></div>',
|
||||
' <div id="one" style="height: 100px;"></div>',
|
||||
' <div id="two" style="height: 100px;"></div>',
|
||||
' <div id="three" style="height: 100px;"></div>',
|
||||
' <div id="spacer" style="height: 100px;"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('#content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
target: '#navigation',
|
||||
offset: Manipulator.position(contentEl).top
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
let firstTime = true
|
||||
|
||||
contentEl.addEventListener('scroll', () => {
|
||||
const active = fixtureEl.querySelector('.active')
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
spy.calls.reset()
|
||||
if (firstTime) {
|
||||
expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1)
|
||||
expect(active.getAttribute('id')).toEqual('two-link')
|
||||
firstTime = false
|
||||
contentEl.scrollTop = 0
|
||||
} else {
|
||||
expect(active).toBeNull()
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
|
||||
contentEl.scrollTop = 201
|
||||
})
|
||||
})
|
||||
|
||||
it('should not clear selection if above the first section and first section is at the top', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="header" style="height: 500px;"></div>',
|
||||
'<nav id="navigation" class="navbar">',
|
||||
' <ul class="navbar-nav">',
|
||||
' <li class="nav-item"><a id="one-link" class="nav-link active" href="#one">One</a></li>',
|
||||
' <li class="nav-item"><a id="two-link" class="nav-link" href="#two">Two</a></li>',
|
||||
' <li class="nav-item"><a id="three-link" class="nav-link" href="#three">Three</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div id="content" style="height: 200px; overflow-y: auto;">',
|
||||
' <div id="one" style="height: 100px;"></div>',
|
||||
' <div id="two" style="height: 100px;"></div>',
|
||||
' <div id="three" style="height: 100px;"></div>',
|
||||
' <div id="spacer" style="height: 100px;"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const negativeHeight = -10
|
||||
const startOfSectionTwo = 101
|
||||
const contentEl = fixtureEl.querySelector('#content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
target: '#navigation',
|
||||
offset: contentEl.offsetTop
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
let firstTime = true
|
||||
|
||||
contentEl.addEventListener('scroll', () => {
|
||||
const active = fixtureEl.querySelector('.active')
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
spy.calls.reset()
|
||||
if (firstTime) {
|
||||
expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1)
|
||||
expect(active.getAttribute('id')).toEqual('two-link')
|
||||
firstTime = false
|
||||
contentEl.scrollTop = negativeHeight
|
||||
} else {
|
||||
expect(fixtureEl.querySelectorAll('.active')).toHaveSize(1)
|
||||
expect(active.getAttribute('id')).toEqual('one-link')
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
|
||||
contentEl.scrollTop = startOfSectionTwo
|
||||
})
|
||||
})
|
||||
|
||||
it('should correctly select navigation element on backward scrolling when each target section height is 100%', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<nav class="navbar">',
|
||||
' <ul class="nav">',
|
||||
' <li class="nav-item"><a id="li-100-1" class="nav-link" href="#div-100-1">div 1</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-2" class="nav-link" href="#div-100-2">div 2</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-3" class="nav-link" href="#div-100-3">div 3</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-4" class="nav-link" href="#div-100-4">div 4</a></li>',
|
||||
' <li class="nav-item"><a id="li-100-5" class="nav-link" href="#div-100-5">div 5</a></li>',
|
||||
' </ul>',
|
||||
'</nav>',
|
||||
'<div class="content" style="position: relative; overflow: auto; height: 100px">',
|
||||
' <div id="div-100-1" style="position: relative; height: 100%; padding: 0; margin: 0">div 1</div>',
|
||||
' <div id="div-100-2" style="position: relative; height: 100%; padding: 0; margin: 0">div 2</div>',
|
||||
' <div id="div-100-3" style="position: relative; height: 100%; padding: 0; margin: 0">div 3</div>',
|
||||
' <div id="div-100-4" style="position: relative; height: 100%; padding: 0; margin: 0">div 4</div>',
|
||||
' <div id="div-100-5" style="position: relative; height: 100%; padding: 0; margin: 0">div 5</div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const contentEl = fixtureEl.querySelector('.content')
|
||||
const scrollSpy = new ScrollSpy(contentEl, {
|
||||
offset: 0,
|
||||
target: '.navbar'
|
||||
})
|
||||
const spy = spyOn(scrollSpy, '_process').and.callThrough()
|
||||
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-5',
|
||||
targetSelector: '#div-100-5',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-4',
|
||||
targetSelector: '#div-100-4',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-3',
|
||||
targetSelector: '#div-100-3',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-2',
|
||||
targetSelector: '#div-100-2',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb() {
|
||||
contentEl.scrollTop = 0
|
||||
testElementIsActiveAfterScroll({
|
||||
elementSelector: '#li-100-1',
|
||||
targetSelector: '#div-100-1',
|
||||
scrollSpy,
|
||||
spy,
|
||||
contentEl,
|
||||
cb: resolve
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
Reference in New Issue
Block a user