diff options
Diffstat (limited to 'js/tests/unit/collapse.spec.js')
| -rw-r--r-- | js/tests/unit/collapse.spec.js | 1211 |
1 files changed, 626 insertions, 585 deletions
diff --git a/js/tests/unit/collapse.spec.js b/js/tests/unit/collapse.spec.js index 89d20a6d8..58c536752 100644 --- a/js/tests/unit/collapse.spec.js +++ b/js/tests/unit/collapse.spec.js @@ -1,6 +1,6 @@ -import Collapse from '../../src/collapse' -import EventHandler from '../../src/dom/event-handler' -import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture' +import Collapse from '../../src/collapse.js' +import EventHandler from '../../src/dom/event-handler.js' +import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js' describe('Collapse', () => { let fixtureEl @@ -112,11 +112,11 @@ describe('Collapse', () => { const collapseEl = fixtureEl.querySelector('div') const collapse = new Collapse(collapseEl) - spyOn(collapse, 'show') + const spy = spyOn(collapse, 'show') collapse.toggle() - expect(collapse.show).toHaveBeenCalled() + expect(spy).toHaveBeenCalled() }) it('should call hide method if show class is present', () => { @@ -127,44 +127,46 @@ describe('Collapse', () => { toggle: false }) - spyOn(collapse, 'hide') + const spy = spyOn(collapse, 'hide') collapse.toggle() - expect(collapse.hide).toHaveBeenCalled() + expect(spy).toHaveBeenCalled() }) - it('should find collapse children if they have collapse class too not only data-bs-parent', done => { - fixtureEl.innerHTML = [ - '<div class="my-collapse">', - ' <div class="item">', - ' <a data-bs-toggle="collapse" href="#">Toggle item 1</a>', - ' <div id="collapse1" class="collapse show">Lorem ipsum 1</div>', - ' </div>', - ' <div class="item">', - ' <a id="triggerCollapse2" data-bs-toggle="collapse" href="#">Toggle item 2</a>', - ' <div id="collapse2" class="collapse">Lorem ipsum 2</div>', - ' </div>', - '</div>' - ].join('') - - const parent = fixtureEl.querySelector('.my-collapse') - const collapseEl1 = fixtureEl.querySelector('#collapse1') - const collapseEl2 = fixtureEl.querySelector('#collapse2') - - const collapseList = [].concat(...fixtureEl.querySelectorAll('.collapse')) - .map(el => new Collapse(el, { - parent, - toggle: false - })) + it('should find collapse children if they have collapse class too not only data-bs-parent', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div class="my-collapse">', + ' <div class="item">', + ' <a data-bs-toggle="collapse" href="#">Toggle item 1</a>', + ' <div id="collapse1" class="collapse show">Lorem ipsum 1</div>', + ' </div>', + ' <div class="item">', + ' <a id="triggerCollapse2" data-bs-toggle="collapse" href="#">Toggle item 2</a>', + ' <div id="collapse2" class="collapse">Lorem ipsum 2</div>', + ' </div>', + '</div>' + ].join('') + + const parent = fixtureEl.querySelector('.my-collapse') + const collapseEl1 = fixtureEl.querySelector('#collapse1') + const collapseEl2 = fixtureEl.querySelector('#collapse2') + + const collapseList = [].concat(...fixtureEl.querySelectorAll('.collapse')) + .map(el => new Collapse(el, { + parent, + toggle: false + })) + + collapseEl2.addEventListener('shown.bs.collapse', () => { + expect(collapseEl2).toHaveClass('show') + expect(collapseEl1).not.toHaveClass('show') + resolve() + }) - collapseEl2.addEventListener('shown.bs.collapse', () => { - expect(collapseEl2.classList.contains('show')).toEqual(true) - expect(collapseEl1.classList.contains('show')).toEqual(false) - done() + collapseList[1].toggle() }) - - collapseList[1].toggle() }) }) @@ -172,7 +174,7 @@ describe('Collapse', () => { it('should do nothing if is transitioning', () => { fixtureEl.innerHTML = '<div></div>' - spyOn(EventHandler, 'trigger') + const spy = spyOn(EventHandler, 'trigger') const collapseEl = fixtureEl.querySelector('div') const collapse = new Collapse(collapseEl, { @@ -182,13 +184,13 @@ describe('Collapse', () => { collapse._isTransitioning = true collapse.show() - expect(EventHandler.trigger).not.toHaveBeenCalled() + expect(spy).not.toHaveBeenCalled() }) it('should do nothing if already shown', () => { fixtureEl.innerHTML = '<div class="show"></div>' - spyOn(EventHandler, 'trigger') + const spy = spyOn(EventHandler, 'trigger') const collapseEl = fixtureEl.querySelector('div') const collapse = new Collapse(collapseEl, { @@ -197,205 +199,218 @@ describe('Collapse', () => { collapse.show() - expect(EventHandler.trigger).not.toHaveBeenCalled() + expect(spy).not.toHaveBeenCalled() }) - it('should show a collapsed element', done => { - fixtureEl.innerHTML = '<div class="collapse" style="height: 0px;"></div>' + it('should show a collapsed element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '<div class="collapse" style="height: 0px;"></div>' - const collapseEl = fixtureEl.querySelector('div') - const collapse = new Collapse(collapseEl, { - toggle: false - }) + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) - collapseEl.addEventListener('show.bs.collapse', () => { - expect(collapseEl.style.height).toEqual('0px') - }) - collapseEl.addEventListener('shown.bs.collapse', () => { - expect(collapseEl.classList.contains('show')).toEqual(true) - expect(collapseEl.style.height).toEqual('') - done() - }) + collapseEl.addEventListener('show.bs.collapse', () => { + expect(collapseEl.style.height).toEqual('0px') + }) + collapseEl.addEventListener('shown.bs.collapse', () => { + expect(collapseEl).toHaveClass('show') + expect(collapseEl.style.height).toEqual('') + resolve() + }) - collapse.show() + collapse.show() + }) }) - it('should show a collapsed element on width', done => { - fixtureEl.innerHTML = '<div class="collapse collapse-horizontal" style="width: 0px;"></div>' + it('should show a collapsed element on width', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '<div class="collapse collapse-horizontal" style="width: 0px;"></div>' - const collapseEl = fixtureEl.querySelector('div') - const collapse = new Collapse(collapseEl, { - toggle: false - }) + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) - collapseEl.addEventListener('show.bs.collapse', () => { - expect(collapseEl.style.width).toEqual('0px') - }) - collapseEl.addEventListener('shown.bs.collapse', () => { - expect(collapseEl.classList.contains('show')).toEqual(true) - expect(collapseEl.style.width).toEqual('') - done() - }) + collapseEl.addEventListener('show.bs.collapse', () => { + expect(collapseEl.style.width).toEqual('0px') + }) + collapseEl.addEventListener('shown.bs.collapse', () => { + expect(collapseEl).toHaveClass('show') + expect(collapseEl.style.width).toEqual('') + resolve() + }) - collapse.show() + collapse.show() + }) }) - it('should collapse only the first collapse', done => { - fixtureEl.innerHTML = [ - '<div class="card" id="accordion1">', - ' <div id="collapse1" class="collapse"></div>', - '</div>', - '<div class="card" id="accordion2">', - ' <div id="collapse2" class="collapse show"></div>', - '</div>' - ].join('') + it('should collapse only the first collapse', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div class="card" id="accordion1">', + ' <div id="collapse1" class="collapse"></div>', + '</div>', + '<div class="card" id="accordion2">', + ' <div id="collapse2" class="collapse show"></div>', + '</div>' + ].join('') + + const el1 = fixtureEl.querySelector('#collapse1') + const el2 = fixtureEl.querySelector('#collapse2') + const collapse = new Collapse(el1, { + toggle: false + }) - const el1 = fixtureEl.querySelector('#collapse1') - const el2 = fixtureEl.querySelector('#collapse2') - const collapse = new Collapse(el1, { - toggle: false - }) + el1.addEventListener('shown.bs.collapse', () => { + expect(el1).toHaveClass('show') + expect(el2).toHaveClass('show') + resolve() + }) - el1.addEventListener('shown.bs.collapse', () => { - expect(el1.classList.contains('show')).toEqual(true) - expect(el2.classList.contains('show')).toEqual(true) - done() + collapse.show() }) - - collapse.show() }) - it('should be able to handle toggling of other children siblings', done => { - fixtureEl.innerHTML = [ - '<div id="parentGroup" class="accordion">', - ' <div id="parentHeader" class="accordion-header">', - ' <button data-bs-target="#parentContent" data-bs-toggle="collapse" role="button" class="accordion-toggle">Parent</button>', - ' </div>', - ' <div id="parentContent" class="accordion-collapse collapse" aria-labelledby="parentHeader" data-bs-parent="#parentGroup">', - ' <div class="accordion-body">', - ' <div id="childGroup" class="accordion">', - ' <div class="accordion-item">', - ' <div id="childHeader1" class="accordion-header">', - ' <button data-bs-target="#childContent1" data-bs-toggle="collapse" role="button" class="accordion-toggle">Child 1</button>', - ' </div>', - ' <div id="childContent1" class="accordion-collapse collapse" aria-labelledby="childHeader1" data-bs-parent="#childGroup">', - ' <div>content</div>', - ' </div>', - ' </div>', - ' <div class="accordion-item">', - ' <div id="childHeader2" class="accordion-header">', - ' <button data-bs-target="#childContent2" data-bs-toggle="collapse" role="button" class="accordion-toggle">Child 2</button>', - ' </div>', - ' <div id="childContent2" class="accordion-collapse collapse" aria-labelledby="childHeader2" data-bs-parent="#childGroup">', - ' <div>content</div>', - ' </div>', - ' </div>', - ' </div>', - ' </div>', - ' </div>', - '</div>' - ].join('') - - const el = selector => fixtureEl.querySelector(selector) - - const parentBtn = el('[data-bs-target="#parentContent"]') - const childBtn1 = el('[data-bs-target="#childContent1"]') - const childBtn2 = el('[data-bs-target="#childContent2"]') - - const parentCollapseEl = el('#parentContent') - const childCollapseEl1 = el('#childContent1') - const childCollapseEl2 = el('#childContent2') + it('should be able to handle toggling of other children siblings', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div id="parentGroup" class="accordion">', + ' <div class="accordion-header">', + ' <button data-bs-target="#parentContent" data-bs-toggle="collapse" class="accordion-toggle">Parent</button>', + ' </div>', + ' <div id="parentContent" class="accordion-collapse collapse" data-bs-parent="#parentGroup">', + ' <div class="accordion-body">', + ' <div id="childGroup" class="accordion">', + ' <div class="accordion-item">', + ' <div class="accordion-header">', + ' <button data-bs-target="#childContent1" data-bs-toggle="collapse" class="accordion-toggle">Child 1</button>', + ' </div>', + ' <div id="childContent1" class="accordion-collapse collapse" data-bs-parent="#childGroup">', + ' <div>content</div>', + ' </div>', + ' </div>', + ' <div class="accordion-item">', + ' <div class="accordion-header">', + ' <button data-bs-target="#childContent2" data-bs-toggle="collapse" class="accordion-toggle">Child 2</button>', + ' </div>', + ' <div id="childContent2" class="accordion-collapse collapse" data-bs-parent="#childGroup">', + ' <div>content</div>', + ' </div>', + ' </div>', + ' </div>', + ' </div>', + ' </div>', + '</div>' + ].join('') + + const el = selector => fixtureEl.querySelector(selector) + + const parentBtn = el('[data-bs-target="#parentContent"]') + const childBtn1 = el('[data-bs-target="#childContent1"]') + const childBtn2 = el('[data-bs-target="#childContent2"]') + + const parentCollapseEl = el('#parentContent') + const childCollapseEl1 = el('#childContent1') + const childCollapseEl2 = el('#childContent2') + + parentCollapseEl.addEventListener('shown.bs.collapse', () => { + expect(parentCollapseEl).toHaveClass('show') + childBtn1.click() + }) + childCollapseEl1.addEventListener('shown.bs.collapse', () => { + expect(childCollapseEl1).toHaveClass('show') + childBtn2.click() + }) + childCollapseEl2.addEventListener('shown.bs.collapse', () => { + expect(childCollapseEl2).toHaveClass('show') + expect(childCollapseEl1).not.toHaveClass('show') + resolve() + }) - parentCollapseEl.addEventListener('shown.bs.collapse', () => { - expect(parentCollapseEl.classList.contains('show')).toEqual(true) - childBtn1.click() + parentBtn.click() }) - childCollapseEl1.addEventListener('shown.bs.collapse', () => { - expect(childCollapseEl1.classList.contains('show')).toEqual(true) - childBtn2.click() - }) - childCollapseEl2.addEventListener('shown.bs.collapse', () => { - expect(childCollapseEl2.classList.contains('show')).toEqual(true) - expect(childCollapseEl1.classList.contains('show')).toEqual(false) - done() - }) - - parentBtn.click() }) - it('should not change tab tabpanels descendants on accordion', done => { - fixtureEl.innerHTML = [ - '<div class="accordion" id="accordionExample">', - ' <div class="accordion-item">', - ' <h2 class="accordion-header" id="headingOne">', - ' <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">', - ' Accordion Item #1', - ' </button>', - ' </h2>', - ' <div id="collapseOne" class="accordion-collapse collapse show" aria-labelledby="headingOne" data-bs-parent="#accordionExample">', - ' <div class="accordion-body">', - ' <nav>', - ' <div class="nav nav-tabs" id="nav-tab" role="tablist">', - ' <button class="nav-link active" id="nav-home-tab" data-bs-toggle="tab" data-bs-target="#nav-home" type="button" role="tab" aria-controls="nav-home" aria-selected="true">Home</button>', - ' <button class="nav-link" id="nav-profile-tab" data-bs-toggle="tab" data-bs-target="#nav-profile" type="button" role="tab" aria-controls="nav-profile" aria-selected="false">Profile</button>', - ' </div>', - ' </nav>', - ' <div class="tab-content" id="nav-tabContent">', - ' <div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab">Home</div>', - ' <div class="tab-pane fade" id="nav-profile" role="tabpanel" aria-labelledby="nav-profile-tab">Profile</div>', - ' </div>', - ' </div>', - ' </div>', - ' </div>', - ' </div>' - ].join('') - const el = fixtureEl.querySelector('#collapseOne') - const activeTabPane = fixtureEl.querySelector('#nav-home') - const collapse = new Collapse(el) - let times = 1 + it('should not change tab tabpanels descendants on accordion', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div class="accordion" id="accordionExample">', + ' <div class="accordion-item">', + ' <h2 class="accordion-header">', + ' <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">', + ' Accordion Item #1', + ' </button>', + ' </h2>', + ' <div id="collapseOne" class="accordion-collapse collapse show" data-bs-parent="#accordionExample">', + ' <div class="accordion-body">', + ' <nav>', + ' <div class="nav nav-tabs" id="nav-tab" role="tablist">', + ' <button class="nav-link active" id="nav-home-tab" data-bs-toggle="tab" data-bs-target="#nav-home" type="button" role="tab" aria-controls="nav-home" aria-selected="true">Home</button>', + ' <button class="nav-link" id="nav-profile-tab" data-bs-toggle="tab" data-bs-target="#nav-profile" type="button" role="tab" aria-controls="nav-profile" aria-selected="false">Profile</button>', + ' </div>', + ' </nav>', + ' <div class="tab-content" id="nav-tabContent">', + ' <div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab">Home</div>', + ' <div class="tab-pane fade" id="nav-profile" role="tabpanel" aria-labelledby="nav-profile-tab">Profile</div>', + ' </div>', + ' </div>', + ' </div>', + ' </div>', + '</div>' + ].join('') + + const el = fixtureEl.querySelector('#collapseOne') + const activeTabPane = fixtureEl.querySelector('#nav-home') + const collapse = new Collapse(el) + let times = 1 + + el.addEventListener('hidden.bs.collapse', () => { + collapse.show() + }) - el.addEventListener('hidden.bs.collapse', () => { - collapse.show() - }) + el.addEventListener('shown.bs.collapse', () => { + expect(activeTabPane).toHaveClass('show') + times++ + if (times === 2) { + resolve() + } - el.addEventListener('shown.bs.collapse', () => { - expect(activeTabPane.classList.contains('show')).toEqual(true) - times++ - if (times === 2) { - done() - } + collapse.hide() + }) - collapse.hide() + collapse.show() }) - - collapse.show() }) - it('should not fire shown when show is prevented', done => { - fixtureEl.innerHTML = '<div class="collapse"></div>' + it('should not fire shown when show is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '<div class="collapse"></div>' - const collapseEl = fixtureEl.querySelector('div') - const collapse = new Collapse(collapseEl, { - toggle: false - }) + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) - const expectEnd = () => { - setTimeout(() => { - expect().nothing() - done() - }, 10) - } + const expectEnd = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + } - collapseEl.addEventListener('show.bs.collapse', event => { - event.preventDefault() - expectEnd() - }) + collapseEl.addEventListener('show.bs.collapse', event => { + event.preventDefault() + expectEnd() + }) - collapseEl.addEventListener('shown.bs.collapse', () => { - throw new Error('should not fire shown event') - }) + collapseEl.addEventListener('shown.bs.collapse', () => { + reject(new Error('should not fire shown event')) + }) - collapse.show() + collapse.show() + }) }) }) @@ -403,7 +418,7 @@ describe('Collapse', () => { it('should do nothing if is transitioning', () => { fixtureEl.innerHTML = '<div></div>' - spyOn(EventHandler, 'trigger') + const spy = spyOn(EventHandler, 'trigger') const collapseEl = fixtureEl.querySelector('div') const collapse = new Collapse(collapseEl, { @@ -413,13 +428,13 @@ describe('Collapse', () => { collapse._isTransitioning = true collapse.hide() - expect(EventHandler.trigger).not.toHaveBeenCalled() + expect(spy).not.toHaveBeenCalled() }) it('should do nothing if already shown', () => { fixtureEl.innerHTML = '<div></div>' - spyOn(EventHandler, 'trigger') + const spy = spyOn(EventHandler, 'trigger') const collapseEl = fixtureEl.querySelector('div') const collapse = new Collapse(collapseEl, { @@ -428,51 +443,55 @@ describe('Collapse', () => { collapse.hide() - expect(EventHandler.trigger).not.toHaveBeenCalled() + expect(spy).not.toHaveBeenCalled() }) - it('should hide a collapsed element', done => { - fixtureEl.innerHTML = '<div class="collapse show"></div>' + it('should hide a collapsed element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '<div class="collapse show"></div>' - const collapseEl = fixtureEl.querySelector('div') - const collapse = new Collapse(collapseEl, { - toggle: false - }) + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) - collapseEl.addEventListener('hidden.bs.collapse', () => { - expect(collapseEl.classList.contains('show')).toEqual(false) - expect(collapseEl.style.height).toEqual('') - done() - }) + collapseEl.addEventListener('hidden.bs.collapse', () => { + expect(collapseEl).not.toHaveClass('show') + expect(collapseEl.style.height).toEqual('') + resolve() + }) - collapse.hide() + collapse.hide() + }) }) - it('should not fire hidden when hide is prevented', done => { - fixtureEl.innerHTML = '<div class="collapse show"></div>' + it('should not fire hidden when hide is prevented', () => { + return new Promise((resolve, reject) => { + fixtureEl.innerHTML = '<div class="collapse show"></div>' - const collapseEl = fixtureEl.querySelector('div') - const collapse = new Collapse(collapseEl, { - toggle: false - }) + const collapseEl = fixtureEl.querySelector('div') + const collapse = new Collapse(collapseEl, { + toggle: false + }) - const expectEnd = () => { - setTimeout(() => { - expect().nothing() - done() - }, 10) - } + const expectEnd = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 10) + } - collapseEl.addEventListener('hide.bs.collapse', event => { - event.preventDefault() - expectEnd() - }) + collapseEl.addEventListener('hide.bs.collapse', event => { + event.preventDefault() + expectEnd() + }) - collapseEl.addEventListener('hidden.bs.collapse', () => { - throw new Error('should not fire hidden event') - }) + collapseEl.addEventListener('hidden.bs.collapse', () => { + reject(new Error('should not fire hidden event')) + }) - collapse.hide() + collapse.hide() + }) }) }) @@ -489,416 +508,438 @@ describe('Collapse', () => { collapse.dispose() - expect(Collapse.getInstance(collapseEl)).toEqual(null) + expect(Collapse.getInstance(collapseEl)).toBeNull() }) }) describe('data-api', () => { - it('should prevent url change if click on nested elements', done => { - fixtureEl.innerHTML = [ - '<a role="button" data-bs-toggle="collapse" class="collapsed" href="#collapse">', - ' <span id="nested"></span>', - '</a>', - '<div id="collapse" class="collapse"></div>' - ].join('') - - const triggerEl = fixtureEl.querySelector('a') - const nestedTriggerEl = fixtureEl.querySelector('#nested') - - spyOn(Event.prototype, 'preventDefault').and.callThrough() + it('should prevent url change if click on nested elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<a role="button" data-bs-toggle="collapse" class="collapsed" href="#collapse">', + ' <span id="nested"></span>', + '</a>', + '<div id="collapse" class="collapse"></div>' + ].join('') + + const triggerEl = fixtureEl.querySelector('a') + const nestedTriggerEl = fixtureEl.querySelector('#nested') + + const spy = spyOn(Event.prototype, 'preventDefault').and.callThrough() + + triggerEl.addEventListener('click', event => { + expect(event.target.isEqualNode(nestedTriggerEl)).toBeTrue() + expect(event.delegateTarget.isEqualNode(triggerEl)).toBeTrue() + expect(spy).toHaveBeenCalled() + resolve() + }) - triggerEl.addEventListener('click', event => { - expect(event.target.isEqualNode(nestedTriggerEl)).toEqual(true) - expect(event.delegateTarget.isEqualNode(triggerEl)).toEqual(true) - expect(Event.prototype.preventDefault).toHaveBeenCalled() - done() + nestedTriggerEl.click() }) - - nestedTriggerEl.click() }) - it('should show multiple collapsed elements', done => { - fixtureEl.innerHTML = [ - '<a role="button" data-bs-toggle="collapse" class="collapsed" href=".multi"></a>', - '<div id="collapse1" class="collapse multi"></div>', - '<div id="collapse2" class="collapse multi"></div>' - ].join('') - - const trigger = fixtureEl.querySelector('a') - const collapse1 = fixtureEl.querySelector('#collapse1') - const collapse2 = fixtureEl.querySelector('#collapse2') + it('should show multiple collapsed elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<a role="button" data-bs-toggle="collapse" class="collapsed" href=".multi"></a>', + '<div id="collapse1" class="collapse multi"></div>', + '<div id="collapse2" class="collapse multi"></div>' + ].join('') + + const trigger = fixtureEl.querySelector('a') + const collapse1 = fixtureEl.querySelector('#collapse1') + const collapse2 = fixtureEl.querySelector('#collapse2') + + collapse2.addEventListener('shown.bs.collapse', () => { + expect(trigger.getAttribute('aria-expanded')).toEqual('true') + expect(trigger).not.toHaveClass('collapsed') + expect(collapse1).toHaveClass('show') + expect(collapse1).toHaveClass('show') + resolve() + }) - collapse2.addEventListener('shown.bs.collapse', () => { - expect(trigger.getAttribute('aria-expanded')).toEqual('true') - expect(trigger.classList.contains('collapsed')).toEqual(false) - expect(collapse1.classList.contains('show')).toEqual(true) - expect(collapse1.classList.contains('show')).toEqual(true) - done() + trigger.click() }) - - trigger.click() }) - it('should hide multiple collapsed elements', done => { - fixtureEl.innerHTML = [ - '<a role="button" data-bs-toggle="collapse" href=".multi"></a>', - '<div id="collapse1" class="collapse multi show"></div>', - '<div id="collapse2" class="collapse multi show"></div>' - ].join('') - - const trigger = fixtureEl.querySelector('a') - const collapse1 = fixtureEl.querySelector('#collapse1') - const collapse2 = fixtureEl.querySelector('#collapse2') + it('should hide multiple collapsed elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<a role="button" data-bs-toggle="collapse" href=".multi"></a>', + '<div id="collapse1" class="collapse multi show"></div>', + '<div id="collapse2" class="collapse multi show"></div>' + ].join('') + + const trigger = fixtureEl.querySelector('a') + const collapse1 = fixtureEl.querySelector('#collapse1') + const collapse2 = fixtureEl.querySelector('#collapse2') + + collapse2.addEventListener('hidden.bs.collapse', () => { + expect(trigger.getAttribute('aria-expanded')).toEqual('false') + expect(trigger).toHaveClass('collapsed') + expect(collapse1).not.toHaveClass('show') + expect(collapse1).not.toHaveClass('show') + resolve() + }) - collapse2.addEventListener('hidden.bs.collapse', () => { - expect(trigger.getAttribute('aria-expanded')).toEqual('false') - expect(trigger.classList.contains('collapsed')).toEqual(true) - expect(collapse1.classList.contains('show')).toEqual(false) - expect(collapse1.classList.contains('show')).toEqual(false) - done() + trigger.click() }) - - trigger.click() }) - it('should remove "collapsed" class from target when collapse is shown', done => { - fixtureEl.innerHTML = [ - '<a id="link1" role="button" data-bs-toggle="collapse" class="collapsed" href="#" data-bs-target="#test1"></a>', - '<a id="link2" role="button" data-bs-toggle="collapse" class="collapsed" href="#" data-bs-target="#test1"></a>', - '<div id="test1"></div>' - ].join('') - - const link1 = fixtureEl.querySelector('#link1') - const link2 = fixtureEl.querySelector('#link2') - const collapseTest1 = fixtureEl.querySelector('#test1') + it('should remove "collapsed" class from target when collapse is shown', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<a id="link1" role="button" data-bs-toggle="collapse" class="collapsed" href="#" data-bs-target="#test1"></a>', + '<a id="link2" role="button" data-bs-toggle="collapse" class="collapsed" href="#" data-bs-target="#test1"></a>', + '<div id="test1"></div>' + ].join('') + + const link1 = fixtureEl.querySelector('#link1') + const link2 = fixtureEl.querySelector('#link2') + const collapseTest1 = fixtureEl.querySelector('#test1') + + collapseTest1.addEventListener('shown.bs.collapse', () => { + expect(link1.getAttribute('aria-expanded')).toEqual('true') + expect(link2.getAttribute('aria-expanded')).toEqual('true') + expect(link1).not.toHaveClass('collapsed') + expect(link2).not.toHaveClass('collapsed') + resolve() + }) - collapseTest1.addEventListener('shown.bs.collapse', () => { - expect(link1.getAttribute('aria-expanded')).toEqual('true') - expect(link2.getAttribute('aria-expanded')).toEqual('true') - expect(link1.classList.contains('collapsed')).toEqual(false) - expect(link2.classList.contains('collapsed')).toEqual(false) - done() + link1.click() }) - - link1.click() }) - it('should add "collapsed" class to target when collapse is hidden', done => { - fixtureEl.innerHTML = [ - '<a id="link1" role="button" data-bs-toggle="collapse" href="#" data-bs-target="#test1"></a>', - '<a id="link2" role="button" data-bs-toggle="collapse" href="#" data-bs-target="#test1"></a>', - '<div id="test1" class="show"></div>' - ].join('') - - const link1 = fixtureEl.querySelector('#link1') - const link2 = fixtureEl.querySelector('#link2') - const collapseTest1 = fixtureEl.querySelector('#test1') + it('should add "collapsed" class to target when collapse is hidden', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<a id="link1" role="button" data-bs-toggle="collapse" href="#" data-bs-target="#test1"></a>', + '<a id="link2" role="button" data-bs-toggle="collapse" href="#" data-bs-target="#test1"></a>', + '<div id="test1" class="show"></div>' + ].join('') + + const link1 = fixtureEl.querySelector('#link1') + const link2 = fixtureEl.querySelector('#link2') + const collapseTest1 = fixtureEl.querySelector('#test1') + + collapseTest1.addEventListener('hidden.bs.collapse', () => { + expect(link1.getAttribute('aria-expanded')).toEqual('false') + expect(link2.getAttribute('aria-expanded')).toEqual('false') + expect(link1).toHaveClass('collapsed') + expect(link2).toHaveClass('collapsed') + resolve() + }) - collapseTest1.addEventListener('hidden.bs.collapse', () => { - expect(link1.getAttribute('aria-expanded')).toEqual('false') - expect(link2.getAttribute('aria-expanded')).toEqual('false') - expect(link1.classList.contains('collapsed')).toEqual(true) - expect(link2.classList.contains('collapsed')).toEqual(true) - done() + link1.click() }) - - link1.click() }) - it('should allow accordion to use children other than card', done => { - fixtureEl.innerHTML = [ - '<div id="accordion">', - ' <div class="item">', - ' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>', - ' <div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-bs-parent="#accordion"></div>', - ' </div>', - ' <div class="item">', - ' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>', - ' <div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-bs-parent="#accordion"></div>', - ' </div>', - '</div>' - ].join('') - - const trigger = fixtureEl.querySelector('#linkTrigger') - const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') - const collapseOne = fixtureEl.querySelector('#collapseOne') - const collapseTwo = fixtureEl.querySelector('#collapseTwo') - - collapseOne.addEventListener('shown.bs.collapse', () => { - expect(collapseOne.classList.contains('show')).toEqual(true) - expect(collapseTwo.classList.contains('show')).toEqual(false) + it('should allow accordion to use children other than card', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div id="accordion">', + ' <div class="item">', + ' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>', + ' <div id="collapseOne" class="collapse" role="tabpanel" data-bs-parent="#accordion"></div>', + ' </div>', + ' <div class="item">', + ' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>', + ' <div id="collapseTwo" class="collapse show" role="tabpanel" data-bs-parent="#accordion"></div>', + ' </div>', + '</div>' + ].join('') + + const trigger = fixtureEl.querySelector('#linkTrigger') + const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') + const collapseOne = fixtureEl.querySelector('#collapseOne') + const collapseTwo = fixtureEl.querySelector('#collapseTwo') + + collapseOne.addEventListener('shown.bs.collapse', () => { + expect(collapseOne).toHaveClass('show') + expect(collapseTwo).not.toHaveClass('show') + + collapseTwo.addEventListener('shown.bs.collapse', () => { + expect(collapseOne).not.toHaveClass('show') + expect(collapseTwo).toHaveClass('show') + resolve() + }) - collapseTwo.addEventListener('shown.bs.collapse', () => { - expect(collapseOne.classList.contains('show')).toEqual(false) - expect(collapseTwo.classList.contains('show')).toEqual(true) - done() + triggerTwo.click() }) - triggerTwo.click() + trigger.click() }) - - trigger.click() }) - it('should not prevent event for input', done => { - fixtureEl.innerHTML = [ - '<input type="checkbox" data-bs-toggle="collapse" data-bs-target="#collapsediv1">', - '<div id="collapsediv1"></div>' - ].join('') + it('should not prevent event for input', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<input type="checkbox" data-bs-toggle="collapse" data-bs-target="#collapsediv1">', + '<div id="collapsediv1"></div>' + ].join('') - const target = fixtureEl.querySelector('input') - const collapseEl = fixtureEl.querySelector('#collapsediv1') + const target = fixtureEl.querySelector('input') + const collapseEl = fixtureEl.querySelector('#collapsediv1') - collapseEl.addEventListener('shown.bs.collapse', () => { - expect(collapseEl.classList.contains('show')).toEqual(true) - expect(target.checked).toEqual(true) - done() - }) + collapseEl.addEventListener('shown.bs.collapse', () => { + expect(collapseEl).toHaveClass('show') + expect(target.checked).toBeTrue() + resolve() + }) - target.click() + target.click() + }) }) - it('should allow accordion to contain nested elements', done => { - fixtureEl.innerHTML = [ - '<div id="accordion">', - ' <div class="row">', - ' <div class="col-lg-6">', - ' <div class="item">', - ' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>', - ' <div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-bs-parent="#accordion"></div>', - ' </div>', - ' </div>', - ' <div class="col-lg-6">', - ' <div class="item">', - ' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>', - ' <div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-bs-parent="#accordion"></div>', - ' </div>', - ' </div>', - ' </div>', - '</div>' - ].join('') - - const triggerEl = fixtureEl.querySelector('#linkTrigger') - const triggerTwoEl = fixtureEl.querySelector('#linkTriggerTwo') - const collapseOneEl = fixtureEl.querySelector('#collapseOne') - const collapseTwoEl = fixtureEl.querySelector('#collapseTwo') - - collapseOneEl.addEventListener('shown.bs.collapse', () => { - expect(collapseOneEl.classList.contains('show')).toEqual(true) - expect(triggerEl.classList.contains('collapsed')).toEqual(false) - expect(triggerEl.getAttribute('aria-expanded')).toEqual('true') - - expect(collapseTwoEl.classList.contains('show')).toEqual(false) - expect(triggerTwoEl.classList.contains('collapsed')).toEqual(true) - expect(triggerTwoEl.getAttribute('aria-expanded')).toEqual('false') - - collapseTwoEl.addEventListener('shown.bs.collapse', () => { - expect(collapseOneEl.classList.contains('show')).toEqual(false) - expect(triggerEl.classList.contains('collapsed')).toEqual(true) - expect(triggerEl.getAttribute('aria-expanded')).toEqual('false') + it('should allow accordion to contain nested elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div id="accordion">', + ' <div class="row">', + ' <div class="col-lg-6">', + ' <div class="item">', + ' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>', + ' <div id="collapseOne" class="collapse" role="tabpanel" data-bs-parent="#accordion"></div>', + ' </div>', + ' </div>', + ' <div class="col-lg-6">', + ' <div class="item">', + ' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>', + ' <div id="collapseTwo" class="collapse show" role="tabpanel" data-bs-parent="#accordion"></div>', + ' </div>', + ' </div>', + ' </div>', + '</div>' + ].join('') + + const triggerEl = fixtureEl.querySelector('#linkTrigger') + const triggerTwoEl = fixtureEl.querySelector('#linkTriggerTwo') + const collapseOneEl = fixtureEl.querySelector('#collapseOne') + const collapseTwoEl = fixtureEl.querySelector('#collapseTwo') + + collapseOneEl.addEventListener('shown.bs.collapse', () => { + expect(collapseOneEl).toHaveClass('show') + expect(triggerEl).not.toHaveClass('collapsed') + expect(triggerEl.getAttribute('aria-expanded')).toEqual('true') + + expect(collapseTwoEl).not.toHaveClass('show') + expect(triggerTwoEl).toHaveClass('collapsed') + expect(triggerTwoEl.getAttribute('aria-expanded')).toEqual('false') + + collapseTwoEl.addEventListener('shown.bs.collapse', () => { + expect(collapseOneEl).not.toHaveClass('show') + expect(triggerEl).toHaveClass('collapsed') + expect(triggerEl.getAttribute('aria-expanded')).toEqual('false') + + expect(collapseTwoEl).toHaveClass('show') + expect(triggerTwoEl).not.toHaveClass('collapsed') + expect(triggerTwoEl.getAttribute('aria-expanded')).toEqual('true') + resolve() + }) - expect(collapseTwoEl.classList.contains('show')).toEqual(true) - expect(triggerTwoEl.classList.contains('collapsed')).toEqual(false) - expect(triggerTwoEl.getAttribute('aria-expanded')).toEqual('true') - done() + triggerTwoEl.click() }) - triggerTwoEl.click() + triggerEl.click() }) - - triggerEl.click() }) - it('should allow accordion to target multiple elements', done => { - fixtureEl.innerHTML = [ - '<div id="accordion">', - ' <a id="linkTriggerOne" data-bs-toggle="collapse" data-bs-target=".collapseOne" href="#" aria-expanded="false" aria-controls="collapseOne"></a>', - ' <a id="linkTriggerTwo" data-bs-toggle="collapse" data-bs-target=".collapseTwo" href="#" aria-expanded="false" aria-controls="collapseTwo"></a>', - ' <div id="collapseOneOne" class="collapse collapseOne" role="tabpanel" data-bs-parent="#accordion"></div>', - ' <div id="collapseOneTwo" class="collapse collapseOne" role="tabpanel" data-bs-parent="#accordion"></div>', - ' <div id="collapseTwoOne" class="collapse collapseTwo" role="tabpanel" data-bs-parent="#accordion"></div>', - ' <div id="collapseTwoTwo" class="collapse collapseTwo" role="tabpanel" data-bs-parent="#accordion"></div>', - '</div>' - ].join('') - - const trigger = fixtureEl.querySelector('#linkTriggerOne') - const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') - const collapseOneOne = fixtureEl.querySelector('#collapseOneOne') - const collapseOneTwo = fixtureEl.querySelector('#collapseOneTwo') - const collapseTwoOne = fixtureEl.querySelector('#collapseTwoOne') - const collapseTwoTwo = fixtureEl.querySelector('#collapseTwoTwo') - const collapsedElements = { - one: false, - two: false - } - - function firstTest() { - expect(collapseOneOne.classList.contains('show')).toEqual(true) - expect(collapseOneTwo.classList.contains('show')).toEqual(true) - - expect(collapseTwoOne.classList.contains('show')).toEqual(false) - expect(collapseTwoTwo.classList.contains('show')).toEqual(false) - - triggerTwo.click() - } - - function secondTest() { - expect(collapseOneOne.classList.contains('show')).toEqual(false) - expect(collapseOneTwo.classList.contains('show')).toEqual(false) - - expect(collapseTwoOne.classList.contains('show')).toEqual(true) - expect(collapseTwoTwo.classList.contains('show')).toEqual(true) - done() - } - - collapseOneOne.addEventListener('shown.bs.collapse', () => { - if (collapsedElements.one) { - firstTest() - } else { - collapsedElements.one = true + it('should allow accordion to target multiple elements', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div id="accordion">', + ' <a id="linkTriggerOne" data-bs-toggle="collapse" data-bs-target=".collapseOne" href="#" aria-expanded="false" aria-controls="collapseOne"></a>', + ' <a id="linkTriggerTwo" data-bs-toggle="collapse" data-bs-target=".collapseTwo" href="#" aria-expanded="false" aria-controls="collapseTwo"></a>', + ' <div id="collapseOneOne" class="collapse collapseOne" role="tabpanel" data-bs-parent="#accordion"></div>', + ' <div id="collapseOneTwo" class="collapse collapseOne" role="tabpanel" data-bs-parent="#accordion"></div>', + ' <div id="collapseTwoOne" class="collapse collapseTwo" role="tabpanel" data-bs-parent="#accordion"></div>', + ' <div id="collapseTwoTwo" class="collapse collapseTwo" role="tabpanel" data-bs-parent="#accordion"></div>', + '</div>' + ].join('') + + const trigger = fixtureEl.querySelector('#linkTriggerOne') + const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') + const collapseOneOne = fixtureEl.querySelector('#collapseOneOne') + const collapseOneTwo = fixtureEl.querySelector('#collapseOneTwo') + const collapseTwoOne = fixtureEl.querySelector('#collapseTwoOne') + const collapseTwoTwo = fixtureEl.querySelector('#collapseTwoTwo') + const collapsedElements = { + one: false, + two: false } - }) - collapseOneTwo.addEventListener('shown.bs.collapse', () => { - if (collapsedElements.one) { - firstTest() - } else { - collapsedElements.one = true - } - }) + function firstTest() { + expect(collapseOneOne).toHaveClass('show') + expect(collapseOneTwo).toHaveClass('show') - collapseTwoOne.addEventListener('shown.bs.collapse', () => { - if (collapsedElements.two) { - secondTest() - } else { - collapsedElements.two = true - } - }) + expect(collapseTwoOne).not.toHaveClass('show') + expect(collapseTwoTwo).not.toHaveClass('show') - collapseTwoTwo.addEventListener('shown.bs.collapse', () => { - if (collapsedElements.two) { - secondTest() - } else { - collapsedElements.two = true + triggerTwo.click() } - }) - trigger.click() - }) + function secondTest() { + expect(collapseOneOne).not.toHaveClass('show') + expect(collapseOneTwo).not.toHaveClass('show') - it('should collapse accordion children but not nested accordion children', done => { - fixtureEl.innerHTML = [ - '<div id="accordion">', - ' <div class="item">', - ' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>', - ' <div id="collapseOne" data-bs-parent="#accordion" class="collapse" role="tabpanel" aria-labelledby="headingThree">', - ' <div id="nestedAccordion">', - ' <div class="item">', - ' <a id="nestedLinkTrigger" data-bs-toggle="collapse" href="#nestedCollapseOne" aria-expanded="false" aria-controls="nestedCollapseOne"></a>', - ' <div id="nestedCollapseOne" data-bs-parent="#nestedAccordion" class="collapse" role="tabpanel" aria-labelledby="headingThree"></div>', - ' </div>', - ' </div>', - ' </div>', - ' </div>', - ' <div class="item">', - ' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>', - ' <div id="collapseTwo" data-bs-parent="#accordion" class="collapse show" role="tabpanel" aria-labelledby="headingTwo"></div>', - ' </div>', - '</div>' - ].join('') + expect(collapseTwoOne).toHaveClass('show') + expect(collapseTwoTwo).toHaveClass('show') + resolve() + } - const trigger = fixtureEl.querySelector('#linkTrigger') - const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') - const nestedTrigger = fixtureEl.querySelector('#nestedLinkTrigger') - const collapseOne = fixtureEl.querySelector('#collapseOne') - const collapseTwo = fixtureEl.querySelector('#collapseTwo') - const nestedCollapseOne = fixtureEl.querySelector('#nestedCollapseOne') - - function handlerCollapseOne() { - expect(collapseOne.classList.contains('show')).toEqual(true) - expect(collapseTwo.classList.contains('show')).toEqual(false) - expect(nestedCollapseOne.classList.contains('show')).toEqual(false) - - nestedCollapseOne.addEventListener('shown.bs.collapse', handlerNestedCollapseOne) - nestedTrigger.click() - collapseOne.removeEventListener('shown.bs.collapse', handlerCollapseOne) - } + collapseOneOne.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.one) { + firstTest() + } else { + collapsedElements.one = true + } + }) - function handlerNestedCollapseOne() { - expect(collapseOne.classList.contains('show')).toEqual(true) - expect(collapseTwo.classList.contains('show')).toEqual(false) - expect(nestedCollapseOne.classList.contains('show')).toEqual(true) + collapseOneTwo.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.one) { + firstTest() + } else { + collapsedElements.one = true + } + }) - collapseTwo.addEventListener('shown.bs.collapse', () => { - expect(collapseOne.classList.contains('show')).toEqual(false) - expect(collapseTwo.classList.contains('show')).toEqual(true) - expect(nestedCollapseOne.classList.contains('show')).toEqual(true) - done() + collapseTwoOne.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.two) { + secondTest() + } else { + collapsedElements.two = true + } }) - triggerTwo.click() - nestedCollapseOne.removeEventListener('shown.bs.collapse', handlerNestedCollapseOne) - } + collapseTwoTwo.addEventListener('shown.bs.collapse', () => { + if (collapsedElements.two) { + secondTest() + } else { + collapsedElements.two = true + } + }) - collapseOne.addEventListener('shown.bs.collapse', handlerCollapseOne) - trigger.click() + trigger.click() + }) }) - it('should add "collapsed" class and set aria-expanded to triggers only when all the targeted collapse are hidden', done => { - fixtureEl.innerHTML = [ - '<a id="trigger1" role="button" data-bs-toggle="collapse" href="#test1"></a>', - '<a id="trigger2" role="button" data-bs-toggle="collapse" href="#test2"></a>', - '<a id="trigger3" role="button" data-bs-toggle="collapse" href=".multi"></a>', - '<div id="test1" class="multi"></div>', - '<div id="test2" class="multi"></div>' - ].join('') + it('should collapse accordion children but not nested accordion children', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div id="accordion">', + ' <div class="item">', + ' <a id="linkTrigger" data-bs-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>', + ' <div id="collapseOne" data-bs-parent="#accordion" class="collapse" role="tabpanel">', + ' <div id="nestedAccordion">', + ' <div class="item">', + ' <a id="nestedLinkTrigger" data-bs-toggle="collapse" href="#nestedCollapseOne" aria-expanded="false" aria-controls="nestedCollapseOne"></a>', + ' <div id="nestedCollapseOne" data-bs-parent="#nestedAccordion" class="collapse" role="tabpanel"></div>', + ' </div>', + ' </div>', + ' </div>', + ' </div>', + ' <div class="item">', + ' <a id="linkTriggerTwo" data-bs-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>', + ' <div id="collapseTwo" data-bs-parent="#accordion" class="collapse show" role="tabpanel"></div>', + ' </div>', + '</div>' + ].join('') + + const trigger = fixtureEl.querySelector('#linkTrigger') + const triggerTwo = fixtureEl.querySelector('#linkTriggerTwo') + const nestedTrigger = fixtureEl.querySelector('#nestedLinkTrigger') + const collapseOne = fixtureEl.querySelector('#collapseOne') + const collapseTwo = fixtureEl.querySelector('#collapseTwo') + const nestedCollapseOne = fixtureEl.querySelector('#nestedCollapseOne') + + function handlerCollapseOne() { + expect(collapseOne).toHaveClass('show') + expect(collapseTwo).not.toHaveClass('show') + expect(nestedCollapseOne).not.toHaveClass('show') + + nestedCollapseOne.addEventListener('shown.bs.collapse', handlerNestedCollapseOne) + nestedTrigger.click() + collapseOne.removeEventListener('shown.bs.collapse', handlerCollapseOne) + } - const trigger1 = fixtureEl.querySelector('#trigger1') - const trigger2 = fixtureEl.querySelector('#trigger2') - const trigger3 = fixtureEl.querySelector('#trigger3') - const target1 = fixtureEl.querySelector('#test1') - const target2 = fixtureEl.querySelector('#test2') + function handlerNestedCollapseOne() { + expect(collapseOne).toHaveClass('show') + expect(collapseTwo).not.toHaveClass('show') + expect(nestedCollapseOne).toHaveClass('show') - const target2Shown = () => { - expect(trigger1.classList.contains('collapsed')).toEqual(false) - expect(trigger1.getAttribute('aria-expanded')).toEqual('true') + collapseTwo.addEventListener('shown.bs.collapse', () => { + expect(collapseOne).not.toHaveClass('show') + expect(collapseTwo).toHaveClass('show') + expect(nestedCollapseOne).toHaveClass('show') + resolve() + }) - expect(trigger2.classList.contains('collapsed')).toEqual(false) - expect(trigger2.getAttribute('aria-expanded')).toEqual('true') + triggerTwo.click() + nestedCollapseOne.removeEventListener('shown.bs.collapse', handlerNestedCollapseOne) + } - expect(trigger3.classList.contains('collapsed')).toEqual(false) - expect(trigger3.getAttribute('aria-expanded')).toEqual('true') + collapseOne.addEventListener('shown.bs.collapse', handlerCollapseOne) + trigger.click() + }) + }) - target2.addEventListener('hidden.bs.collapse', () => { - expect(trigger1.classList.contains('collapsed')).toEqual(false) + it('should add "collapsed" class and set aria-expanded to triggers only when all the targeted collapse are hidden', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<a id="trigger1" role="button" data-bs-toggle="collapse" href="#test1"></a>', + '<a id="trigger2" role="button" data-bs-toggle="collapse" href="#0/my/id"></a>', + '<a id="trigger3" role="button" data-bs-toggle="collapse" href=".multi"></a>', + '<div id="test1" class="multi"></div>', + '<div id="0/my/id" class="multi"></div>' + ].join('') + + const trigger1 = fixtureEl.querySelector('#trigger1') + const trigger2 = fixtureEl.querySelector('#trigger2') + const trigger3 = fixtureEl.querySelector('#trigger3') + const target1 = fixtureEl.querySelector('#test1') + const target2 = fixtureEl.querySelector(`#${CSS.escape('0/my/id')}`) + + const target2Shown = () => { + expect(trigger1).not.toHaveClass('collapsed') expect(trigger1.getAttribute('aria-expanded')).toEqual('true') - expect(trigger2.classList.contains('collapsed')).toEqual(true) - expect(trigger2.getAttribute('aria-expanded')).toEqual('false') + expect(trigger2).not.toHaveClass('collapsed') + expect(trigger2.getAttribute('aria-expanded')).toEqual('true') - expect(trigger3.classList.contains('collapsed')).toEqual(false) + expect(trigger3).not.toHaveClass('collapsed') expect(trigger3.getAttribute('aria-expanded')).toEqual('true') - target1.addEventListener('hidden.bs.collapse', () => { - expect(trigger1.classList.contains('collapsed')).toEqual(true) - expect(trigger1.getAttribute('aria-expanded')).toEqual('false') + target2.addEventListener('hidden.bs.collapse', () => { + expect(trigger1).not.toHaveClass('collapsed') + expect(trigger1.getAttribute('aria-expanded')).toEqual('true') - expect(trigger2.classList.contains('collapsed')).toEqual(true) + expect(trigger2).toHaveClass('collapsed') expect(trigger2.getAttribute('aria-expanded')).toEqual('false') - expect(trigger3.classList.contains('collapsed')).toEqual(true) - expect(trigger3.getAttribute('aria-expanded')).toEqual('false') - done() - }) + expect(trigger3).not.toHaveClass('collapsed') + expect(trigger3.getAttribute('aria-expanded')).toEqual('true') - trigger1.click() - }) + target1.addEventListener('hidden.bs.collapse', () => { + expect(trigger1).toHaveClass('collapsed') + expect(trigger1.getAttribute('aria-expanded')).toEqual('false') - trigger2.click() - } + expect(trigger2).toHaveClass('collapsed') + expect(trigger2.getAttribute('aria-expanded')).toEqual('false') - target2.addEventListener('shown.bs.collapse', target2Shown) - trigger3.click() + expect(trigger3).toHaveClass('collapsed') + expect(trigger3.getAttribute('aria-expanded')).toEqual('false') + resolve() + }) + + trigger1.click() + }) + + trigger2.click() + } + + target2.addEventListener('shown.bs.collapse', target2Shown) + trigger3.click() + }) }) }) @@ -961,7 +1002,7 @@ describe('Collapse', () => { const div = fixtureEl.querySelector('div') - expect(Collapse.getInstance(div)).toEqual(null) + expect(Collapse.getInstance(div)).toBeNull() }) }) @@ -982,7 +1023,7 @@ describe('Collapse', () => { const div = fixtureEl.querySelector('div') - expect(Collapse.getInstance(div)).toEqual(null) + expect(Collapse.getInstance(div)).toBeNull() expect(Collapse.getOrCreateInstance(div)).toBeInstanceOf(Collapse) }) @@ -991,13 +1032,13 @@ describe('Collapse', () => { const div = fixtureEl.querySelector('div') - expect(Collapse.getInstance(div)).toEqual(null) + expect(Collapse.getInstance(div)).toBeNull() const collapse = Collapse.getOrCreateInstance(div, { toggle: false }) expect(collapse).toBeInstanceOf(Collapse) - expect(collapse._config.toggle).toEqual(false) + expect(collapse._config.toggle).toBeFalse() }) it('should return the instance when exists without given configuration', () => { @@ -1015,7 +1056,7 @@ describe('Collapse', () => { expect(collapse).toBeInstanceOf(Collapse) expect(collapse2).toEqual(collapse) - expect(collapse2._config.toggle).toEqual(false) + expect(collapse2._config.toggle).toBeFalse() }) }) }) |
