|
@@ -3,12 +3,13 @@
|
|
|
*/
|
|
|
/* global Element: true, Document: true, Node: true, window: true */
|
|
|
|
|
|
-exports.version = '0.9.a';
|
|
|
+exports.version = '0.10.a';
|
|
|
|
|
|
exports.module = function(phantomas) {
|
|
|
'use strict';
|
|
|
|
|
|
phantomas.setMetric('DOMqueries'); // @desc number of all DOM queries @offenders
|
|
|
+ phantomas.setMetric('DOMqueriesWithoutResults'); // @desc number of DOM queries that retutned nothing @offenders
|
|
|
phantomas.setMetric('DOMqueriesById'); // @desc number of document.getElementById calls
|
|
|
phantomas.setMetric('DOMqueriesByClassName'); // @desc number of document.getElementsByClassName calls
|
|
|
phantomas.setMetric('DOMqueriesByTagName'); // @desc number of document.getElementsByTagName calls
|
|
@@ -21,14 +22,13 @@ exports.module = function(phantomas) {
|
|
|
phantomas.once('init', function() {
|
|
|
phantomas.evaluate(function() {
|
|
|
(function(phantomas) {
|
|
|
- function querySpy(type, query, fnName, context) {
|
|
|
- phantomas.emit('domQuery', type, query, fnName, context); // @desc DOM query has been made
|
|
|
+ function querySpy(type, query, fnName, context, hasNoResults) {
|
|
|
+ phantomas.emit('domQuery', type, query, fnName, context, hasNoResults); // @desc DOM query has been made
|
|
|
}
|
|
|
|
|
|
phantomas.spy(Document.prototype, 'getElementById', function(id) {
|
|
|
phantomas.incrMetric('DOMqueriesById');
|
|
|
phantomas.addOffender('DOMqueriesById', '#%s (in %s)', id, '#document');
|
|
|
- querySpy('id', '#' + id, 'getElementById', '#document');
|
|
|
|
|
|
phantomas.enterContext({
|
|
|
type: 'getElementById',
|
|
@@ -41,9 +41,13 @@ exports.module = function(phantomas) {
|
|
|
backtrace: phantomas.getBacktrace()
|
|
|
});
|
|
|
|
|
|
- }, function(result) {
|
|
|
+ }, function(result, args) {
|
|
|
+ var id = args[0];
|
|
|
+
|
|
|
+ querySpy('id', '#' + id, 'getElementById', '#document', (result === null));
|
|
|
+
|
|
|
var moreData = {
|
|
|
- resultsNumber : result ? 1 : 0
|
|
|
+ resultsNumber : (result === null) ? 0 : 1
|
|
|
};
|
|
|
phantomas.leaveContext(moreData);
|
|
|
});
|
|
@@ -56,7 +60,6 @@ exports.module = function(phantomas) {
|
|
|
|
|
|
phantomas.incrMetric('DOMqueriesByClassName');
|
|
|
phantomas.addOffender('DOMqueriesByClassName', '.%s (in %s)', className, context);
|
|
|
- querySpy('class', '.' + className, 'getElementsByClassName', context);
|
|
|
|
|
|
phantomas.enterContext({
|
|
|
type: 'getElementsByClassName',
|
|
@@ -70,7 +73,14 @@ exports.module = function(phantomas) {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- function selectorClassNameAfter(result) {
|
|
|
+ function selectorClassNameAfter(result, args) {
|
|
|
+ /*jshint validthis: true */
|
|
|
+
|
|
|
+ var className = args[0];
|
|
|
+ var context = phantomas.getDOMPath(this);
|
|
|
+
|
|
|
+ querySpy('class', '.' + className, 'getElementsByClassName', context, (result.length === 0));
|
|
|
+
|
|
|
var moreData = {
|
|
|
resultsNumber : (result && result.length > 0) ? result.length : 0
|
|
|
};
|
|
@@ -88,7 +98,6 @@ exports.module = function(phantomas) {
|
|
|
|
|
|
phantomas.incrMetric('DOMqueriesByTagName');
|
|
|
phantomas.addOffender('DOMqueriesByTagName', '%s (in %s)', tagName, context);
|
|
|
- querySpy('tag name', tagName.toLowerCase(), 'getElementsByTagName', context);
|
|
|
|
|
|
phantomas.enterContext({
|
|
|
type: 'getElementsByTagName',
|
|
@@ -102,7 +111,14 @@ exports.module = function(phantomas) {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- function selectorTagNameSpyAfter(result) {
|
|
|
+ function selectorTagNameSpyAfter(result, args) {
|
|
|
+ /*jshint validthis: true */
|
|
|
+
|
|
|
+ var tagName = args[0];
|
|
|
+ var context = phantomas.getDOMPath(this);
|
|
|
+
|
|
|
+ querySpy('tag name', tagName.toLowerCase(), 'getElementsByTagName', context, (result.length === 0));
|
|
|
+
|
|
|
var moreData = {
|
|
|
resultsNumber : (result && result.length > 0) ? result.length : 0
|
|
|
};
|
|
@@ -112,11 +128,11 @@ exports.module = function(phantomas) {
|
|
|
phantomas.spy(Document.prototype, 'getElementsByTagName', selectorTagNameSpyBefore, selectorTagNameSpyAfter);
|
|
|
phantomas.spy(Element.prototype, 'getElementsByTagName', selectorTagNameSpyBefore, selectorTagNameSpyAfter);
|
|
|
|
|
|
+
|
|
|
// selector queries
|
|
|
function selectorQuerySpy(selector, context) {
|
|
|
phantomas.incrMetric('DOMqueriesByQuerySelectorAll');
|
|
|
phantomas.addOffender('DOMqueriesByQuerySelectorAll', '%s (in %s)', selector, context);
|
|
|
- querySpy('selector', selector, 'querySelectorAll', context);
|
|
|
}
|
|
|
|
|
|
function selectorQuerySpyBefore(selector) {
|
|
@@ -137,7 +153,14 @@ exports.module = function(phantomas) {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- function selectorQuerySpyAfter(result) {
|
|
|
+ function selectorQuerySpyAfter(result, args) {
|
|
|
+ /*jshint validthis: true */
|
|
|
+
|
|
|
+ var selector = args[0];
|
|
|
+ var context = phantomas.getDOMPath(this);
|
|
|
+
|
|
|
+ querySpy('selector', selector, 'querySelectorAll', context, (!result || result.length === 0));
|
|
|
+
|
|
|
var moreData = {
|
|
|
resultsNumber : result ? 1 : 0
|
|
|
};
|
|
@@ -162,7 +185,14 @@ exports.module = function(phantomas) {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- function selectorAllQuerySpryAfter(result) {
|
|
|
+ function selectorAllQuerySpryAfter(result, args) {
|
|
|
+ /*jshint validthis: true */
|
|
|
+
|
|
|
+ var selector = args[0];
|
|
|
+ var context = phantomas.getDOMPath(this);
|
|
|
+
|
|
|
+ querySpy('selector', selector, 'querySelectorAll', context, (!result || result.length === 0));
|
|
|
+
|
|
|
var moreData = {
|
|
|
resultsNumber : (result && result.length > 0) ? result.length : 0
|
|
|
};
|
|
@@ -244,6 +274,19 @@ exports.module = function(phantomas) {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+ // report DOM queries that return no results (issue #420)
|
|
|
+ phantomas.on('domQuery', function(type, query, fnName, context, hasNoResults) {
|
|
|
+ // ignore DOM queries within DOM fragments (used internally by jQuery)
|
|
|
+ if (context.indexOf('body') !== 0 && context.indexOf('#document') !== 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hasNoResults === true) {
|
|
|
+ phantomas.incrMetric('DOMqueriesWithoutResults');
|
|
|
+ phantomas.addOffender('DOMqueriesWithoutResults', '%s (in %s) using %s', query, context, fnName);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
// count DOM queries by either ID, tag name, class name and selector query
|
|
|
// @see https://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-doctype
|
|
|
var Collection = require('../../../../../../node_modules/phantomas/lib/collection'),
|