JSHint integration
JSHint helps enforcing coding standards for the javascript files similarly to pep8. It is integrated with the existing qUnit tests with the qhint library. This approach has the advantage of running every time the selenium test suite runs and does not introduce dependency to Node.js. Partially implements: blueprint js-coding-style-checks Change-Id: I77e75e7cdd5fd3426b9b981c4e0df5d30ef7b196
This commit is contained in:
parent
494b7f8b20
commit
7711a78ac4
horizon
static/horizon
templates/horizon
test/tests
61442
horizon/static/horizon/lib/jshint-2.3.0.js
Normal file
61442
horizon/static/horizon/lib/jshint-2.3.0.js
Normal file
File diff suppressed because it is too large
Load Diff
88
horizon/static/horizon/lib/qhint.js
Normal file
88
horizon/static/horizon/lib/qhint.js
Normal file
@ -0,0 +1,88 @@
|
||||
/*! qHint 1.1 | http://gyoshev.mit-license.org */
|
||||
(function() {
|
||||
var qHint =
|
||||
window.jsHintTest =
|
||||
window.qHint =
|
||||
function qHint(name, sourceFile, options, globals) {
|
||||
if (sourceFile === undefined || typeof(sourceFile) == "object") {
|
||||
// jsHintTest('file.js', [options])
|
||||
globals = options;
|
||||
options = sourceFile;
|
||||
sourceFile = name;
|
||||
}
|
||||
|
||||
return asyncTest(name, function() {
|
||||
qHint.sendRequest(sourceFile, function(req) {
|
||||
start();
|
||||
|
||||
if (req.status == 200) {
|
||||
qHint.validateFile(req.responseText, options, globals);
|
||||
} else {
|
||||
ok(false, "HTTP error " + req.status +
|
||||
" while fetching " + sourceFile);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
qHint.validateFile = function (source, options, globals) {
|
||||
var i, len, err;
|
||||
|
||||
if (JSHINT(source, options, globals)) {
|
||||
ok(true);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, len = JSHINT.errors.length; i < len; i++) {
|
||||
err = JSHINT.errors[i];
|
||||
if (!err) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ok(false, err.reason +
|
||||
" on line " + err.line +
|
||||
", character " + err.character);
|
||||
}
|
||||
};
|
||||
|
||||
var XMLHttpFactories = [
|
||||
function () { return new XMLHttpRequest(); },
|
||||
function () { return new ActiveXObject("Msxml2.XMLHTTP"); },
|
||||
function () { return new ActiveXObject("Msxml3.XMLHTTP"); },
|
||||
function () { return new ActiveXObject("Microsoft.XMLHTTP"); }
|
||||
];
|
||||
|
||||
function createXMLHTTPObject() {
|
||||
for (var i = 0; i < XMLHttpFactories.length; i++) {
|
||||
try {
|
||||
return XMLHttpFactories[i]();
|
||||
} catch (e) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// modified version of XHR script by PPK
|
||||
// http://www.quirksmode.org/js/xmlhttp.html
|
||||
// attached to qHint to allow substitution / mocking
|
||||
qHint.sendRequest = function (url, callback) {
|
||||
var req = createXMLHTTPObject();
|
||||
if (!req) {
|
||||
return;
|
||||
}
|
||||
|
||||
var method = "GET";
|
||||
req.open(method,url,true);
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState != 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(req);
|
||||
};
|
||||
|
||||
if (req.readyState == 4) {
|
||||
return;
|
||||
}
|
||||
req.send();
|
||||
};
|
||||
})();
|
61
horizon/static/horizon/tests/jshint.js
Normal file
61
horizon/static/horizon/tests/jshint.js
Normal file
@ -0,0 +1,61 @@
|
||||
horizon.addInitFunction(function () {
|
||||
module('Coding Style (jsHint)');
|
||||
|
||||
test('jsHint', function () {
|
||||
expect(0);
|
||||
|
||||
config = {
|
||||
// Warnings reported by JSHint. Suppressing for now...
|
||||
'asi': true, // missing semicolons
|
||||
'-W004': true, // already defined
|
||||
'-W009': true, // array literal notation [] is preferrable
|
||||
'-W014': true, // bad line breaking
|
||||
'-W018': true, // confusing use
|
||||
'-W038': true, // out of scope
|
||||
'-W041': true, // use '!==' or '===' for comparison
|
||||
'-W046': true, // extra leading zeros
|
||||
'-W069': true, // better written in dot notation
|
||||
'-W065': true, // missing radix parameter
|
||||
'-W075': true, // duplicate key
|
||||
'-W080': true, // it's not necessary to initialize to 'undefined'
|
||||
'-W093': true, // conditional instead of an assignment
|
||||
|
||||
// Proposed set of rules
|
||||
//'camelcase' : true,
|
||||
//'indent': 2,
|
||||
//'undef': true,
|
||||
//'quotmark': 'single',
|
||||
//'maxlen': 80,
|
||||
//'trailing': true,
|
||||
//'curly': true
|
||||
};
|
||||
|
||||
jsHintTest('horizon.communication.js', '/static/horizon/js/horizon.communication.js', config);
|
||||
jsHintTest('horizon.conf.js', '/static/horizon/js/horizon.conf.js', config);
|
||||
jsHintTest('horizon.cookies.js', '/static/horizon/js/horizon.cookies.js', config);
|
||||
jsHintTest('horizon.d3linechart.js', '/static/horizon/js/horizon.d3linechart.js', config);
|
||||
jsHintTest('horizon.d3piechart.js', '/static/horizon/js/horizon.d3piechart.js', config);
|
||||
jsHintTest('horizon.firewalls.js', '/static/horizon/js/horizon.firewalls.js', config);
|
||||
jsHintTest('horizon.forms.js', '/static/horizon/js/horizon.forms.js', config);
|
||||
jsHintTest('horizon.heattop.js', '/static/horizon/js/horizon.heattop.js', config);
|
||||
jsHintTest('horizon.instances.js', '/static/horizon/js/horizon.instances.js', config);
|
||||
jsHintTest('horizon.js', '/static/horizon/js/horizon.js', config);
|
||||
jsHintTest('horizon.membership.js', '/static/horizon/js/horizon.membership.js', config);
|
||||
jsHintTest('horizon.messages.js', '/static/horizon/js/horizon.messages.js', config);
|
||||
jsHintTest('horizon.modals.js', '/static/horizon/js/horizon.modals.js', config);
|
||||
jsHintTest('horizon.networktopology.js', '/static/horizon/js/horizon.networktopology.js', config);
|
||||
jsHintTest('horizon.quota.js', '/static/horizon/js/horizon.quota.js', config);
|
||||
jsHintTest('horizon.tables.js', '/static/horizon/js/horizon.tables.js', config);
|
||||
jsHintTest('horizon.tabs.js', '/static/horizon/js/horizon.tabs.js', config);
|
||||
jsHintTest('horizon.templates.js', '/static/horizon/js/horizon.templates.js', config);
|
||||
jsHintTest('horizon.users.js', '/static/horizon/js/horizon.users.js', config);
|
||||
jsHintTest('horizon.utils.js', '/static/horizon/js/horizon.utils.js', config);
|
||||
|
||||
jsHintTest('tests/jshint.js', '/static/horizon/tests/jshint.js', config);
|
||||
jsHintTest('tests/messages.js', '/static/horizon/tests/messages.js', config);
|
||||
jsHintTest('tests/modals.js', '/static/horizon/tests/modals.js', config);
|
||||
jsHintTest('tests/tables.js', '/static/horizon/tests/tables.js', config);
|
||||
jsHintTest('tests/templates.js', '/static/horizon/tests/templates.js', config);
|
||||
});
|
||||
});
|
||||
|
@ -6,6 +6,8 @@
|
||||
<link rel="stylesheet" href="{{ STATIC_URL }}horizon/lib/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/lib/jquery/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/lib/qunit/qunit.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/lib/jshint-2.3.0.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/lib/qhint.js"></script>
|
||||
{% include "horizon/_conf.html" %}
|
||||
|
||||
{% comment %}Load test modules here.{% endcomment %}
|
||||
@ -13,6 +15,7 @@
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/tests/modals.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/tests/templates.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/tests/tables.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}horizon/tests/jshint.js"></script>
|
||||
{% comment %}End test modules.{% endcomment %}
|
||||
|
||||
{% include "horizon/_scripts.html" %}
|
||||
|
@ -20,7 +20,7 @@ from horizon.test import helpers as test
|
||||
class BrowserTests(test.SeleniumTestCase):
|
||||
def test_qunit(self):
|
||||
self.selenium.get("%s%s" % (self.live_server_url, "/qunit/"))
|
||||
wait = self.ui.WebDriverWait(self.selenium, 10)
|
||||
wait = self.ui.WebDriverWait(self.selenium, 20)
|
||||
|
||||
def qunit_done(driver):
|
||||
text = driver.find_element_by_id("qunit-testresult").text
|
||||
@ -28,4 +28,9 @@ class BrowserTests(test.SeleniumTestCase):
|
||||
|
||||
wait.until(qunit_done)
|
||||
failed = self.selenium.find_element_by_class_name("failed")
|
||||
self.assertEqual(int(failed.text), 0)
|
||||
if int(failed.text) > 0:
|
||||
filename = self.selenium.find_element_by_css_selector(
|
||||
"#qunit-tests > li.fail span.test-name").text
|
||||
message = self.selenium.find_element_by_css_selector(
|
||||
"#qunit-tests > li.fail span.test-message").text
|
||||
self.fail('%s: %s' % (filename, message))
|
||||
|
Loading…
x
Reference in New Issue
Block a user