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

XhmikosR's avatar
XhmikosR committed
4
  var Popover = typeof window.bootstrap === 'undefined' ? window.Popover : window.bootstrap.Popover
5

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

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

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

31
32
33
34
35
36
  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
37
38
    } catch (error) {
      assert.strictEqual(error.message, 'No method named "noMethod"')
39
40
41
    }
  })

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

50
  QUnit.test('should render popover element', function (assert) {
51
    assert.expect(2)
52
53
    var done = assert.async()
    $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>')
XhmikosR's avatar
XhmikosR committed
54
      .appendTo('#qunit-fixture')
55
56
57
58
59
60
61
62
      .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()
      })
63
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
64
65
  })

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

70
    assert.ok(Popover._getInstance($popover[0]), 'popover instance exists')
XhmikosR's avatar
XhmikosR committed
71
72
  })

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

    $popover.bootstrapPopover('show')

81
    assert.ok(Popover._getInstance($('.popover')[0]), 'popover trigger stored in instance data')
82
83
  })

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

98
99
100
101
102
103
104
105
106
107
108
109
    $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
110
111
  })

112
113
114
115
116
117
  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
118
119
120
121
122
      .bootstrapPopover({
        html: true,
        title: title,
        content: content
      })
123
124
125
126

    $popover.bootstrapPopover('show')

    assert.notEqual($('.popover').length, 0, 'popover inserted')
Mark Otto's avatar
Mark Otto committed
127
    assert.strictEqual($('.popover .popover-header').text(), '@glebm <3 writing tests', 'title inserted')
128
129
    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
130
    assert.strictEqual($('.popover .popover-body').html().toLowerCase(), '<i>¯\\_(ツ)_/¯</i>', 'content inserted')
131
132
133
134
135
136
137
138
139
    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
140
141
142
143
      .bootstrapPopover({
        title: title,
        content: content
      })
144
145
146
147

    $popover.bootstrapPopover('show')

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

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

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

168
169
170
171
    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
172

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

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

180
181
182
183
184
185
186
187
188
189
190
          $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
191
192
  })

193
  QUnit.test('should get title and content from attributes', function (assert) {
194
    assert.expect(4)
195
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
196
    var $popover = $('<a href="#" title="@mdo" data-content="loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻" >@mdo</a>')
XhmikosR's avatar
XhmikosR committed
197
      .appendTo('#qunit-fixture')
198
      .bootstrapPopover()
199
200
201
202
203
204
205
206
207
208
      .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()
      })
209
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
210
211
  })

212
  QUnit.test('should get title and content from attributes ignoring options passed via js', function (assert) {
213
    assert.expect(4)
214
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
215
    var $popover = $('<a href="#" title="@mdo" data-content="loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻" >@mdo</a>')
XhmikosR's avatar
XhmikosR committed
216
      .appendTo('#qunit-fixture')
217
      .bootstrapPopover({
XhmikosR's avatar
XhmikosR committed
218
219
        title: 'ignored title option',
        content: 'ignored content option'
220
      })
221
222
223
224
225
226
227
228
229
230
      .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()
      })
231
      .bootstrapPopover('show')
XhmikosR's avatar
XhmikosR committed
232
233
  })

234
  QUnit.test('should respect custom template', function (assert) {
235
    assert.expect(3)
236
    var done = assert.async()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
237
    var $popover = $('<a href="#">@fat</a>')
XhmikosR's avatar
XhmikosR committed
238
      .appendTo('#qunit-fixture')
239
      .bootstrapPopover({
XhmikosR's avatar
XhmikosR committed
240
241
        title: 'Test',
        content: 'Test',
242
        template: '<div class="popover foobar"><div class="popover-arrow"></div><div class="inner"><h3 class="title"/><div class="content"><p/></div></div></div>'
243
      })
244
245
246
247
248
249
250
251
252
253
      .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
254
255
  })

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

264
    assert.ok(Popover._getInstance($popover[0]), 'popover has data')
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._getInstance($popover[0]), 'popover does not have data')
XhmikosR's avatar
XhmikosR committed
271
  })
272

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

291
    $div.find('a')[0].click()
292
293
  })

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

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

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

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

334
335
336
337
338
339
340
341
342
  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')
343
    assert.ok(Popover._getInstance($popover[0]) === null, 'should not initialize the popover')
344
345
  })

fat's avatar
fat committed
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  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')
  })

364
365
366
367
368
369
  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
370
371
    } catch (error) {
      assert.strictEqual(error.message, 'Please use show on visible elements')
372
373
374
      done()
    }
  })
375
376
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

  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')
  })
407
408
409
410
411
412
413
414
415
416
417

  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
418
419
        assert.strictEqual($('.popover .popover-header').text(), '5')
        assert.strictEqual($('.popover .popover-body').text(), '7')
420
421
422
423
424
        done()
      })

    $popover.bootstrapPopover('show')
  })
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440

  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')
441
    $popover[0].click()
442
443
444
    setTimeout(function () {
      assert.strictEqual($('.popover').length === 0, true)
      $popover.bootstrapPopover('enable')
445
      $popover[0].click()
446
447
    }, 200)
  })
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466

  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()
      })

467
    $popover[0].click()
468
  })
469
470
471
472
473

  QUnit.test('should return the version', function (assert) {
    assert.expect(1)
    assert.strictEqual(typeof Popover.VERSION, 'string')
  })
474
})