Replaced DOMqueriesWithoutResults by queriesWithoutResults to include jQuery queries

This commit is contained in:
Gaël Métais
2015-05-22 18:54:32 +02:00
parent 2fb4a7bd6a
commit 33621af3ad
5 changed files with 52 additions and 41 deletions
+11
View File
@@ -22,6 +22,17 @@ yltApp.run(['$rootScope', '$location', function($rootScope, $location) {
$rootScope.isTouchDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent); $rootScope.isTouchDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent);
$rootScope.loadedRunId = null; $rootScope.loadedRunId = null;
var oldHash;
// We don't want the hash to be kept between two pages
$rootScope.$on('$locationChangeStart', function(param1, param2, param3, param4){
var newHash = $location.hash();
if (newHash === oldHash) {
$location.hash(null);
}
oldHash = newHash;
});
// Google Analytics // Google Analytics
$rootScope.$on('$routeChangeSuccess', function(){ $rootScope.$on('$routeChangeSuccess', function(){
ga('send', 'pageview', {'page': $location.path()}); ga('send', 'pageview', {'page': $location.path()});
+28 -8
View File
@@ -4,14 +4,6 @@ timelineCtrl.controller('TimelineCtrl', ['$scope', '$rootScope', '$routeParams',
$scope.runId = $routeParams.runId; $scope.runId = $routeParams.runId;
$scope.Menu = Menu.setCurrentPage('timeline', $scope.runId); $scope.Menu = Menu.setCurrentPage('timeline', $scope.runId);
$scope.warningsFilterOn = false;
$scope.warningsFilters = {
queryWithoutResults: true,
jQueryCallOnEmptyObject: true,
eventNotDelegated: true,
jsError: true
};
function loadResults() { function loadResults() {
// Load result if needed // Load result if needed
if (!$rootScope.loadedResult || $rootScope.loadedResult.runId !== $routeParams.runId) { if (!$rootScope.loadedResult || $rootScope.loadedResult.runId !== $routeParams.runId) {
@@ -27,12 +19,40 @@ timelineCtrl.controller('TimelineCtrl', ['$scope', '$rootScope', '$routeParams',
} }
function render() { function render() {
initFilters();
initScriptFiltering(); initScriptFiltering();
initExecutionTree(); initExecutionTree();
initTimeline(); initTimeline();
$timeout(initProfiler, 100); $timeout(initProfiler, 100);
} }
function initFilters() {
var hash = $location.hash();
var filter = null;
if (hash.indexOf('filter=') === 0) {
filter = hash.substr(7);
}
$scope.warningsFilterOn = (filter !== null);
$scope.warningsFilters = {
queryWithoutResults: (filter === null || filter === 'queryWithoutResults'),
jQueryCallOnEmptyObject: (filter === null || filter === 'jQueryCallOnEmptyObject'),
eventNotDelegated: (filter === null || filter === 'eventNotDelegated'),
jsError: (filter === null || filter === 'jsError')
};
// If a filter is defined in the hash (ie: "/result/xxxxx/timeline#filter=queryWithoutResults")
var hash = $location.hash();
if (hash.indexOf('filter=') === 0) {
var filter = hash.substr(7);
$scope.warningsFilterOn = true;
for (var key in $scope.warningsFilter) {
}
}
}
function initScriptFiltering() { function initScriptFiltering() {
var offenders = $scope.result.rules.jsCount.offendersObj.list; var offenders = $scope.result.rules.jsCount.offendersObj.list;
$scope.scripts = []; $scope.scripts = [];
+6 -5
View File
@@ -30,10 +30,6 @@
<div ng-if="policyName === 'DOMidDuplicated'"> <div ng-if="policyName === 'DOMidDuplicated'">
<b>{{offender.id}}</b>: {{offender.occurrences}} occurrences <b>{{offender.id}}</b>: {{offender.occurrences}} occurrences
</div> </div>
<div ng-if="policyName === 'DOMqueriesWithoutResults'">
<b>{{offender.query}}</b> (in <dom-element-button obj="offender.context"></dom-element-button>) using {{offender.fn}}
</div>
<div ng-if="policyName === 'DOMqueriesAvoidable'"> <div ng-if="policyName === 'DOMqueriesAvoidable'">
<b>{{offender.query}}</b> (in <dom-element-button obj="offender.context"></dom-element-button>) using {{offender.fn}}: <b>{{offender.count}} queries</b> <b>{{offender.query}}</b> (in <dom-element-button obj="offender.context"></dom-element-button>) using {{offender.fn}}: <b>{{offender.count}} queries</b>
@@ -214,10 +210,15 @@
</div> </div>
<div ng-if="policyName === 'DOMaccesses'"> <div ng-if="policyName === 'DOMaccesses'">
<h3>Offenders</h3> <h3>{{rule.value}} offenders</h3>
Please open the <a href="/result/{{runId}}/timeline">JS timeline</a> Please open the <a href="/result/{{runId}}/timeline">JS timeline</a>
</div> </div>
<div ng-if="policyName === 'queriesWithoutResults'">
<h3>{{rule.value}} offenders</h3>
Please open the <a href="/result/{{runId}}/timeline#filter=queryWithoutResults">JS timeline, filtered by "Queries without results"</a>
</div>
<div ng-if="!rule && rule !== null" class="notFound"> <div ng-if="!rule && rule !== null" class="notFound">
<h2>404</h2> <h2>404</h2>
Rule "{{policyName}}"" not found Rule "{{policyName}}"" not found
+6 -27
View File
@@ -73,37 +73,16 @@ var policies = {
"isOkThreshold": 50, "isOkThreshold": 50,
"isBadThreshold": 1500, "isBadThreshold": 1500,
"isAbnormalThreshold": 3000, "isAbnormalThreshold": 3000,
"hasOffenders": true "hasOffenders": false
}, },
"DOMqueriesWithoutResults": { "queriesWithoutResults": {
"tool": "phantomas", "tool": "jsExecutionTransformer",
"label": "DOM queries without result", "label": "Queries without result",
"message": "<p>Number of queries that return no result.</p><p>It suggests the query is not used on the page, probably because it is some dead code.</p><p>Or maybe the code is trying to find an HTML block that is not always here. Look at the JS Timeline to see if the scripts correctly figures out the HTML block is not here and immediatly stops interacting further with the DOM.</p>", "message": "<p>Number of queries that return no result. Both native and jQuery DOM requests are counted.</p><p>It suggests the query is not used on the page, probably because it is some dead code.</p><p>Or maybe the code is trying to find an HTML block that is not always here. Look at the JS Timeline to see if the scripts correctly figures out the HTML block is not here and immediatly stops interacting further with the DOM.</p>",
"isOkThreshold": 0, "isOkThreshold": 0,
"isBadThreshold": 100, "isBadThreshold": 100,
"isAbnormalThreshold": 200, "isAbnormalThreshold": 200,
"hasOffenders": true, "hasOffenders": false
"offendersTransformFn": function(offenders) {
return {
count: offenders.length,
list: offenders.map(function(offender) {
var parts = /^(.*) ?\(in ?(.*)\) ?using ?(.*)$/.exec(offender);
if (!parts) {
debug('DOMqueriesWithoutResults offenders transform function error with "%s"', offender);
return {
parseError: offender
};
}
return {
query: parts[1],
context: offendersHelpers.domPathToDomElementObj(parts[2]),
fn: parts[3]
};
})
};
}
}, },
"DOMqueriesAvoidable": { "DOMqueriesAvoidable": {
"tool": "phantomas", "tool": "phantomas",
+1 -1
View File
@@ -13,7 +13,7 @@
"label": "DOM manipulations", "label": "DOM manipulations",
"policies": { "policies": {
"DOMaccesses": 3, "DOMaccesses": 3,
"DOMqueriesWithoutResults": 1, "queriesWithoutResults": 1,
"DOMqueriesAvoidable": 1 "DOMqueriesAvoidable": 1
} }
}, },