Parcourir la source

Introducing custom score calculations (jQuery version)

Gaël Métais il y a 10 ans
Parent
commit
521a81ca1d

+ 56 - 15
lib/metadata/policies.json → lib/metadata/policies.js

@@ -1,4 +1,6 @@
-{
+var debug = require('debug')('ylt:policies');
+
+var policies = {
     "DOMelementsCount": {
         "tool": "phantomas",
         "label": "DOM elements count",
@@ -103,24 +105,61 @@
         "isBadThreshold": 50,
         "isAbnormalThreshold": 200
     },
-    "inBodyDomManipulations": {
-        "tool": "ylt",
-        "label": "DOM manipulations in body",
-        "message": "<p>This metric counts the number of DOM queries, DOM inserts, binds, etc. made by the JavaScript before the DOMContentLoaded event.</p><p>Wait for this event before manipulating the DOM. Do not execute JavaScript in the middle of the BODY as it slows down the construction of the DOM and makes a poor maintainability. This is what i call spaghetti code.</p><p>The JS Timeline tab can help you identify what's happening.</p>",
-        "isOkThreshold": 10,
-        "isBadThreshold": 50,
-        "isAbnormalThreshold": 100
-    },
     "jQueryVersion": {
-        "tool": "ylt",
         "label": "jQuery version",
         "message": "<p>Current latest versions of jQuery are 1.11 (with support for old IE versions) and 2.1 (without).</p><p>Each new version of jQuery optimizes performances. Do not keep an old version of jQuery. Updating can sometimes break a few things, but it is generally quite easy to fix them up. So don't hesitate.</p>",
-        "isOkThreshold": 1,
-        "isBadThreshold": 2,
-        "isAbnormalThreshold": 3
+        "scoreFn": function(data) {
+            var differentVersions = data.toolsResults.phantomas.metrics.jQueryDifferentVersions;
+
+            if (differentVersions === 0 || differentVersions > 1) {
+                // Not applicable
+                return null;
+            } else {
+                var value = data.toolsResults.phantomas.metrics.jQueryVersion;
+                var score;
+
+                if (value.indexOf('1.11.') === 0 ||
+                    value.indexOf('1.12.') === 0 ||
+                    value.indexOf('2.1.') === 0 ||
+                    value.indexOf('2.2.') === 0 ||
+                    value.indexOf('3.0.') === 0) {
+                    score = 100;
+                } else if (value.indexOf('1.10.') === 0 ||
+                           value.indexOf('2.0.') === 0) {
+                    score = 90;
+                } else if (value.indexOf('1.9.') === 0) {
+                    score = 70;
+                } else if (value.indexOf('1.8.') === 0) {
+                    score = 50;
+                } else if (value.indexOf('1.7.') === 0) {
+                    score = 40;
+                } else if (value.indexOf('1.6.') === 0) {
+                    score = 30;
+                } else if (value.indexOf('1.5.') === 0) {
+                    score = 20;
+                } else if (value.indexOf('1.4.') === 0) {
+                    score = 10;
+                } else if (value.indexOf('1.3.') === 0) {
+                    score = 0;
+                } else if (value.indexOf('1.2.') === 0) {
+                    score = 0;
+                } else {
+                    debug('Unknown jQuery version "%s"', value);
+                    return null;
+                }
+
+                return {
+                    value: value,
+                    score: score,
+                    bad: value < 100,
+                    abnormal: false,
+                    abnormalityScore: 0
+                };
+            }
+        }
     },
     "jQueryDifferentVersions": {
-        "tool": "ylt",
+        "tool": "phantomas",
         "label": "Several versions loaded",
         "message": "<p>jQuery is a heavy library. You should <b>never<b> load jQuery more than one on the same page.</p>",
         "isOkThreshold": 1,
@@ -367,4 +406,6 @@
         "isBadThreshold": 25,
         "isAbnormalThreshold": 50
     }
-}
+};
+
+module.exports = policies;

+ 1 - 2
lib/metadata/scoreProfileGeneric.json

@@ -25,8 +25,7 @@
                 "evalCalls": 1,
                 "documentWriteCalls": 2,
                 "consoleMessages": 0.5,
-                "globalVariables": 0.5,
-                "inBodyDomManipulations": 1
+                "globalVariables": 0.5
             }
         },
         "jQueryVersion": {

+ 27 - 3
lib/rulesChecker.js

@@ -12,12 +12,14 @@ var RulesChecker = function() {
 
         for (var metricName in policies) {
             var policy = policies[metricName];
+            var rule;
 
-            if (data.toolsResults[policy.tool] &&
+            if (policy.tool &&
+                data.toolsResults[policy.tool] &&
                 data.toolsResults[policy.tool].metrics &&
                 (data.toolsResults[policy.tool].metrics[metricName] || data.toolsResults[policy.tool].metrics[metricName] === 0)) {
-                    
-                    var rule = {
+
+                    rule = {
                         value: data.toolsResults[policy.tool].metrics[metricName],
                         policy: policy
                     };
@@ -40,7 +42,29 @@ var RulesChecker = function() {
                     rule.abnormalityScore = Math.min(Math.round(abnormalityScore), 0);
 
                     results[metricName] = rule;
+                    debug('Metric %s calculated. Score: %d', metricName, rule.score);
+
             
+            } else if (policy.scoreFn) {
+
+                debug('Custom score function for %s', metricName);
+                
+                // Custom score function
+                rule = policy.scoreFn(data);
+
+                // Check returned values (if the result is null, just don't save)
+                if (rule) {
+                    rule.policy = {
+                        label: policy.label,
+                        message: policy.message
+                    };
+
+                    results[metricName] = rule;
+                    debug('Metric %s calculated. Score: %d', metricName, rule.score);
+                } else {
+                    debug('Metric %s is null. Ignored.', metricName);
+                }
+
             } else {
 
                 debug('Metric %s not found for tool %s', metricName, policy.tool);

+ 9 - 9
lib/runner.js

@@ -21,11 +21,18 @@ var Runner = function(params) {
     phantomasWrapper.execute(data).then(function(phantomasResults) {
         data.toolsResults.phantomas = phantomasResults;
 
-        // Other tools go there
+        // Get the JS Execution Tree from offenders and put in the main object
+        try {
+            data.javascriptExecutionTree = JSON.parse(data.toolsResults.phantomas.offenders.javascriptExecutionTree[0]);    
+        } catch(e) {
+            debug('Could not find nor parse phantomas.offenders.javascriptExecutionTree');
+        }
+
+        // Other tools go here
 
 
         // Rules checker
-        var policies = require('./metadata/policies.json');
+        var policies = require('./metadata/policies');
         data.rules = rulesChecker.check(data, policies);
 
 
@@ -35,13 +42,6 @@ var Runner = function(params) {
             generic : scoreCalculator.calculate(data, scoreProfileGeneric)
         };
 
-
-        // Get the JS Execution Tree from offenders and put in the main object
-        try {
-            data.javascriptExecutionTree = JSON.parse(data.toolsResults.phantomas.offenders.javascriptExecutionTree[0]);    
-        } catch(e) {
-            debug('Could not find nor parse phantomas.offenders.javascriptExecutionTree');
-        }
         
         delete data.toolsResults.phantomas.metrics.javascriptExecutionTree;
         delete data.toolsResults.phantomas.offenders.javascriptExecutionTree;

+ 87 - 0
test/core/customPoliciesTest.js

@@ -0,0 +1,87 @@
+var should = require('chai').should();
+var rulesChecker = require('../../lib/rulesChecker');
+
+describe('rulesChecker', function() {
+    
+    var policies = require('../../lib/metadata/policies.js');
+
+ 
+    it('should grade correctly jQuery versions', function() {
+        
+
+        var versions = {
+            '1.2.9': 0,
+            '1.3.9': 0,
+            '1.4.4': 10,
+            '1.5.0': 20,
+            '1.6.3': 30,
+            '1.7.0': 40,
+            '1.8.3a': 50,
+            '1.9.2': 70,
+            '1.10.1': 90,
+            '2.0.0-rc1': 90,
+            '1.11.1': 100,
+            '2.1.1-beta1': 100,
+            '3.0.0': 100
+        };
+
+        for (var version in versions) {
+            results = rulesChecker.check({
+                "toolsResults": {
+                    "phantomas": {
+                        "metrics": {
+                            "jQueryVersion": version
+                        }
+                    }
+                }
+            }, policies);
+            results.jQueryVersion.score.should.equal(versions[version]);
+        }
+
+
+        // Unknown jQuery version
+        results = rulesChecker.check({
+            "toolsResults": {
+                "phantomas": {
+                    "metrics": {
+                        "jQueryVersion": "wooot"
+                    }
+                }
+            }
+        }, policies);
+        results.should.deep.equals({});
+
+
+        // If jQueryDifferentVersions is 0
+        results = rulesChecker.check({
+            "toolsResults": {
+                "phantomas": {
+                    "metrics": {
+                        "jQueryVersion": "1.6.0",
+                        "jQueryDifferentVersions": 0
+                    }
+                }
+            }
+        }, policies);
+        results.should.not.have.a.property('jQueryVersion');
+        results.should.have.a.property('jQueryDifferentVersions');
+        results.jQueryDifferentVersions.should.have.a.property('score').that.equals(100);
+
+
+        // If there are more than 1 jQuery version
+        results = rulesChecker.check({
+            "toolsResults": {
+                "phantomas": {
+                    "metrics": {
+                        "jQueryVersion": "1.6.0",
+                        "jQueryDifferentVersions": 2
+                    }
+                }
+            }
+        }, policies);
+        results.should.not.have.a.property('jQueryVersion');
+        results.should.have.a.property('jQueryDifferentVersions');
+        results.jQueryDifferentVersions.should.have.a.property('score').that.equals(0);
+        results.jQueryDifferentVersions.should.have.a.property('abnormal').that.equals(true);
+    });
+});