diff options
author | GeoSot <geo.sotis@gmail.com> | 2022-01-30 15:30:04 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-30 15:30:04 +0300 |
commit | aa650f0f1e30279f0868433a4afab9c3efa93b2c (patch) | |
tree | 88cf537f2e7b6613bc2e53d4e38ca93798786d07 /js/tests/unit/tab.spec.js | |
parent | d09281705988690b63a5364548447c603cb557fd (diff) |
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.
Diffstat (limited to 'js/tests/unit/tab.spec.js')
-rw-r--r-- | js/tests/unit/tab.spec.js | 914 |
1 files changed, 476 insertions, 438 deletions
diff --git a/js/tests/unit/tab.spec.js b/js/tests/unit/tab.spec.js index bafa085526..43adee53b2 100644 --- a/js/tests/unit/tab.spec.js +++ b/js/tests/unit/tab.spec.js @@ -1,5 +1,5 @@ import Tab from '../../src/tab' -import { getFixture, clearFixture, jQueryMock } from '../helpers/fixture' +import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture' describe('Tab', () => { let fixtureEl @@ -39,314 +39,336 @@ describe('Tab', () => { }) describe('show', () => { - it('should activate element by tab id (using buttons, the preferred semantic way)', done => { - fixtureEl.innerHTML = [ - '<ul class="nav" role="tablist">', - ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', - ' <li><button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button></li>', - '</ul>', - '<ul>', - ' <li id="home" role="tabpanel"></li>', - ' <li id="profile" role="tabpanel"></li>', - '</ul>' - ].join('') - - const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') - const tab = new Tab(profileTriggerEl) + it('should activate element by tab id (using buttons, the preferred semantic way)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav" role="tablist">', + ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', + ' <li><button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button></li>', + '</ul>', + '<ul>', + ' <li id="home" role="tabpanel"></li>', + ' <li id="profile" role="tabpanel"></li>', + '</ul>' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true') + resolve() + }) - profileTriggerEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelector('#profile')).toHaveClass('active') - expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true') - done() + tab.show() }) - - tab.show() }) - it('should activate element by tab id (using links for tabs - not ideal, but still supported)', done => { - fixtureEl.innerHTML = [ - '<ul class="nav" role="tablist">', - ' <li><a href="#home" role="tab">Home</a></li>', - ' <li><a id="triggerProfile" href="#profile" role="tab">Profile</a></li>', - '</ul>', - '<ul>', - ' <li id="home" role="tabpanel"></li>', - ' <li id="profile" role="tabpanel"></li>', - '</ul>' - ].join('') - - const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') - const tab = new Tab(profileTriggerEl) + it('should activate element by tab id (using links for tabs - not ideal, but still supported)', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav" role="tablist">', + ' <li><a href="#home" role="tab">Home</a></li>', + ' <li><a id="triggerProfile" href="#profile" role="tab">Profile</a></li>', + '</ul>', + '<ul>', + ' <li id="home" role="tabpanel"></li>', + ' <li id="profile" role="tabpanel"></li>', + '</ul>' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true') + resolve() + }) - profileTriggerEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelector('#profile')).toHaveClass('active') - expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true') - done() + tab.show() }) - - tab.show() }) - it('should activate element by tab id in ordered list', done => { - fixtureEl.innerHTML = [ - '<ol class="nav nav-pills">', - ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', - ' <li><button type="button" id="triggerProfile" href="#profile" role="tab">Profile</button></li>', - '</ol>', - '<ol>', - ' <li id="home" role="tabpanel"></li>', - ' <li id="profile" role="tabpanel"></li>', - '</ol>' - ].join('') - - const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') - const tab = new Tab(profileTriggerEl) + it('should activate element by tab id in ordered list', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ol class="nav nav-pills">', + ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', + ' <li><button type="button" id="triggerProfile" href="#profile" role="tab">Profile</button></li>', + '</ol>', + '<ol>', + ' <li id="home" role="tabpanel"></li>', + ' <li id="profile" role="tabpanel"></li>', + '</ol>' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) - profileTriggerEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelector('#profile')).toHaveClass('active') - done() + tab.show() }) - - tab.show() }) - it('should activate element by tab id in nav list', done => { - fixtureEl.innerHTML = [ - '<nav class="nav">', - ' <button type="button" data-bs-target="#home" role="tab">Home</button>', - ' <button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button>', - '</nav>', - '<div>', - ' <div id="home" role="tabpanel"></div>', - ' <div id="profile" role="tabpanel"></div>', - '</div>' - ].join('') - - const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') - const tab = new Tab(profileTriggerEl) + it('should activate element by tab id in nav list', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<nav class="nav">', + ' <button type="button" data-bs-target="#home" role="tab">Home</button>', + ' <button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button>', + '</nav>', + '<div>', + ' <div id="home" role="tabpanel"></div>', + ' <div id="profile" role="tabpanel"></div>', + '</div>' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) - profileTriggerEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelector('#profile')).toHaveClass('active') - done() + tab.show() }) - - tab.show() }) - it('should activate element by tab id in list group', done => { - fixtureEl.innerHTML = [ - '<div class="list-group" role="tablist">', - ' <button type="button" data-bs-target="#home" role="tab">Home</button>', - ' <button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button>', - '</div>', - '<div>', - ' <div id="home" role="tabpanel"></div>', - ' <div id="profile" role="tabpanel"></div>', - '</div>' - ].join('') - - const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') - const tab = new Tab(profileTriggerEl) + it('should activate element by tab id in list group', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<div class="list-group" role="tablist">', + ' <button type="button" data-bs-target="#home" role="tab">Home</button>', + ' <button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button>', + '</div>', + '<div>', + ' <div id="home" role="tabpanel"></div>', + ' <div id="profile" role="tabpanel"></div>', + '</div>' + ].join('') + + const profileTriggerEl = fixtureEl.querySelector('#triggerProfile') + const tab = new Tab(profileTriggerEl) + + profileTriggerEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) - profileTriggerEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelector('#profile')).toHaveClass('active') - done() + tab.show() }) - - tab.show() }) - it('should not fire shown when show is prevented', done => { - fixtureEl.innerHTML = '<div class="nav"></div>' + it('should not fire shown when show is prevented', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = '<div class="nav"></div>' - const navEl = fixtureEl.querySelector('div') - const tab = new Tab(navEl) - const expectDone = () => { - setTimeout(() => { - expect().nothing() - done() - }, 30) - } + const navEl = fixtureEl.querySelector('div') + const tab = new Tab(navEl) + const expectDone = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + } - navEl.addEventListener('show.bs.tab', ev => { - ev.preventDefault() - expectDone() - }) + navEl.addEventListener('show.bs.tab', ev => { + ev.preventDefault() + expectDone() + }) - navEl.addEventListener('shown.bs.tab', () => { - throw new Error('should not trigger shown event') - }) + navEl.addEventListener('shown.bs.tab', () => { + throw new Error('should not trigger shown event') + }) - tab.show() + tab.show() + }) }) - it('should not fire shown when tab is already active', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', - ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#profile" class="nav-link" role="tab">Profile</button></li>', - '</ul>', - '<div class="tab-content">', - ' <div class="tab-pane active" id="home" role="tabpanel"></div>', - ' <div class="tab-pane" id="profile" role="tabpanel"></div>', - '</div>' - ].join('') - - const triggerActive = fixtureEl.querySelector('button.active') - const tab = new Tab(triggerActive) + it('should not fire shown when tab is already active', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', + ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#profile" class="nav-link" role="tab">Profile</button></li>', + '</ul>', + '<div class="tab-content">', + ' <div class="tab-pane active" id="home" role="tabpanel"></div>', + ' <div class="tab-pane" id="profile" role="tabpanel"></div>', + '</div>' + ].join('') + + const triggerActive = fixtureEl.querySelector('button.active') + const tab = new Tab(triggerActive) + + triggerActive.addEventListener('shown.bs.tab', () => { + throw new Error('should not trigger shown event') + }) - triggerActive.addEventListener('shown.bs.tab', () => { - throw new Error('should not trigger shown event') + tab.show() + setTimeout(() => { + expect().nothing() + resolve() + }, 30) }) - - tab.show() - setTimeout(() => { - expect().nothing() - done() - }, 30) }) - it('show and shown events should reference correct relatedTarget', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', - ' <li class="nav-item" role="presentation"><button type="button" id="triggerProfile" data-bs-target="#profile" class="nav-link" role="tab">Profile</button></li>', - '</ul>', - '<div class="tab-content">', - ' <div class="tab-pane active" id="home" role="tabpanel"></div>', - ' <div class="tab-pane" id="profile" role="tabpanel"></div>', - '</div>' - ].join('') - - const secondTabTrigger = fixtureEl.querySelector('#triggerProfile') - const secondTab = new Tab(secondTabTrigger) + it('show and shown events should reference correct relatedTarget', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', + ' <li class="nav-item" role="presentation"><button type="button" id="triggerProfile" data-bs-target="#profile" class="nav-link" role="tab">Profile</button></li>', + '</ul>', + '<div class="tab-content">', + ' <div class="tab-pane active" id="home" role="tabpanel"></div>', + ' <div class="tab-pane" id="profile" role="tabpanel"></div>', + '</div>' + ].join('') + + const secondTabTrigger = fixtureEl.querySelector('#triggerProfile') + const secondTab = new Tab(secondTabTrigger) + + secondTabTrigger.addEventListener('show.bs.tab', ev => { + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#home') + }) - secondTabTrigger.addEventListener('show.bs.tab', ev => { - expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#home') - }) + secondTabTrigger.addEventListener('shown.bs.tab', ev => { + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#home') + expect(secondTabTrigger.getAttribute('aria-selected')).toEqual('true') + expect(fixtureEl.querySelector('button:not(.active)').getAttribute('aria-selected')).toEqual('false') + resolve() + }) - secondTabTrigger.addEventListener('shown.bs.tab', ev => { - expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#home') - expect(secondTabTrigger.getAttribute('aria-selected')).toEqual('true') - expect(fixtureEl.querySelector('button:not(.active)').getAttribute('aria-selected')).toEqual('false') - done() + secondTab.show() }) - - secondTab.show() }) - it('should fire hide and hidden events', done => { - fixtureEl.innerHTML = [ - '<ul class="nav" role="tablist">', - ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', - ' <li><button type="button" data-bs-target="#profile">Profile</button></li>', - '</ul>' - ].join('') + it('should fire hide and hidden events', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav" role="tablist">', + ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', + ' <li><button type="button" data-bs-target="#profile">Profile</button></li>', + '</ul>' + ].join('') - const triggerList = fixtureEl.querySelectorAll('button') - const firstTab = new Tab(triggerList[0]) - const secondTab = new Tab(triggerList[1]) + const triggerList = fixtureEl.querySelectorAll('button') + const firstTab = new Tab(triggerList[0]) + const secondTab = new Tab(triggerList[1]) - let hideCalled = false - triggerList[0].addEventListener('shown.bs.tab', () => { - secondTab.show() - }) + let hideCalled = false + triggerList[0].addEventListener('shown.bs.tab', () => { + secondTab.show() + }) - triggerList[0].addEventListener('hide.bs.tab', ev => { - hideCalled = true - expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#profile') - }) + triggerList[0].addEventListener('hide.bs.tab', ev => { + hideCalled = true + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#profile') + }) - triggerList[0].addEventListener('hidden.bs.tab', ev => { - expect(hideCalled).toBeTrue() - expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#profile') - done() - }) + triggerList[0].addEventListener('hidden.bs.tab', ev => { + expect(hideCalled).toBeTrue() + expect(ev.relatedTarget.getAttribute('data-bs-target')).toEqual('#profile') + resolve() + }) - firstTab.show() + firstTab.show() + }) }) - it('should not fire hidden when hide is prevented', done => { - fixtureEl.innerHTML = [ - '<ul class="nav" role="tablist">', - ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', - ' <li><button type="button" data-bs-target="#profile" role="tab">Profile</button></li>', - '</ul>' - ].join('') - - const triggerList = fixtureEl.querySelectorAll('button') - const firstTab = new Tab(triggerList[0]) - const secondTab = new Tab(triggerList[1]) - const expectDone = () => { - setTimeout(() => { - expect().nothing() - done() - }, 30) - } + it('should not fire hidden when hide is prevented', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav" role="tablist">', + ' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>', + ' <li><button type="button" data-bs-target="#profile" role="tab">Profile</button></li>', + '</ul>' + ].join('') + + const triggerList = fixtureEl.querySelectorAll('button') + const firstTab = new Tab(triggerList[0]) + const secondTab = new Tab(triggerList[1]) + const expectDone = () => { + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + } + + triggerList[0].addEventListener('shown.bs.tab', () => { + secondTab.show() + }) - triggerList[0].addEventListener('shown.bs.tab', () => { - secondTab.show() - }) + triggerList[0].addEventListener('hide.bs.tab', ev => { + ev.preventDefault() + expectDone() + }) - triggerList[0].addEventListener('hide.bs.tab', ev => { - ev.preventDefault() - expectDone() - }) + triggerList[0].addEventListener('hidden.bs.tab', () => { + throw new Error('should not trigger hidden') + }) - triggerList[0].addEventListener('hidden.bs.tab', () => { - throw new Error('should not trigger hidden') + firstTab.show() }) - - firstTab.show() }) - it('should handle removed tabs', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation">', - ' <a class="nav-link nav-tab" href="#profile" role="tab" data-bs-toggle="tab">', - ' <button class="btn-close" aria-label="Close"></button>', - ' </a>', - ' </li>', - ' <li class="nav-item" role="presentation">', - ' <a id="secondNav" class="nav-link nav-tab" href="#buzz" role="tab" data-bs-toggle="tab">', - ' <button class="btn-close" aria-label="Close"></button>', - ' </a>', - ' </li>', - ' <li class="nav-item" role="presentation">', - ' <a class="nav-link nav-tab" href="#references" role="tab" data-bs-toggle="tab">', - ' <button id="btnClose" class="btn-close" aria-label="Close"></button>', - ' </a>', - ' </li>', - '</ul>', - '<div class="tab-content">', - ' <div role="tabpanel" class="tab-pane fade show active" id="profile">test 1</div>', - ' <div role="tabpanel" class="tab-pane fade" id="buzz">test 2</div>', - ' <div role="tabpanel" class="tab-pane fade" id="references">test 3</div>', - '</div>' - ].join('') - - const secondNavEl = fixtureEl.querySelector('#secondNav') - const btnCloseEl = fixtureEl.querySelector('#btnClose') - const secondNavTab = new Tab(secondNavEl) + it('should handle removed tabs', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation">', + ' <a class="nav-link nav-tab" href="#profile" role="tab" data-bs-toggle="tab">', + ' <button class="btn-close" aria-label="Close"></button>', + ' </a>', + ' </li>', + ' <li class="nav-item" role="presentation">', + ' <a id="secondNav" class="nav-link nav-tab" href="#buzz" role="tab" data-bs-toggle="tab">', + ' <button class="btn-close" aria-label="Close"></button>', + ' </a>', + ' </li>', + ' <li class="nav-item" role="presentation">', + ' <a class="nav-link nav-tab" href="#references" role="tab" data-bs-toggle="tab">', + ' <button id="btnClose" class="btn-close" aria-label="Close"></button>', + ' </a>', + ' </li>', + '</ul>', + '<div class="tab-content">', + ' <div role="tabpanel" class="tab-pane fade show active" id="profile">test 1</div>', + ' <div role="tabpanel" class="tab-pane fade" id="buzz">test 2</div>', + ' <div role="tabpanel" class="tab-pane fade" id="references">test 3</div>', + '</div>' + ].join('') + + const secondNavEl = fixtureEl.querySelector('#secondNav') + const btnCloseEl = fixtureEl.querySelector('#btnClose') + const secondNavTab = new Tab(secondNavEl) + + secondNavEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelectorAll('.nav-tab')).toHaveSize(2) + resolve() + }) - secondNavEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelectorAll('.nav-tab')).toHaveSize(2) - done() - }) + btnCloseEl.addEventListener('click', () => { + const linkEl = btnCloseEl.parentNode + const liEl = linkEl.parentNode + const tabId = linkEl.getAttribute('href') + const tabIdEl = fixtureEl.querySelector(tabId) - btnCloseEl.addEventListener('click', () => { - const linkEl = btnCloseEl.parentNode - const liEl = linkEl.parentNode - const tabId = linkEl.getAttribute('href') - const tabIdEl = fixtureEl.querySelector(tabId) + liEl.remove() + tabIdEl.remove() + secondNavTab.show() + }) - liEl.remove() - tabIdEl.remove() - secondNavTab.show() + btnCloseEl.click() }) - - btnCloseEl.click() }) }) @@ -464,27 +486,29 @@ describe('Tab', () => { }) describe('data-api', () => { - it('should create dynamically a tab', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', - ' <li class="nav-item" role="presentation"><button type="button" id="triggerProfile" data-bs-toggle="tab" data-bs-target="#profile" class="nav-link" role="tab">Profile</button></li>', - '</ul>', - '<div class="tab-content">', - ' <div class="tab-pane active" id="home" role="tabpanel"></div>', - ' <div class="tab-pane" id="profile" role="tabpanel"></div>', - '</div>' - ].join('') - - const secondTabTrigger = fixtureEl.querySelector('#triggerProfile') + it('should create dynamically a tab', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', + ' <li class="nav-item" role="presentation"><button type="button" id="triggerProfile" data-bs-toggle="tab" data-bs-target="#profile" class="nav-link" role="tab">Profile</button></li>', + '</ul>', + '<div class="tab-content">', + ' <div class="tab-pane active" id="home" role="tabpanel"></div>', + ' <div class="tab-pane" id="profile" role="tabpanel"></div>', + '</div>' + ].join('') + + const secondTabTrigger = fixtureEl.querySelector('#triggerProfile') + + secondTabTrigger.addEventListener('shown.bs.tab', () => { + expect(secondTabTrigger).toHaveClass('active') + expect(fixtureEl.querySelector('#profile')).toHaveClass('active') + resolve() + }) - secondTabTrigger.addEventListener('shown.bs.tab', () => { - expect(secondTabTrigger).toHaveClass('active') - expect(fixtureEl.querySelector('#profile')).toHaveClass('active') - done() + secondTabTrigger.click() }) - - secondTabTrigger.click() }) it('selected tab should deactivate previous selected link in dropdown', () => { @@ -567,202 +591,216 @@ describe('Tab', () => { expect(fixtureEl.querySelector('.nav-link')).not.toHaveClass('active') }) - it('should handle nested tabs', done => { - fixtureEl.innerHTML = [ - '<nav class="nav nav-tabs" role="tablist">', - ' <button type="button" id="tab1" data-bs-target="#x-tab1" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</button>', - ' <button type="button" data-bs-target="#x-tab2" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</button>', - ' <button type="button" data-bs-target="#x-tab3" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</button>', - '</nav>', - '<div class="tab-content">', - ' <div class="tab-pane" id="x-tab1" role="tabpanel">', - ' <nav class="nav nav-tabs" role="tablist">', - ' <button type="button" data-bs-target="#nested-tab1" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</button>', - ' <button type="button" id="tabNested2" data-bs-target="#nested-tab2" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</button>', - ' </nav>', - ' <div class="tab-content">', - ' <div class="tab-pane active" id="nested-tab1" role="tabpanel">Nested Tab1 Content</div>', - ' <div class="tab-pane" id="nested-tab2" role="tabpanel">Nested Tab2 Content</div>', - ' </div>', - ' </div>', - ' <div class="tab-pane active" id="x-tab2" role="tabpanel">Tab2 Content</div>', - ' <div class="tab-pane" id="x-tab3" role="tabpanel">Tab3 Content</div>', - '</div>' - ].join('') - - const tab1El = fixtureEl.querySelector('#tab1') - const tabNested2El = fixtureEl.querySelector('#tabNested2') - const xTab1El = fixtureEl.querySelector('#x-tab1') + it('should handle nested tabs', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<nav class="nav nav-tabs" role="tablist">', + ' <button type="button" id="tab1" data-bs-target="#x-tab1" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</button>', + ' <button type="button" data-bs-target="#x-tab2" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</button>', + ' <button type="button" data-bs-target="#x-tab3" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</button>', + '</nav>', + '<div class="tab-content">', + ' <div class="tab-pane" id="x-tab1" role="tabpanel">', + ' <nav class="nav nav-tabs" role="tablist">', + ' <button type="button" data-bs-target="#nested-tab1" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</button>', + ' <button type="button" id="tabNested2" data-bs-target="#nested-tab2" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</button>', + ' </nav>', + ' <div class="tab-content">', + ' <div class="tab-pane active" id="nested-tab1" role="tabpanel">Nested Tab1 Content</div>', + ' <div class="tab-pane" id="nested-tab2" role="tabpanel">Nested Tab2 Content</div>', + ' </div>', + ' </div>', + ' <div class="tab-pane active" id="x-tab2" role="tabpanel">Tab2 Content</div>', + ' <div class="tab-pane" id="x-tab3" role="tabpanel">Tab3 Content</div>', + '</div>' + ].join('') + + const tab1El = fixtureEl.querySelector('#tab1') + const tabNested2El = fixtureEl.querySelector('#tabNested2') + const xTab1El = fixtureEl.querySelector('#x-tab1') + + tabNested2El.addEventListener('shown.bs.tab', () => { + expect(xTab1El).toHaveClass('active') + resolve() + }) - tabNested2El.addEventListener('shown.bs.tab', () => { - expect(xTab1El).toHaveClass('active') - done() - }) + tab1El.addEventListener('shown.bs.tab', () => { + expect(xTab1El).toHaveClass('active') + tabNested2El.click() + }) - tab1El.addEventListener('shown.bs.tab', () => { - expect(xTab1El).toHaveClass('active') - tabNested2El.click() + tab1El.click() }) - - tab1El.click() }) - it('should not remove fade class if no active pane is present', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation"><button type="button" id="tab-home" data-bs-target="#home" class="nav-link" data-bs-toggle="tab" role="tab">Home</button></li>', - ' <li class="nav-item" role="presentation"><button type="button" id="tab-profile" data-bs-target="#profile" class="nav-link" data-bs-toggle="tab" role="tab">Profile</button></li>', - '</ul>', - '<div class="tab-content">', - ' <div class="tab-pane fade" id="home" role="tabpanel"></div>', - ' <div class="tab-pane fade" id="profile" role="tabpanel"></div>', - '</div>' - ].join('') - - const triggerTabProfileEl = fixtureEl.querySelector('#tab-profile') - const triggerTabHomeEl = fixtureEl.querySelector('#tab-home') - const tabProfileEl = fixtureEl.querySelector('#profile') - const tabHomeEl = fixtureEl.querySelector('#home') + it('should not remove fade class if no active pane is present', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation"><button type="button" id="tab-home" data-bs-target="#home" class="nav-link" data-bs-toggle="tab" role="tab">Home</button></li>', + ' <li class="nav-item" role="presentation"><button type="button" id="tab-profile" data-bs-target="#profile" class="nav-link" data-bs-toggle="tab" role="tab">Profile</button></li>', + '</ul>', + '<div class="tab-content">', + ' <div class="tab-pane fade" id="home" role="tabpanel"></div>', + ' <div class="tab-pane fade" id="profile" role="tabpanel"></div>', + '</div>' + ].join('') + + const triggerTabProfileEl = fixtureEl.querySelector('#tab-profile') + const triggerTabHomeEl = fixtureEl.querySelector('#tab-home') + const tabProfileEl = fixtureEl.querySelector('#profile') + const tabHomeEl = fixtureEl.querySelector('#home') + + triggerTabProfileEl.addEventListener('shown.bs.tab', () => { + expect(tabProfileEl).toHaveClass('fade') + expect(tabProfileEl).toHaveClass('show') - triggerTabProfileEl.addEventListener('shown.bs.tab', () => { - expect(tabProfileEl).toHaveClass('fade') - expect(tabProfileEl).toHaveClass('show') + triggerTabHomeEl.addEventListener('shown.bs.tab', () => { + expect(tabProfileEl).toHaveClass('fade') + expect(tabProfileEl).not.toHaveClass('show') - triggerTabHomeEl.addEventListener('shown.bs.tab', () => { - expect(tabProfileEl).toHaveClass('fade') - expect(tabProfileEl).not.toHaveClass('show') + expect(tabHomeEl).toHaveClass('fade') + expect(tabHomeEl).toHaveClass('show') - expect(tabHomeEl).toHaveClass('fade') - expect(tabHomeEl).toHaveClass('show') + resolve() + }) - done() + triggerTabHomeEl.click() }) - triggerTabHomeEl.click() + triggerTabProfileEl.click() }) - - triggerTabProfileEl.click() }) - it('should not add show class to tab panes if there is no `.fade` class', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation">', - ' <button type="button" class="nav-link nav-tab" data-bs-target="#home" role="tab" data-bs-toggle="tab">Home</button>', - ' </li>', - ' <li class="nav-item" role="presentation">', - ' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target="#profile" role="tab" data-bs-toggle="tab">Profile</button>', - ' </li>', - '</ul>', - '<div class="tab-content">', - ' <div role="tabpanel" class="tab-pane" id="home">test 1</div>', - ' <div role="tabpanel" class="tab-pane" id="profile">test 2</div>', - '</div>' - ].join('') - - const secondNavEl = fixtureEl.querySelector('#secondNav') + it('should not add show class to tab panes if there is no `.fade` class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation">', + ' <button type="button" class="nav-link nav-tab" data-bs-target="#home" role="tab" data-bs-toggle="tab">Home</button>', + ' </li>', + ' <li class="nav-item" role="presentation">', + ' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target="#profile" role="tab" data-bs-toggle="tab">Profile</button>', + ' </li>', + '</ul>', + '<div class="tab-content">', + ' <div role="tabpanel" class="tab-pane" id="home">test 1</div>', + ' <div role="tabpanel" class="tab-pane" id="profile">test 2</div>', + '</div>' + ].join('') + + const secondNavEl = fixtureEl.querySelector('#secondNav') + + secondNavEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelectorAll('.show')).toHaveSize(0) + resolve() + }) - secondNavEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelectorAll('.show')).toHaveSize(0) - done() + secondNavEl.click() }) - - secondNavEl.click() }) - it('should add show class to tab panes if there is a `.fade` class', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation">', - ' <button type="button" class="nav-link nav-tab" data-bs-target="#home" role="tab" data-bs-toggle="tab">Home</button>', - ' </li>', - ' <li class="nav-item" role="presentation">', - ' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target="#profile" role="tab" data-bs-toggle="tab">Profile</button>', - ' </li>', - '</ul>', - '<div class="tab-content">', - ' <div role="tabpanel" class="tab-pane fade" id="home">test 1</div>', - ' <div role="tabpanel" class="tab-pane fade" id="profile">test 2</div>', - '</div>' - ].join('') - - const secondNavEl = fixtureEl.querySelector('#secondNav') + it('should add show class to tab panes if there is a `.fade` class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation">', + ' <button type="button" class="nav-link nav-tab" data-bs-target="#home" role="tab" data-bs-toggle="tab">Home</button>', + ' </li>', + ' <li class="nav-item" role="presentation">', + ' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target="#profile" role="tab" data-bs-toggle="tab">Profile</button>', + ' </li>', + '</ul>', + '<div class="tab-content">', + ' <div role="tabpanel" class="tab-pane fade" id="home">test 1</div>', + ' <div role="tabpanel" class="tab-pane fade" id="profile">test 2</div>', + '</div>' + ].join('') + + const secondNavEl = fixtureEl.querySelector('#secondNav') + + secondNavEl.addEventListener('shown.bs.tab', () => { + expect(fixtureEl.querySelectorAll('.show')).toHaveSize(1) + resolve() + }) - secondNavEl.addEventListener('shown.bs.tab', () => { - expect(fixtureEl.querySelectorAll('.show')).toHaveSize(1) - done() + secondNavEl.click() }) - - secondNavEl.click() }) - it('should prevent default when the trigger is <a> or <area>', done => { - fixtureEl.innerHTML = [ - '<ul class="nav" role="tablist">', - ' <li><a type="button" href="#test" class="active" role="tab" data-bs-toggle="tab">Home</a></li>', - ' <li><a type="button" href="#test2" role="tab" data-bs-toggle="tab">Home</a></li>', - '</ul>' - ].join('') + it('should prevent default when the trigger is <a> or <area>', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav" role="tablist">', + ' <li><a type="button" href="#test" class="active" role="tab" data-bs-toggle="tab">Home</a></li>', + ' <li><a type="button" href="#test2" role="tab" data-bs-toggle="tab">Home</a></li>', + '</ul>' + ].join('') - const tabEl = fixtureEl.querySelector('[href="#test2"]') - spyOn(Event.prototype, 'preventDefault').and.callThrough() + const tabEl = fixtureEl.querySelector('[href="#test2"]') + spyOn(Event.prototype, 'preventDefault').and.callThrough() - tabEl.addEventListener('shown.bs.tab', () => { - expect(tabEl).toHaveClass('active') - expect(Event.prototype.preventDefault).toHaveBeenCalled() - done() - }) + tabEl.addEventListener('shown.bs.tab', () => { + expect(tabEl).toHaveClass('active') + expect(Event.prototype.preventDefault).toHaveBeenCalled() + resolve() + }) - tabEl.click() + tabEl.click() + }) }) - it('should not fire shown when tab has disabled attribute', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', - ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#profile" class="nav-link" disabled role="tab">Profile</button></li>', - '</ul>', - '<div class="tab-content">', - ' <div class="tab-pane active" id="home" role="tabpanel"></div>', - ' <div class="tab-pane" id="profile" role="tabpanel"></div>', - '</div>' - ].join('') + it('should not fire shown when tab has disabled attribute', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#home" class="nav-link active" role="tab" aria-selected="true">Home</button></li>', + ' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#profile" class="nav-link" disabled role="tab">Profile</button></li>', + '</ul>', + '<div class="tab-content">', + ' <div class="tab-pane active" id="home" role="tabpanel"></div>', + ' <div class="tab-pane" id="profile" role="tabpanel"></div>', + '</div>' + ].join('') + + const triggerDisabled = fixtureEl.querySelector('button[disabled]') + triggerDisabled.addEventListener('shown.bs.tab', () => { + throw new Error('should not trigger shown event') + }) - const triggerDisabled = fixtureEl.querySelector('button[disabled]') - triggerDisabled.addEventListener('shown.bs.tab', () => { - throw new Error('should not trigger shown event') + triggerDisabled.click() + setTimeout(() => { + expect().nothing() + resolve() + }, 30) }) - - triggerDisabled.click() - setTimeout(() => { - expect().nothing() - done() - }, 30) }) - it('should not fire shown when tab has disabled class', done => { - fixtureEl.innerHTML = [ - '<ul class="nav nav-tabs" role="tablist">', - ' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab" aria-selected="true">Home</a></li>', - ' <li class="nav-item" role="presentation"><a href="#profile" class="nav-link disabled" role="tab">Profile</a></li>', - '</ul>', - '<div class="tab-content">', - ' <div class="tab-pane active" id="home" role="tabpanel"></div>', - ' <div class="tab-pane" id="profile" role="tabpanel"></div>', - '</div>' - ].join('') + it('should not fire shown when tab has disabled class', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = [ + '<ul class="nav nav-tabs" role="tablist">', + ' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab" aria-selected="true">Home</a></li>', + ' <li class="nav-item" role="presentation"><a href="#profile" class="nav-link disabled" role="tab">Profile</a></li>', + '</ul>', + '<div class="tab-content">', + ' <div class="tab-pane active" id="home" role="tabpanel"></div>', + ' <div class="tab-pane" id="profile" role="tabpanel"></div>', + '</div>' + ].join('') - const triggerDisabled = fixtureEl.querySelector('a.disabled') + const triggerDisabled = fixtureEl.querySelector('a.disabled') - triggerDisabled.addEventListener('shown.bs.tab', () => { - throw new Error('should not trigger shown event') - }) + triggerDisabled.addEventListener('shown.bs.tab', () => { + throw new Error('should not trigger shown event') + }) - triggerDisabled.click() - setTimeout(() => { - expect().nothing() - done() - }, 30) + triggerDisabled.click() + setTimeout(() => { + expect().nothing() + resolve() + }, 30) + }) }) }) }) |