@@ -21,15 +21,39 @@ describe('Tab', () => {
21
21
} )
22
22
23
23
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 => {
25
25
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">' ,
27
51
' <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>' ,
29
53
'</ul>' ,
30
54
'<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>' ,
33
57
'</ul>'
34
58
] . join ( '' )
35
59
@@ -48,12 +72,12 @@ describe('Tab', () => {
48
72
it ( 'should activate element by tab id in ordered list' , done => {
49
73
fixtureEl . innerHTML = [
50
74
'<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>' ,
53
77
'</ol>' ,
54
78
'<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>' ,
57
81
'</ol>'
58
82
] . join ( '' )
59
83
@@ -71,10 +95,10 @@ describe('Tab', () => {
71
95
it ( 'should activate element by tab id in nav list' , done => {
72
96
fixtureEl . innerHTML = [
73
97
'<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>' ,
76
100
'</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 >'
78
102
] . join ( '' )
79
103
80
104
const profileTriggerEl = fixtureEl . querySelector ( '#triggerProfile' )
@@ -90,11 +114,11 @@ describe('Tab', () => {
90
114
91
115
it ( 'should activate element by tab id in list group' , done => {
92
116
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 >' ,
96
120
'</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 >'
98
122
] . join ( '' )
99
123
100
124
const profileTriggerEl = fixtureEl . querySelector ( '#triggerProfile' )
@@ -135,16 +159,16 @@ describe('Tab', () => {
135
159
it ( 'should not fire shown when tab is already active' , done => {
136
160
fixtureEl . innerHTML = [
137
161
'<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>' ,
140
164
'</ul>' ,
141
165
'<div class="tab-content">' ,
142
166
' <div class="tab-pane active" id="home" role="tabpanel"></div>' ,
143
167
' <div class="tab-pane" id="profile" role="tabpanel"></div>' ,
144
168
'</div>'
145
169
] . join ( '' )
146
170
147
- const triggerActive = fixtureEl . querySelector ( 'a .active' )
171
+ const triggerActive = fixtureEl . querySelector ( 'button .active' )
148
172
const tab = new Tab ( triggerActive )
149
173
150
174
triggerActive . addEventListener ( 'shown.bs.tab' , ( ) => {
@@ -161,16 +185,16 @@ describe('Tab', () => {
161
185
it ( 'should not fire shown when tab is disabled' , done => {
162
186
fixtureEl . innerHTML = [
163
187
'<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>' ,
166
190
'</ul>' ,
167
191
'<div class="tab-content">' ,
168
192
' <div class="tab-pane active" id="home" role="tabpanel"></div>' ,
169
193
' <div class="tab-pane" id="profile" role="tabpanel"></div>' ,
170
194
'</div>'
171
195
] . join ( '' )
172
196
173
- const triggerDisabled = fixtureEl . querySelector ( 'a .disabled' )
197
+ const triggerDisabled = fixtureEl . querySelector ( 'button .disabled' )
174
198
const tab = new Tab ( triggerDisabled )
175
199
176
200
triggerDisabled . addEventListener ( 'shown.bs.tab' , ( ) => {
@@ -187,8 +211,8 @@ describe('Tab', () => {
187
211
it ( 'show and shown events should reference correct relatedTarget' , done => {
188
212
fixtureEl . innerHTML = [
189
213
'<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>' ,
192
216
'</ul>' ,
193
217
'<div class="tab-content">' ,
194
218
' <div class="tab-pane active" id="home" role="tabpanel"></div>' ,
@@ -200,13 +224,13 @@ describe('Tab', () => {
200
224
const secondTab = new Tab ( secondTabTrigger )
201
225
202
226
secondTabTrigger . addEventListener ( 'show.bs.tab' , ev => {
203
- expect ( ev . relatedTarget . hash ) . toEqual ( '#home' )
227
+ expect ( ev . relatedTarget . getAttribute ( 'data-bs-target' ) ) . toEqual ( '#home' )
204
228
} )
205
229
206
230
secondTabTrigger . addEventListener ( 'shown.bs.tab' , ev => {
207
- expect ( ev . relatedTarget . hash ) . toEqual ( '#home' )
231
+ expect ( ev . relatedTarget . getAttribute ( 'data-bs-target' ) ) . toEqual ( '#home' )
208
232
expect ( secondTabTrigger . getAttribute ( 'aria-selected' ) ) . toEqual ( 'true' )
209
- expect ( fixtureEl . querySelector ( 'a :not(.active)' ) . getAttribute ( 'aria-selected' ) ) . toEqual ( 'false' )
233
+ expect ( fixtureEl . querySelector ( 'button :not(.active)' ) . getAttribute ( 'aria-selected' ) ) . toEqual ( 'false' )
210
234
done ( )
211
235
} )
212
236
@@ -215,13 +239,13 @@ describe('Tab', () => {
215
239
216
240
it ( 'should fire hide and hidden events' , done => {
217
241
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>' ,
221
245
'</ul>'
222
246
] . join ( '' )
223
247
224
- const triggerList = fixtureEl . querySelectorAll ( 'a ' )
248
+ const triggerList = fixtureEl . querySelectorAll ( 'button ' )
225
249
const firstTab = new Tab ( triggerList [ 0 ] )
226
250
const secondTab = new Tab ( triggerList [ 1 ] )
227
251
@@ -232,12 +256,12 @@ describe('Tab', () => {
232
256
233
257
triggerList [ 0 ] . addEventListener ( 'hide.bs.tab' , ev => {
234
258
hideCalled = true
235
- expect ( ev . relatedTarget . hash ) . toEqual ( '#profile' )
259
+ expect ( ev . relatedTarget . getAttribute ( 'data-bs-target' ) ) . toEqual ( '#profile' )
236
260
} )
237
261
238
262
triggerList [ 0 ] . addEventListener ( 'hidden.bs.tab' , ev => {
239
263
expect ( hideCalled ) . toEqual ( true )
240
- expect ( ev . relatedTarget . hash ) . toEqual ( '#profile' )
264
+ expect ( ev . relatedTarget . getAttribute ( 'data-bs-target' ) ) . toEqual ( '#profile' )
241
265
done ( )
242
266
} )
243
267
@@ -246,13 +270,13 @@ describe('Tab', () => {
246
270
247
271
it ( 'should not fire hidden when hide is prevented' , done => {
248
272
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>' ,
252
276
'</ul>'
253
277
] . join ( '' )
254
278
255
- const triggerList = fixtureEl . querySelectorAll ( 'a ' )
279
+ const triggerList = fixtureEl . querySelectorAll ( 'button ' )
256
280
const firstTab = new Tab ( triggerList [ 0 ] )
257
281
const secondTab = new Tab ( triggerList [ 1 ] )
258
282
const expectDone = ( ) => {
@@ -423,8 +447,8 @@ describe('Tab', () => {
423
447
it ( 'should create dynamically a tab' , done => {
424
448
fixtureEl . innerHTML = [
425
449
'<ul class="nav nav-tabs" role="tablist">' ,
426
- ' <li class="nav-item" role="presentation"><a href=" #home" class="nav-link active" role="tab">Home</a ></li>' ,
427
- ' <li class="nav-item" role="presentation"><a id="triggerProfile" data-bs-toggle="tab" href ="#profile" class="nav-link" role="tab">Profile</a ></li>' ,
450
+ ' <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>' ,
451
+ ' <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>' ,
428
452
'</ul>' ,
429
453
'<div class="tab-content">' ,
430
454
' <div class="tab-pane active" id="home" role="tabpanel"></div>' ,
@@ -469,15 +493,15 @@ describe('Tab', () => {
469
493
it ( 'should handle nested tabs' , done => {
470
494
fixtureEl . innerHTML = [
471
495
'<nav class="nav nav-tabs" role="tablist">' ,
472
- ' <a id="tab1" href ="#x-tab1" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</a >' ,
473
- ' <a href=" #x-tab2" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</a >' ,
474
- ' <a href=" #x-tab3" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</a >' ,
496
+ ' <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 >' ,
497
+ ' <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 >' ,
498
+ ' <button type="button" data-bs-target=" #x-tab3" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</button >' ,
475
499
'</nav>' ,
476
500
'<div class="tab-content">' ,
477
501
' <div class="tab-pane" id="x-tab1" role="tabpanel">' ,
478
502
' <nav class="nav nav-tabs" role="tablist">' ,
479
- ' <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 >' ,
480
- ' <a id="tabNested2" href ="#nested-tab2" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</a >' ,
503
+ ' <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 >' ,
504
+ ' <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 >' ,
481
505
' </nav>' ,
482
506
' <div class="tab-content">' ,
483
507
' <div class="tab-pane active" id="nested-tab1" role="tabpanel">Nested Tab1 Content</div>' ,
@@ -509,8 +533,8 @@ describe('Tab', () => {
509
533
it ( 'should not remove fade class if no active pane is present' , done => {
510
534
fixtureEl . innerHTML = [
511
535
'<ul class="nav nav-tabs" role="tablist">' ,
512
- ' <li class="nav-item" role="presentation"><a id="tab-home" href ="#home" class="nav-link" data-bs-toggle="tab" role="tab">Home</a ></li>' ,
513
- ' <li class="nav-item" role="presentation"><a id="tab-profile" href ="#profile" class="nav-link" data-bs-toggle="tab" role="tab">Profile</a ></li>' ,
536
+ ' <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>' ,
537
+ ' <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>' ,
514
538
'</ul>' ,
515
539
'<div class="tab-content">' ,
516
540
' <div class="tab-pane fade" id="home" role="tabpanel"></div>' ,
@@ -547,10 +571,10 @@ describe('Tab', () => {
547
571
fixtureEl . innerHTML = [
548
572
'<ul class="nav nav-tabs" role="tablist">' ,
549
573
' <li class="nav-item" role="presentation">' ,
550
- ' <a class="nav-link nav-tab" href ="#home" role="tab" data-bs-toggle="tab">Home</a >' ,
574
+ ' <button type="button" class="nav-link nav-tab" data-bs-target ="#home" role="tab" data-bs-toggle="tab">Home</button >' ,
551
575
' </li>' ,
552
576
' <li class="nav-item" role="presentation">' ,
553
- ' <a id="secondNav" class="nav-link nav-tab" href ="#profile" role="tab" data-bs-toggle="tab">Profile</a >' ,
577
+ ' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target ="#profile" role="tab" data-bs-toggle="tab">Profile</button >' ,
554
578
' </li>' ,
555
579
'</ul>' ,
556
580
'<div class="tab-content">' ,
@@ -573,10 +597,10 @@ describe('Tab', () => {
573
597
fixtureEl . innerHTML = [
574
598
'<ul class="nav nav-tabs" role="tablist">' ,
575
599
' <li class="nav-item" role="presentation">' ,
576
- ' <a class="nav-link nav-tab" href ="#home" role="tab" data-bs-toggle="tab">Home</a >' ,
600
+ ' <button type="button" class="nav-link nav-tab" data-bs-target ="#home" role="tab" data-bs-toggle="tab">Home</button >' ,
577
601
' </li>' ,
578
602
' <li class="nav-item" role="presentation">' ,
579
- ' <a id="secondNav" class="nav-link nav-tab" href ="#profile" role="tab" data-bs-toggle="tab">Profile</a >' ,
603
+ ' <button type="button" id="secondNav" class="nav-link nav-tab" data-bs-target ="#profile" role="tab" data-bs-toggle="tab">Profile</button >' ,
580
604
' </li>' ,
581
605
'</ul>' ,
582
606
'<div class="tab-content">' ,
0 commit comments