Skip to content

Commit 34f38ce

Browse files
committed
Update js unit and visual test accordingly
- replace links with buttons - make one specific test that uses links instead of buttons, as we still want to support it despite it being non-semantically appropriate - remove tests involving dropdown tabs, as they're discouraged (though still silently supported)
1 parent fe7577a commit 34f38ce

File tree

2 files changed

+91
-123
lines changed

2 files changed

+91
-123
lines changed

js/tests/unit/tab.spec.js

Lines changed: 71 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,39 @@ describe('Tab', () => {
2121
})
2222

2323
describe('show', () => {
24-
it('should activate element by tab id', done => {
24+
it('should activate element by tab id (using buttons, the preferred semantic way)', done => {
2525
fixtureEl.innerHTML = [
26-
'<ul class="nav">',
26+
'<ul class="nav" role="tablist">',
27+
' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>',
28+
' <li><button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button></li>',
29+
'</ul>',
30+
'<ul>',
31+
' <li id="home" role="tabpanel"></li>',
32+
' <li id="profile" role="tabpanel"></li>',
33+
'</ul>'
34+
].join('')
35+
36+
const profileTriggerEl = fixtureEl.querySelector('#triggerProfile')
37+
const tab = new Tab(profileTriggerEl)
38+
39+
profileTriggerEl.addEventListener('shown.bs.tab', () => {
40+
expect(fixtureEl.querySelector('#profile').classList.contains('active')).toEqual(true)
41+
expect(profileTriggerEl.getAttribute('aria-selected')).toEqual('true')
42+
done()
43+
})
44+
45+
tab.show()
46+
})
47+
48+
it('should activate element by tab id (using links for tabs - not ideal, but still supported)', done => {
49+
fixtureEl.innerHTML = [
50+
'<ul class="nav" role="tablist">',
2751
' <li><a href="#home" role="tab">Home</a></li>',
28-
' <li><a id="triggerProfile" role="tab" href="#profile">Profile</a></li>',
52+
' <li><a id="triggerProfile" href="#profile" role="tab">Profile</a></li>',
2953
'</ul>',
3054
'<ul>',
31-
' <li id="home"></li>',
32-
' <li id="profile"></li>',
55+
' <li id="home" role="tabpanel"></li>',
56+
' <li id="profile" role="tabpanel"></li>',
3357
'</ul>'
3458
].join('')
3559

@@ -48,12 +72,12 @@ describe('Tab', () => {
4872
it('should activate element by tab id in ordered list', done => {
4973
fixtureEl.innerHTML = [
5074
'<ol class="nav nav-pills">',
51-
' <li><a href="#home">Home</a></li>',
52-
' <li><a id="triggerProfile" href="#profile">Profile</a></li>',
75+
' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>',
76+
' <li><button type="button" id="triggerProfile" href="#profile" role="tab">Profile</button></li>',
5377
'</ol>',
5478
'<ol>',
55-
' <li id="home"></li>',
56-
' <li id="profile"></li>',
79+
' <li id="home" role="tabpanel"></li>',
80+
' <li id="profile" role="tabpanel"></li>',
5781
'</ol>'
5882
].join('')
5983

@@ -71,10 +95,10 @@ describe('Tab', () => {
7195
it('should activate element by tab id in nav list', done => {
7296
fixtureEl.innerHTML = [
7397
'<nav class="nav">',
74-
' <a href="#home">Home</a>',
75-
' <a id="triggerProfile" href="#profile">Profile</a>',
98+
' <button type="button" data-bs-target="#home" role="tab">Home</button>',
99+
' <button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</a>',
76100
'</nav>',
77-
'<nav><div id="home"></div><div id="profile"></div></nav>'
101+
'<div><div id="home" role="tabpanel"></div><div id="profile" role="tabpanel"></div></div>'
78102
].join('')
79103

80104
const profileTriggerEl = fixtureEl.querySelector('#triggerProfile')
@@ -90,11 +114,11 @@ describe('Tab', () => {
90114

91115
it('should activate element by tab id in list group', done => {
92116
fixtureEl.innerHTML = [
93-
'<div class="list-group">',
94-
' <a href="#home">Home</a>',
95-
' <a id="triggerProfile" href="#profile">Profile</a>',
117+
'<div class="list-group" role="tablist">',
118+
' <button type="button" data-bs-target="#home" role="tab">Home</button>',
119+
' <button type="button" id="triggerProfile" data-bs-target="#profile" role="tab">Profile</button>',
96120
'</div>',
97-
'<nav><div id="home"></div><div id="profile"></div></nav>'
121+
'<div><div id="home" role="tabpanel"></div><div id="profile" role="tabpanel"></div></div>'
98122
].join('')
99123

100124
const profileTriggerEl = fixtureEl.querySelector('#triggerProfile')
@@ -135,8 +159,8 @@ describe('Tab', () => {
135159
it('should not fire shown when tab is already active', done => {
136160
fixtureEl.innerHTML = [
137161
'<ul class="nav nav-tabs" role="tablist">',
138-
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
139-
' <li class="nav-item" role="presentation"><a href="#profile" class="nav-link" role="tab">Profile</a></li>',
162+
' <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>',
163+
' <li class="nav-item" role="presentation"><button type="button" href="#profile" class="nav-link" role="tab">Profile</button></li>',
140164
'</ul>',
141165
'<div class="tab-content">',
142166
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@@ -161,8 +185,8 @@ describe('Tab', () => {
161185
it('should not fire shown when tab is disabled', done => {
162186
fixtureEl.innerHTML = [
163187
'<ul class="nav nav-tabs" role="tablist">',
164-
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
165-
' <li class="nav-item" role="presentation"><a href="#profile" class="nav-link disabled" role="tab">Profile</a></li>',
188+
' <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>',
189+
' <li class="nav-item" role="presentation"><button type="button" data-bs-target="#profile" class="nav-link disabled" role="tab">Profile</button></li>',
166190
'</ul>',
167191
'<div class="tab-content">',
168192
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@@ -187,8 +211,8 @@ describe('Tab', () => {
187211
it('show and shown events should reference correct relatedTarget', done => {
188212
fixtureEl.innerHTML = [
189213
'<ul class="nav nav-tabs" role="tablist">',
190-
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
191-
' <li class="nav-item" role="presentation"><a id="triggerProfile" href="#profile" class="nav-link" role="tab">Profile</a></li>',
214+
' <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>',
215+
' <li class="nav-item" role="presentation"><button type="button" id="triggerProfile" data-bs-target="#profile" class="nav-link" role="tab">Profile</button></li>',
192216
'</ul>',
193217
'<div class="tab-content">',
194218
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@@ -215,9 +239,9 @@ describe('Tab', () => {
215239

216240
it('should fire hide and hidden events', done => {
217241
fixtureEl.innerHTML = [
218-
'<ul class="nav">',
219-
' <li><a href="#home">Home</a></li>',
220-
' <li><a href="#profile">Profile</a></li>',
242+
'<ul class="nav" role="tablist">',
243+
' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>',
244+
' <li><button type="button" data-bs-target="#profile">Profile</button></li>',
221245
'</ul>'
222246
].join('')
223247

@@ -246,9 +270,9 @@ describe('Tab', () => {
246270

247271
it('should not fire hidden when hide is prevented', done => {
248272
fixtureEl.innerHTML = [
249-
'<ul class="nav">',
250-
' <li><a href="#home">Home</a></li>',
251-
' <li><a href="#profile">Profile</a></li>',
273+
'<ul class="nav" role="tablist">',
274+
' <li><button type="button" data-bs-target="#home" role="tab">Home</button></li>',
275+
' <li><button type="button" data-bs-target="#profile" role="tab">Profile</button></li>',
252276
'</ul>'
253277
].join('')
254278

@@ -282,19 +306,19 @@ describe('Tab', () => {
282306
fixtureEl.innerHTML = [
283307
'<ul class="nav nav-tabs" role="tablist">',
284308
' <li class="nav-item" role="presentation">',
285-
' <a class="nav-link nav-tab" href="#profile" role="tab" data-bs-toggle="tab">',
309+
' <button type="button" class="nav-link nav-tab" data-bs-target="#profile" role="tab" data-bs-toggle="tab">',
286310
' <button class="btn-close" aria-label="Close"></button>',
287-
' </a>',
311+
' </button>',
288312
' </li>',
289313
' <li class="nav-item" role="presentation">',
290-
' <a id="secondNav" class="nav-link nav-tab" href="#buzz" role="tab" data-bs-toggle="tab">',
314+
' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target="#buzz" role="tab" data-bs-toggle="tab">',
291315
' <button class="btn-close" aria-label="Close"></button>',
292-
' </a>',
316+
' </button>',
293317
' </li>',
294318
' <li class="nav-item" role="presentation">',
295-
' <a class="nav-link nav-tab" href="#references" role="tab" data-bs-toggle="tab">',
319+
' <button type="button" class="nav-link nav-tab" data-bs-target="#references" role="tab" data-bs-toggle="tab">',
296320
' <button id="btnClose" class="btn-close" aria-label="Close"></button>',
297-
' </a>',
321+
' </button>',
298322
' </li>',
299323
'</ul>',
300324
'<div class="tab-content">',
@@ -425,8 +449,8 @@ describe('Tab', () => {
425449
it('should create dynamically a tab', done => {
426450
fixtureEl.innerHTML = [
427451
'<ul class="nav nav-tabs" role="tablist">',
428-
' <li class="nav-item" role="presentation"><a href="#home" class="nav-link active" role="tab">Home</a></li>',
429-
' <li class="nav-item" role="presentation"><a id="triggerProfile" data-bs-toggle="tab" href="#profile" class="nav-link" role="tab">Profile</a></li>',
452+
' <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>',
453+
' <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>',
430454
'</ul>',
431455
'<div class="tab-content">',
432456
' <div class="tab-pane active" id="home" role="tabpanel"></div>',
@@ -445,41 +469,18 @@ describe('Tab', () => {
445469
secondTabTrigger.click()
446470
})
447471

448-
it('selected tab should deactivate previous selected link in dropdown', () => {
449-
fixtureEl.innerHTML = [
450-
'<ul class="nav nav-tabs">',
451-
' <li class="nav-item"><a class="nav-link" href="#home" data-bs-toggle="tab">Home</a></li>',
452-
' <li class="nav-item"><a class="nav-link" href="#profile" data-bs-toggle="tab">Profile</a></li>',
453-
' <li class="nav-item dropdown">',
454-
' <a class="nav-link dropdown-toggle active" data-bs-toggle="dropdown" href="#">Dropdown</a>',
455-
' <div class="dropdown-menu">',
456-
' <a class="dropdown-item active" href="#dropdown1" id="dropdown1-tab" data-bs-toggle="tab">@fat</a>',
457-
' <a class="dropdown-item" href="#dropdown2" id="dropdown2-tab" data-bs-toggle="tab">@mdo</a>',
458-
' </div>',
459-
' </li>',
460-
'</ul>'
461-
].join('')
462-
463-
const firstLiLinkEl = fixtureEl.querySelector('li:first-child a')
464-
465-
firstLiLinkEl.click()
466-
expect(firstLiLinkEl.classList.contains('active')).toEqual(true)
467-
expect(fixtureEl.querySelector('li:last-child a').classList.contains('active')).toEqual(false)
468-
expect(fixtureEl.querySelector('li:last-child .dropdown-menu a:first-child').classList.contains('active')).toEqual(false)
469-
})
470-
471472
it('should handle nested tabs', done => {
472473
fixtureEl.innerHTML = [
473474
'<nav class="nav nav-tabs" role="tablist">',
474-
' <a id="tab1" href="#x-tab1" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</a>',
475-
' <a href="#x-tab2" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</a>',
476-
' <a href="#x-tab3" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</a>',
475+
' <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>',
476+
' <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>',
477+
' <button type="button" data-bs-target="#x-tab3" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</button>',
477478
'</nav>',
478479
'<div class="tab-content">',
479480
' <div class="tab-pane" id="x-tab1" role="tabpanel">',
480481
' <nav class="nav nav-tabs" role="tablist">',
481-
' <a href="#nested-tab1" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</a>',
482-
' <a id="tabNested2" href="#nested-tab2" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</a>',
482+
' <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>',
483+
' <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>',
483484
' </nav>',
484485
' <div class="tab-content">',
485486
' <div class="tab-pane active" id="nested-tab1" role="tabpanel">Nested Tab1 Content</div>',
@@ -511,8 +512,8 @@ describe('Tab', () => {
511512
it('should not remove fade class if no active pane is present', done => {
512513
fixtureEl.innerHTML = [
513514
'<ul class="nav nav-tabs" role="tablist">',
514-
' <li class="nav-item" role="presentation"><a id="tab-home" href="#home" class="nav-link" data-bs-toggle="tab" role="tab">Home</a></li>',
515-
' <li class="nav-item" role="presentation"><a id="tab-profile" href="#profile" class="nav-link" data-bs-toggle="tab" role="tab">Profile</a></li>',
515+
' <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>',
516+
' <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>',
516517
'</ul>',
517518
'<div class="tab-content">',
518519
' <div class="tab-pane fade" id="home" role="tabpanel"></div>',
@@ -549,10 +550,10 @@ describe('Tab', () => {
549550
fixtureEl.innerHTML = [
550551
'<ul class="nav nav-tabs" role="tablist">',
551552
' <li class="nav-item" role="presentation">',
552-
' <a class="nav-link nav-tab" href="#home" role="tab" data-bs-toggle="tab">Home</a>',
553+
' <button type="button" class="nav-link nav-tab" data-bs-target="#home" role="tab" data-bs-toggle="tab">Home</button>',
553554
' </li>',
554555
' <li class="nav-item" role="presentation">',
555-
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-bs-toggle="tab">Profile</a>',
556+
' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target="#profile" role="tab" data-bs-toggle="tab">Profile</button>',
556557
' </li>',
557558
'</ul>',
558559
'<div class="tab-content">',
@@ -575,10 +576,10 @@ describe('Tab', () => {
575576
fixtureEl.innerHTML = [
576577
'<ul class="nav nav-tabs" role="tablist">',
577578
' <li class="nav-item" role="presentation">',
578-
' <a class="nav-link nav-tab" href="#home" role="tab" data-bs-toggle="tab">Home</a>',
579+
' <button type="button" class="nav-link nav-tab" data-bs-target="#home" role="tab" data-bs-toggle="tab">Home</button>',
579580
' </li>',
580581
' <li class="nav-item" role="presentation">',
581-
' <a id="secondNav" class="nav-link nav-tab" href="#profile" role="tab" data-bs-toggle="tab">Profile</a>',
582+
' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target="#profile" role="tab" data-bs-toggle="tab">Profile</button>',
582583
' </li>',
583584
'</ul>',
584585
'<div class="tab-content">',

0 commit comments

Comments
 (0)