Home | History | Annotate | Download | only in test
      1 <!doctype html>
      2 <!--
      3 @license
      4 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
      5 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
      6 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
      7 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
      8 Code distributed by Google as part of the polymer project is also
      9 subject 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