blob: 54558d1cd3643aee714c78c4a225daa06106db8b [file] [log] [blame]
// Copyright 2009 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.CheckboxTest');
goog.setTestOnly('goog.ui.CheckboxTest');
goog.require('goog.a11y.aria');
goog.require('goog.a11y.aria.Role');
goog.require('goog.a11y.aria.State');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.events');
goog.require('goog.events.KeyCodes');
goog.require('goog.testing.events');
goog.require('goog.testing.jsunit');
goog.require('goog.ui.Checkbox');
goog.require('goog.ui.CheckboxRenderer');
goog.require('goog.ui.Component');
goog.require('goog.ui.ControlRenderer');
goog.require('goog.ui.decorate');
var checkbox;
function setUp() {
checkbox = new goog.ui.Checkbox();
}
function tearDown() {
checkbox.dispose();
}
function testClassNames() {
checkbox.createDom();
checkbox.setChecked(false);
assertSameElements('classnames of unchecked checkbox',
['goog-checkbox', 'goog-checkbox-unchecked'],
goog.dom.classlist.get(checkbox.getElement()));
checkbox.setChecked(true);
assertSameElements('classnames of checked checkbox',
['goog-checkbox', 'goog-checkbox-checked'],
goog.dom.classlist.get(checkbox.getElement()));
checkbox.setChecked(null);
assertSameElements('classnames of partially checked checkbox',
['goog-checkbox', 'goog-checkbox-undetermined'],
goog.dom.classlist.get(checkbox.getElement()));
checkbox.setEnabled(false);
assertSameElements('classnames of partially checked disabled checkbox',
['goog-checkbox',
'goog-checkbox-undetermined',
'goog-checkbox-disabled'],
goog.dom.classlist.get(checkbox.getElement()));
}
function testIsEnabled() {
assertTrue('enabled by default', checkbox.isEnabled());
checkbox.setEnabled(false);
assertFalse('has been disabled', checkbox.isEnabled());
}
function testCheckedState() {
assertTrue('unchecked by default', !checkbox.isChecked() &&
checkbox.isUnchecked() && !checkbox.isUndetermined());
checkbox.setChecked(true);
assertTrue('set to checked', checkbox.isChecked() &&
!checkbox.isUnchecked() && !checkbox.isUndetermined());
checkbox.setChecked(null);
assertTrue('set to partially checked', !checkbox.isChecked() &&
!checkbox.isUnchecked() && checkbox.isUndetermined());
}
function testToggle() {
checkbox.setChecked(null);
checkbox.toggle();
assertTrue('undetermined -> checked', checkbox.getChecked());
checkbox.toggle();
assertFalse('checked -> unchecked', checkbox.getChecked());
checkbox.toggle();
assertTrue('unchecked -> checked', checkbox.getChecked());
}
function testEvents() {
checkbox.render();
var events = [];
goog.events.listen(checkbox,
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.CHECK,
goog.ui.Component.EventType.UNCHECK,
goog.ui.Component.EventType.CHANGE
],
function(e) {
events.push(e.type);
});
checkbox.setEnabled(false);
goog.testing.events.fireClickSequence(checkbox.getElement());
assertArrayEquals('disabled => no events', [], events);
assertFalse('checked state did not change', checkbox.getChecked());
events = [];
checkbox.setEnabled(true);
goog.testing.events.fireClickSequence(checkbox.getElement());
assertArrayEquals('ACTION+CHECK+CHANGE fired',
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.CHECK,
goog.ui.Component.EventType.CHANGE
],
events);
assertTrue('checkbox became checked', checkbox.getChecked());
events = [];
goog.testing.events.fireClickSequence(checkbox.getElement());
assertArrayEquals('ACTION+UNCHECK+CHANGE fired',
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.UNCHECK,
goog.ui.Component.EventType.CHANGE
],
events);
assertFalse('checkbox became unchecked', checkbox.getChecked());
events = [];
goog.events.listen(checkbox, goog.ui.Component.EventType.CHECK,
function(e) {
e.preventDefault();
});
goog.testing.events.fireClickSequence(checkbox.getElement());
assertArrayEquals('ACTION+CHECK fired',
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.CHECK
],
events);
assertFalse('toggling has been prevented', checkbox.getChecked());
}
function testCheckboxAriaLabelledby() {
var label = goog.dom.createElement('div');
var label2 = goog.dom.createElement('div', {id: checkbox.makeId('foo')});
document.body.appendChild(label);
document.body.appendChild(label2);
try {
checkbox.setChecked(false);
checkbox.setLabel(label);
checkbox.render(label);
assertNotNull(checkbox.getElement());
assertEquals(label.id,
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.LABELLEDBY));
checkbox.setLabel(label2);
assertEquals(label2.id,
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.LABELLEDBY));
} finally {
document.body.removeChild(label);
document.body.removeChild(label2);
}
}
function testLabel() {
var label = goog.dom.createElement('div');
document.body.appendChild(label);
try {
checkbox.setChecked(false);
checkbox.setLabel(label);
checkbox.render(label);
// Clicking on label toggles checkbox.
goog.testing.events.fireClickSequence(label);
assertTrue('checkbox toggled if the label is clicked',
checkbox.getChecked());
goog.testing.events.fireClickSequence(checkbox.getElement());
assertFalse('checkbox toggled if it is clicked', checkbox.getChecked());
// Test that mouse events on the label have the correct effect on the
// checkbox state when it is enabled.
checkbox.setEnabled(true);
goog.testing.events.fireMouseOverEvent(label);
assertTrue(checkbox.hasState(goog.ui.Component.State.HOVER));
assertContains('checkbox gets hover state on mouse over',
'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
goog.testing.events.fireMouseDownEvent(label);
assertTrue(checkbox.hasState(goog.ui.Component.State.ACTIVE));
assertContains('checkbox gets active state on label mousedown',
'goog-checkbox-active',
goog.dom.classlist.get(checkbox.getElement()));
goog.testing.events.fireMouseOutEvent(checkbox.getElement());
assertFalse(checkbox.hasState(goog.ui.Component.State.HOVER));
assertNotContains('checkbox does not have hover state after mouse out',
'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
assertFalse(checkbox.hasState(goog.ui.Component.State.ACTIVE));
assertNotContains('checkbox does not have active state after mouse out',
'goog-checkbox-active', goog.dom.classlist.get(checkbox.getElement()));
// Test label mouse events on disabled checkbox.
checkbox.setEnabled(false);
goog.testing.events.fireMouseOverEvent(label);
assertFalse(checkbox.hasState(goog.ui.Component.State.HOVER));
assertNotContains(
'disabled checkbox does not get hover state on mouseover',
'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
goog.testing.events.fireMouseDownEvent(label);
assertFalse(checkbox.hasState(goog.ui.Component.State.ACTIVE));
assertNotContains('disabled checkbox does not get active state mousedown',
'goog-checkbox-active',
goog.dom.classlist.get(checkbox.getElement()));
goog.testing.events.fireMouseOutEvent(checkbox.getElement());
assertFalse(checkbox.hasState(goog.ui.Component.State.ACTIVE));
assertNotContains('checkbox does not get stuck in hover state',
'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
// Making the label null prevents it from affecting checkbox state.
checkbox.setEnabled(true);
checkbox.setLabel(null);
goog.testing.events.fireClickSequence(label);
assertFalse('label element deactivated', checkbox.getChecked());
goog.testing.events.fireClickSequence(checkbox.getElement());
assertTrue('checkbox still active', checkbox.getChecked());
} finally {
document.body.removeChild(label);
}
}
function testConstructor() {
assertEquals('state is unchecked', goog.ui.Checkbox.State.UNCHECKED,
checkbox.getChecked());
var testCheckboxWithState = new goog.ui.Checkbox(
goog.ui.Checkbox.State.UNDETERMINED);
assertNotNull('checkbox created with custom state', testCheckboxWithState);
assertEquals('checkbox state is undetermined',
goog.ui.Checkbox.State.UNDETERMINED,
testCheckboxWithState.getChecked());
testCheckboxWithState.dispose();
}
function testCustomRenderer() {
var cssClass = 'my-custom-checkbox';
var renderer = goog.ui.ControlRenderer.getCustomRenderer(
goog.ui.CheckboxRenderer, cssClass);
var customCheckbox = new goog.ui.Checkbox(
undefined, undefined, renderer);
customCheckbox.createDom();
assertElementsEquals(
['my-custom-checkbox', 'my-custom-checkbox-unchecked'],
goog.dom.classlist.get(customCheckbox.getElement()));
customCheckbox.setChecked(true);
assertElementsEquals(
['my-custom-checkbox', 'my-custom-checkbox-checked'],
goog.dom.classlist.get(customCheckbox.getElement()));
customCheckbox.setChecked(null);
assertElementsEquals(
['my-custom-checkbox', 'my-custom-checkbox-undetermined'],
goog.dom.classlist.get(customCheckbox.getElement()));
customCheckbox.dispose();
}
function testGetAriaRole() {
checkbox.createDom();
assertNotNull(checkbox.getElement());
assertEquals("Checkbox's ARIA role should be 'checkbox'",
goog.a11y.aria.Role.CHECKBOX,
goog.a11y.aria.getRole(checkbox.getElement()));
}
function testCreateDomUpdateAriaState() {
checkbox.createDom();
assertNotNull(checkbox.getElement());
assertEquals('Checkbox must have default false ARIA state aria-checked',
'false', goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
checkbox.setChecked(goog.ui.Checkbox.State.CHECKED);
assertEquals('Checkbox must have true ARIA state aria-checked', 'true',
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
checkbox.setChecked(goog.ui.Checkbox.State.UNCHECKED);
assertEquals('Checkbox must have false ARIA state aria-checked', 'false',
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
checkbox.setChecked(goog.ui.Checkbox.State.UNDETERMINED);
assertEquals('Checkbox must have mixed ARIA state aria-checked', 'mixed',
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
}
function testDecorateUpdateAriaState() {
var decorateSpan = goog.dom.getElement('decorate');
checkbox.decorate(decorateSpan);
assertEquals('Checkbox must have default false ARIA state aria-checked',
'false', goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
checkbox.setChecked(goog.ui.Checkbox.State.CHECKED);
assertEquals('Checkbox must have true ARIA state aria-checked', 'true',
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
checkbox.setChecked(goog.ui.Checkbox.State.UNCHECKED);
assertEquals('Checkbox must have false ARIA state aria-checked', 'false',
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
checkbox.setChecked(goog.ui.Checkbox.State.UNDETERMINED);
assertEquals('Checkbox must have mixed ARIA state aria-checked', 'mixed',
goog.a11y.aria.getState(checkbox.getElement(),
goog.a11y.aria.State.CHECKED));
}
function testSpaceKey() {
var normalSpan = goog.dom.getElement('normal');
checkbox.decorate(normalSpan);
assertEquals('default state is unchecked',
goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
assertEquals('SPACE toggles checkbox to be checked',
goog.ui.Checkbox.State.CHECKED, checkbox.getChecked());
goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
assertEquals('another SPACE toggles checkbox to be unchecked',
goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
// Enter for example doesn't work
goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.ENTER);
assertEquals('Enter leaves checkbox unchecked',
goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
}
function testSpaceKeyFiresEvents() {
var normalSpan = goog.dom.getElement('normal');
checkbox.decorate(normalSpan);
var events = [];
goog.events.listen(checkbox,
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.CHECK,
goog.ui.Component.EventType.UNCHECK,
goog.ui.Component.EventType.CHANGE
],
function(e) {
events.push(e.type);
});
assertEquals('Unexpected default state.',
goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
assertArrayEquals('Unexpected events fired when checking with spacebar.',
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.CHECK,
goog.ui.Component.EventType.CHANGE
],
events);
assertEquals('Unexpected state after checking.',
goog.ui.Checkbox.State.CHECKED, checkbox.getChecked());
events = [];
goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
assertArrayEquals('Unexpected events fired when unchecking with spacebar.',
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.UNCHECK,
goog.ui.Component.EventType.CHANGE
],
events);
assertEquals('Unexpected state after unchecking.',
goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
events = [];
goog.events.listenOnce(checkbox, goog.ui.Component.EventType.CHECK,
function(e) {
e.preventDefault();
});
goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
assertArrayEquals('Unexpected events fired when checking with spacebar and ' +
'the check event is cancelled.',
[
goog.ui.Component.EventType.ACTION,
goog.ui.Component.EventType.CHECK
],
events);
assertEquals('Unexpected state after check event is cancelled.',
goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
}
function testDecorate() {
var normalSpan = goog.dom.getElement('normal');
var checkedSpan = goog.dom.getElement('checked');
var uncheckedSpan = goog.dom.getElement('unchecked');
var undeterminedSpan = goog.dom.getElement('undetermined');
var disabledSpan = goog.dom.getElement('disabled');
validateCheckBox(normalSpan, goog.ui.Checkbox.State.UNCHECKED);
validateCheckBox(checkedSpan, goog.ui.Checkbox.State.CHECKED);
validateCheckBox(uncheckedSpan, goog.ui.Checkbox.State.UNCHECKED);
validateCheckBox(undeterminedSpan, goog.ui.Checkbox.State.UNDETERMINED);
validateCheckBox(disabledSpan, goog.ui.Checkbox.State.UNCHECKED, true);
}
function validateCheckBox(span, state, opt_disabled) {
var testCheckbox = goog.ui.decorate(span);
assertNotNull('checkbox created', testCheckbox);
assertEquals('decorate was successful',
goog.ui.Checkbox, testCheckbox.constructor);
assertEquals('checkbox state should be: ' + state, state,
testCheckbox.getChecked());
assertEquals('checkbox is ' + (!opt_disabled ? 'enabled' : 'disabled'),
!opt_disabled, testCheckbox.isEnabled());
testCheckbox.dispose();
}
function testSetAriaLabel() {
assertNull('Checkbox must not have aria label by default',
checkbox.getAriaLabel());
checkbox.setAriaLabel('Checkbox 1');
checkbox.render();
var el = checkbox.getElementStrict();
assertEquals('Checkbox element must have expected aria-label', 'Checkbox 1',
el.getAttribute('aria-label'));
assertEquals('Checkbox element must have expected aria-role', 'checkbox',
el.getAttribute('role'));
checkbox.setAriaLabel('Checkbox 2');
assertEquals('Checkbox element must have updated aria-label', 'Checkbox 2',
el.getAttribute('aria-label'));
assertEquals('Checkbox element must have expected aria-role', 'checkbox',
el.getAttribute('role'));
}