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

4
5
  var Collapse = typeof window.bootstrap !== 'undefined' ? window.bootstrap.Collapse : window.Collapse

6
  QUnit.module('collapse plugin')
XhmikosR's avatar
XhmikosR committed
7

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

13
  QUnit.module('collapse', {
14
    beforeEach: function () {
15
16
17
      // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
      $.fn.bootstrapCollapse = $.fn.collapse.noConflict()
    },
18
    afterEach: function () {
19
20
      $.fn.collapse = $.fn.bootstrapCollapse
      delete $.fn.bootstrapCollapse
21
      $('#qunit-fixture').html('')
22
23
24
    }
  })

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

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

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

49
  QUnit.test('should show a collapsed element', function (assert) {
50
    assert.expect(2)
51
52
    var done = assert.async()
    var $el = $('<div class="collapse"/>')
53

54
55
56
57
58
    $el.one('shown.bs.collapse', function () {
      assert.ok($el.hasClass('show'), 'has class "show"')
      assert.ok(!/height/i.test($el.attr('style')), 'has height reset')
      done()
    }).bootstrapCollapse('show')
XhmikosR's avatar
XhmikosR committed
59
60
  })

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  QUnit.test('should show multiple collapsed elements', function (assert) {
    assert.expect(4)
    var done = assert.async()
    var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href=".multi"/>').appendTo('#qunit-fixture')
    var $el = $('<div class="collapse multi"/>').appendTo('#qunit-fixture')
    var $el2 = $('<div class="collapse multi"/>').appendTo('#qunit-fixture')
    $el.one('shown.bs.collapse', function () {
      assert.ok($el.hasClass('show'), 'has class "show"')
      assert.ok(!/height/i.test($el.attr('style')), 'has height reset')
    })
    $el2.one('shown.bs.collapse', function () {
      assert.ok($el2.hasClass('show'), 'has class "show"')
      assert.ok(!/height/i.test($el2.attr('style')), 'has height reset')
      done()
    })
76
    $target[0].click()
77
78
  })

79
80
  QUnit.test('should collapse only the first collapse', function (assert) {
    assert.expect(2)
81
    var done = assert.async()
82
83
    var html = [
      '<div class="panel-group" id="accordion1">',
84
85
86
      '<div class="panel">',
      '<div id="collapse1" class="collapse"/>',
      '</div>',
87
88
      '</div>',
      '<div class="panel-group" id="accordion2">',
89
      '<div class="panel">',
Starsam80's avatar
Starsam80 committed
90
      '<div id="collapse2" class="collapse show"/>',
91
      '</div>',
92
93
94
95
96
      '</div>'
    ].join('')
    $(html).appendTo('#qunit-fixture')
    var $el1 = $('#collapse1')
    var $el2 = $('#collapse2')
97
98
99
100
101
    $el1.one('shown.bs.collapse', function () {
      assert.ok($el1.hasClass('show'))
      assert.ok($el2.hasClass('show'))
      done()
    }).bootstrapCollapse('show')
102
103
  })

104
  QUnit.test('should hide a collapsed element', function (assert) {
105
    assert.expect(1)
106
107
    var $el = $('<div class="collapse"/>').bootstrapCollapse('hide')

Starsam80's avatar
Starsam80 committed
108
    assert.ok(!$el.hasClass('show'), 'does not have class "show"')
XhmikosR's avatar
XhmikosR committed
109
110
  })

111
  QUnit.test('should not fire shown when show is prevented', function (assert) {
112
    assert.expect(1)
113
    var done = assert.async()
114

XhmikosR's avatar
XhmikosR committed
115
116
    $('<div class="collapse"/>')
      .on('show.bs.collapse', function (e) {
117
        e.preventDefault()
118
        assert.ok(true, 'show event fired')
119
        done()
120
      })
XhmikosR's avatar
XhmikosR committed
121
      .on('shown.bs.collapse', function () {
122
        assert.ok(false, 'shown event fired')
123
      })
124
      .bootstrapCollapse('show')
XhmikosR's avatar
XhmikosR committed
125
126
  })

127
  QUnit.test('should reset style to auto after finishing opening collapse', function (assert) {
128
    assert.expect(2)
129
    var done = assert.async()
130

XhmikosR's avatar
XhmikosR committed
131
132
    $('<div class="collapse" style="height: 0px"/>')
      .on('show.bs.collapse', function () {
133
        assert.strictEqual(this.style.height, '0px', 'height is 0px')
134
      })
XhmikosR's avatar
XhmikosR committed
135
      .on('shown.bs.collapse', function () {
136
        assert.strictEqual(this.style.height, '', 'height is auto')
137
        done()
138
      })
139
      .bootstrapCollapse('show')
XhmikosR's avatar
XhmikosR committed
140
  })
141

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  QUnit.test('should reset style to auto after finishing closing collapse', function (assert) {
    assert.expect(1)
    var done = assert.async()

    $('<div class="collapse"/>')
      .on('shown.bs.collapse', function () {
        $(this).bootstrapCollapse('hide')
      })
      .on('hidden.bs.collapse', function () {
        assert.strictEqual(this.style.height, '', 'height is auto')
        done()
      })
      .bootstrapCollapse('show')
  })

157
  QUnit.test('should remove "collapsed" class from target when collapse is shown', function (assert) {
158
    assert.expect(1)
159
    var done = assert.async()
160

161
    var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture')
162

163
164
    $('<div id="test1"/>')
      .appendTo('#qunit-fixture')
165
      .on('shown.bs.collapse', function () {
166
        assert.ok(!$target.hasClass('collapsed'), 'target does not have collapsed class')
167
        done()
168
169
      })

170
    $target[0].dispatchEvent(new Event('click'))
XhmikosR's avatar
XhmikosR committed
171
  })
172

173
  QUnit.test('should add "collapsed" class to target when collapse is hidden', function (assert) {
174
    assert.expect(1)
175
    var done = assert.async()
176

177
    var $target = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
178

Starsam80's avatar
Starsam80 committed
179
    $('<div id="test1" class="show"/>')
180
      .appendTo('#qunit-fixture')
181
      .on('hidden.bs.collapse', function () {
182
        assert.ok($target.hasClass('collapsed'), 'target has collapsed class')
183
        done()
184
185
      })

186
    $target[0].dispatchEvent(new Event('click'))
XhmikosR's avatar
XhmikosR committed
187
  })
188

189
  QUnit.test('should remove "collapsed" class from all triggers targeting the collapse when the collapse is shown', function (assert) {
190
    assert.expect(2)
191
    var done = assert.async()
192

193
194
    var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture')
    var $alt = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture')
195
196
197
198
199
200
201
202
203

    $('<div id="test1"/>')
      .appendTo('#qunit-fixture')
      .on('shown.bs.collapse', function () {
        assert.ok(!$target.hasClass('collapsed'), 'target trigger does not have collapsed class')
        assert.ok(!$alt.hasClass('collapsed'), 'alt trigger does not have collapsed class')
        done()
      })

204
    $target[0].dispatchEvent(new Event('click'))
205
206
207
  })

  QUnit.test('should add "collapsed" class to all triggers targeting the collapse when the collapse is hidden', function (assert) {
208
    assert.expect(2)
209
210
    var done = assert.async()

211
212
    var $target = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
    var $alt = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
213

Starsam80's avatar
Starsam80 committed
214
    $('<div id="test1" class="show"/>')
215
216
217
218
      .appendTo('#qunit-fixture')
      .on('hidden.bs.collapse', function () {
        assert.ok($target.hasClass('collapsed'), 'target has collapsed class')
        assert.ok($alt.hasClass('collapsed'), 'alt trigger has collapsed class')
219
        done()
220
221
      })

222
    $target[0].dispatchEvent(new Event('click'))
XhmikosR's avatar
XhmikosR committed
223
  })
224

225
  QUnit.test('should not close a collapse when initialized with "show" option if already shown', function (assert) {
226
    assert.expect(0)
227
    var done = assert.async()
228

Starsam80's avatar
Starsam80 committed
229
    var $test = $('<div id="test1" class="show"/>')
230
231
      .appendTo('#qunit-fixture')
      .on('hide.bs.collapse', function () {
232
        assert.ok(false)
233
234
235
236
      })

    $test.bootstrapCollapse('show')

237
    setTimeout(done, 0)
238
239
  })

240
  QUnit.test('should open a collapse when initialized with "show" option if not already shown', function (assert) {
241
    assert.expect(1)
242
    var done = assert.async()
243
244
245
246

    var $test = $('<div id="test1" />')
      .appendTo('#qunit-fixture')
      .on('show.bs.collapse', function () {
247
        assert.ok(true)
248
249
250
251
      })

    $test.bootstrapCollapse('show')

252
    setTimeout(done, 0)
253
254
  })

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
  QUnit.test('should not show a collapse when initialized with "hide" option if already hidden', function (assert) {
    assert.expect(0)
    var done = assert.async()

    $('<div class="collapse"></div>')
      .appendTo('#qunit-fixture')
      .on('show.bs.collapse', function () {
        assert.ok(false, 'showing a previously-uninitialized hidden collapse when the "hide" method is called')
      })
      .bootstrapCollapse('hide')

    setTimeout(done, 0)
  })

  QUnit.test('should hide a collapse when initialized with "hide" option if not already hidden', function (assert) {
    assert.expect(1)
    var done = assert.async()

Starsam80's avatar
Starsam80 committed
273
    $('<div class="collapse show"></div>')
274
275
276
277
278
279
280
281
282
      .appendTo('#qunit-fixture')
      .on('hide.bs.collapse', function () {
        assert.ok(true, 'hiding a previously-uninitialized shown collapse when the "hide" method is called')
      })
      .bootstrapCollapse('hide')

    setTimeout(done, 0)
  })

283
  QUnit.test('should remove "collapsed" class from active accordion target', function (assert) {
284
    assert.expect(3)
285
    var done = assert.async()
286

XhmikosR's avatar
XhmikosR committed
287
288
289
290
291
    var accordionHTML = '<div id="accordion">' +
        '<div class="card"/>' +
        '<div class="card"/>' +
        '<div class="card"/>' +
        '</div>'
Johann-S's avatar
Johann-S committed
292
    var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
293

294
    var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" />').appendTo($groups.eq(0))
295

296
    $('<div id="body1" class="show" data-parent="#accordion"/>').appendTo($groups.eq(0))
297

298
    var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2" />').appendTo($groups.eq(1))
299

300
    $('<div id="body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
301

302
    var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" />').appendTo($groups.eq(2))
303

304
    $('<div id="body3" data-parent="#accordion"/>')
305
      .appendTo($groups.eq(2))
306
      .on('shown.bs.collapse', function () {
307
308
309
        assert.ok($target1.hasClass('collapsed'), 'inactive target 1 does have class "collapsed"')
        assert.ok($target2.hasClass('collapsed'), 'inactive target 2 does have class "collapsed"')
        assert.ok(!$target3.hasClass('collapsed'), 'active target 3 does not have class "collapsed"')
310

311
        done()
312
313
      })

314
    $target3[0].dispatchEvent(new Event('click'))
XhmikosR's avatar
XhmikosR committed
315
  })
316

317
  QUnit.test('should allow dots in data-parent', function (assert) {
318
    assert.expect(3)
319
    var done = assert.async()
320

XhmikosR's avatar
XhmikosR committed
321
322
323
324
325
    var accordionHTML = '<div class="accordion">' +
        '<div class="card"/>' +
        '<div class="card"/>' +
        '<div class="card"/>' +
        '</div>'
Johann-S's avatar
Johann-S committed
326
    var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
327

328
    var $target1 = $('<a role="button" data-toggle="collapse" href="#body1"/>').appendTo($groups.eq(0))
329

330
    $('<div id="body1" class="show" data-parent=".accordion"/>').appendTo($groups.eq(0))
331

332
    var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2"/>').appendTo($groups.eq(1))
333

334
    $('<div id="body2" data-parent=".accordion"/>').appendTo($groups.eq(1))
335

336
    var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3"/>').appendTo($groups.eq(2))
337

338
    $('<div id="body3" data-parent=".accordion"/>')
339
      .appendTo($groups.eq(2))
340
      .on('shown.bs.collapse', function () {
341
342
343
        assert.ok($target1.hasClass('collapsed'), 'inactive target 1 does have class "collapsed"')
        assert.ok($target2.hasClass('collapsed'), 'inactive target 2 does have class "collapsed"')
        assert.ok(!$target3.hasClass('collapsed'), 'active target 3 does not have class "collapsed"')
344

345
        done()
346
347
      })

348
    $target3[0].dispatchEvent(new Event('click'))
XhmikosR's avatar
XhmikosR committed
349
350
  })

351
  QUnit.test('should set aria-expanded="true" on trigger/control when collapse is shown', function (assert) {
352
    assert.expect(1)
353
    var done = assert.async()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
354

355
    var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1" aria-expanded="false"/>').appendTo('#qunit-fixture')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
356
357
358

    $('<div id="test1"/>')
      .appendTo('#qunit-fixture')
359
      .on('shown.bs.collapse', function () {
360
        assert.strictEqual($target.attr('aria-expanded'), 'true', 'aria-expanded on target is "true"')
361
        done()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
362
363
      })

364
    $target[0].dispatchEvent(new Event('click'))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
365
366
  })

367
  QUnit.test('should set aria-expanded="false" on trigger/control when collapse is hidden', function (assert) {
368
    assert.expect(1)
369
    var done = assert.async()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
370

371
    var $target = $('<a role="button" data-toggle="collapse" href="#test1" aria-expanded="true"/>').appendTo('#qunit-fixture')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
372

Starsam80's avatar
Starsam80 committed
373
    $('<div id="test1" class="show"/>')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
374
      .appendTo('#qunit-fixture')
375
      .on('hidden.bs.collapse', function () {
376
        assert.strictEqual($target.attr('aria-expanded'), 'false', 'aria-expanded on target is "false"')
377
        done()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
378
379
      })

380
    $target[0].dispatchEvent(new Event('click'))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
381
382
  })

383
  QUnit.test('should set aria-expanded="true" on all triggers targeting the collapse when the collapse is shown', function (assert) {
384
    assert.expect(2)
385
    var done = assert.async()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
386

387
388
    var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1" aria-expanded="false"/>').appendTo('#qunit-fixture')
    var $alt = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1" aria-expanded="false"/>').appendTo('#qunit-fixture')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
389
390
391

    $('<div id="test1"/>')
      .appendTo('#qunit-fixture')
392
      .on('shown.bs.collapse', function () {
393
394
        assert.strictEqual($target.attr('aria-expanded'), 'true', 'aria-expanded on trigger/control is "true"')
        assert.strictEqual($alt.attr('aria-expanded'), 'true', 'aria-expanded on alternative trigger/control is "true"')
395
        done()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
396
397
      })

398
    $target[0].dispatchEvent(new Event('click'))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
399
400
  })

401
  QUnit.test('should set aria-expanded="false" on all triggers targeting the collapse when the collapse is hidden', function (assert) {
402
    assert.expect(2)
403
    var done = assert.async()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
404

405
406
    var $target = $('<a role="button" data-toggle="collapse" href="#test1" aria-expanded="true"/>').appendTo('#qunit-fixture')
    var $alt = $('<a role="button" data-toggle="collapse" href="#test1" aria-expanded="true"/>').appendTo('#qunit-fixture')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
407

Starsam80's avatar
Starsam80 committed
408
    $('<div id="test1" class="show"/>')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
409
      .appendTo('#qunit-fixture')
410
      .on('hidden.bs.collapse', function () {
411
412
        assert.strictEqual($target.attr('aria-expanded'), 'false', 'aria-expanded on trigger/control is "false"')
        assert.strictEqual($alt.attr('aria-expanded'), 'false', 'aria-expanded on alternative trigger/control is "false"')
413
        done()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
414
415
      })

416
    $target[0].dispatchEvent(new Event('click'))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
417
418
  })

419
  QUnit.test('should change aria-expanded from active accordion trigger/control to "false" and set the trigger/control for the newly active one to "true"', function (assert) {
420
    assert.expect(3)
421
    var done = assert.async()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
422

XhmikosR's avatar
XhmikosR committed
423
424
425
426
427
    var accordionHTML = '<div id="accordion">' +
        '<div class="card"/>' +
        '<div class="card"/>' +
        '<div class="card"/>' +
        '</div>'
Johann-S's avatar
Johann-S committed
428
    var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
429

430
    var $target1 = $('<a role="button" data-toggle="collapse" aria-expanded="true" href="#body1"/>').appendTo($groups.eq(0))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
431

432
    $('<div id="body1" class="show" data-parent="#accordion"/>').appendTo($groups.eq(0))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
433

434
    var $target2 = $('<a role="button" data-toggle="collapse" aria-expanded="false" href="#body2" class="collapsed" aria-expanded="false" />').appendTo($groups.eq(1))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
435

436
    $('<div id="body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
437

438
    var $target3 = $('<a class="collapsed" data-toggle="collapse" aria-expanded="false" role="button" href="#body3"/>').appendTo($groups.eq(2))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
439

440
    $('<div id="body3" data-parent="#accordion"/>')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
441
      .appendTo($groups.eq(2))
442
      .on('shown.bs.collapse', function () {
443
444
445
        assert.strictEqual($target1.attr('aria-expanded'), 'false', 'inactive trigger/control 1 has aria-expanded="false"')
        assert.strictEqual($target2.attr('aria-expanded'), 'false', 'inactive trigger/control 2 has aria-expanded="false"')
        assert.strictEqual($target3.attr('aria-expanded'), 'true', 'active trigger/control 3 has aria-expanded="true"')
Patrick H. Lauke's avatar
Patrick H. Lauke committed
446

447
        done()
Patrick H. Lauke's avatar
Patrick H. Lauke committed
448
449
      })

450
    $target3[0].dispatchEvent(new Event('click'))
Patrick H. Lauke's avatar
Patrick H. Lauke committed
451
452
  })

453
  QUnit.test('should not fire show event if show is prevented because other element is still transitioning', function (assert) {
454
    assert.expect(1)
455
    var done = assert.async()
456

XhmikosR's avatar
XhmikosR committed
457
458
459
460
    var accordionHTML = '<div id="accordion">' +
        '<div class="card"/>' +
        '<div class="card"/>' +
        '</div>'
461
    var showFired = false
Johann-S's avatar
Johann-S committed
462
    var $groups   = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
463

464
    var $target1 = $('<a role="button" data-toggle="collapse" href="#body1"/>').appendTo($groups.eq(0))
465

466
    $('<div id="body1" class="collapse" data-parent="#accordion"/>')
467
468
469
470
471
      .appendTo($groups.eq(0))
      .on('show.bs.collapse', function () {
        showFired = true
      })

472
473
    var $target2 = $('<a role="button" data-toggle="collapse" href="#body2"/>').appendTo($groups.eq(1))
    var $body2   = $('<div id="body2" class="collapse" data-parent="#accordion"/>').appendTo($groups.eq(1))
474

475
    $target2[0].dispatchEvent(new Event('click'))
476

Johann-S's avatar
Johann-S committed
477
    $body2.toggleClass('show collapsing')
478
    Collapse._getInstance($body2[0])._isTransitioning = true
479

480
    $target1[0].dispatchEvent(new Event('click'))
481
482

    setTimeout(function () {
483
      assert.ok(!showFired, 'show event did not fire')
484
      done()
485
486
487
    }, 1)
  })

488
  QUnit.test('should add "collapsed" class to target when collapse is hidden via manual invocation', function (assert) {
489
    assert.expect(1)
490
    var done = assert.async()
491

492
    var $target = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
493

Starsam80's avatar
Starsam80 committed
494
    $('<div id="test1" class="show"/>')
495
496
      .appendTo('#qunit-fixture')
      .on('hidden.bs.collapse', function () {
497
        assert.ok($target.hasClass('collapsed'))
498
        done()
499
500
501
502
      })
      .bootstrapCollapse('hide')
  })

503
  QUnit.test('should remove "collapsed" class from target when collapse is shown via manual invocation', function (assert) {
504
    assert.expect(1)
505
    var done = assert.async()
506

507
    var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href="#test1"/>').appendTo('#qunit-fixture')
508
509
510
511

    $('<div id="test1"/>')
      .appendTo('#qunit-fixture')
      .on('shown.bs.collapse', function () {
512
        assert.ok(!$target.hasClass('collapsed'))
513
        done()
514
515
516
517
      })
      .bootstrapCollapse('show')
  })

Johann-S's avatar
Johann-S committed
518
  QUnit.test('should allow accordion to use children other than card', function (assert) {
519
    assert.expect(4)
Johann-S's avatar
Johann-S committed
520
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
521
522
523
524
525
526
527
528
529
530
    var accordionHTML = '<div id="accordion">' +
        '<div class="item">' +
        '<a id="linkTrigger" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>' +
        '<div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-parent="#accordion"></div>' +
        '</div>' +
        '<div class="item">' +
        '<a id="linkTriggerTwo" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>' +
        '<div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-parent="#accordion"></div>' +
        '</div>' +
        '</div>'
531
532
533
534
535
536
537
538
539
540
541
542
543
544

    $(accordionHTML).appendTo('#qunit-fixture')
    var $trigger = $('#linkTrigger')
    var $triggerTwo = $('#linkTriggerTwo')
    var $collapseOne = $('#collapseOne')
    var $collapseTwo = $('#collapseTwo')
    $collapseOne.on('shown.bs.collapse', function () {
      assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown')
      assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown')
      $collapseTwo.on('shown.bs.collapse', function () {
        assert.ok(!$collapseOne.hasClass('show'), '#collapseOne is not shown')
        assert.ok($collapseTwo.hasClass('show'), '#collapseTwo is shown')
        done()
      })
545
      $triggerTwo[0].dispatchEvent(new Event('click'))
546
    })
547
    $trigger[0].dispatchEvent(new Event('click'))
548
549
550
551
552
  })

  QUnit.test('should allow accordion to contain nested elements', function (assert) {
    assert.expect(4)
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
    var accordionHTML = '<div id="accordion">' +
        '<div class="row">' +
        '<div class="col-lg-6">' +
        '<div class="item">' +
        '<a id="linkTrigger" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>' +
        '<div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree" data-parent="#accordion"></div>' +
        '</div>' +
        '</div>' +
        '<div class="col-lg-6">' +
        '<div class="item">' +
        '<a id="linkTriggerTwo" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>' +
        '<div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo" data-parent="#accordion"></div>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '</div>'
Johann-S's avatar
Johann-S committed
569
570

    $(accordionHTML).appendTo('#qunit-fixture')
571
572
573
574
    var $trigger = $('#linkTrigger')
    var $triggerTwo = $('#linkTriggerTwo')
    var $collapseOne = $('#collapseOne')
    var $collapseTwo = $('#collapseTwo')
Johann-S's avatar
Johann-S committed
575

576
577
578
    $collapseOne.on('shown.bs.collapse', function () {
      assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown')
      assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown')
Johann-S's avatar
Johann-S committed
579

580
581
582
583
584
      $collapseTwo.on('shown.bs.collapse', function () {
        assert.ok(!$collapseOne.hasClass('show'), '#collapseOne is not shown')
        assert.ok($collapseTwo.hasClass('show'), '#collapseTwo is shown')
        done()
      })
585
      $triggerTwo[0].dispatchEvent(new Event('click'))
Johann-S's avatar
Johann-S committed
586
    })
587
    $trigger[0].dispatchEvent(new Event('click'))
588
589
  })

590
591
592
  QUnit.test('should allow accordion to target multiple elements', function (assert) {
    assert.expect(8)
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
593
594
595
596
597
598
599
600
    var accordionHTML = '<div id="accordion">' +
      '<a id="linkTriggerOne" data-toggle="collapse" data-target=".collapseOne" href="#" aria-expanded="false" aria-controls="collapseOne"></a>' +
      '<a id="linkTriggerTwo" data-toggle="collapse" data-target=".collapseTwo" href="#" aria-expanded="false" aria-controls="collapseTwo"></a>' +
      '<div id="collapseOneOne" class="collapse collapseOne" role="tabpanel" data-parent="#accordion"></div>' +
      '<div id="collapseOneTwo" class="collapse collapseOne" role="tabpanel" data-parent="#accordion"></div>' +
      '<div id="collapseTwoOne" class="collapse collapseTwo" role="tabpanel" data-parent="#accordion"></div>' +
      '<div id="collapseTwoTwo" class="collapse collapseTwo" role="tabpanel" data-parent="#accordion"></div>' +
      '</div>'
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

    $(accordionHTML).appendTo('#qunit-fixture')
    var $trigger = $('#linkTriggerOne')
    var $triggerTwo = $('#linkTriggerTwo')
    var $collapseOneOne = $('#collapseOneOne')
    var $collapseOneTwo = $('#collapseOneTwo')
    var $collapseTwoOne = $('#collapseTwoOne')
    var $collapseTwoTwo = $('#collapseTwoTwo')
    var collapsedElements = {
      one : false,
      two : false
    }

    function firstTest() {
      assert.ok($collapseOneOne.hasClass('show'), '#collapseOneOne is shown')
      assert.ok($collapseOneTwo.hasClass('show'), '#collapseOneTwo is shown')
      assert.ok(!$collapseTwoOne.hasClass('show'), '#collapseTwoOne is not shown')
      assert.ok(!$collapseTwoTwo.hasClass('show'), '#collapseTwoTwo is not shown')
619
      $triggerTwo[0].dispatchEvent(new Event('click'))
620
621
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
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
    }

    function secondTest() {
      assert.ok(!$collapseOneOne.hasClass('show'), '#collapseOneOne is not shown')
      assert.ok(!$collapseOneTwo.hasClass('show'), '#collapseOneTwo is not shown')
      assert.ok($collapseTwoOne.hasClass('show'), '#collapseTwoOne is shown')
      assert.ok($collapseTwoTwo.hasClass('show'), '#collapseTwoTwo is shown')
      done()
    }

    $collapseOneOne.on('shown.bs.collapse', function () {
      if (collapsedElements.one) {
        firstTest()
      } else {
        collapsedElements.one = true
      }
    })

    $collapseOneTwo.on('shown.bs.collapse', function () {
      if (collapsedElements.one) {
        firstTest()
      } else {
        collapsedElements.one = true
      }
    })

    $collapseTwoOne.on('shown.bs.collapse', function () {
      if (collapsedElements.two) {
        secondTest()
      } else {
        collapsedElements.two = true
      }
    })

    $collapseTwoTwo.on('shown.bs.collapse', function () {
      if (collapsedElements.two) {
        secondTest()
      } else {
        collapsedElements.two = true
      }
    })

662
    $trigger[0].dispatchEvent(new Event('click'))
663
664
  })

665
666
667
  QUnit.test('should collapse accordion children but not nested accordion children', function (assert) {
    assert.expect(9)
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
    $('<div id="accordion">' +
        '<div class="item">' +
        '<a id="linkTrigger" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>' +
        '<div id="collapseOne" data-parent="#accordion" class="collapse" role="tabpanel" aria-labelledby="headingThree">' +
        '<div id="nestedAccordion">' +
        '<div class="item">' +
        '<a id="nestedLinkTrigger" data-toggle="collapse" href="#nestedCollapseOne" aria-expanded="false" aria-controls="nestedCollapseOne"></a>' +
        '<div id="nestedCollapseOne" data-parent="#nestedAccordion" class="collapse" role="tabpanel" aria-labelledby="headingThree">' +
        '</div>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '</div>' +
        '<div class="item">' +
        '<a id="linkTriggerTwo" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>' +
        '<div id="collapseTwo" data-parent="#accordion" class="collapse show" role="tabpanel" aria-labelledby="headingTwo"></div>' +
        '</div>' +
        '</div>').appendTo('#qunit-fixture')
686
687
688
689
690
691
692
    var $trigger = $('#linkTrigger')
    var $triggerTwo = $('#linkTriggerTwo')
    var $nestedTrigger = $('#nestedLinkTrigger')
    var $collapseOne = $('#collapseOne')
    var $collapseTwo = $('#collapseTwo')
    var $nestedCollapseOne = $('#nestedCollapseOne')

693
    function handlerCollapseOne() {
694
695
696
      assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown')
      assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown')
      assert.ok(!$('#nestedCollapseOne').hasClass('show'), '#nestedCollapseOne is not shown')
Johann-S's avatar
Johann-S committed
697

698
699
700
701
702
703
704
705
706
707
708
709
710
      $nestedCollapseOne[0].addEventListener('shown.bs.collapse', handlerNestedCollapseOne)
      $nestedTrigger[0].dispatchEvent(new Event('click'))
      $collapseOne[0].removeEventListener('shown.bs.collapse', handlerCollapseOne)
    }

    function handlerNestedCollapseOne() {
      assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown')
      assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown')
      assert.ok($nestedCollapseOne.hasClass('show'), '#nestedCollapseOne is shown')

      $collapseTwo[0].addEventListener('shown.bs.collapse', function () {
        assert.ok(!$collapseOne.hasClass('show'), '#collapseOne is not shown')
        assert.ok($collapseTwo.hasClass('show'), '#collapseTwo is shown')
711
        assert.ok($nestedCollapseOne.hasClass('show'), '#nestedCollapseOne is shown')
712
        done()
713
      })
714
715
716
717
718
719
      $triggerTwo[0].dispatchEvent(new Event('click'))
      $nestedCollapseOne[0].removeEventListener('shown.bs.collapse', handlerNestedCollapseOne)
    }

    $collapseOne[0].addEventListener('shown.bs.collapse', handlerCollapseOne)
    $trigger[0].dispatchEvent(new Event('click'))
Johann-S's avatar
Johann-S committed
720
  })
721
722

  QUnit.test('should not prevent event for input', function (assert) {
723
    assert.expect(3)
724
725
    var done = assert.async()
    var $target = $('<input type="checkbox" data-toggle="collapse" data-target="#collapsediv1" />').appendTo('#qunit-fixture')
Johann-S's avatar
Johann-S committed
726
    var $collapse = $('<div id="collapsediv1"/>').appendTo('#qunit-fixture')
727

728
    $collapse[0].addEventListener('shown.bs.collapse', function () {
Johann-S's avatar
Johann-S committed
729
730
731
732
733
      assert.ok($collapse.hasClass('show'))
      assert.ok($target.attr('aria-expanded') === 'true')
      assert.ok($target.prop('checked'))
      done()
    })
734
735
736

    $target.trigger($.Event('click'))
  })
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

  QUnit.test('should add "collapsed" class to triggers only when all the targeted collapse are hidden', function (assert) {
    assert.expect(9)
    var done = assert.async()

    var $trigger1 = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
    var $trigger2 = $('<a role="button" data-toggle="collapse" href="#test2"/>').appendTo('#qunit-fixture')
    var $trigger3 = $('<a role="button" data-toggle="collapse" href=".multi"/>').appendTo('#qunit-fixture')

    var $target1 = $('<div id="test1" class="multi"/>').appendTo('#qunit-fixture')
    var $target2 = $('<div id="test2" class="multi"/>').appendTo('#qunit-fixture')

    $target2.one('shown.bs.collapse', function () {
      assert.ok(!$trigger1.hasClass('collapsed'), 'trigger1 does not have collapsed class')
      assert.ok(!$trigger2.hasClass('collapsed'), 'trigger2 does not have collapsed class')
      assert.ok(!$trigger3.hasClass('collapsed'), 'trigger3 does not have collapsed class')
      $target2.one('hidden.bs.collapse', function () {
        assert.ok(!$trigger1.hasClass('collapsed'), 'trigger1 does not have collapsed class')
        assert.ok($trigger2.hasClass('collapsed'), 'trigger2 has collapsed class')
        assert.ok(!$trigger3.hasClass('collapsed'), 'trigger3 does not have collapsed class')
        $target1.one('hidden.bs.collapse', function () {
          assert.ok($trigger1.hasClass('collapsed'), 'trigger1 has collapsed class')
          assert.ok($trigger2.hasClass('collapsed'), 'trigger2 has collapsed class')
          assert.ok($trigger3.hasClass('collapsed'), 'trigger3 has collapsed class')
          done()
        })
763
        $trigger1[0].click()
764
      })
765
      $trigger2[0].click()
766
    })
767
    $trigger3[0].click()
768
769
  })

770
  QUnit.test('should set aria-expanded="true" to triggers targeting shown collaspe and aria-expanded="false" only when all the targeted collapses are shown', function (assert) {
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
    assert.expect(9)
    var done = assert.async()

    var $trigger1 = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
    var $trigger2 = $('<a role="button" data-toggle="collapse" href="#test2"/>').appendTo('#qunit-fixture')
    var $trigger3 = $('<a role="button" data-toggle="collapse" href=".multi"/>').appendTo('#qunit-fixture')

    var $target1 = $('<div id="test1" class="multi collapse"/>').appendTo('#qunit-fixture')
    var $target2 = $('<div id="test2" class="multi collapse"/>').appendTo('#qunit-fixture')

    $target2.one('shown.bs.collapse', function () {
      assert.strictEqual($trigger1.attr('aria-expanded'), 'true', 'aria-expanded on trigger1 is "true"')
      assert.strictEqual($trigger2.attr('aria-expanded'), 'true', 'aria-expanded on trigger2 is "true"')
      assert.strictEqual($trigger3.attr('aria-expanded'), 'true', 'aria-expanded on trigger3 is "true"')
      $target2.one('hidden.bs.collapse', function () {
        assert.strictEqual($trigger1.attr('aria-expanded'), 'true', 'aria-expanded on trigger1 is "true"')
        assert.strictEqual($trigger2.attr('aria-expanded'), 'false', 'aria-expanded on trigger2 is "false"')
        assert.strictEqual($trigger3.attr('aria-expanded'), 'true', 'aria-expanded on trigger3 is "true"')
        $target1.one('hidden.bs.collapse', function () {
          assert.strictEqual($trigger1.attr('aria-expanded'), 'false', 'aria-expanded on trigger1 is "fasle"')
          assert.strictEqual($trigger2.attr('aria-expanded'), 'false', 'aria-expanded on trigger2 is "false"')
          assert.strictEqual($trigger3.attr('aria-expanded'), 'false', 'aria-expanded on trigger3 is "false"')
          done()
        })
795
        $trigger1[0].click()
796
      })
797
      $trigger2[0].click()
798
    })
799
    $trigger3[0].click()
800
  })
801
802
803
804
805
806
807
808
809
810

  QUnit.test('should not prevent interactions inside the collapse element', function (assert) {
    assert.expect(2)
    var done = assert.async()

    var $target = $('<input type="checkbox" data-toggle="collapse" data-target="#collapsediv1" />').appendTo('#qunit-fixture')
    var htmlCollapse =
      '<div id="collapsediv1" class="collapse">' +
      ' <input type="checkbox" id="testCheckbox" />' +
      '</div>'
Johann-S's avatar
Johann-S committed
811
812
    var $collapse = $(htmlCollapse).appendTo('#qunit-fixture')

813
    $collapse[0].addEventListener('shown.bs.collapse', function () {
Johann-S's avatar
Johann-S committed
814
815
816
817
818
819
820
821
      assert.ok($target.prop('checked'), '$trigger is checked')
      var $testCheckbox = $('#testCheckbox')
      $testCheckbox.trigger($.Event('click'))
      setTimeout(function () {
        assert.ok($testCheckbox.prop('checked'), '$testCheckbox is checked too')
        done()
      }, 5)
    })
822
823
    $target.trigger($.Event('click'))
  })
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840

  QUnit.test('should allow jquery object in parent config', function (assert) {
    assert.expect(1)
    var html =
    '<div class="my-collapse">' +
    '  <div class="item">' +
    '    <a data-toggle="collapse" href="#">Toggle item</a>' +
    '    <div class="collapse">Lorem ipsum</div>' +
    '  </div>' +
    '</div>'

    $(html).appendTo('#qunit-fixture')
    try {
      $('[data-toggle="collapse"]').bootstrapCollapse({
        parent: $('.my-collapse')
      })
      assert.ok(true, 'collapse correctly created')
XhmikosR's avatar
XhmikosR committed
841
    } catch (err) {
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
      assert.ok(false, 'collapse not created')
    }
  })

  QUnit.test('should allow DOM object in parent config', function (assert) {
    assert.expect(1)
    var html =
    '<div class="my-collapse">' +
    '  <div class="item">' +
    '    <a data-toggle="collapse" href="#">Toggle item</a>' +
    '    <div class="collapse">Lorem ipsum</div>' +
    '  </div>' +
    '</div>'

    $(html).appendTo('#qunit-fixture')
    try {
      $('[data-toggle="collapse"]').bootstrapCollapse({
        parent: $('.my-collapse')[0]
      })
      assert.ok(true, 'collapse correctly created')
XhmikosR's avatar
XhmikosR committed
862
    } catch (err) {
863
864
865
      assert.ok(false, 'collapse not created')
    }
  })
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

  QUnit.test('should find collapse children if they have collapse class too not only data-parent', function (assert) {
    assert.expect(2)
    var done = assert.async()

    var html =
    '<div class="my-collapse">' +
    '  <div class="item">' +
    '    <a data-toggle="collapse" href="#">Toggle item 1</a>' +
    '    <div id="collapse1" class="collapse show">Lorem ipsum 1</div>' +
    '  </div>' +
    '  <div class="item">' +
    '    <a id="triggerCollapse2" data-toggle="collapse" href="#">Toggle item 2</a>' +
    '    <div id="collapse2" class="collapse">Lorem ipsum 2</div>' +
    '  </div>' +
    '</div>'

    $(html).appendTo('#qunit-fixture')

    var $parent = $('.my-collapse')
    var $collapse2 = $('#collapse2')
    $parent.find('.collapse').bootstrapCollapse({
      parent: $parent,
      toggle: false
    })

    $collapse2.on('shown.bs.collapse', function () {
      assert.ok($collapse2.hasClass('show'))
      assert.ok(!$('#collapse1').hasClass('show'))
      done()
    })

    $collapse2.bootstrapCollapse('toggle')
  })
Heinrich Fenkart's avatar
Heinrich Fenkart committed
900
})