blob: e2d06ac2acd716c87ce8ec4e05a0ff32fb99d076 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* TestFixture for testing the formatting of settings pages.
* @extends {testing.Test}
* @constructor
*/
function SettingsFormatWebUITest() {}
/**
* Map of rule exemptions grouped by test.
* @const
*/
SettingsFormatWebUITest.Filters = {
/**
* Exemption for checkboxes that do not require an id or pref property.
* Input methods use inputMethodId instead of id for unique identification.
*/
'pref': ['language-options-input-method-template',
'language-options-input-method-list']
};
/**
* Collection of error messages.
* @const
*/
SettingsFormatWebUITest.Messages = {
MISSING_CHECK_WRAPPER: 'Element $1 should be enclosed in <div class="$2">',
MISSING_ID_OR_PREF: 'Missing id or pref preoperty for checkbox $1.',
MISSING_RADIO_BUTTON_NAME: 'Radio button $1 is missing the name property',
MISSING_RADIO_BUTTON_VALUE: 'Radio button $1 is missing the value property',
};
SettingsFormatWebUITest.prototype = {
__proto__: testing.Test.prototype,
/**
* Navigate to browser settings.
*/
browsePreload: 'chrome://settings-frame/settings',
/**
* List of errors generated during a test. Used instead of expect* functions
* to suppress verbosity. The implementation of errorsToMessage in the
* testing API generates a call stack for each error produced which greatly
* reduces readability.
* @type {Array.<string>}
*/
errors: null,
setUp: function() {
this.errors = [];
},
tearDown: function() {
assertTrue(this.errors.length == 0, '\n' + this.errors.join('\n'));
},
/**
* Generates a failure message. During tear down of the test, the accumulation
* of pending messages triggers a test failure.
* @param {string} key Label of the message formatting string.
* @param {!Element} element The element that triggered the failure.
* @param {...string} args Additional arguments for formatting the message.
*/
fail: function(key, element, args) {
var subs = [this.getLabel(element)].concat(
Array.prototype.slice.call(arguments, 2));
var message = SettingsFormatWebUITest.Messages[key].replace(
/\$\d/g,
function(m) {
return subs[m[1] - 1] || '$' + m[1];
});
assertFalse(/\$\d/.test(message), 'found unreplaced subs');
this.errors.push(message);
},
/**
* String for identifying a node within an error message.
* @param {!Element} element The target element to identify.
* @return {string} Name to facilitate tracking down the element.
*/
getLabel: function(element) {
if (element.id)
return element.id;
if (element.pref)
return element.pref;
if (element.name && element.value)
return element.name + '-' + element.value;
return this.getLabel(element.parentNode);
},
/**
* Checks if the node is exempt from following the formatting rule.
* @param {!Element} element The candidate element.
* @param {Array.<string>} filters List of exemptions.
* @return {boolean} True if the element is exempt.
*/
isExempt: function(element, filters) {
var target = this.getLabel(element);
for (var i = 0; i < filters.length; i++) {
if (filters[i] == target)
return true;
}
return false;
}
};
/**
* Ensure that radio and checkbox buttons have consistent layout.
*/
TEST_F('SettingsFormatWebUITest', 'RadioCheckboxStyleCheck', function() {
var settings = $('settings');
assertTrue(settings != null, 'Unable to access settings');
var query = 'input[type=checkbox], input[type=radio]';
var elements = document.querySelectorAll(query);
assertTrue(elements.length > 0);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (!findAncestorByClass(element, element.type))
this.fail('MISSING_CHECK_WRAPPER', element, element.type);
}
});
/**
* Each checkbox requires an id or pref property.
*/
TEST_F('SettingsFormatWebUITest', 'CheckboxIdOrPrefCheck', function() {
var query = 'input[type=checkbox]:not([pref]):not([id])';
var elements = document.querySelectorAll(query);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (!this.isExempt(element, SettingsFormatWebUITest.Filters['pref']))
this.fail('MISSING_ID_OR_PREF', element);
}
});
/**
* Each radio button requires name and value properties.
*/
TEST_F('SettingsFormatWebUITest', 'RadioButtonNameValueCheck', function() {
var elements = document.querySelectorAll('input[type=radio]');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (!element.name)
this.fail('MISSING_RADIO_BUTTON_NAME', element);
if (!element.getAttribute("value"))
this.fail('MISSING_RADIO_BUTTON_VALUE', element);
}
});