949 lines
34 KiB
JavaScript
949 lines
34 KiB
JavaScript
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
goog.provide('goog.ui.SliderBaseTest');
|
|
goog.setTestOnly('goog.ui.SliderBaseTest');
|
|
|
|
goog.require('goog.a11y.aria');
|
|
goog.require('goog.a11y.aria.State');
|
|
goog.require('goog.dom');
|
|
goog.require('goog.dom.classlist');
|
|
goog.require('goog.events');
|
|
goog.require('goog.events.EventType');
|
|
goog.require('goog.events.KeyCodes');
|
|
goog.require('goog.fx.Animation');
|
|
goog.require('goog.math.Coordinate');
|
|
goog.require('goog.style');
|
|
goog.require('goog.style.bidi');
|
|
goog.require('goog.testing.MockClock');
|
|
goog.require('goog.testing.MockControl');
|
|
goog.require('goog.testing.events');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.testing.mockmatchers');
|
|
goog.require('goog.testing.recordFunction');
|
|
goog.require('goog.ui.Component');
|
|
goog.require('goog.ui.SliderBase');
|
|
goog.require('goog.userAgent');
|
|
|
|
var oneThumbSlider;
|
|
var oneThumbSliderRtl;
|
|
var oneChangeEventCount;
|
|
|
|
var twoThumbSlider;
|
|
var twoThumbSliderRtl;
|
|
var twoChangeEventCount;
|
|
|
|
var mockClock;
|
|
var mockAnimation;
|
|
|
|
|
|
|
|
/**
|
|
* A basic class to implement the abstract goog.ui.SliderBase for testing.
|
|
* @constructor
|
|
* @extends {goog.ui.SliderBase}
|
|
*/
|
|
function OneThumbSlider() {
|
|
goog.ui.SliderBase.call(this, undefined /* domHelper */, function(value) {
|
|
return value > 5 ? 'A big value.' : 'A small value.';
|
|
});
|
|
}
|
|
goog.inherits(OneThumbSlider, goog.ui.SliderBase);
|
|
|
|
|
|
/** @override */
|
|
OneThumbSlider.prototype.createThumbs = function() {
|
|
this.valueThumb = this.extentThumb = goog.dom.getElement('thumb');
|
|
};
|
|
|
|
|
|
/** @override */
|
|
OneThumbSlider.prototype.getCssClass = function(orientation) {
|
|
return goog.getCssName('test-slider', orientation);
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* A basic class to implement the abstract goog.ui.SliderBase for testing.
|
|
* @constructor
|
|
* @extends {goog.ui.SliderBase}
|
|
*/
|
|
function TwoThumbSlider() {
|
|
goog.ui.SliderBase.call(this);
|
|
}
|
|
goog.inherits(TwoThumbSlider, goog.ui.SliderBase);
|
|
|
|
|
|
/** @override */
|
|
TwoThumbSlider.prototype.createThumbs = function() {
|
|
this.valueThumb = goog.dom.getElement('valueThumb');
|
|
this.extentThumb = goog.dom.getElement('extentThumb');
|
|
this.rangeHighlight = goog.dom.getElement('rangeHighlight');
|
|
};
|
|
|
|
|
|
/** @override */
|
|
TwoThumbSlider.prototype.getCssClass = function(orientation) {
|
|
return goog.getCssName('test-slider', orientation);
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* Basic class that implements the AnimationFactory interface for testing.
|
|
* @param {!goog.fx.Animation|!Array<!goog.fx.Animation>} testAnimations The
|
|
* test animations to use.
|
|
* @constructor
|
|
* @implements {goog.ui.SliderBase.AnimationFactory}
|
|
*/
|
|
function AnimationFactory(testAnimations) {
|
|
this.testAnimations = testAnimations;
|
|
}
|
|
|
|
|
|
/** @override */
|
|
AnimationFactory.prototype.createAnimations = function() {
|
|
return this.testAnimations;
|
|
};
|
|
|
|
|
|
function setUp() {
|
|
var sandBox = goog.dom.getElement('sandbox');
|
|
mockClock = new goog.testing.MockClock(true);
|
|
|
|
var oneThumbElem = goog.dom.createDom(
|
|
'div', {'id': 'oneThumbSlider'},
|
|
goog.dom.createDom('span', {'id': 'thumb'}));
|
|
sandBox.appendChild(oneThumbElem);
|
|
oneThumbSlider = new OneThumbSlider();
|
|
oneThumbSlider.decorate(oneThumbElem);
|
|
oneChangeEventCount = 0;
|
|
goog.events.listen(oneThumbSlider, goog.ui.Component.EventType.CHANGE,
|
|
function() {
|
|
oneChangeEventCount++;
|
|
});
|
|
|
|
var twoThumbElem = goog.dom.createDom(
|
|
'div', {'id': 'twoThumbSlider'},
|
|
goog.dom.createDom('div', {'id': 'rangeHighlight'}),
|
|
goog.dom.createDom('span', {'id': 'valueThumb'}),
|
|
goog.dom.createDom('span', {'id': 'extentThumb'}));
|
|
sandBox.appendChild(twoThumbElem);
|
|
twoThumbSlider = new TwoThumbSlider();
|
|
twoThumbSlider.decorate(twoThumbElem);
|
|
twoChangeEventCount = 0;
|
|
goog.events.listen(twoThumbSlider, goog.ui.Component.EventType.CHANGE,
|
|
function() {
|
|
twoChangeEventCount++;
|
|
});
|
|
|
|
var sandBoxRtl = goog.dom.createDom('div',
|
|
{'dir': 'rtl', 'style': 'position:absolute;'});
|
|
sandBox.appendChild(sandBoxRtl);
|
|
|
|
var oneThumbElemRtl = goog.dom.createDom(
|
|
'div', {'id': 'oneThumbSliderRtl'},
|
|
goog.dom.createDom('span', {'id': 'thumbRtl'}));
|
|
sandBoxRtl.appendChild(oneThumbElemRtl);
|
|
oneThumbSliderRtl = new OneThumbSlider();
|
|
oneThumbSliderRtl.enableFlipForRtl(true);
|
|
oneThumbSliderRtl.decorate(oneThumbElemRtl);
|
|
goog.events.listen(oneThumbSliderRtl, goog.ui.Component.EventType.CHANGE,
|
|
function() {
|
|
oneChangeEventCount++;
|
|
});
|
|
|
|
var twoThumbElemRtl = goog.dom.createDom(
|
|
'div', {'id': 'twoThumbSliderRtl'},
|
|
goog.dom.createDom('div', {'id': 'rangeHighlightRtl'}),
|
|
goog.dom.createDom('span', {'id': 'valueThumbRtl'}),
|
|
goog.dom.createDom('span', {'id': 'extentThumbRtl'}));
|
|
sandBoxRtl.appendChild(twoThumbElemRtl);
|
|
twoThumbSliderRtl = new TwoThumbSlider();
|
|
twoThumbSliderRtl.enableFlipForRtl(true);
|
|
twoThumbSliderRtl.decorate(twoThumbElemRtl);
|
|
twoChangeEventCount = 0;
|
|
goog.events.listen(twoThumbSliderRtl, goog.ui.Component.EventType.CHANGE,
|
|
function() {
|
|
twoChangeEventCount++;
|
|
});
|
|
}
|
|
|
|
function tearDown() {
|
|
oneThumbSlider.dispose();
|
|
twoThumbSlider.dispose();
|
|
oneThumbSliderRtl.dispose();
|
|
twoThumbSliderRtl.dispose();
|
|
mockClock.dispose();
|
|
goog.dom.getElement('sandbox').innerHTML = '';
|
|
}
|
|
|
|
function testGetAndSetValue() {
|
|
oneThumbSlider.setValue(30);
|
|
assertEquals(30, oneThumbSlider.getValue());
|
|
assertEquals('Setting valid value must dispatch only a single change event.',
|
|
1, oneChangeEventCount);
|
|
|
|
oneThumbSlider.setValue(30);
|
|
assertEquals(30, oneThumbSlider.getValue());
|
|
assertEquals('Setting to same value must not dispatch change event.',
|
|
1, oneChangeEventCount);
|
|
|
|
oneThumbSlider.setValue(-30);
|
|
assertEquals('Setting invalid value must not change value.',
|
|
30, oneThumbSlider.getValue());
|
|
assertEquals('Setting invalid value must not dispatch change event.',
|
|
1, oneChangeEventCount);
|
|
|
|
|
|
// Value thumb can't go past extent thumb, so we must move that first to
|
|
// allow setting value.
|
|
twoThumbSlider.setExtent(70);
|
|
twoChangeEventCount = 0;
|
|
twoThumbSlider.setValue(60);
|
|
assertEquals(60, twoThumbSlider.getValue());
|
|
assertEquals('Setting valid value must dispatch only a single change event.',
|
|
1, twoChangeEventCount);
|
|
|
|
twoThumbSlider.setValue(60);
|
|
assertEquals(60, twoThumbSlider.getValue());
|
|
assertEquals('Setting to same value must not dispatch change event.',
|
|
1, twoChangeEventCount);
|
|
|
|
twoThumbSlider.setValue(-60);
|
|
assertEquals('Setting invalid value must not change value.',
|
|
60, twoThumbSlider.getValue());
|
|
assertEquals('Setting invalid value must not dispatch change event.',
|
|
1, twoChangeEventCount);
|
|
}
|
|
|
|
function testGetAndSetValueRtl() {
|
|
var thumbElement = goog.dom.getElement('thumbRtl');
|
|
assertEquals(0, goog.style.bidi.getOffsetStart(thumbElement));
|
|
assertEquals('', thumbElement.style.left);
|
|
assertTrue(thumbElement.style.right >= 0);
|
|
|
|
oneThumbSliderRtl.setValue(30);
|
|
assertEquals(30, oneThumbSliderRtl.getValue());
|
|
assertEquals('Setting valid value must dispatch only a single change event.',
|
|
1, oneChangeEventCount);
|
|
|
|
assertEquals('', thumbElement.style.left);
|
|
assertTrue(thumbElement.style.right >= 0);
|
|
|
|
oneThumbSliderRtl.setValue(30);
|
|
assertEquals(30, oneThumbSliderRtl.getValue());
|
|
assertEquals('Setting to same value must not dispatch change event.',
|
|
1, oneChangeEventCount);
|
|
|
|
oneThumbSliderRtl.setValue(-30);
|
|
assertEquals('Setting invalid value must not change value.',
|
|
30, oneThumbSliderRtl.getValue());
|
|
assertEquals('Setting invalid value must not dispatch change event.',
|
|
1, oneChangeEventCount);
|
|
|
|
|
|
// Value thumb can't go past extent thumb, so we must move that first to
|
|
// allow setting value.
|
|
var valueThumbElement = goog.dom.getElement('valueThumbRtl');
|
|
var extentThumbElement = goog.dom.getElement('extentThumbRtl');
|
|
assertEquals(0, goog.style.bidi.getOffsetStart(valueThumbElement));
|
|
assertEquals(0, goog.style.bidi.getOffsetStart(extentThumbElement));
|
|
assertEquals('', valueThumbElement.style.left);
|
|
assertTrue(valueThumbElement.style.right >= 0);
|
|
assertEquals('', extentThumbElement.style.left);
|
|
assertTrue(extentThumbElement.style.right >= 0);
|
|
|
|
twoThumbSliderRtl.setExtent(70);
|
|
twoChangeEventCount = 0;
|
|
twoThumbSliderRtl.setValue(60);
|
|
assertEquals(60, twoThumbSliderRtl.getValue());
|
|
assertEquals('Setting valid value must dispatch only a single change event.',
|
|
1, twoChangeEventCount);
|
|
|
|
twoThumbSliderRtl.setValue(60);
|
|
assertEquals(60, twoThumbSliderRtl.getValue());
|
|
assertEquals('Setting to same value must not dispatch change event.',
|
|
1, twoChangeEventCount);
|
|
|
|
assertEquals('', valueThumbElement.style.left);
|
|
assertTrue(valueThumbElement.style.right >= 0);
|
|
assertEquals('', extentThumbElement.style.left);
|
|
assertTrue(extentThumbElement.style.right >= 0);
|
|
|
|
twoThumbSliderRtl.setValue(-60);
|
|
assertEquals('Setting invalid value must not change value.',
|
|
60, twoThumbSliderRtl.getValue());
|
|
assertEquals('Setting invalid value must not dispatch change event.',
|
|
1, twoChangeEventCount);
|
|
}
|
|
|
|
function testGetAndSetExtent() {
|
|
// Note(user): With a one thumb slider the API only really makes sense if you
|
|
// always use setValue since there is no extent.
|
|
|
|
twoThumbSlider.setExtent(7);
|
|
assertEquals(7, twoThumbSlider.getExtent());
|
|
assertEquals('Setting valid value must dispatch only a single change event.',
|
|
1, twoChangeEventCount);
|
|
|
|
twoThumbSlider.setExtent(7);
|
|
assertEquals(7, twoThumbSlider.getExtent());
|
|
assertEquals('Setting to same value must not dispatch change event.',
|
|
1, twoChangeEventCount);
|
|
|
|
twoThumbSlider.setExtent(-7);
|
|
assertEquals('Setting invalid value must not change value.',
|
|
7, twoThumbSlider.getExtent());
|
|
assertEquals('Setting invalid value must not dispatch change event.',
|
|
1, twoChangeEventCount);
|
|
}
|
|
|
|
function testUpdateValueExtent() {
|
|
twoThumbSlider.setValueAndExtent(30, 50);
|
|
|
|
assertNotNull(twoThumbSlider.getElement());
|
|
assertEquals('Setting value results in updating aria-valuenow',
|
|
'30',
|
|
goog.a11y.aria.getState(twoThumbSlider.getElement(),
|
|
goog.a11y.aria.State.VALUENOW));
|
|
assertEquals(30, twoThumbSlider.getValue());
|
|
assertEquals(50, twoThumbSlider.getExtent());
|
|
}
|
|
|
|
function testValueText() {
|
|
oneThumbSlider.setValue(10);
|
|
assertEquals('Setting value results in correct aria-valuetext',
|
|
'A big value.', goog.a11y.aria.getState(oneThumbSlider.getElement(),
|
|
goog.a11y.aria.State.VALUETEXT));
|
|
oneThumbSlider.setValue(2);
|
|
assertEquals('Updating value results in updated aria-valuetext',
|
|
'A small value.', goog.a11y.aria.getState(oneThumbSlider.getElement(),
|
|
goog.a11y.aria.State.VALUETEXT));
|
|
}
|
|
|
|
function testGetValueText() {
|
|
oneThumbSlider.setValue(10);
|
|
assertEquals('Getting the text value gets the correct description',
|
|
'A big value.', oneThumbSlider.getTextValue());
|
|
oneThumbSlider.setValue(2);
|
|
assertEquals(
|
|
'Getting the updated text value gets the correct updated description',
|
|
'A small value.', oneThumbSlider.getTextValue());
|
|
}
|
|
|
|
function testRangeListener() {
|
|
var slider = new goog.ui.SliderBase;
|
|
slider.updateUi_ = slider.updateAriaStates = function() {};
|
|
slider.rangeModel.setValue(0);
|
|
|
|
var f = goog.testing.recordFunction();
|
|
goog.events.listen(slider, goog.ui.Component.EventType.CHANGE, f);
|
|
|
|
slider.rangeModel.setValue(50);
|
|
assertEquals(1, f.getCallCount());
|
|
|
|
slider.exitDocument();
|
|
slider.rangeModel.setValue(0);
|
|
assertEquals('The range model listener should not have been removed so we ' +
|
|
'should have gotten a second event dispatch',
|
|
2, f.getCallCount());
|
|
}
|
|
|
|
|
|
/**
|
|
* Verifies that rangeHighlight position and size are correct for the given
|
|
* startValue and endValue. Assumes slider has default min/max values [0, 100],
|
|
* width of 1020px, and thumb widths of 20px, with rangeHighlight drawn from
|
|
* the centers of the thumbs.
|
|
* @param {number} rangeHighlight The range highlight.
|
|
* @param {number} startValue The start value.
|
|
* @param {number} endValue The end value.
|
|
*/
|
|
function assertHighlightedRange(rangeHighlight, startValue, endValue) {
|
|
var rangeStr = '[' + startValue + ', ' + endValue + ']';
|
|
var rangeStart = 10 + 10 * startValue;
|
|
assertEquals('Range highlight for ' + rangeStr + ' should start at ' +
|
|
rangeStart + 'px.', rangeStart, rangeHighlight.offsetLeft);
|
|
var rangeSize = 10 * (endValue - startValue);
|
|
assertEquals('Range highlight for ' + rangeStr + ' should have size ' +
|
|
rangeSize + 'px.', rangeSize, rangeHighlight.offsetWidth);
|
|
}
|
|
|
|
function testKeyHandlingTests() {
|
|
twoThumbSlider.setValue(0);
|
|
twoThumbSlider.setExtent(100);
|
|
assertEquals(0, twoThumbSlider.getValue());
|
|
assertEquals(100, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
|
|
assertEquals(1, twoThumbSlider.getValue());
|
|
assertEquals(99, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
|
|
assertEquals(2, twoThumbSlider.getValue());
|
|
assertEquals(98, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
|
|
assertEquals(1, twoThumbSlider.getValue());
|
|
assertEquals(98, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
|
|
assertEquals(0, twoThumbSlider.getValue());
|
|
assertEquals(98, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT,
|
|
{ shiftKey: true });
|
|
assertEquals(10, twoThumbSlider.getValue());
|
|
assertEquals(90, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT,
|
|
{ shiftKey: true });
|
|
assertEquals(20, twoThumbSlider.getValue());
|
|
assertEquals(80, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT,
|
|
{ shiftKey: true });
|
|
assertEquals(10, twoThumbSlider.getValue());
|
|
assertEquals(80, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT,
|
|
{ shiftKey: true });
|
|
assertEquals(0, twoThumbSlider.getValue());
|
|
assertEquals(80, twoThumbSlider.getExtent());
|
|
}
|
|
|
|
function testKeyHandlingLargeStepSize() {
|
|
twoThumbSlider.setValue(0);
|
|
twoThumbSlider.setExtent(100);
|
|
twoThumbSlider.setStep(5);
|
|
assertEquals(0, twoThumbSlider.getValue());
|
|
assertEquals(100, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
|
|
assertEquals(5, twoThumbSlider.getValue());
|
|
assertEquals(95, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
|
|
assertEquals(10, twoThumbSlider.getValue());
|
|
assertEquals(90, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
|
|
assertEquals(5, twoThumbSlider.getValue());
|
|
assertEquals(90, twoThumbSlider.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
|
|
assertEquals(0, twoThumbSlider.getValue());
|
|
assertEquals(90, twoThumbSlider.getExtent());
|
|
}
|
|
|
|
function testKeyHandlingRtl() {
|
|
twoThumbSliderRtl.setValue(0);
|
|
twoThumbSliderRtl.setExtent(100);
|
|
assertEquals(0, twoThumbSliderRtl.getValue());
|
|
assertEquals(100, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT);
|
|
assertEquals(0, twoThumbSliderRtl.getValue());
|
|
assertEquals(99, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT);
|
|
assertEquals(0, twoThumbSliderRtl.getValue());
|
|
assertEquals(98, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT);
|
|
assertEquals(1, twoThumbSliderRtl.getValue());
|
|
assertEquals(98, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT);
|
|
assertEquals(2, twoThumbSliderRtl.getValue());
|
|
assertEquals(98, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT,
|
|
{ shiftKey: true });
|
|
assertEquals(0, twoThumbSliderRtl.getValue());
|
|
assertEquals(90, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT,
|
|
{ shiftKey: true });
|
|
assertEquals(0, twoThumbSliderRtl.getValue());
|
|
assertEquals(80, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT,
|
|
{ shiftKey: true });
|
|
assertEquals(10, twoThumbSliderRtl.getValue());
|
|
assertEquals(80, twoThumbSliderRtl.getExtent());
|
|
|
|
goog.testing.events.fireKeySequence(
|
|
twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT,
|
|
{ shiftKey: true });
|
|
assertEquals(20, twoThumbSliderRtl.getValue());
|
|
assertEquals(80, twoThumbSliderRtl.getExtent());
|
|
}
|
|
|
|
function testRangeHighlight() {
|
|
var rangeHighlight = goog.dom.getElement('rangeHighlight');
|
|
|
|
// Test [0, 100]
|
|
twoThumbSlider.setValue(0);
|
|
twoThumbSlider.setExtent(100);
|
|
assertHighlightedRange(rangeHighlight, 0, 100);
|
|
|
|
// Test [25, 75]
|
|
twoThumbSlider.setValue(25);
|
|
twoThumbSlider.setExtent(50);
|
|
assertHighlightedRange(rangeHighlight, 25, 75);
|
|
|
|
// Test [50, 50]
|
|
twoThumbSlider.setValue(50);
|
|
twoThumbSlider.setExtent(0);
|
|
assertHighlightedRange(rangeHighlight, 50, 50);
|
|
}
|
|
|
|
function testRangeHighlightAnimation() {
|
|
var animationDelay = 160; // Delay in ms, is a bit higher than actual delay.
|
|
if (goog.userAgent.IE) {
|
|
// For some reason, (probably due to how timing works), IE7 and IE8 will not
|
|
// stop if we don't wait for it.
|
|
animationDelay = 250;
|
|
}
|
|
|
|
var rangeHighlight = goog.dom.getElement('rangeHighlight');
|
|
twoThumbSlider.setValue(0);
|
|
twoThumbSlider.setExtent(100);
|
|
|
|
// Animate right thumb, final range is [0, 75]
|
|
twoThumbSlider.animatedSetValue(75);
|
|
assertHighlightedRange(rangeHighlight, 0, 100);
|
|
mockClock.tick(animationDelay);
|
|
assertHighlightedRange(rangeHighlight, 0, 75);
|
|
|
|
// Animate left thumb, final range is [25, 75]
|
|
twoThumbSlider.animatedSetValue(25);
|
|
assertHighlightedRange(rangeHighlight, 0, 75);
|
|
mockClock.tick(animationDelay);
|
|
assertHighlightedRange(rangeHighlight, 25, 75);
|
|
}
|
|
|
|
|
|
/**
|
|
* Verifies that no error occurs and that the range highlight is sized correctly
|
|
* for a zero-size slider (i.e. doesn't attempt to set a negative size). The
|
|
* test tries to resize the slider from its original size to 0, then checks
|
|
* that the range highlight's size is correctly set to 0.
|
|
*
|
|
* The size verification is needed because Webkit/Gecko outright ignore calls
|
|
* to set negative sizes on an element, leaving it at its former size. IE
|
|
* throws an error in the same situation.
|
|
*/
|
|
function testRangeHighlightForZeroSizeSlider() {
|
|
// Make sure range highlight spans whole slider before zeroing width.
|
|
twoThumbSlider.setExtent(100);
|
|
twoThumbSlider.getElement().style.width = 0;
|
|
|
|
// The setVisible call is used to force a UI update.
|
|
twoThumbSlider.setVisible(true);
|
|
assertEquals('Range highlight size should be 0 when slider size is 0',
|
|
0, goog.dom.getElement('rangeHighlight').offsetWidth);
|
|
}
|
|
|
|
function testAnimatedSetValueAnimatesFactoryCreatedAnimations() {
|
|
// Create and set the factory.
|
|
var ignore = goog.testing.mockmatchers.ignoreArgument;
|
|
var mockControl = new goog.testing.MockControl();
|
|
var mockAnimation1 = mockControl.createLooseMock(goog.fx.Animation);
|
|
var mockAnimation2 = mockControl.createLooseMock(goog.fx.Animation);
|
|
var testAnimations = [mockAnimation1, mockAnimation2];
|
|
oneThumbSlider.setAdditionalAnimations(new AnimationFactory(testAnimations));
|
|
|
|
// Expect the animations to be played.
|
|
mockAnimation1.play(false);
|
|
mockAnimation2.play(false);
|
|
mockAnimation1.addEventListener(ignore, ignore, ignore);
|
|
mockAnimation2.addEventListener(ignore, ignore, ignore);
|
|
|
|
// Animate and verify.
|
|
mockControl.$replayAll();
|
|
oneThumbSlider.animatedSetValue(50);
|
|
mockControl.$verifyAll();
|
|
mockControl.$resetAll();
|
|
mockControl.$tearDown();
|
|
}
|
|
|
|
function testMouseWheelEventHandlerEnable() {
|
|
// Mouse wheel handling should be enabled by default.
|
|
assertTrue(oneThumbSlider.isHandleMouseWheel());
|
|
|
|
// Test disabling the mouse wheel handler
|
|
oneThumbSlider.setHandleMouseWheel(false);
|
|
assertFalse(oneThumbSlider.isHandleMouseWheel());
|
|
|
|
// Test that enabling again works fine.
|
|
oneThumbSlider.setHandleMouseWheel(true);
|
|
assertTrue(oneThumbSlider.isHandleMouseWheel());
|
|
|
|
// Test that mouse wheel handling can be disabled before rendering a slider.
|
|
var wheelDisabledElem = goog.dom.createDom(
|
|
'div', {}, goog.dom.createDom('span'));
|
|
var wheelDisabledSlider = new OneThumbSlider();
|
|
wheelDisabledSlider.setHandleMouseWheel(false);
|
|
wheelDisabledSlider.decorate(wheelDisabledElem);
|
|
assertFalse(wheelDisabledSlider.isHandleMouseWheel());
|
|
}
|
|
|
|
function testDisabledAndEnabledSlider() {
|
|
// Check that a slider is enabled by default
|
|
assertTrue(oneThumbSlider.isEnabled());
|
|
|
|
var listenerCount = oneThumbSlider.getHandler().getListenerCount();
|
|
// Disable the slider and check its state
|
|
oneThumbSlider.setEnabled(false);
|
|
assertFalse(oneThumbSlider.isEnabled());
|
|
assertTrue(goog.dom.classlist.contains(
|
|
oneThumbSlider.getElement(), 'goog-slider-disabled'));
|
|
assertEquals(0, oneThumbSlider.getHandler().getListenerCount());
|
|
|
|
// setValue should work unaffected even when the slider is disabled.
|
|
oneThumbSlider.setValue(30);
|
|
assertEquals(30, oneThumbSlider.getValue());
|
|
assertEquals('Setting valid value must dispatch a change event ' +
|
|
'even when slider is disabled.', 1, oneChangeEventCount);
|
|
|
|
// Test the transition from disabled to enabled
|
|
oneThumbSlider.setEnabled(true);
|
|
assertTrue(oneThumbSlider.isEnabled());
|
|
assertFalse(goog.dom.classlist.contains(
|
|
oneThumbSlider.getElement(), 'goog-slider-disabled'));
|
|
assertTrue(listenerCount == oneThumbSlider.getHandler().getListenerCount());
|
|
}
|
|
|
|
function testBlockIncrementingWithEnableAndDisabled() {
|
|
var doc = goog.dom.getOwnerDocument(oneThumbSlider.getElement());
|
|
// Case when slider is not disabled between the mouse down and up events.
|
|
goog.testing.events.fireMouseDownEvent(oneThumbSlider.getElement());
|
|
assertEquals(1, goog.events.getListeners(
|
|
oneThumbSlider.getElement(),
|
|
goog.events.EventType.MOUSEMOVE, false).length);
|
|
assertEquals(1, goog.events.getListeners(
|
|
doc, goog.events.EventType.MOUSEUP, true).length);
|
|
|
|
goog.testing.events.fireMouseUpEvent(oneThumbSlider.getElement());
|
|
|
|
assertEquals(0, goog.events.getListeners(
|
|
oneThumbSlider.getElement(),
|
|
goog.events.EventType.MOUSEMOVE, false).length);
|
|
assertEquals(0, goog.events.getListeners(
|
|
doc, goog.events.EventType.MOUSEUP, true).length);
|
|
|
|
// Case when the slider is disabled between the mouse down and up events.
|
|
goog.testing.events.fireMouseDownEvent(oneThumbSlider.getElement());
|
|
assertEquals(1, goog.events.getListeners(
|
|
oneThumbSlider.getElement(),
|
|
goog.events.EventType.MOUSEMOVE, false).length);
|
|
assertEquals(1,
|
|
goog.events.getListeners(doc,
|
|
goog.events.EventType.MOUSEUP, true).length);
|
|
|
|
oneThumbSlider.setEnabled(false);
|
|
|
|
assertEquals(0, goog.events.getListeners(
|
|
oneThumbSlider.getElement(),
|
|
goog.events.EventType.MOUSEMOVE, false).length);
|
|
assertEquals(0, goog.events.getListeners(
|
|
doc, goog.events.EventType.MOUSEUP, true).length);
|
|
assertEquals(1, oneThumbSlider.getHandler().getListenerCount());
|
|
|
|
goog.testing.events.fireMouseUpEvent(oneThumbSlider.getElement());
|
|
assertEquals(0, goog.events.getListeners(
|
|
oneThumbSlider.getElement(),
|
|
goog.events.EventType.MOUSEMOVE, false).length);
|
|
assertEquals(0, goog.events.getListeners(
|
|
doc, goog.events.EventType.MOUSEUP, true).length);
|
|
}
|
|
|
|
function testMouseClickWithMoveToPointEnabled() {
|
|
var stepSize = 20;
|
|
oneThumbSlider.setStep(stepSize);
|
|
oneThumbSlider.setMoveToPointEnabled(true);
|
|
var initialValue = oneThumbSlider.getValue();
|
|
|
|
// Figure out the number of pixels per step.
|
|
var numSteps = Math.round(
|
|
(oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum()) / stepSize);
|
|
var size = goog.style.getSize(oneThumbSlider.getElement());
|
|
var pixelsPerStep = Math.round(size.width / numSteps);
|
|
|
|
var coords = goog.style.getClientPosition(oneThumbSlider.getElement());
|
|
coords.x += pixelsPerStep / 2;
|
|
|
|
// Case when value is increased
|
|
goog.testing.events.fireClickSequence(oneThumbSlider.getElement(),
|
|
/* opt_button */ undefined, coords);
|
|
assertEquals(oneThumbSlider.getValue(), initialValue + stepSize);
|
|
|
|
// Case when value is decreased
|
|
goog.testing.events.fireClickSequence(oneThumbSlider.getElement(),
|
|
/* opt_button */ undefined, coords);
|
|
assertEquals(oneThumbSlider.getValue(), initialValue);
|
|
|
|
// Case when thumb is clicked
|
|
goog.testing.events.fireClickSequence(oneThumbSlider.getElement());
|
|
assertEquals(oneThumbSlider.getValue(), initialValue);
|
|
}
|
|
|
|
function testNonIntegerStepSize() {
|
|
var stepSize = 0.02;
|
|
oneThumbSlider.setStep(stepSize);
|
|
oneThumbSlider.setMinimum(-1);
|
|
oneThumbSlider.setMaximum(1);
|
|
oneThumbSlider.setValue(0.7);
|
|
assertRoughlyEquals(0.7, oneThumbSlider.getValue(), 0.000001);
|
|
oneThumbSlider.setValue(0.3);
|
|
assertRoughlyEquals(0.3, oneThumbSlider.getValue(), 0.000001);
|
|
}
|
|
|
|
function testSingleThumbSliderHasZeroExtent() {
|
|
var stepSize = 0.02;
|
|
oneThumbSlider.setStep(stepSize);
|
|
oneThumbSlider.setMinimum(-1);
|
|
oneThumbSlider.setMaximum(1);
|
|
oneThumbSlider.setValue(0.7);
|
|
assertEquals(0, oneThumbSlider.getExtent());
|
|
oneThumbSlider.setValue(0.3);
|
|
assertEquals(0, oneThumbSlider.getExtent());
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests getThumbCoordinateForValue method.
|
|
*/
|
|
function testThumbCoordinateForValueWithHorizontalSlider() {
|
|
// Make sure the y-coordinate stays the same for the horizontal slider.
|
|
var originalY = goog.style.getPosition(oneThumbSlider.valueThumb).y;
|
|
var width = oneThumbSlider.getElement().clientWidth -
|
|
oneThumbSlider.valueThumb.offsetWidth;
|
|
var range = oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum();
|
|
|
|
// Verify coordinate for a particular value.
|
|
var value = 20;
|
|
var expectedX = Math.round(value / range * width);
|
|
var expectedCoord = new goog.math.Coordinate(expectedX, originalY);
|
|
var coord = oneThumbSlider.getThumbCoordinateForValue(value);
|
|
assertObjectEquals(expectedCoord, coord);
|
|
|
|
// Verify this works regardless of current position.
|
|
oneThumbSlider.setValue(value / 2);
|
|
coord = oneThumbSlider.getThumbCoordinateForValue(value);
|
|
assertObjectEquals(expectedCoord, coord);
|
|
}
|
|
|
|
function testThumbCoordinateForValueWithVerticalSlider() {
|
|
// Make sure the x-coordinate stays the same for the vertical slider.
|
|
oneThumbSlider.setOrientation(goog.ui.SliderBase.Orientation.VERTICAL);
|
|
var originalX = goog.style.getPosition(oneThumbSlider.valueThumb).x;
|
|
var height = oneThumbSlider.getElement().clientHeight -
|
|
oneThumbSlider.valueThumb.offsetHeight;
|
|
var range = oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum();
|
|
|
|
// Verify coordinate for a particular value.
|
|
var value = 20;
|
|
var expectedY = height - Math.round(value / range * height);
|
|
var expectedCoord = new goog.math.Coordinate(originalX, expectedY);
|
|
var coord = oneThumbSlider.getThumbCoordinateForValue(value);
|
|
assertObjectEquals(expectedCoord, coord);
|
|
|
|
// Verify this works regardless of current position.
|
|
oneThumbSlider.setValue(value / 2);
|
|
coord = oneThumbSlider.getThumbCoordinateForValue(value);
|
|
assertObjectEquals(expectedCoord, coord);
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests getValueFromMousePosition method.
|
|
*/
|
|
function testValueFromMousePosition() {
|
|
var value = 30;
|
|
oneThumbSlider.setValue(value);
|
|
var offset = goog.style.getPageOffset(oneThumbSlider.valueThumb);
|
|
var size = goog.style.getSize(oneThumbSlider.valueThumb);
|
|
offset.x += size.width / 2;
|
|
offset.y += size.height / 2;
|
|
var e = null;
|
|
goog.events.listen(oneThumbSlider, goog.events.EventType.MOUSEMOVE,
|
|
function(evt) {
|
|
e = evt;
|
|
});
|
|
goog.testing.events.fireMouseMoveEvent(oneThumbSlider, offset);
|
|
assertNotEquals(e, null);
|
|
assertEquals(
|
|
value, Math.round(oneThumbSlider.getValueFromMousePosition(e)));
|
|
// Verify this works regardless of current position.
|
|
oneThumbSlider.setValue(value / 2);
|
|
assertEquals(
|
|
value, Math.round(oneThumbSlider.getValueFromMousePosition(e)));
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests ignoring click event after mousedown event.
|
|
*/
|
|
function testClickAfterMousedown() {
|
|
// Get the center of the thumb at value zero.
|
|
oneThumbSlider.setValue(0);
|
|
var offset = goog.style.getPageOffset(oneThumbSlider.valueThumb);
|
|
var size = goog.style.getSize(oneThumbSlider.valueThumb);
|
|
offset.x += size.width / 2;
|
|
offset.y += size.height / 2;
|
|
|
|
var sliderElement = oneThumbSlider.getElement();
|
|
var width = sliderElement.clientWidth - size.width;
|
|
var range = oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum();
|
|
var offsetXAtZero = offset.x;
|
|
|
|
// Temporarily control time.
|
|
var theTime = goog.now();
|
|
var saveGoogNow = goog.now;
|
|
goog.now = function() { return theTime; };
|
|
|
|
// set coordinate for a particular value.
|
|
var valueOne = 10;
|
|
offset.x = offsetXAtZero + Math.round(valueOne / range * width);
|
|
goog.testing.events.fireMouseDownEvent(sliderElement, null, offset);
|
|
assertEquals(valueOne, oneThumbSlider.getValue());
|
|
|
|
// Verify a click event with another value that follows quickly is ignored.
|
|
theTime += oneThumbSlider.MOUSE_DOWN_DELAY_ / 2;
|
|
var valueTwo = 20;
|
|
offset.x = offsetXAtZero + Math.round(valueTwo / range * width);
|
|
goog.testing.events.fireClickEvent(sliderElement, null, offset);
|
|
assertEquals(valueOne, oneThumbSlider.getValue());
|
|
|
|
// Verify a click later in time does move the thumb.
|
|
theTime += oneThumbSlider.MOUSE_DOWN_DELAY_;
|
|
goog.testing.events.fireClickEvent(sliderElement, null, offset);
|
|
assertEquals(valueTwo, oneThumbSlider.getValue());
|
|
|
|
goog.now = saveGoogNow;
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests dragging events.
|
|
*/
|
|
function testDragEvents() {
|
|
var offset = goog.style.getPageOffset(oneThumbSlider.valueThumb);
|
|
var size = goog.style.getSize(oneThumbSlider.valueThumb);
|
|
offset.x += size.width / 2;
|
|
offset.y += size.height / 2;
|
|
var event_types = [];
|
|
var handler = function(evt) {
|
|
event_types.push(evt.type);
|
|
};
|
|
|
|
goog.events.listen(oneThumbSlider,
|
|
[goog.ui.SliderBase.EventType.DRAG_START,
|
|
goog.ui.SliderBase.EventType.DRAG_END,
|
|
goog.ui.SliderBase.EventType.DRAG_VALUE_START,
|
|
goog.ui.SliderBase.EventType.DRAG_VALUE_END,
|
|
goog.ui.SliderBase.EventType.DRAG_EXTENT_START,
|
|
goog.ui.SliderBase.EventType.DRAG_EXTENT_END,
|
|
goog.ui.Component.EventType.CHANGE],
|
|
handler);
|
|
|
|
// Since the order of the events between value and extent is not guaranteed
|
|
// accross browsers, we need to allow for both here and once we have
|
|
// them all, make sure that they were different.
|
|
function isValueOrExtentDragStart(type) {
|
|
return type == goog.ui.SliderBase.EventType.DRAG_VALUE_START ||
|
|
type == goog.ui.SliderBase.EventType.DRAG_EXTENT_START;
|
|
};
|
|
function isValueOrExtentDragEnd(type) {
|
|
return type == goog.ui.SliderBase.EventType.DRAG_VALUE_END ||
|
|
type == goog.ui.SliderBase.EventType.DRAG_EXTENT_END;
|
|
};
|
|
|
|
// Test that dragging the thumb calls all the correct events.
|
|
goog.testing.events.fireMouseDownEvent(oneThumbSlider.valueThumb);
|
|
offset.x += 100;
|
|
goog.testing.events.fireMouseMoveEvent(oneThumbSlider.valueThumb, offset);
|
|
goog.testing.events.fireMouseUpEvent(oneThumbSlider.valueThumb);
|
|
|
|
assertEquals(9, event_types.length);
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[0]);
|
|
assertTrue(isValueOrExtentDragStart(event_types[1]));
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[2]);
|
|
assertTrue(isValueOrExtentDragStart(event_types[3]));
|
|
|
|
assertEquals(goog.ui.Component.EventType.CHANGE, event_types[4]);
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[5]);
|
|
assertTrue(isValueOrExtentDragEnd(event_types[6]));
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[7]);
|
|
assertTrue(isValueOrExtentDragEnd(event_types[8]));
|
|
|
|
assertFalse(event_types[1] == event_types[3]);
|
|
assertFalse(event_types[6] == event_types[8]);
|
|
|
|
// Test that clicking the thumb without moving the mouse does not cause a
|
|
// CHANGE event between DRAG_START/DRAG_END.
|
|
event_types = [];
|
|
goog.testing.events.fireMouseDownEvent(oneThumbSlider.valueThumb);
|
|
goog.testing.events.fireMouseUpEvent(oneThumbSlider.valueThumb);
|
|
|
|
assertEquals(8, event_types.length);
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[0]);
|
|
assertTrue(isValueOrExtentDragStart(event_types[1]));
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[2]);
|
|
assertTrue(isValueOrExtentDragStart(event_types[3]));
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[4]);
|
|
assertTrue(isValueOrExtentDragEnd(event_types[5]));
|
|
|
|
assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[6]);
|
|
assertTrue(isValueOrExtentDragEnd(event_types[7]));
|
|
|
|
assertFalse(event_types[1] == event_types[3]);
|
|
assertFalse(event_types[5] == event_types[7]);
|
|
|
|
// Early listener removal, do not wait for tearDown, to avoid building up
|
|
// arrays of events unnecessarilly in further tests.
|
|
goog.events.removeAll(oneThumbSlider);
|
|
}
|