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

4
  QUnit.module('popover 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).popover, 'popover method is defined')
XhmikosR's avatar
XhmikosR committed
9
10
  })

11
  QUnit.module('popover', {
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.bootstrapPopover = $.fn.popover.noConflict()
    },
16
    afterEach: function () {
17
18
      $.fn.popover = $.fn.bootstrapPopover
      delete $.fn.bootstrapPopover
fat's avatar
fat committed
19
      $('.popover').remove()
20
      $('#qunit-fixture').html('')
21
22
23
    }
  })

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

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

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

48
  QUnit.test('should render popover element', function (assert) {
49
    assert.expect(2)
50
51
    var done = assert.async()
    $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>')
XhmikosR's avatar
XhmikosR committed
52
      .appendTo('#qunit-fixture')
53
54
55
56
57
58
59
60
      .on('shown.bs.popover', function () {
        assert.notEqual($('.popover').length, 0, 'popover was inserted')
        $(this).bootstrapPopover('hide')
      })
      .on('hidden.bs.popover', function () {
        assert.strictEqual($('.popover').length, 0, 'popover removed')
        done()
      })
61
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
62
63
  })

64
  QUnit.test('should store popover instance in popover data object', function (assert) {
65
    assert.expect(1)
66
    var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>').bootstrapPopover()
XhmikosR's avatar
XhmikosR committed
67

68
    assert.ok($popover.data('bs.popover'), 'popover instance exists')
XhmikosR's avatar
XhmikosR committed
69
70
  })

71
  QUnit.test('should store popover trigger in popover instance data object', function (assert) {
72
    assert.expect(1)
Heinrich Fenkart's avatar
Heinrich Fenkart committed
73
    var $popover = $('<a href="#" title="ResentedHook">@ResentedHook</a>')
74
75
      .appendTo('#qunit-fixture')
      .bootstrapPopover()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
76
77
78

    $popover.bootstrapPopover('show')

79
    assert.ok($('.popover').data('bs.popover'), 'popover trigger stored in instance data')
80
81
  })

82
  QUnit.test('should get title and content from options', function (assert) {
83
    assert.expect(4)
84
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
85
    var $popover = $('<a href="#">@fat</a>')
XhmikosR's avatar
XhmikosR committed
86
      .appendTo('#qunit-fixture')
87
      .bootstrapPopover({
XhmikosR's avatar
XhmikosR committed
88
89
90
91
92
93
        title: function () {
          return '@fat'
        },
        content: function () {
          return 'loves writing tests (╯°□°)╯︵ ┻━┻'
        }
94
95
      })

96
97
98
99
100
101
102
103
104
105
106
107
    $popover
      .one('shown.bs.popover', function () {
        assert.notEqual($('.popover').length, 0, 'popover was inserted')
        assert.strictEqual($('.popover .popover-header').text(), '@fat', 'title correctly inserted')
        assert.strictEqual($('.popover .popover-body').text(), 'loves writing tests (╯°□°)╯︵ ┻━┻', 'content correctly inserted')
        $popover.bootstrapPopover('hide')
      })
      .one('hidden.bs.popover', function () {
        assert.strictEqual($('.popover').length, 0, 'popover was removed')
        done()
      })
      .bootstrapPopover('show')
Stefan Neculai's avatar
Stefan Neculai committed
108
109
  })

110
111
112
113
114
115
  QUnit.test('should allow DOMElement title and content (html: true)', function (assert) {
    assert.expect(5)
    var title = document.createTextNode('@glebm <3 writing tests')
    var content = $('<i>¯\\_(ツ)_/¯</i>').get(0)
    var $popover = $('<a href="#" rel="tooltip"/>')
      .appendTo('#qunit-fixture')
XhmikosR's avatar
XhmikosR committed
116
117
118
119
120
      .bootstrapPopover({
        html: true,
        title: title,
        content: content
      })
121
122
123
124

    $popover.bootstrapPopover('show')

    assert.notEqual($('.popover').length, 0, 'popover inserted')
Mark Otto's avatar
Mark Otto committed
125
    assert.strictEqual($('.popover .popover-header').text(), '@glebm <3 writing tests', 'title inserted')
126
127
    assert.ok($.contains($('.popover').get(0), title), 'title node moved, not copied')
    // toLowerCase because IE8 will return <I>...</I>
Mark Otto's avatar
Mark Otto committed
128
    assert.strictEqual($('.popover .popover-body').html().toLowerCase(), '<i>¯\\_(ツ)_/¯</i>', 'content inserted')
129
130
131
132
133
134
135
136
137
    assert.ok($.contains($('.popover').get(0), content), 'content node moved, not copied')
  })

  QUnit.test('should allow DOMElement title and content (html: false)', function (assert) {
    assert.expect(5)
    var title = document.createTextNode('@glebm <3 writing tests')
    var content = $('<i>¯\\_(ツ)_/¯</i>').get(0)
    var $popover = $('<a href="#" rel="tooltip"/>')
      .appendTo('#qunit-fixture')
XhmikosR's avatar
XhmikosR committed
138
139
140
141
      .bootstrapPopover({
        title: title,
        content: content
      })
142
143
144
145

    $popover.bootstrapPopover('show')

    assert.notEqual($('.popover').length, 0, 'popover inserted')
Mark Otto's avatar
Mark Otto committed
146
    assert.strictEqual($('.popover .popover-header').text(), '@glebm <3 writing tests', 'title inserted')
147
    assert.ok(!$.contains($('.popover').get(0), title), 'title node copied, not moved')
Mark Otto's avatar
Mark Otto committed
148
    assert.strictEqual($('.popover .popover-body').html(), '¯\\_(ツ)_/¯', 'content inserted')
149
150
151
    assert.ok(!$.contains($('.popover').get(0), content), 'content node copied, not moved')
  })

152
  QUnit.test('should not duplicate HTML object', function (assert) {
153
    assert.expect(6)
154
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
155
    var $div = $('<div/>').html('loves writing tests (╯°□°)╯︵ ┻━┻')
Stefan Neculai's avatar
Stefan Neculai committed
156

Heinrich Fenkart's avatar
Heinrich Fenkart committed
157
    var $popover = $('<a href="#">@fat</a>')
Stefan Neculai's avatar
Stefan Neculai committed
158
      .appendTo('#qunit-fixture')
159
      .bootstrapPopover({
fat's avatar
fat committed
160
        html: true,
Stefan Neculai's avatar
Stefan Neculai committed
161
162
163
164
165
        content: function () {
          return $div
        }
      })

166
167
168
169
    function popoverInserted() {
      assert.notEqual($('.popover').length, 0, 'popover was inserted')
      assert.equal($('.popover .popover-body').html(), $div[0].outerHTML, 'content correctly inserted')
    }
Stefan Neculai's avatar
Stefan Neculai committed
170

171
172
173
    $popover
      .one('shown.bs.popover', function () {
        popoverInserted()
Stefan Neculai's avatar
Stefan Neculai committed
174

175
176
        $popover.one('hidden.bs.popover', function () {
          assert.strictEqual($('.popover').length, 0, 'popover was removed')
Stefan Neculai's avatar
Stefan Neculai committed
177

178
179
180
181
182
183
184
185
186
187
188
          $popover.one('shown.bs.popover', function () {
            popoverInserted()

            $popover.one('hidden.bs.popover', function () {
              assert.strictEqual($('.popover').length, 0, 'popover was removed')
              done()
            }).bootstrapPopover('hide')
          }).bootstrapPopover('show')
        }).bootstrapPopover('hide')
      })
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
189
190
  })

191
  QUnit.test('should get title and content from attributes', function (assert) {
192
    assert.expect(4)
193
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
194
    var $popover = $('<a href="#" title="@mdo" data-content="loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻" >@mdo</a>')
XhmikosR's avatar
XhmikosR committed
195
      .appendTo('#qunit-fixture')
196
      .bootstrapPopover()
197
198
199
200
201
202
203
204
205
206
      .one('shown.bs.popover', function () {
        assert.notEqual($('.popover').length, 0, 'popover was inserted')
        assert.strictEqual($('.popover .popover-header').text(), '@mdo', 'title correctly inserted')
        assert.strictEqual($('.popover .popover-body').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted')
        $popover.bootstrapPopover('hide')
      })
      .one('hidden.bs.popover', function () {
        assert.strictEqual($('.popover').length, 0, 'popover was removed')
        done()
      })
207
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
208
209
  })

210
  QUnit.test('should get title and content from attributes ignoring options passed via js', function (assert) {
211
    assert.expect(4)
212
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
213
    var $popover = $('<a href="#" title="@mdo" data-content="loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻" >@mdo</a>')
XhmikosR's avatar
XhmikosR committed
214
      .appendTo('#qunit-fixture')
215
      .bootstrapPopover({
XhmikosR's avatar
XhmikosR committed
216
217
        title: 'ignored title option',
        content: 'ignored content option'
218
      })
219
220
221
222
223
224
225
226
227
228
      .one('shown.bs.popover', function () {
        assert.notEqual($('.popover').length, 0, 'popover was inserted')
        assert.strictEqual($('.popover .popover-header').text(), '@mdo', 'title correctly inserted')
        assert.strictEqual($('.popover .popover-body').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted')
        $popover.bootstrapPopover('hide')
      })
      .one('hidden.bs.popover', function () {
        assert.strictEqual($('.popover').length, 0, 'popover was removed')
        done()
      })
229
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
230
231
  })

232
  QUnit.test('should respect custom template', function (assert) {
233
    assert.expect(3)
234
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
235
    var $popover = $('<a href="#">@fat</a>')
XhmikosR's avatar
XhmikosR committed
236
      .appendTo('#qunit-fixture')
237
      .bootstrapPopover({
XhmikosR's avatar
XhmikosR committed
238
239
        title: 'Test',
        content: 'Test',
fat's avatar
fat committed
240
        template: '<div class="popover foobar"><div class="arrow"></div><div class="inner"><h3 class="title"/><div class="content"><p/></div></div></div>'
241
      })
242
243
244
245
246
247
248
249
250
251
      .one('shown.bs.popover', function () {
        assert.notEqual($('.popover').length, 0, 'popover was inserted')
        assert.ok($('.popover').hasClass('foobar'), 'custom class is present')
        $popover.bootstrapPopover('hide')
      })
      .one('hidden.bs.popover', function () {
        assert.strictEqual($('.popover').length, 0, 'popover was removed')
        done()
      })
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
252
253
  })

254
  QUnit.test('should destroy popover', function (assert) {
255
    assert.expect(7)
fat's avatar
fat committed
256
    var $popover = $('<div/>')
Heinrich Fenkart's avatar
Heinrich Fenkart committed
257
258
259
260
261
      .bootstrapPopover({
        trigger: 'hover'
      })
      .on('click.foo', $.noop)

262
263
    assert.ok($popover.data('bs.popover'), 'popover has data')
    assert.ok($._data($popover[0], 'events').mouseover && $._data($popover[0], 'events').mouseout, 'popover has hover event')
264
    assert.strictEqual($._data($popover[0], 'events').click[0].namespace, 'foo', 'popover has extra click.foo event')
Heinrich Fenkart's avatar
Heinrich Fenkart committed
265
266

    $popover.bootstrapPopover('show')
fat's avatar
fat committed
267
    $popover.bootstrapPopover('dispose')
Heinrich Fenkart's avatar
Heinrich Fenkart committed
268

Starsam80's avatar
Starsam80 committed
269
    assert.ok(!$popover.hasClass('show'), 'popover is hidden')
270
    assert.ok(!$popover.data('popover'), 'popover does not have data')
271
    assert.strictEqual($._data($popover[0], 'events').click[0].namespace, 'foo', 'popover still has click.foo')
272
    assert.ok(!$._data($popover[0], 'events').mouseover && !$._data($popover[0], 'events').mouseout, 'popover does not have any events')
XhmikosR's avatar
XhmikosR committed
273
  })
274

275
  QUnit.test('should render popover element using delegated selector', function (assert) {
276
    assert.expect(2)
277
    var done = assert.async()
XhmikosR's avatar
XhmikosR committed
278
    var $div = $('<div><a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a></div>')
279
280
281
282
283
      .appendTo('#qunit-fixture')
      .bootstrapPopover({
        selector: 'a',
        trigger: 'click'
      })
284
285
286
287
288
289
290
291
      .one('shown.bs.popover', function () {
        assert.notEqual($('.popover').length, 0, 'popover was inserted')
        $div.find('a').trigger('click')
      })
      .one('hidden.bs.popover', function () {
        assert.strictEqual($('.popover').length, 0, 'popover was removed')
        done()
      })
292

293
    $div.find('a').trigger('click')
294
295
  })

296
  QUnit.test('should detach popover content rather than removing it so that event handlers are left intact', function (assert) {
297
    assert.expect(1)
Chris Rebert's avatar
Chris Rebert committed
298
    var $content = $('<div class="content-with-handler"><a class="btn btn-warning">Button with event handler</a></div>').appendTo('#qunit-fixture')
299

300
    var handlerCalled = false
301
    $('.content-with-handler .btn').on('click', function () {
Chris Rebert's avatar
Chris Rebert committed
302
      handlerCalled = true
303
    })
Chris Rebert's avatar
Chris Rebert committed
304
305

    var $div = $('<div><a href="#">Show popover</a></div>')
306
307
      .appendTo('#qunit-fixture')
      .bootstrapPopover({
Chris Rebert's avatar
Chris Rebert committed
308
309
310
        html: true,
        trigger: 'manual',
        container: 'body',
311
        animation: false,
Chris Rebert's avatar
Chris Rebert committed
312
        content: function () {
313
          return $content
Chris Rebert's avatar
Chris Rebert committed
314
        }
315
316
      })

317
    var done = assert.async()
Chris Rebert's avatar
Chris Rebert committed
318
319
320
321
322
323
    $div
      .one('shown.bs.popover', function () {
        $div
          .one('hidden.bs.popover', function () {
            $div
              .one('shown.bs.popover', function () {
324
                $('.content-with-handler .btn').trigger('click')
325
                assert.ok(handlerCalled, 'content\'s event handler still present')
326
                $div.bootstrapPopover('dispose')
327
                done()
Chris Rebert's avatar
Chris Rebert committed
328
329
330
331
332
333
              })
              .bootstrapPopover('show')
          })
          .bootstrapPopover('hide')
      })
      .bootstrapPopover('show')
334
  })
335

336
337
338
339
340
341
342
343
344
  QUnit.test('should do nothing when an attempt is made to hide an uninitialized popover', function (assert) {
    assert.expect(1)

    var $popover = $('<span data-toggle="popover" data-title="some title" data-content="some content">some text</span>')
      .appendTo('#qunit-fixture')
      .on('hidden.bs.popover shown.bs.popover', function () {
        assert.ok(false, 'should not fire any popover events')
      })
      .bootstrapPopover('hide')
XhmikosR's avatar
XhmikosR committed
345
    assert.strictEqual(typeof $popover.data('bs.popover'), 'undefined', 'should not initialize the popover')
346
347
  })

fat's avatar
fat committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  QUnit.test('should fire inserted event', function (assert) {
    assert.expect(2)
    var done = assert.async()

    $('<a href="#">@Johann-S</a>')
      .appendTo('#qunit-fixture')
      .on('inserted.bs.popover', function () {
        assert.notEqual($('.popover').length, 0, 'popover was inserted')
        assert.ok(true, 'inserted event fired')
        done()
      })
      .bootstrapPopover({
        title: 'Test',
        content: 'Test'
      })
      .bootstrapPopover('show')
  })

366
367
368
369
370
371
  QUnit.test('should throw an error when show is called on hidden elements', function (assert) {
    assert.expect(1)
    var done = assert.async()

    try {
      $('<div data-toggle="popover" data-title="some title" data-content="@Johann-S" style="display: none"/>').bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
372
    } catch (err) {
373
374
375
376
      assert.strictEqual(err.message, 'Please use show on visible elements')
      done()
    }
  })
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

  QUnit.test('should hide popovers when their containing modal is closed', function (assert) {
    assert.expect(1)
    var done = assert.async()
    var templateHTML = '<div id="modal-test" class="modal">' +
                          '<div class="modal-dialog" role="document">' +
                            '<div class="modal-content">' +
                              '<div class="modal-body">' +
                                '<button id="popover-test" type="button" class="btn btn-secondary" data-toggle="popover" data-placement="top" data-content="Popover">' +
                                  'Popover on top' +
                                '</button>' +
                              '</div>' +
                            '</div>' +
                          '</div>' +
                        '</div>'

    $(templateHTML).appendTo('#qunit-fixture')
    $('#popover-test')
      .on('shown.bs.popover', function () {
        $('#modal-test').modal('hide')
      })
      .on('hide.bs.popover', function () {
        assert.ok(true, 'popover hide')
        done()
      })

    $('#modal-test')
      .on('shown.bs.modal', function () {
        $('#popover-test').bootstrapPopover('show')
      })
      .modal('show')
  })
409
410
411
412
413
414
415
416
417
418
419

  QUnit.test('should convert number to string without error for content and title', function (assert) {
    assert.expect(2)
    var done = assert.async()
    var $popover = $('<a href="#">@mdo</a>')
      .appendTo('#qunit-fixture')
      .bootstrapPopover({
        title: 5,
        content: 7
      })
      .on('shown.bs.popover', function () {
Mark Otto's avatar
Mark Otto committed
420
421
        assert.strictEqual($('.popover .popover-header').text(), '5')
        assert.strictEqual($('.popover .popover-body').text(), '7')
422
423
424
425
426
        done()
      })

    $popover.bootstrapPopover('show')
  })
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

  QUnit.test('popover should be shown right away after the call of disable/enable', function (assert) {
    assert.expect(2)
    var done = assert.async()
    var $popover = $('<a href="#">@mdo</a>')
      .appendTo('#qunit-fixture')
      .bootstrapPopover({
        title: 'Test popover',
        content: 'with disable/enable'
      })
      .on('shown.bs.popover', function () {
        assert.strictEqual($('.popover').hasClass('show'), true)
        done()
      })

    $popover.bootstrapPopover('disable')
    $popover.trigger($.Event('click'))
    setTimeout(function () {
      assert.strictEqual($('.popover').length === 0, true)
      $popover.bootstrapPopover('enable')
      $popover.trigger($.Event('click'))
    }, 200)
  })
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470

  QUnit.test('popover should call content function only once', function (assert) {
    assert.expect(1)
    var done = assert.async()
    var nbCall = 0
    $('<div id="popover" style="display:none">content</div>').appendTo('#qunit-fixture')
    var $popover = $('<a href="#">@Johann-S</a>')
      .appendTo('#qunit-fixture')
      .bootstrapPopover({
        content: function () {
          nbCall++
          return $('#popover').clone().show().get(0)
        }
      })
      .on('shown.bs.popover', function () {
        assert.strictEqual(nbCall, 1)
        done()
      })

    $popover.trigger($.Event('click'))
  })
471
})