• 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>iron-dropdown basic 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="../iron-dropdown.html">
23  <link rel="import" href="../../test-fixture/test-fixture.html">
24
25</head>
26<style>
27  body {
28    margin: 0;
29    padding: 0;
30  }
31
32  .container {
33    display: block;
34    position: relative;
35    width: 100px;
36    height: 100px;
37    background-color: yellow;
38  }
39
40  .positioned {
41    position: absolute;
42    top: 40px;
43    left: 40px;
44  }
45
46  .dropdown-content {
47    width: 50px;
48    height: 50px;
49    background-color: orange;
50  }
51
52  .big {
53    width: 3000px;
54    height: 3000px;
55  }
56</style>
57<body>
58
59  <test-fixture id="TrivialDropdown">
60    <template>
61      <iron-dropdown>
62        <div class="dropdown-content"></div>
63      </iron-dropdown>
64    </template>
65  </test-fixture>
66
67  <test-fixture id="NonLockingDropdown">
68    <template>
69      <iron-dropdown allow-outside-scroll>
70        <div class="dropdown-content">I don't lock scroll!</div>
71      </iron-dropdown>
72    </template>
73  </test-fixture>
74
75  <test-fixture id="AlignedDropdown">
76    <template>
77      <div class="container">
78        <iron-dropdown horizontal-align="right" vertical-align="top">
79          <div class="dropdown-content big"></div>
80        </iron-dropdown>
81      </div>
82    </template>
83  </test-fixture>
84
85  <!-- Absolutely position the dropdown so that it has enough space to move around -->
86  <test-fixture id="OffsetDropdownTopLeft">
87    <template>
88      <div class="container positioned">
89        <iron-dropdown>
90          <div class="dropdown-content"></div>
91        </iron-dropdown>
92      </div>
93    </template>
94  </test-fixture>
95
96  <test-fixture id="OffsetDropdownBottomRight">
97    <template>
98      <div class="container positioned">
99        <iron-dropdown horizontal-align="right" vertical-align="bottom">
100          <div class="dropdown-content"></div>
101        </iron-dropdown>
102      </div>
103    </template>
104  </test-fixture>
105
106  <test-fixture id="FocusableContentDropdown">
107    <template>
108      <iron-dropdown>
109        <div class="dropdown-content" tabindex="0">
110          <div class="subcontent" tabindex="0"></div>
111        </div>
112      </iron-dropdown>
113    </template>
114  </test-fixture>
115
116  <test-fixture id="RTLDropdownLeft">
117    <template>
118      <div dir="rtl" class="container">
119        <iron-dropdown>
120          <div class="dropdown-content"></div>
121        </iron-dropdown>
122      </div>
123    </template>
124  </test-fixture>
125
126  <test-fixture id="RTLDropdownRight">
127    <template>
128      <div dir="rtl" class="container">
129        <iron-dropdown horizontal-align="right">
130          <div class="dropdown-content"></div>
131        </iron-dropdown>
132      </div>
133    </template>
134  </test-fixture>
135
136  <script>
137    function elementIsVisible(element) {
138      var contentRect = element.getBoundingClientRect();
139      var computedStyle = window.getComputedStyle(element);
140
141      return computedStyle.display !== 'none' &&
142        contentRect.width > 0 &&
143        contentRect.height > 0;
144    }
145
146    function runAfterOpen(overlay, callback) {
147      overlay.addEventListener('iron-overlay-opened', callback);
148      overlay.open();
149    }
150
151    suite('<iron-dropdown>', function() {
152      var dropdown;
153      var content;
154
155      suite('basic', function() {
156        setup(function() {
157          dropdown = fixture('TrivialDropdown');
158          content = Polymer.dom(dropdown).querySelector('.dropdown-content');
159        });
160
161        test('effectively hides the dropdown content', function() {
162          expect(elementIsVisible(content)).to.be.equal(false);
163        });
164
165        test('shows dropdown content when opened', function(done) {
166          runAfterOpen(dropdown, function () {
167            expect(elementIsVisible(content)).to.be.equal(true);
168            done();
169          });
170        });
171
172        test('hides dropdown content when outside is clicked', function(done) {
173          runAfterOpen(dropdown, function () {
174            expect(elementIsVisible(content)).to.be.equal(true);
175            dropdown.addEventListener('iron-overlay-closed', function() {
176              expect(elementIsVisible(content)).to.be.equal(false);
177              done();
178            });
179            MockInteractions.tap(dropdown.parentNode);
180          });
181        });
182
183        suite('when content is focusable', function() {
184          setup(function() {
185            dropdown = fixture('FocusableContentDropdown');
186            content = Polymer.dom(dropdown).querySelector('.dropdown-content');
187          });
188          test('focuses the content when opened', function(done) {
189            runAfterOpen(dropdown, function () {
190              expect(document.activeElement).to.be.equal(content);
191              done();
192            });
193          });
194
195          test('focuses a configured focus target', function(done) {
196            var focusableChild = Polymer.dom(content).querySelector('div[tabindex]');
197            dropdown.focusTarget = focusableChild;
198
199            runAfterOpen(dropdown, function () {
200              expect(document.activeElement).to.not.be.equal(content);
201              expect(document.activeElement).to.be.equal(focusableChild);
202              done();
203            });
204          });
205        });
206      });
207
208      suite('locking scroll', function() {
209
210        setup(function() {
211          dropdown = fixture('TrivialDropdown');
212        });
213
214        test('should lock, only once', function(done) {
215          var openCount = 0;
216          runAfterOpen(dropdown, function() {
217            expect(Polymer.IronDropdownScrollManager._lockingElements.length)
218              .to.be.equal(1);
219            expect(Polymer.IronDropdownScrollManager.elementIsScrollLocked(document.body))
220              .to.be.equal(true);
221
222            if(openCount === 0) {
223              // This triggers a second `pushScrollLock` with the same element, however
224              // that should not add the element to the `_lockingElements` stack twice
225              dropdown.close();
226              dropdown.open();
227            } else {
228              done();
229            }
230            openCount++;
231          });
232        });
233      });
234
235      suite('non locking scroll', function() {
236
237        setup(function() {
238          dropdown = fixture('NonLockingDropdown');
239        });
240
241        test('can be disabled with `allowOutsideScroll`', function(done) {
242          runAfterOpen(dropdown, function() {
243            expect(Polymer.IronDropdownScrollManager.elementIsScrollLocked(document.body))
244              .to.be.equal(false);
245            done();
246          });
247        });
248      });
249
250      suite('aligned dropdown', function() {
251        var parent;
252        var parentRect;
253        var dropdownRect;
254
255        setup(function() {
256          parent = fixture('AlignedDropdown');
257          dropdown = parent.querySelector('iron-dropdown');
258        });
259
260        test('can be re-aligned to the right and the top', function(done) {
261          runAfterOpen(dropdown, function () {
262            dropdownRect = dropdown.getBoundingClientRect();
263            parentRect = parent.getBoundingClientRect();
264            assert.equal(dropdownRect.top, parentRect.top, 'top ok');
265            assert.equal(dropdownRect.left, 0, 'left ok');
266            assert.equal(dropdownRect.bottom, document.documentElement.clientHeight, 'bottom ok');
267            assert.equal(dropdownRect.right, parentRect.right, 'right ok');
268            done();
269          });
270        });
271
272        test('can be re-aligned to the bottom', function(done) {
273          dropdown.verticalAlign = 'bottom';
274          runAfterOpen(dropdown, function () {
275            parentRect = parent.getBoundingClientRect();
276            dropdownRect = dropdown.getBoundingClientRect();
277            assert.equal(dropdownRect.top, 0, 'top ok');
278            assert.equal(dropdownRect.left, 0, 'left ok');
279            assert.equal(dropdownRect.bottom, parentRect.bottom, 'bottom ok');
280            assert.equal(dropdownRect.right, parentRect.right, 'right ok');
281            done();
282          });
283        });
284
285        test('handles parent\'s stacking context', function(done) {
286          // This will create a new stacking context.
287          parent.style.transform = 'translateZ(0)';
288          runAfterOpen(dropdown, function () {
289            dropdownRect = dropdown.getBoundingClientRect();
290            parentRect = parent.getBoundingClientRect();
291            assert.equal(dropdownRect.top, parentRect.top, 'top ok');
292            assert.equal(dropdownRect.left, 0, 'left ok');
293            assert.equal(dropdownRect.bottom, document.documentElement.clientHeight, 'bottom ok');
294            assert.equal(dropdownRect.right, parentRect.right, 'right ok');
295            done();
296          });
297        });
298      });
299
300      suite('when align is left/top, with an offset', function() {
301        var dropdownRect;
302        var offsetDropdownRect;
303        setup(function() {
304          var parent = fixture('OffsetDropdownTopLeft');
305          dropdown = parent.querySelector('iron-dropdown');
306        });
307
308        test('can be offset towards the bottom right', function(done) {
309          runAfterOpen(dropdown, function () {
310            dropdownRect = dropdown.getBoundingClientRect();
311            dropdown.verticalOffset = 10;
312            dropdown.horizontalOffset = 10;
313            // Force refit instead of waiting for requestAnimationFrame.
314            dropdown.refit();
315            offsetDropdownRect = dropdown.getBoundingClientRect();
316            // verticalAlign is top, so a positive offset moves down.
317            assert.equal(dropdownRect.top + 10, offsetDropdownRect.top, 'top ok');
318            // horizontalAlign is left, so a positive offset moves to the right.
319            assert.equal(dropdownRect.left + 10, offsetDropdownRect.left, 'left ok');
320            done();
321          });
322        });
323
324        test('can be offset towards the top left', function(done) {
325          runAfterOpen(dropdown, function () {
326            dropdownRect = dropdown.getBoundingClientRect();
327            dropdown.verticalOffset = -10;
328            dropdown.horizontalOffset = -10;
329            // Force refit instead of waiting for requestAnimationFrame.
330            dropdown.refit();
331            offsetDropdownRect = dropdown.getBoundingClientRect();
332            // verticalAlign is top, so a negative offset moves up.
333            assert.equal(dropdownRect.top - 10, offsetDropdownRect.top, 'top ok');
334            // horizontalAlign is left, so a negative offset moves to the left.
335            assert.equal(dropdownRect.left - 10, offsetDropdownRect.left, 'left ok');
336            done();
337          });
338        });
339      });
340
341      suite('when align is right/bottom, with an offset', function() {
342        var dropdownRect;
343        var offsetDropdownRect;
344        setup(function() {
345          var parent = fixture('OffsetDropdownBottomRight');
346          dropdown = parent.querySelector('iron-dropdown');
347        });
348
349        test('can be offset towards the top left', function(done) {
350          runAfterOpen(dropdown, function () {
351            dropdownRect = dropdown.getBoundingClientRect();
352            dropdown.verticalOffset = 10;
353            dropdown.horizontalOffset = 10;
354            // Force refit instead of waiting for requestAnimationFrame.
355            dropdown.refit();
356            offsetDropdownRect = dropdown.getBoundingClientRect();
357            // verticalAlign is bottom, so a positive offset moves up.
358            assert.equal(dropdownRect.bottom - 10, offsetDropdownRect.bottom, 'bottom ok');
359            // horizontalAlign is right, so a positive offset moves to the left.
360            assert.equal(dropdownRect.right - 10, offsetDropdownRect.right, 'right ok');
361            done();
362          });
363        });
364
365        test('can be offset towards the bottom right', function(done) {
366          runAfterOpen(dropdown, function () {
367            dropdownRect = dropdown.getBoundingClientRect();
368            dropdown.verticalOffset = -10;
369            dropdown.horizontalOffset = -10;
370            // Force refit instead of waiting for requestAnimationFrame.
371            dropdown.refit();
372            offsetDropdownRect = dropdown.getBoundingClientRect();
373            // verticalAlign is bottom, so a negative offset moves down.
374            assert.equal(dropdownRect.bottom + 10, offsetDropdownRect.bottom, 'bottom ok');
375            // horizontalAlign is right, so a positive offset moves to the right.
376            assert.equal(dropdownRect.right + 10, offsetDropdownRect.right, 'right ok');
377            done();
378          });
379        });
380      });
381
382      suite('RTL', function() {
383        var dropdownRect;
384
385        test('with horizontalAlign=left', function(done) {
386          var parent = fixture('RTLDropdownLeft');
387          dropdown = parent.querySelector('iron-dropdown');
388          runAfterOpen(dropdown, function () {
389            // In RTL, if `horizontalAlign` is "left", that's the same as
390            // being right-aligned in LTR. So the dropdown should be in the top
391            // right corner.
392            dropdownRect = dropdown.getBoundingClientRect();
393            expect(dropdownRect.top).to.be.equal(0);
394            expect(dropdownRect.right).to.be.equal(100);
395            done();
396          });
397        });
398
399        test('with horizontalAlign=right', function(done) {
400          var parent = fixture('RTLDropdownRight');
401          dropdown = parent.querySelector('iron-dropdown');
402          runAfterOpen(dropdown, function () {
403            // In RTL, if `horizontalAlign` is "right", that's the same as
404            // being left-aligned in LTR. So the dropdown should be in the top
405            // left corner.
406            dropdownRect = dropdown.getBoundingClientRect();
407            expect(dropdownRect.top).to.be.equal(0);
408            expect(dropdownRect.left).to.be.equal(0);
409            done();
410          });
411        });
412      });
413    });
414  </script>
415</body>
416</html>
417