blob: d9a6a9243337262520ec9df44ad77d560f5f2bab [file] [log] [blame]
// 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);
}