diff --git a/spec/tests/scrollspy/scrollspySpec.js b/spec/tests/scrollspy/scrollspySpec.js index 98849925b8..4528ffd527 100644 --- a/spec/tests/scrollspy/scrollspySpec.js +++ b/spec/tests/scrollspy/scrollspySpec.js @@ -1,4 +1,5 @@ describe('Scrollspy Plugin', () => { + const DELAY_IN_MS = 600; const fixture = `
@@ -33,6 +34,7 @@ describe('Scrollspy Plugin', () => {
+
`; let scrollspyInstances = []; @@ -45,7 +47,7 @@ describe('Scrollspy Plugin', () => { }); afterEach(() => { - destroyScrollspyInstances(scrollspyInstances); + scrollspyInstances.forEach((value) => value.destroy()); XunloadFixtures(); }); @@ -56,50 +58,18 @@ describe('Scrollspy Plugin', () => { scrollspyInstances = M.ScrollSpy.init(elements, options); } - function destroyScrollspyInstances(scrollspyInstances) { - scrollspyInstances.forEach((value) => value.destroy()); - } - function clickLink(value) { document.querySelector(`a[href="#${value}"]`).click(); } - describe('Scrollspy basic test cases', () => { - const originalAddEventListener = EventTarget.prototype.addEventListener; - const originalRemoveEventListener = EventTarget.prototype.removeEventListener; - const listenersByTypeByInstance = new Map(); - - beforeEach(() => { - window.L = listenersByTypeByInstance; - EventTarget.prototype.addEventListener = function (type, listener, options) { - let listenersByType = new Map(); - if (listenersByTypeByInstance.has(this)) { - listenersByType = listenersByTypeByInstance.get(this); - } else { - listenersByTypeByInstance.set(this, listenersByType); - } - listenersByType.set(type, listener); - originalAddEventListener.call(this, type, listener, options); - }; - EventTarget.prototype.removeEventListener = function (type, listener, options) { - if (listenersByTypeByInstance.has(this)) { - const listenersByType = listenersByTypeByInstance.get(this); - if (listenersByType.has(type)) { - listenersByType.delete(type); - } - } - originalRemoveEventListener.call(this, type, listener, options); - }; - }); - - afterEach(() => { - // listenersByTypeByInstance.clear(); - EventTarget.prototype.addEventListener = originalAddEventListener; - EventTarget.prototype.removeEventListener = originalRemoveEventListener; - }); + function isItemActive(value, activeClassName) { + activeClassName = activeClassName ? activeClassName : 'active'; + const element = document.querySelector(`a[href="#${value}"]`); + return Array.from(element.classList).includes(activeClassName); + } + describe('Scrollspy basic test cases', () => { it('Test scrollspy smooth behavior positive case', (done) => { - resetScrollspy(); const viewportHeightPx = window.innerHeight; clickLink('options'); @@ -107,13 +77,11 @@ describe('Scrollspy Plugin', () => { const scrollTop = window.scrollY; expect(scrollTop).toBe(viewportHeightPx * 2); done(); - }, 600); + }, DELAY_IN_MS); }); it('Test scrollspy smooth behavior negative case', (done) => { - resetScrollspy(); const viewportHeightPx = window.innerHeight; - clickLink('options'); setTimeout(() => { const scrollTop = window.scrollY; @@ -123,5 +91,78 @@ describe('Scrollspy Plugin', () => { done(); }, 5); }); + + it('Test click on an item in the table of contents should make item active', (done) => { + const viewportHeightPx = window.innerHeight; + + clickLink('introduction'); + setTimeout(() => { + const scrollTop = window.scrollY; + expect(scrollTop).toBe(viewportHeightPx * 0); + expect(isItemActive('introduction')).toBeTrue(); + expect(isItemActive('initialization')).toBeFalse(); + expect(isItemActive('options')).toBeFalse(); + + clickLink('initialization'); + setTimeout(() => { + const scrollTop = window.scrollY; + expect(scrollTop).toBe(viewportHeightPx * 1); + expect(isItemActive('introduction')).toBeFalse(); + expect(isItemActive('initialization')).toBeTrue(); + expect(isItemActive('options')).toBeFalse(); + + clickLink('options'); + setTimeout(() => { + const scrollTop = window.scrollY; + expect(scrollTop).toBe(viewportHeightPx * 2); + expect(isItemActive('introduction')).toBeFalse(); + expect(isItemActive('initialization')).toBeFalse(); + expect(isItemActive('options')).toBeTrue(); + + done(); + }, DELAY_IN_MS); + }, DELAY_IN_MS); + }, DELAY_IN_MS); + }); + + it('Test click on an item in the table of contents should make item active with explicit class', (done) => { + resetScrollspy({ activeClass: 'otherActiveExample' }); + + clickLink('options'); + setTimeout(() => { + expect(isItemActive('introduction', 'active')).toBeFalse(); + expect(isItemActive('initialization', 'active')).toBeFalse(); + expect(isItemActive('options', 'active')).toBeFalse(); + + expect(isItemActive('introduction', 'otherActiveExample')).toBeFalse(); + expect(isItemActive('initialization', 'otherActiveExample')).toBeFalse(); + expect(isItemActive('options', 'otherActiveExample')).toBeTrue(); + + done(); + }, DELAY_IN_MS); + }); + + it('Test explicit getActiveElement implementation', (done) => { + const customGetActiveElement = (id) => { + const selector = 'div#testContainerId'; + const testDivElement = document.querySelector(selector); + testDivElement.textContent = id; + return selector; + }; + resetScrollspy({ getActiveElement: customGetActiveElement }); + + clickLink('options'); + setTimeout(() => { + expect(isItemActive('introduction')).toBeFalse(); + expect(isItemActive('initialization')).toBeFalse(); + expect(isItemActive('options')).toBeFalse(); + + const element = document.querySelector('div#testContainerId'); + + expect(element.textContent).toBe('options'); + expect(Array.from(element.classList)).toEqual(['active']); + done(); + }, DELAY_IN_MS); + }); }); });