• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!doctype html>
2<!--
3@license
4Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
5This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
6The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
7The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
8Code distributed by Google as part of the polymer project is also
9subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
10-->
11<html>
12<head>
13  <meta charset="UTF-8">
14  <title>paper-tooltip tests</title>
15  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
16
17  <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
18  <script src="../../web-component-tester/browser.js"></script>
19  <script src="../../test-fixture/test-fixture-mocha.js"></script>
20  <script src="../../iron-test-helpers/mock-interactions.js"></script>
21
22  <link rel="import" href="../../test-fixture/test-fixture.html">
23  <link rel="import" href="../paper-tooltip.html">
24  <link rel="import" href="test-button.html">
25
26</head>
27<style>
28  body {
29    margin: 0;
30    padding: 0;
31  }
32  #target {
33    width: 100px;
34    height: 20px;
35    background-color: red;
36  }
37  paper-tooltip {
38    width: 70px;
39    height: 30px;
40  }
41
42  .wide {
43    width: 200px;
44  }
45
46  [hidden] {
47    display: none;
48  }
49</style>
50
51<body>
52
53  <test-fixture id="basic">
54    <template>
55      <div>
56        <div id="target"></div>
57        <paper-tooltip for="target" animation-delay="0">Tooltip text</paper-tooltip>
58      </div>
59    </template>
60  </test-fixture>
61
62  <test-fixture id="fitted">
63    <template>
64      <div>
65        <div id="target" style="position:absolute"></div>
66        <paper-tooltip for="target" class="wide" fit-to-visible-bounds>Tooltip text</paper-tooltip>
67      </div>
68    </template>
69  </test-fixture>
70
71  <test-fixture id="no-text">
72    <template>
73      <div>
74        <div id="target"></div>
75        <paper-tooltip for="target"></paper-tooltip>
76      </div>
77    </template>
78  </test-fixture>
79
80  <test-fixture id="dynamic">
81    <template>
82      <div>
83        <div id="target"></div>
84        <paper-tooltip>Tooltip text</paper-tooltip>
85      </div>
86    </template>
87  </test-fixture>
88
89  <test-fixture id="custom">
90    <template>
91      <test-button></test-button>
92    </template>
93  </test-fixture>
94
95  <test-fixture id="no-offset-parent">
96    <template>
97      <div>
98        <div id="target"></div>
99        <paper-tooltip for="target" animation-delay="0" hidden></paper-tooltip>
100      </div>
101    </template>
102  </test-fixture>
103
104  <script>
105    function isHidden(element) {
106      var rect = element.getBoundingClientRect();
107      return (rect.width == 0 && rect.height == 0);
108    }
109
110    suite('basic', function() {
111      test('tooltip is shown when target is focused', function() {
112        var f = fixture('no-text');
113        var target = f.querySelector('#target');
114        var tooltip = f.querySelector('paper-tooltip');
115
116        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
117        assert.isTrue(isHidden(actualTooltip));
118
119        MockInteractions.focus(target);
120        assert.isTrue(isHidden(actualTooltip));
121      });
122
123      test('tooltip is not shown if empty', function() {
124        var f = fixture('basic');
125        var target = f.querySelector('#target');
126        var tooltip = f.querySelector('paper-tooltip');
127
128        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
129        assert.isTrue(isHidden(actualTooltip));
130
131        MockInteractions.focus(target);
132        assert.isFalse(isHidden(actualTooltip));
133      });
134
135      test('tooltip doesn\'t throw an exception if it has no offsetParent', function() {
136        var f = fixture('no-offset-parent');
137        var target = f.querySelector('#target');
138        var tooltip = f.querySelector('paper-tooltip');
139
140        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
141        assert.isTrue(isHidden(actualTooltip));
142        tooltip.updatePosition();
143        tooltip.show();
144
145        // Doesn't get shown since there's no position computed.
146        assert.isTrue(isHidden(actualTooltip));
147      });
148
149      test('tooltip is positioned correctly (bottom)', function() {
150        var f = fixture('basic');
151        var target = f.querySelector('#target');
152        var tooltip = f.querySelector('paper-tooltip');
153
154        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
155        assert.isTrue(isHidden(actualTooltip));
156
157        MockInteractions.focus(target);
158        assert.isFalse(isHidden(actualTooltip));
159
160        var divRect = target.getBoundingClientRect();
161        expect(divRect.width).to.be.equal(100);
162        expect(divRect.height).to.be.equal(20);
163
164        var contentRect = tooltip.getBoundingClientRect();
165        expect(contentRect.width).to.be.equal(70);
166        expect(contentRect.height).to.be.equal(30);
167
168        // The target div width is 100, and the tooltip width is 70, and
169        // it's centered. The height of the target div is 20, and the
170        // tooltip is 14px below.
171        expect(contentRect.left).to.be.equal((100 - 70)/2);
172        expect(contentRect.top).to.be.equal(20 + 14);
173
174        // Also check the math, just in case.
175        expect(contentRect.left).to.be.equal((divRect.width - contentRect.width)/2);
176        expect(contentRect.top).to.be.equal(divRect.height + tooltip.offset);
177      });
178
179      test('tooltip is positioned correctly (top)', function() {
180        var f = fixture('basic');
181        var target = f.querySelector('#target');
182        var tooltip = f.querySelector('paper-tooltip');
183        tooltip.position = 'top';
184
185        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
186        assert.isTrue(isHidden(actualTooltip));
187
188        MockInteractions.focus(target);
189        assert.isFalse(isHidden(actualTooltip));
190
191        var divRect = target.getBoundingClientRect();
192        expect(divRect.width).to.be.equal(100);
193        expect(divRect.height).to.be.equal(20);
194
195        var contentRect = tooltip.getBoundingClientRect();
196        expect(contentRect.width).to.be.equal(70);
197        expect(contentRect.height).to.be.equal(30);
198
199        // The target div width is 100, and the tooltip width is 70, and
200        // it's centered. The height of the tooltip is 30, and the
201        // tooltip is 14px above the target.
202        expect(contentRect.left).to.be.equal((100 - 70)/2);
203        expect(contentRect.top).to.be.equal(0 - 30 - 14);
204
205        // Also check the math, just in case.
206        expect(contentRect.left).to.be.equal((divRect.width - contentRect.width)/2);
207        expect(contentRect.top).to.be.equal(0 - contentRect.height - tooltip.offset);
208      });
209
210      test('tooltip is positioned correctly (right)', function() {
211        var f = fixture('basic');
212        var target = f.querySelector('#target');
213        var tooltip = f.querySelector('paper-tooltip');
214        tooltip.position = 'right';
215
216        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
217        assert.isTrue(isHidden(actualTooltip));
218
219        MockInteractions.focus(target);
220        assert.isFalse(isHidden(actualTooltip));
221
222        var divRect = target.getBoundingClientRect();
223        expect(divRect.width).to.be.equal(100);
224        expect(divRect.height).to.be.equal(20);
225
226        var contentRect = tooltip.getBoundingClientRect();
227        expect(contentRect.width).to.be.equal(70);
228        expect(contentRect.height).to.be.equal(30);
229
230        // The target div width is 100, and the tooltip is 14px to the right.
231        // The target div height is 20, the height of the tooltip is 20px, and
232        // the tooltip is centered.
233        expect(contentRect.left).to.be.equal(100 + 14);
234        expect(contentRect.top).to.be.equal((20 - 30)/2);
235
236        // Also check the math, just in case.
237        expect(contentRect.left).to.be.equal(divRect.width + tooltip.offset);
238        expect(contentRect.top).to.be.equal((divRect.height - contentRect.height)/2);
239      });
240
241      test('tooltip is positioned correctly (left)', function() {
242        var f = fixture('basic');
243        var target = f.querySelector('#target');
244        var tooltip = f.querySelector('paper-tooltip');
245        tooltip.position = 'left';
246
247        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
248        assert.isTrue(isHidden(actualTooltip));
249
250        MockInteractions.focus(target);
251        assert.isFalse(isHidden(actualTooltip));
252
253        var divRect = target.getBoundingClientRect();
254        expect(divRect.width).to.be.equal(100);
255        expect(divRect.height).to.be.equal(20);
256
257        var contentRect = tooltip.getBoundingClientRect();
258        expect(contentRect.width).to.be.equal(70);
259        expect(contentRect.height).to.be.equal(30);
260
261        // The tooltip width is 70px, and the tooltip is 14px to the left of the target.
262        // The target div height is 20, the height of the tooltip is 20px, and
263        // the tooltip is centered.
264        expect(contentRect.left).to.be.equal(0 - 70 - 14);
265        expect(contentRect.top).to.be.equal((20 - 30)/2);
266
267        // Also check the math, just in case.
268        expect(contentRect.left).to.be.equal(0 - contentRect.width - tooltip.offset);
269        expect(contentRect.top).to.be.equal((divRect.height - contentRect.height)/2);
270      });
271
272      test('tooltip is fitted correctly if out of bounds', function() {
273        var f = fixture('fitted');
274        var target = f.querySelector('#target');
275        var tooltip = f.querySelector('paper-tooltip');
276        target.style.top = 0;
277        target.style.left = 0;
278
279        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
280        assert.isTrue(isHidden(actualTooltip));
281
282        MockInteractions.focus(target);
283        assert.isFalse(isHidden(actualTooltip));
284
285        var contentRect = tooltip.getBoundingClientRect();
286        var divRect = target.getBoundingClientRect();
287
288        // Should be fitted on the left side.
289        expect(contentRect.left).to.be.equal(0);
290        expect(contentRect.top).to.be.equal(divRect.height + tooltip.offset);
291      });
292
293      test('tooltip is positioned correctly after being dynamically set', function() {
294        var f = fixture('dynamic');
295        var target = f.querySelector('#target');
296        var tooltip = f.querySelector('paper-tooltip');
297
298        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
299        assert.isTrue(isHidden(actualTooltip));
300
301        // Skip animations in this test, which means we'll show and hide
302        // the tooltip manually, instead of calling focus and blur.
303
304        // The tooltip is shown because it's a sibling of the target,
305        // but it's positioned incorrectly
306        tooltip.toggleClass('hidden', false, actualTooltip);
307        assert.isFalse(isHidden(actualTooltip));
308
309        var contentRect = tooltip.getBoundingClientRect();
310        expect(contentRect.left).to.not.be.equal((100 - 70)/2);
311
312        tooltip.for = 'target';
313
314        // The tooltip needs to hide before it gets repositioned.
315        tooltip.toggleClass('hidden', true, actualTooltip);
316        tooltip.updatePosition();
317        tooltip.toggleClass('hidden', false, actualTooltip);
318        assert.isFalse(isHidden(actualTooltip));
319
320        // The target div width is 100, and the tooltip width is 70, and
321        // it's centered. The height of the target div is 20, and the
322        // tooltip is 14px below.
323        contentRect = tooltip.getBoundingClientRect();
324        expect(contentRect.left).to.be.equal((100 - 70)/2);
325        expect(contentRect.top).to.be.equal(20 + 14);
326      });
327
328      test('tooltip is hidden after target is blurred', function(done) {
329        var f = fixture('basic');
330        var target = f.querySelector('#target');
331        var tooltip = f.querySelector('paper-tooltip');
332
333        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
334        assert.isTrue(isHidden(actualTooltip));
335        // Simulate but don't actually run the entry animation.
336        tooltip.toggleClass('hidden', false, actualTooltip);
337        tooltip._showing = true;
338        assert.isFalse(isHidden(actualTooltip));
339
340        tooltip.addEventListener('neon-animation-finish', function() {
341          assert.isTrue(isHidden(actualTooltip));
342          done();
343        });
344        MockInteractions.blur(target);
345      });
346
347      test('tooltip unlistens to target on detach', function(done) {
348        var f = fixture('basic');
349        var target = f.querySelector('#target');
350        var tooltip = f.querySelector('paper-tooltip');
351
352        sinon.spy(tooltip, 'show');
353
354        MockInteractions.focus(target);
355        expect(tooltip.show.callCount).to.be.equal(1);
356
357        MockInteractions.focus(target);
358        expect(tooltip.show.callCount).to.be.equal(2);
359
360        f.removeChild(tooltip);
361
362        setTimeout(function() {
363          // No more listener means no more calling show.
364          MockInteractions.focus(target);
365          expect(tooltip.show.callCount).to.be.equal(2);
366          done();
367        }, 200);
368      });
369    });
370
371    suite('tooltip is inside a custom element', function() {
372      var f, tooltip, target;
373
374      setup(function() {
375        f = fixture('custom');
376        target = f.$.button;
377        tooltip = f.$.buttonTooltip;
378      });
379
380      test('tooltip is shown when target is focused', function() {
381        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
382        assert.isTrue(isHidden(actualTooltip));
383
384        MockInteractions.focus(target);
385        assert.isFalse(isHidden(actualTooltip));
386      });
387
388      test('tooltip is positioned correctly', function() {
389        var actualTooltip = Polymer.dom(tooltip.root).querySelector('#tooltip');
390        assert.isTrue(isHidden(actualTooltip));
391
392        MockInteractions.focus(target);
393        assert.isFalse(isHidden(actualTooltip));
394
395        var divRect = target.getBoundingClientRect();
396        expect(divRect.width).to.be.equal(100);
397        expect(divRect.height).to.be.equal(20);
398
399        var contentRect = tooltip.getBoundingClientRect();
400        expect(contentRect.width).to.be.equal(70);
401        expect(contentRect.height).to.be.equal(30);
402
403        // The target div width is 100, and the tooltip width is 70, and
404        // it's centered. The height of the target div is 20, and the
405        // tooltip is 14px below.
406        expect(contentRect.left).to.be.equal((100 - 70)/2);
407        expect(contentRect.top).to.be.equal(20 + 14);
408
409        // Also check the math, just in case.
410        expect(contentRect.left).to.be.equal((divRect.width - contentRect.width)/2);
411        expect(contentRect.top).to.be.equal(divRect.height + tooltip.offset);
412      });
413    });
414
415    suite('a11y', function() {
416      test('has aria role "tooltip"', function() {
417        var f = fixture('basic');
418        var tooltip = f.querySelector('paper-tooltip');
419
420        assert.isTrue(tooltip.getAttribute('role') == 'tooltip');
421      });
422
423      var ignoredRules = ['roleTooltipRequiresDescribedby'];
424
425      a11ySuite('basic', ignoredRules);
426      a11ySuite('fitted', ignoredRules);
427      a11ySuite('no-text', ignoredRules);
428      a11ySuite('dynamic', ignoredRules);
429      a11ySuite('custom', ignoredRules);
430    });
431  </script>
432</body>
433</html>
434