jellyfin-web/dashboard-ui/bower_components/iron-overlay-behavior/test/iron-overlay-behavior.html
2016-02-06 01:33:34 -05:00

640 lines
24 KiB
HTML

<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<title>iron-overlay-behavior tests</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../web-component-tester/browser.js"></script>
<link rel="import" href="../../iron-test-helpers/iron-test-helpers.html">
<link rel="import" href="test-overlay.html">
<link rel="import" href="test-overlay2.html">
</head>
<body>
<test-fixture id="basic">
<template>
<test-overlay>
Basic Overlay
</test-overlay>
</template>
</test-fixture>
<test-fixture id="opened">
<template>
<test-overlay opened>
Basic Overlay
</test-overlay>
</template>
</test-fixture>
<test-fixture id="autofocus">
<template>
<test-overlay>
Autofocus
<button autofocus>button</button>
</test-overlay>
</template>
</test-fixture>
<test-fixture id="multiple">
<template>
<test-overlay class="overlay-1">
Overlay 1
</test-overlay>
<test-overlay class="overlay-2">
Overlay 2
</test-overlay>
<test-overlay class="overlay-3">
Overlay 3
</test-overlay>
</template>
</test-fixture>
<test-fixture id="backdrop-multiple">
<template>
<test-overlay with-backdrop class="overlay-1">
Overlay 1 with backdrop
</test-overlay>
<test-overlay with-backdrop class="overlay-2">
Overlay 2 with backdrop
</test-overlay>
<test-overlay with-backdrop class="overlay-3">
Overlay 3 with backdrop
</test-overlay>
</template>
</test-fixture>
<test-fixture id="backdrop-different-elements">
<template>
<test-overlay with-backdrop class="overlay-1">
Overlay 1 with backdrop
</test-overlay>
<test-overlay2 with-backdrop class="overlay-2">
Overlay 2 with backdrop
</test-overlay2>
</template>
</test-fixture>
<script>
function runAfterOpen(overlay, cb) {
overlay.addEventListener('iron-overlay-opened', function() {
Polymer.Base.async(cb, 1);
});
overlay.open();
}
suite('basic overlay tests', function() {
var overlay;
setup(function() {
overlay = fixture('basic');
});
test('overlay starts hidden', function() {
assert.isFalse(overlay.opened, 'overlay starts closed');
assert.equal(getComputedStyle(overlay).display, 'none', 'overlay starts hidden');
});
test('overlay open by default', function(done) {
overlay = fixture('opened');
overlay.addEventListener('iron-overlay-opened', function() {
assert.isTrue(overlay.opened, 'overlay starts opened');
assert.notEqual(getComputedStyle(overlay).display, 'none', 'overlay starts showing');
done();
});
});
test('overlay positioned & sized properly', function(done) {
overlay = fixture('opened');
overlay.addEventListener('iron-overlay-opened', function() {
var s = getComputedStyle(overlay);
assert.equal(parseFloat(s.left), (window.innerWidth - overlay.offsetWidth)/2, 'centered horizontally');
assert.equal(parseFloat(s.top), (window.innerHeight - overlay.offsetHeight)/2, 'centered vertically');
done();
});
});
test('overlay open/close events', function(done) {
var nevents = 0;
overlay.addEventListener('iron-overlay-opened', function() {
nevents += 1;
overlay.opened = false;
});
overlay.addEventListener('iron-overlay-closed', function() {
nevents += 1;
assert.equal(nevents, 2, 'opened and closed events fired');
done();
});
overlay.opened = true;
});
test('open overlay refits on iron-resize', function() {
var overlay = fixture('opened');
var spy = sinon.spy(overlay, 'refit');
overlay.fire('iron-resize');
assert.isTrue(spy.called, 'overlay should refit');
});
test('closed overlay does not refit on iron-resize', function() {
var spy = sinon.spy(overlay, 'refit');
overlay.fire('iron-resize');
assert.isFalse(spy.called, 'overlay should not refit');
});
test('open() triggers iron-resize', function(done) {
// Ignore iron-resize triggered by window resize.
var callCount = 0;
window.addEventListener('resize', function() { callCount--; }, true);
overlay.addEventListener('iron-resize', function () { callCount++; });
runAfterOpen(overlay, function () {
assert.equal(callCount, 1, 'iron-resize should be called once');
done();
});
});
test('closed overlay does not trigger iron-resize when its content changes', function(done) {
// Ignore iron-resize triggered by window resize.
var callCount = 0;
window.addEventListener('resize', function() { callCount--; }, true);
overlay.addEventListener('iron-resize', function () { callCount++; });
var child = document.createElement('div');
child.innerHTML = 'hi';
Polymer.dom(overlay).appendChild(child);
overlay.async(function () {
assert.equal(callCount, 0, 'iron-resize should not be called');
done();
}, 10);
});
test('open overlay triggers iron-resize when its content changes', function(done) {
runAfterOpen(overlay, function () {
// Ignore iron-resize triggered by window resize.
var callCount = 0;
window.addEventListener('resize', function() { callCount--; }, true);
overlay.addEventListener('iron-resize', function () { callCount++; });
var child = document.createElement('div');
child.innerHTML = 'hi';
Polymer.dom(overlay).appendChild(child);
overlay.async(function () {
assert.equal(callCount, 1, 'iron-resize should be called once');
done();
}, 10);
});
});
test('close an overlay quickly after open', function(done) {
// first, open the overlay
overlay.open();
overlay.async(function() {
// during the opening transition, close the overlay
this.close();
// wait for any exceptions to be thrown until the transition is done
this.async(function() {
done();
}, 300);
});
});
test('close an overlay in proximity to another overlay', function(done) {
var secondOverlay = fixture('basic');
// Open and close a separate overlay.
secondOverlay.open();
secondOverlay.close();
// Open the overlay we care about.
overlay.open();
// Wait for infinite recursion, otherwise we win:
overlay.addEventListener('iron-overlay-closed', function() {
done();
});
// Immediately close the first overlay:
overlay.close();
});
test('clicking an overlay does not close it', function(done) {
runAfterOpen(overlay, function() {
var spy = sinon.stub();
overlay.addEventListener('iron-overlay-closed', spy);
overlay.fire('click');
setTimeout(function() {
assert.isFalse(spy.called, 'iron-overlay-closed should not fire');
done();
}, 10);
});
});
test('node with autofocus is focused', function(done) {
overlay = fixture('autofocus');
runAfterOpen(overlay, function() {
assert.equal(Polymer.dom(overlay).querySelector('[autofocus]'), document.activeElement, '<button autofocus> is focused');
done();
});
});
test('cancel an overlay by clicking outside', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-canceled', function(event) {
done();
});
MockInteractions.tap(document.body);
});
});
test('close an overlay by clicking outside', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-closed', function(event) {
assert.isTrue(event.detail.canceled, 'overlay is canceled');
done();
});
MockInteractions.tap(document.body);
});
});
test('cancel event can be prevented', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-canceled', function(event) {
event.preventDefault();
});
var spy = sinon.stub();
overlay.addEventListener('iron-overlay-closed', spy);
MockInteractions.tap(document.body);
setTimeout(function() {
assert.isFalse(spy.called, 'iron-overlay-closed should not fire');
done();
}, 10);
});
});
test('cancel an overlay with esc key', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-canceled', function(event) {
done();
});
fireEvent('keydown', {
keyCode: 27
}, document);
});
});
test('close an overlay with esc key', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-closed', function(event) {
assert.isTrue(event.detail.canceled, 'overlay is canceled');
done();
});
fireEvent('keydown', {
keyCode: 27
}, document);
});
});
test('no-cancel-on-outside-click property', function(done) {
overlay.noCancelOnOutsideClick = true;
runAfterOpen(overlay, function() {
var spy = sinon.stub();
overlay.addEventListener('iron-overlay-closed', spy);
MockInteractions.tap(document.body);
setTimeout(function() {
assert.isFalse(spy.called, 'iron-overlay-closed should not fire');
done();
}, 10);
});
});
test('no-cancel-on-outside-click property; focus stays on overlay when click outside', function(done) {
overlay = fixture('autofocus');
overlay.noCancelOnOutsideClick = true;
runAfterOpen(overlay, function() {
MockInteractions.tap(document.body);
setTimeout(function() {
assert.equal(Polymer.dom(overlay).querySelector('[autofocus]'), document.activeElement, '<button autofocus> is focused');
done();
}, 10);
});
});
test('no-cancel-on-esc-key property', function(done) {
overlay.noCancelOnEscKey = true;
runAfterOpen(overlay, function() {
var spy = sinon.stub();
overlay.addEventListener('iron-overlay-closed', spy);
fireEvent('keydown', {
keyCode: 27
}, document);
setTimeout(function() {
assert.isFalse(spy.called, 'iron-overlay-cancel should not fire');
done();
}, 10);
});
});
});
suite('multiple overlays', function() {
var overlays;
setup(function() {
overlays = fixture('multiple');
});
test('new overlays appear on top', function(done) {
runAfterOpen(overlays[0], function() {
runAfterOpen(overlays[1], function() {
var styleZ = parseInt(window.getComputedStyle(overlays[0]).zIndex, 10);
var styleZ1 = parseInt(window.getComputedStyle(overlays[1]).zIndex, 10);
assert.isTrue(styleZ1 > styleZ, 'overlays[1] has higher z-index than overlays[0]');
done();
});
});
});
test('ESC closes only one opened overlay', function(done) {
runAfterOpen(overlays[0], function() {
runAfterOpen(overlays[1], function() {
// keydown is sync, keyup async (but no need to wait for it).
MockInteractions.pressAndReleaseKeyOn(document.body, 27);
// Ideally overlays[1] should be closed and overlays[0] still open,
// but in this test env overlays[0]._onCaptureKeydown gets called before
// overlays[1]._onCaptureKeydown.
// TODO investigate if this is because of CustomEvents in MockInteractions.
var opened0 = overlays[0].opened && !overlays[1].opened;
var opened1 = !overlays[0].opened && overlays[1].opened;
assert.isTrue(opened0 || opened1, 'only one overlay is still opened');
done();
});
});
});
});
suite('z-ordering', function() {
var overlays;
var originalMinimumZ;
setup(function() {
overlays = fixture('multiple');
originalMinimumZ = Polymer.IronOverlayManager._minimumZ;
});
teardown(function() {
Polymer.IronOverlayManager._minimumZ = originalMinimumZ;
});
// for iframes
test('default z-index is greater than 100', function(done) {
runAfterOpen(overlays[0], function() {
var styleZ = parseInt(window.getComputedStyle(overlays[0]).zIndex, 10);
assert.isTrue(styleZ > 100, 'overlays[0] z-index is <= 100');
done();
});
});
test('ensureMinimumZ() effects z-index', function(done) {
Polymer.IronOverlayManager.ensureMinimumZ(1000);
runAfterOpen(overlays[0], function() {
var styleZ = parseInt(window.getComputedStyle(overlays[0]).zIndex, 10);
assert.isTrue(styleZ > 1000, 'overlays[0] z-index is <= 1000');
done();
});
});
test('ensureMinimumZ() never decreases the minimum z-index', function(done) {
Polymer.IronOverlayManager.ensureMinimumZ(1000);
Polymer.IronOverlayManager.ensureMinimumZ(500);
runAfterOpen(overlays[0], function() {
var styleZ = parseInt(window.getComputedStyle(overlays[0]).zIndex, 10);
assert.isTrue(styleZ > 1000, 'overlays[0] z-index is <= 1000');
done();
});
});
});
suite('overlays with backdrop', function() {
var overlays;
setup(function() {
overlays = fixture('backdrop-multiple');
});
test('backdrop appears behind the overlay', function(done) {
runAfterOpen(overlays[0], function() {
assert.isDefined(overlays[0].backdropElement, 'backdrop is defined');
assert.isDefined(overlays[0].backdropElement.parentNode, 'backdrop is inserted in the DOM');
styleZ = parseInt(window.getComputedStyle(overlays[0]).zIndex, 10);
backdropStyleZ = parseInt(window.getComputedStyle(overlays[0].backdropElement).zIndex, 10);
assert.isTrue(styleZ > backdropStyleZ, 'overlay has higher z-index than backdrop');
done();
});
});
test('backdrop is removed when the element is removed from DOM', function(done) {
runAfterOpen(overlays[0], function() {
var backdrop = overlays[0].backdropElement;
Polymer.dom(backdrop.parentNode).removeChild(backdrop);
Polymer.dom.flush();
assert.isNull(backdrop.parentNode, 'backdrop is removed from DOM');
assert.lengthOf(document.querySelectorAll('iron-overlay-backdrop'), (0));
done();
});
});
test('backdrop is opened when iron-overlay-open-completed fires', function(done) {
runAfterOpen(overlays[0], function() {
assert.isTrue(overlays[0].backdropElement.opened, 'backdrop is opened');
done();
});
});
test('manager backdrops immediately updated on opened changes', function() {
overlays[0].opened = true;
assert.equal(overlays[0]._manager.getBackdrops().length, 1, 'overlay added to manager backdrops');
overlays[0].opened = false;
assert.equal(overlays[0]._manager.getBackdrops().length, 0, 'overlay removed from manager backdrops');
});
test('with-backdrop sets tabindex=-1 and removes it', function() {
var overlay = fixture('basic');
overlay.withBackdrop = true;
assert.equal(overlay.getAttribute('tabindex'), '-1', 'tabindex is -1');
overlay.withBackdrop = false;
assert.isFalse(overlay.hasAttribute('tabindex'), 'tabindex removed');
});
test('with-backdrop does not override tabindex if already set', function() {
var overlay = fixture('basic');
overlay.setAttribute('tabindex', '1');
overlay.withBackdrop = true;
assert.equal(overlay.getAttribute('tabindex'), '1', 'tabindex is 1');
overlay.withBackdrop = false;
assert.equal(overlay.getAttribute('tabindex'), '1', 'tabindex is still 1');
});
test('with-backdrop traps the focus within the overlay', function(done) {
// Add button to try to "steal" focus.
var button = document.createElement('button');
var focusSpy = sinon.stub();
button.addEventListener('focus', focusSpy, true);
document.body.appendChild(button);
var overlay = fixture('autofocus');
overlay.withBackdrop = true;
runAfterOpen(overlay, function() {
// Try to steal the focus
MockInteractions.focus(button);
assert.isFalse(focusSpy.called, 'button in body did not get the focus');
assert.equal(Polymer.dom(overlay).querySelector('[autofocus]'), document.activeElement, '<button autofocus> is focused');
button.parentNode.removeChild(button);
done();
});
});
});
suite('multiple overlays with backdrop', function() {
var overlays;
setup(function() {
overlays = fixture('backdrop-multiple');
});
test('multiple overlays share the same backdrop', function() {
assert.isTrue(overlays[0].backdropElement === overlays[1].backdropElement, 'overlays[0] has the same backdrop element as overlays[1]');
});
test('newest overlay appear on top', function(done) {
runAfterOpen(overlays[0], function() {
runAfterOpen(overlays[1], function() {
var styleZ = parseInt(window.getComputedStyle(overlays[0]).zIndex, 10);
var style1Z = parseInt(window.getComputedStyle(overlays[1]).zIndex, 10);
var bgStyleZ = parseInt(window.getComputedStyle(overlays[0].backdropElement).zIndex, 10);
assert.isTrue(style1Z > styleZ, 'overlays[1] has higher z-index than overlays[0]');
assert.isTrue(styleZ > bgStyleZ, 'overlays[0] has higher z-index than backdrop');
done();
});
});
});
test('updating with-backdrop to false closes backdrop', function(done) {
// no waiting for animations
overlays[0].backdropElement.style.transitionDuration = '0s';
runAfterOpen(overlays[0], function() {
overlays[0].withBackdrop = false;
assert.isFalse(overlays[0].backdropElement.opened, 'backdrop is closed');
assert.isNotObject(overlays[0].backdropElement.parentNode, 'backdrop is removed from document');
overlays[0].backdropElement.style.transitionDuration = '';
done();
});
});
test('backdrop is removed when toggling overlay opened', function(done) {
overlays[0].open();
assert.isObject(overlays[0].backdropElement.parentNode, 'backdrop is immediately inserted in the document');
overlays[0].close();
// Wait a tick (overlay will call backdropElement.close in the _openChangedAsync)
setTimeout(function() {
assert.isFalse(overlays[0].backdropElement.opened, 'backdrop is closed');
assert.isNotObject(overlays[0].backdropElement.parentNode, 'backdrop is removed from document');
done();
}, 1);
});
test('updating with-backdrop updates z-index', function(done) {
runAfterOpen(overlays[0], function() {
runAfterOpen(overlays[1], function() {
overlays[0].withBackdrop = false;
var styleZ = parseInt(window.getComputedStyle(overlays[0]).zIndex, 10);
var style1Z = parseInt(window.getComputedStyle(overlays[1]).zIndex, 10);
var bgStyleZ = parseInt(window.getComputedStyle(overlays[0].backdropElement).zIndex, 10);
assert.isTrue(style1Z > bgStyleZ, 'overlays[1] has higher z-index than backdrop');
assert.isTrue(styleZ < bgStyleZ, 'overlays[0] has lower z-index than backdrop');
done();
});
});
});
});
suite('multiple overlays with backdrop implemented in different elements', function () {
var overlays;
setup(function() {
overlays = fixture('backdrop-different-elements');
});
test('multiple overlays share the same backdrop', function() {
assert.equal(overlays[0].backdropElement, overlays[1].backdropElement);
});
test('when overlays close, the backdrop is closed', function(done) {
runAfterOpen(overlays[0], function () {
assert.lengthOf(document.querySelectorAll('iron-overlay-backdrop'), 1);
// After second overlay is closed, both backdrops should be hidden
overlays[1].addEventListener('iron-overlay-closed', function() {
Polymer.Base.async(function () {
assert.isFalse(overlays[1].backdropElement.opened, 'second overlay backdrop is closed');
assert.isFalse(overlays[0].backdropElement.opened, 'first overlay backdrop is closed');
done();
}, 1);
});
// After second overlay is opened, immediately close it
overlays[1].addEventListener('iron-overlay-opened', function() {
Polymer.Base.async(function () {
overlays[1].close();
}, 1);
});
// Immediately close first overlay and open the other one
overlays[0].close();
overlays[1].open();
});
});
})
suite('a11y', function() {
test('overlay has aria-hidden=true when opened', function() {
var overlay = fixture('basic');
assert.equal(overlay.getAttribute('aria-hidden'), 'true', 'overlay has aria-hidden="true"');
overlay.open();
assert.isFalse(overlay.hasAttribute('aria-hidden'), 'overlay does not have aria-hidden attribute');
overlay.close();
assert.equal(overlay.getAttribute('aria-hidden'), 'true', 'overlay has aria-hidden="true"');
});
})
</script>
</body>
</html>