dropdown.js 24 KB
Newer Older
1
$(function () {
2
  'use strict'
3

4
  QUnit.module('dropdowns plugin')
XhmikosR's avatar
XhmikosR committed
5

6
  QUnit.test('should be defined on jquery object', function (assert) {
7
    assert.expect(1)
8
    assert.ok($(document.body).dropdown, 'dropdown method is defined')
XhmikosR's avatar
XhmikosR committed
9
10
  })

11
  QUnit.module('dropdowns', {
12
    beforeEach: function () {
13
14
15
      // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
      $.fn.bootstrapDropdown = $.fn.dropdown.noConflict()
    },
16
    afterEach: function () {
17
18
19
20
21
      $.fn.dropdown = $.fn.bootstrapDropdown
      delete $.fn.bootstrapDropdown
    }
  })

22
  QUnit.test('should provide no conflict', function (assert) {
23
    assert.expect(1)
XhmikosR's avatar
XhmikosR committed
24
    assert.strictEqual(typeof $.fn.dropdown, 'undefined', 'dropdown was set back to undefined (org value)')
25
26
  })

27
28
29
30
31
32
33
34
35
36
37
38
  QUnit.test('should throw explicit error on undefined method', function (assert) {
    assert.expect(1)
    var $el = $('<div/>')
    $el.bootstrapDropdown()
    try {
      $el.bootstrapDropdown('noMethod')
    }
    catch (err) {
      assert.strictEqual(err.message, 'No method named "noMethod"')
    }
  })

39
  QUnit.test('should return jquery collection containing the element', function (assert) {
40
    assert.expect(2)
41
42
    var $el = $('<div/>')
    var $dropdown = $el.bootstrapDropdown()
43
44
    assert.ok($dropdown instanceof $, 'returns jquery collection')
    assert.strictEqual($dropdown[0], $el[0], 'collection contains element')
XhmikosR's avatar
XhmikosR committed
45
46
  })

47
  QUnit.test('should not open dropdown if target is disabled via attribute', function (assert) {
Johann-S's avatar
Johann-S committed
48
49
    assert.expect(1)
    var done = assert.async()
50
51
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
52
        + '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>'
53
54
55
56
57
58
59
60
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
Johann-S's avatar
Johann-S committed
61
62
63
64
65
66
67
    $(dropdownHTML).appendTo('#qunit-fixture')
    var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
    $dropdown.on('click', function () {
      assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
      done()
    })
    $dropdown.trigger($.Event('click'))
XhmikosR's avatar
XhmikosR committed
68
69
  })

70
  QUnit.test('should set aria-expanded="true" on target when dropdown menu is shown', function (assert) {
71
    assert.expect(1)
72
    var done = assert.async()
73
74
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
75
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">Dropdown</a>'
76
77
78
79
80
81
82
83
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
Johann-S's avatar
Johann-S committed
84
85
86
87
    var $dropdown = $(dropdownHTML)
          .appendTo('#qunit-fixture')
          .find('[data-toggle="dropdown"]')
          .bootstrapDropdown()
88
89
90
91
92
93
94
    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.strictEqual($dropdown.attr('aria-expanded'), 'true', 'aria-expanded is set to string "true" on click')
        done()
      })
    $dropdown.trigger('click')
95
96
97
  })

  QUnit.test('should set aria-expanded="false" on target when dropdown menu is hidden', function (assert) {
98
    assert.expect(1)
99
    var done = assert.async()
100
101
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
102
        + '<a href="#" class="dropdown-toggle" aria-expanded="false" data-toggle="dropdown">Dropdown</a>'
103
104
105
106
107
108
109
110
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
111
112
113
114
115
116
117
118
119
120
121
122
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

    $dropdown
      .parent('.dropdown')
      .on('hidden.bs.dropdown', function () {
        assert.strictEqual($dropdown.attr('aria-expanded'), 'false', 'aria-expanded is set to string "false" on hide')
        done()
      })

123
124
    $dropdown.trigger('click')
    $(document.body).trigger('click')
125
126
  })

127
  QUnit.test('should not open dropdown if target is disabled via class', function (assert) {
Johann-S's avatar
Johann-S committed
128
129
    assert.expect(1)
    var done = assert.async()
130
131
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
132
        + '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>'
133
134
135
136
137
138
139
140
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
Johann-S's avatar
Johann-S committed
141
142
143
144
145
146
147
148

    $(dropdownHTML).appendTo('#qunit-fixture')
    var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
    $dropdown.on('click', function () {
      assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
      done()
    })
    $dropdown.trigger($.Event('click'))
XhmikosR's avatar
XhmikosR committed
149
150
  })

Starsam80's avatar
Starsam80 committed
151
  QUnit.test('should add class show to menu if clicked', function (assert) {
152
    assert.expect(1)
153
    var done = assert.async()
154
155
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
156
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
157
158
159
160
161
162
163
164
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
165
166
167
168
169
170
171
172
    var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown()
    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
        done()
      })
    $dropdown.trigger('click')
XhmikosR's avatar
XhmikosR committed
173
174
  })

175
  QUnit.test('should test if element has a # before assuming it\'s a selector', function (assert) {
176
    assert.expect(1)
177
    var done = assert.async()
178
179
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
180
        + '<a href="/foo/" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
181
182
183
184
185
186
187
188
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
189
190
191
192
193
194
195
196
    var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown()
    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
        done()
      })
    $dropdown.trigger('click')
XhmikosR's avatar
XhmikosR committed
197
198
199
  })


Starsam80's avatar
Starsam80 committed
200
  QUnit.test('should remove "show" class if body is clicked', function (assert) {
201
    assert.expect(2)
202
    var done = assert.async()
203
204
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
205
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
206
207
208
209
210
211
212
213
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
214
215
216
217
218
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

219
220
221
222
223
224
225
226
227
228
    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
        $(document.body).trigger('click')
      }).on('hidden.bs.dropdown', function () {
        assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
        done()
      })
    $dropdown.trigger('click')
XhmikosR's avatar
XhmikosR committed
229
230
  })

Pierre-Denis Vanduynslager's avatar
Pierre-Denis Vanduynslager committed
231
  QUnit.test('should remove "show" class if tabbing outside of menu', function (assert) {
232
    assert.expect(2)
233
    var done = assert.async()
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="dropdown-divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
    var $dropdown = $(dropdownHTML)
       .appendTo('#qunit-fixture')
       .find('[data-toggle="dropdown"]')
       .bootstrapDropdown()
249
250
251
252
    $dropdown
     .parent('.dropdown')
     .on('shown.bs.dropdown', function () {
       assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
Pierre-Denis Vanduynslager's avatar
Pierre-Denis Vanduynslager committed
253
254
255
       var e = $.Event('keyup')
       e.which = 9 // Tab
       $(document.body).trigger(e)
256
257
258
259
260
     }).on('hidden.bs.dropdown', function () {
       assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
       done()
     })
    $dropdown.trigger('click')
261
262
  })

Starsam80's avatar
Starsam80 committed
263
  QUnit.test('should remove "show" class if body is clicked, with multiple dropdowns', function (assert) {
264
    assert.expect(7)
265
    var done = assert.async()
266
267
    var dropdownHTML = '<div class="nav">'
        + '<div class="dropdown" id="testmenu">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
268
        + '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>'
269
270
271
272
273
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#sub1">Submenu 1</a>'
        + '</div>'
        + '</div>'
        + '</div>'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
274
275
        + '<div class="btn-group">'
        + '<button class="btn">Actions</button>'
276
        + '<button class="btn dropdown-toggle" data-toggle="dropdown"></button>'
277
278
279
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Action 1</a>'
        + '</div>'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
280
        + '</div>'
281
282
283
    var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
    var $first = $dropdowns.first()
    var $last = $dropdowns.last()
XhmikosR's avatar
XhmikosR committed
284

285
    assert.strictEqual($dropdowns.length, 2, 'two dropdowns')
XhmikosR's avatar
XhmikosR committed
286

287
288
289
    $first.parent('.dropdown')
    .on('shown.bs.dropdown', function () {
      assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
290
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
291
292
      $(document.body).trigger('click')
    }).on('hidden.bs.dropdown', function () {
293
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
294
295
296
297
298
299
      $last.trigger('click')
    })

    $last.parent('.btn-group')
    .on('shown.bs.dropdown', function () {
      assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
300
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
301
302
      $(document.body).trigger('click')
    }).on('hidden.bs.dropdown', function () {
303
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
304
305
      done()
    })
306
    $first.trigger('click')
XhmikosR's avatar
XhmikosR committed
307
308
  })

Pierre-Denis Vanduynslager's avatar
Pierre-Denis Vanduynslager committed
309
  QUnit.test('should remove "show" class if body if tabbing outside of menu, with multiple dropdowns', function (assert) {
310
    assert.expect(7)
311
    var done = assert.async()
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
    var dropdownHTML = '<div class="nav">'
        + '<div class="dropdown" id="testmenu">'
        + '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>'
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#sub1">Submenu 1</a>'
        + '</div>'
        + '</div>'
        + '</div>'
        + '<div class="btn-group">'
        + '<button class="btn">Actions</button>'
        + '<button class="btn dropdown-toggle" data-toggle="dropdown"><span class="caret"/></button>'
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Action 1</a>'
        + '</div>'
        + '</div>'
    var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
    var $first = $dropdowns.first()
    var $last = $dropdowns.last()

    assert.strictEqual($dropdowns.length, 2, 'two dropdowns')

333
334
335
    $first.parent('.dropdown')
    .on('shown.bs.dropdown', function () {
      assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
336
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
Pierre-Denis Vanduynslager's avatar
Pierre-Denis Vanduynslager committed
337
338
339
      var e = $.Event('keyup')
      e.which = 9 // Tab
      $(document.body).trigger(e)
340
    }).on('hidden.bs.dropdown', function () {
341
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
342
343
344
345
346
347
      $last.trigger('click')
    })

    $last.parent('.btn-group')
    .on('shown.bs.dropdown', function () {
      assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
348
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
Pierre-Denis Vanduynslager's avatar
Pierre-Denis Vanduynslager committed
349
350
351
      var e = $.Event('keyup')
      e.which = 9 // Tab
      $(document.body).trigger(e)
352
    }).on('hidden.bs.dropdown', function () {
353
      assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
354
355
      done()
    })
356
357
358
    $first.trigger('click')
  })

359
  QUnit.test('should fire show and hide event', function (assert) {
360
    assert.expect(2)
361
362
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
363
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
364
365
366
367
368
369
370
371
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
372
373
374
375
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()
XhmikosR's avatar
XhmikosR committed
376

377
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
378

379
    $dropdown
XhmikosR's avatar
XhmikosR committed
380
      .parent('.dropdown')
381
      .on('show.bs.dropdown', function () {
382
        assert.ok(true, 'show was fired')
383
      })
384
      .on('hide.bs.dropdown', function () {
385
        assert.ok(true, 'hide was fired')
386
        done()
387
388
      })

389
390
    $dropdown.trigger('click')
    $(document.body).trigger('click')
XhmikosR's avatar
XhmikosR committed
391
392
393
  })


394
  QUnit.test('should fire shown and hidden event', function (assert) {
395
    assert.expect(2)
396
397
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
Heinrich Fenkart's avatar
Heinrich Fenkart committed
398
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
399
400
401
402
403
404
405
406
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
407
408
409
410
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()
XhmikosR's avatar
XhmikosR committed
411

412
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
413

414
    $dropdown
XhmikosR's avatar
XhmikosR committed
415
      .parent('.dropdown')
416
      .on('shown.bs.dropdown', function () {
417
        assert.ok(true, 'shown was fired')
418
      })
419
      .on('hidden.bs.dropdown', function () {
420
        assert.ok(true, 'hidden was fired')
421
        done()
422
423
      })

424
425
    $dropdown.trigger('click')
    $(document.body).trigger('click')
XhmikosR's avatar
XhmikosR committed
426
  })
427

428
429
  QUnit.test('should fire shown and hidden event with a relatedTarget', function (assert) {
    assert.expect(2)
430
431
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
432
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
433
434
435
436
437
438
439
440
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()
    var done = assert.async()

    $dropdown.parent('.dropdown')
      .on('hidden.bs.dropdown', function (e) {
        assert.strictEqual(e.relatedTarget, $dropdown[0])
        done()
      })
      .on('shown.bs.dropdown', function (e) {
        assert.strictEqual(e.relatedTarget, $dropdown[0])
        $(document.body).trigger('click')
      })

    $dropdown.trigger('click')
  })

460
  QUnit.test('should ignore keyboard events within <input>s and <textarea>s', function (assert) {
461
    assert.expect(3)
462
    var done = assert.async()
463

464
465
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
466
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
467
468
469
470
471
472
473
474
475
476
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item" href="#">Secondary link</a>'
        + '<a class="dropdown-item" href="#">Something else here</a>'
        + '<div class="divider"/>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '<input type="text" id="input">'
        + '<textarea id="textarea"/>'
        + '</div>'
        + '</div>'
        + '</div>'
477
478
479
480
481
482
483
484
485
486
487
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

    var $input = $('#input')
    var $textarea = $('#textarea')

    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
488
        assert.ok(true, 'shown was fired')
489

490
        $input.trigger('focus').trigger($.Event('keydown', { which: 38 }))
491
        assert.ok($(document.activeElement).is($input), 'input still focused')
492

493
        $textarea.trigger('focus').trigger($.Event('keydown', { which: 38 }))
494
        assert.ok($(document.activeElement).is($textarea), 'textarea still focused')
495

496
        done()
497
498
      })

499
    $dropdown.trigger('click')
500
501
  })

502
  QUnit.test('should skip disabled element when using keyboard navigation', function (assert) {
503
504
    assert.expect(2)
    var done = assert.async()
505
506
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
507
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
508
509
510
511
512
513
        + '<div class="dropdown-menu">'
        + '<a class="dropdown-item disabled" href="#">Disabled link</a>'
        + '<a class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
514
515
516
517
518
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

519
520
521
522
523
524
525
526
527
528
    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok(true, 'shown was fired')
        $dropdown.trigger($.Event('keydown', { which: 40 }))
        $dropdown.trigger($.Event('keydown', { which: 40 }))
        assert.ok(!$(document.activeElement).is('.disabled'), '.disabled is not focused')
        done()
      })
    $dropdown.trigger('click')
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  })

  QUnit.test('should focus next/previous element when using keyboard navigation', function (assert) {
    assert.expect(4)
    var done = assert.async()
    var dropdownHTML = '<div class="tabs">'
        + '<div class="dropdown">'
        + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
        + '<div class="dropdown-menu">'
        + '<a id="item1" class="dropdown-item" href="#">A link</a>'
        + '<a id="item2" class="dropdown-item" href="#">Another link</a>'
        + '</div>'
        + '</div>'
        + '</div>'
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok(true, 'shown was fired')
        $dropdown.trigger($.Event('keydown', { which: 40 }))
553
        assert.ok($(document.activeElement).is($('#item1')), 'item1 is focused')
554
555

        $(document.activeElement).trigger($.Event('keydown', { which: 40 }))
556
        assert.ok($(document.activeElement).is($('#item2')), 'item2 is focused')
557
558

        $(document.activeElement).trigger($.Event('keydown', { which: 38 }))
559
        assert.ok($(document.activeElement).is($('#item1')), 'item1 is focused')
560
561
562
        done()
      })
    $dropdown.trigger('click')
563
564

  })
565
566

  QUnit.test('should not close the dropdown if the user clicks on a text field', function (assert) {
567
    assert.expect(2)
568
569
    var done = assert.async()
    var dropdownHTML = '<div class="dropdown">'
570
        + '<button type="button" data-toggle="dropdown">Dropdown</button>'
571
572
573
        + '<div class="dropdown-menu">'
        + '<input id="textField" type="text" />'
        + '</div>'
574
575
576
577
578
579
        + '</div>'
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

580
581
582
583
584
585
    var $textfield = $('#textField')
    $textfield.on('click', function () {
      assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
      done()
    })

586
587
588
589
    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
590
        $textfield.trigger($.Event('click'))
591
592
      })
    $dropdown.trigger('click')
593
594
595
  })

  QUnit.test('should not close the dropdown if the user clicks on a textarea', function (assert) {
596
    assert.expect(2)
597
598
    var done = assert.async()
    var dropdownHTML = '<div class="dropdown">'
599
        + '<button type="button" data-toggle="dropdown">Dropdown</button>'
600
601
602
        + '<div class="dropdown-menu">'
        + '<textarea id="textArea"></textarea>'
        + '</div>'
603
604
605
606
607
608
        + '</div>'
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

609
610
611
612
613
614
    var $textarea = $('#textArea')
    $textarea.on('click', function () {
      assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
      done()
    })

615
616
617
618
    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
619
        $textarea.trigger($.Event('click'))
620
621
      })
    $dropdown.trigger('click')
622
  })
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

  QUnit.test('Dropdown should not use Popper.js in navbar', function (assert) {
    assert.expect(1)
    var done = assert.async()
    var html = '<nav class="navbar navbar-expand-md navbar-light bg-light">'
        + '<div class="dropdown">'
        + '  <a class="nav-link dropdown-toggle" href="#" id="dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>'
        + '  <div class="dropdown-menu" aria-labelledby="dropdown">'
        + '    <a class="dropdown-item" href="#">Action</a>'
        + '    <a class="dropdown-item" href="#">Another action</a>'
        + '    <a class="dropdown-item" href="#">Something else here</a>'
        + '  </div>'
        + '</div>'
        + '</nav>'

    $(html).appendTo('#qunit-fixture')
    var $triggerDropdown = $('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()
    var $dropdownMenu = $triggerDropdown.next()

    $triggerDropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
XhmikosR's avatar
XhmikosR committed
647
        assert.ok(typeof $dropdownMenu.attr('style') === 'undefined', 'No inline style applied by Popper.js')
648
649
650
651
        done()
      })
    $triggerDropdown.trigger($.Event('click'))
  })
652
})