Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #296 from alex-seville/development

v1.1.5
  • Loading branch information...
commit 5e6eaa6d1cb49250d321f5d23d235689c22c0aea 2 parents 6c1b00f + 0389f3f
@alex-seville authored
Showing with 1,414 additions and 4,859 deletions.
  1. +1 −1  component.json
  2. +450 −2,306 dist/jasmine/blanket_jasmine.js
  3. +1 −1  dist/jasmine/blanket_jasmine.min.js
  4. +436 −2,292 dist/qunit/blanket.js
  5. +1 −1  dist/qunit/blanket.min.js
  6. +4 −4 docs/advanced_browser.md
  7. +111 −0 docs/browser_options.md
  8. +15 −2 docs/intermediate_browser.md
  9. +1 −10 grunt.js
  10. +3 −3 package.json
  11. +1 −1  src/adapters/jasmine-blanket.js
  12. +2 −2 src/blanket.js
  13. +245 −131 src/blanketRequire.js
  14. +27 −39 src/blanket_browser.js
  15. +6 −17 src/config.js
  16. +18 −13 src/index.js
  17. +1 −1  src/qunit/qunit.js
  18. +69 −11 src/qunit/reporter.js
  19. +7 −6 src/reporters/lcov_reporter.js
  20. +6 −5 src/reporters/simple_json_reporter.js
  21. +1 −1  tasks/blanketTests.js
  22. +1 −0  test/helpers/phantom_qunit_runner.js
  23. +0 −5 test/lib-tests/blanket_test.js
  24. +3 −3 test/requirejs/chutzpah.html
  25. +1 −1  test/requirejs/require_runner.html
  26. +3 −3 test/test-node/fixture/core_fixtures.js
  27. 0  test/test-node/fixture/{simple_test_file.js → simple_test_file.js.js}
  28. 0  test/test-node/fixture/{simple_test_file_instrumented.js → simple_test_file_instrumented.js.js}
  29. 0  test/test-node/fixture/{simple_test_file_instrumented_full.js → simple_test_file_instrumented_full.js.js}
View
2  component.json
@@ -1,5 +1,5 @@
{
"name": "blanket",
- "version": "1.1.4",
+ "version": "1.1.5",
"main": ["./dist/qunit/blanket.js"]
}
View
2,756 dist/jasmine/blanket_jasmine.js
450 additions, 2,306 deletions not shown
View
2  dist/jasmine/blanket_jasmine.min.js
1 addition, 1 deletion not shown
View
2,728 dist/qunit/blanket.js
436 additions, 2,292 deletions not shown
View
2  dist/qunit/blanket.min.js
1 addition, 1 deletion not shown
View
8 docs/advanced_browser.md
@@ -40,15 +40,15 @@ Custom reporters are used by Blanket to display the coverage results. Blanket c
See the [simple_json_reporter](https://raw.github.com/alex-seville/blanket/master/src/reporters/simple_json_reporter.js) as a very basic example of a reporter.
-Reporters need to be wrapped in a define statement, and return a function that accept the coverage results object as an argument, ex:
+Reporters are functions assigned to blanket.customReporter, which accept the coverage results object as an argument, ex:
```
-define([],function myReporter(){
+(function myReporter(){
//your reporter code
- return function(coverage_results){
+ blanket.customReporter=function(coverage_results){
console.log(coverage_results);
};
-};
+})();
```
The example above will create a reporter that will print the coverage result object to the console. Not useful, but it illustrates the pattern.
View
111 docs/browser_options.md
@@ -0,0 +1,111 @@
+# Blanket Options (browser version)
+
+This guide details all the configuration options available for the browser version of Blanket.js
+
+1. data-cover-adapter
+2. data-cover-customVariable
+3. data-cover-flags
+ a. autoStart
+ b. branchTracking
+ c. commonJS
+ d. debug
+ e. engineOnly
+ f. existingRequireJS
+ g. ignoreCors
+ h. ignoreError
+ i. instrumentCache
+ j. sourceURL
+4. data-cover-loader
+5. data-cover-modulepattern
+6. data-cover-never
+7. data-cover-only
+8. data-cover-reporter
+9. data-cover-reporter-options
+10. data-cover-testReadyCallback
+11. data-cover-timeout
+
+
+1. data-cover-adapter
+
+Use this option to configure a custom adapter for Blanket. Examples include adapters for Jasmine or Mocha. An adapter can be any code intended to run in concert with Blanket. Adapters do not have any special execution scope or access to Blanket, but they are required to override the default QUnit bindings.
+
+The value for this setting must be a string representing a valid url path to the adapter JavaScript file.
+
+Syntax: data-cover-adapter="<path/to/adapter>"
+Example: `data-cover-adapter="src/adapters/mocha-blanket.js"
+Result: The mocha-blanket adapter, located in src/adapters, will be loaded when the main Blanket script is executed.
+
+
+2. data-cover-customVariable
+
+This option can be used to override the default coverage variable name (_$blanket). Often this isn't required, but there may be use cases where you'd like it to match the variable name of another coverage package (i.e. _$jscoverage) or avoid collisions with local variables in your code.
+
+NOTE: There are no checks done to ensure that the variable you provide is valid. It is your responsibility to ensure that a valid, conflict-free variable name is provided.
+
+Syntax: data-cover-customVariable="<custom variable name>"
+Example: data-cover-customVariable="myCoverageVariable"
+Result: Blanket will use `myCoverageVariable` as the coverage variable. After covered files are executed you can retrieve coverage information by querying the `myCoverageVariable` variable.
+
+
+3. data-cover-flags
+
+The data-cover-flags option is used to set a variety of boolean settings. It is a string value, and if an option is included in the string it will be set to `true`.
+
+The syntax for data-cover-flag values is `data-cover-flags="<whitespace separated list of flags>"`, i.e. `data-cover-flags="ignoreError debug"`.
+
+ a. autoStart
+
+ h. ignoreError
+
+ This option is used to force Blanket to continue processing even if an error occurs during instrumentation. This allows users to manage error handling in their prefered manner.
+
+
+
+
+7. data-cover-only
+
+This option is used to indicate which files you want included for coverage. The value can be a string, regular expression, array, or function.
+If you're including it in a data attribute, you must use the following format:
+
+regular expression: data-cover-only="//<your regular expression>"
+example: data-cover-only="//sourcefile[0-9]{2}.js$/i"
+result: the file `sourcefile89.js` would be covered.
+
+array: data-cover-only="[<comma separated list of strings, regular expressions, arryas or functions>]"
+example: data-cover-only="['src/','modules/']"
+result: files contains `src/` and `modules/` in their files paths will be covered.
+
+function: data-cover-only="#<function declaration or function name>"
+example: data-cover-only="#function(str){ return str.length < 5; }"
+result: any files whose path is less than 5 characters will be covered.
+
+
+6. data-cover-never
+
+This option is used to indicate which files you want excluded from coverage. If a file matches this setting it will be excluded, even if it matches a pattern from `data-cover-only`. The value can be a string, regular expression, array, or function.
+If you're including it in a data attribute, you must use the following format:
+
+regular expression: data-cover-never="//<your regular expression>"
+example: data-cover-never="//sourcefile[0-9]{2}.js$/i"
+result: the file `sourcefile89.js` would be excluded from coverage.
+
+array: data-cover-never="[<comma separated list of strings, regular expressions, arryas or functions>]"
+example: data-cover-never="['src/','modules/']"
+result: files contains `src/` and `modules/` in their files paths will be excluded from coverage.
+
+function: data-cover-never="#<function declaration or function name>"
+example: data-cover-never="#function(str){ return str.length < 5; }"
+result: any files whose path is less than 5 characters will be excluded from coverage.
+
+
+8. data-cover-reporter
+
+This option is used to set a custom reporter for Blanket. The value can be a string (valid file path to reporter file), or a function (accepting the coverage result as an argument).
+
+string: data-cover-reporter="<path/to/custom/reporter>"
+example: data-cover-reporter="mocha_blanket_reporter.js"
+result: The reporter defined in mocha_blanket_reporter will be attached as the reporter for Blanket coverage results.
+
+function: blanket.options('data-cover-reporter',<reporter function>);
+example: blanket.options('data-cover-reporter',function myReporter(cov){ alert(cov); });
+result: The full coverage object will be outputted via an alert dialog.
View
17 docs/intermediate_browser.md
@@ -23,6 +23,19 @@ NOTE: PhantomJS and other third-party JS runtimes may not support synchronous XH
```<script src="blanket.min.js" data-cover-adapter="jasmine-blanket.js"
data-cover-only="['source1.js','src/source2.js']"></script>```
-5. Open the test runner in the browser. The coverage details will be appended below the test results.
+5. Add a `data-cover-modulepattern` attribute to have the reporter generate total coverage statistics for each module in your application. (*Currently only supported using QUnit reporter.*) This is useful for tracking code coverage across multiple teams that work on different modules. Modules are determined by the regular expression pattern you pass via this attribute. The regular expression is expected to have one pattern matching section in parenthesis, which will be captured as the module name. For example, let's say that the files in your blanket report look like this:
-6. If you will always be using the adapter, consider making a [custom build](https://github.com/alex-seville/blanket/blob/master/README.md#roll-your-own) of blanket (i.e. `dist/jasmine/blanket_jasmine.js`).
+```
+./core/src/js/MainView.js
+./core/src/js/NavBar.js
+./gallery/src/js/GalleryView.js
+./cart/src/js/Cart.js
+```
+
+In this case, we want the module to be recognized as the characters in between the first two slashes, such that we end up with modules `core`, `gallery`, and `cart`. To achieve this, specify an attribute like so: `data-cover-modulepattern="\.\/(.*?)\/"`
+
+This regular expression says, look for a period, followed by a slash, followed by any number of characters up until the next slash (which we store as a matched pattern). For more info on regular expressions, see the [MDN RegEx guide](https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Regular_Expressions).
+
+6. Open the test runner in the browser. The coverage details will be appended below the test results.
+
+7. If you will always be using the adapter, consider making a [custom build](https://github.com/alex-seville/blanket/blob/master/README.md#roll-your-own) of blanket (i.e. `dist/jasmine/blanket_jasmine.js`).
View
11 grunt.js
@@ -9,8 +9,6 @@ module.exports = function(grunt) {
falafelEnd: 'window.falafel = module.exports;})(function(){return {parse: esprima.parse};},{exports: {}});',
esprimaStart: '(function(define){',
esprimaEnd: '})(null);<%= "" %>',
- requireStart: 'blanket.setupRequireJS=function(context){',
- requireEnd: 'context.require=require; context.define=define; context.requirejs=requirejs; };'
},
blanketTest: {
normal:{
@@ -29,7 +27,7 @@ module.exports = function(grunt) {
browserBootstrap: "<%= cmds.phantom %> <%= phantom.qunit_old %> <%= runners.browserBootstrap %>",
browserCoffeeScript: "<%= cmds.phantom %> <%= phantom.qunit %> <%= runners.browserCoffeeScript %>",
browserJasmineRequire: "<%= cmds.phantom %> <%= phantom.jasmine %> <%= runners.browserJasmineRequire %>",
- browserChutzpah: "<%= cmds.phantom %> <%= phantom.qunit %> <%= runners.browserChutzpah %>",
+ //browserChutzpah: "<%= cmds.phantom %> <%= phantom.qunit %> <%= runners.browserChutzpah %>",
browserCommonjs: "<%= cmds.phantom %> <%= phantom.qunit %> <%= runners.browserCommonjs %>"
},
coverage:{
@@ -55,9 +53,6 @@ module.exports = function(grunt) {
'<banner:meta.falafelEnd>',
'src/blanket.js',
'src/blanket_browser.js',
- '<banner:meta.requireStart>',
- 'node_modules/requirejs/require.js',
- '<banner:meta.requireEnd>',
"src/qunit/reporter.js",
"src/config.js",
"src/blanketRequire.js",
@@ -74,9 +69,6 @@ module.exports = function(grunt) {
'<banner:meta.falafelEnd>',
'src/blanket.js',
'src/blanket_browser.js',
- '<banner:meta.requireStart>',
- 'node_modules/requirejs/require.js',
- '<banner:meta.requireEnd>',
"src/qunit/reporter.js",
"src/config.js",
"src/blanketRequire.js",
@@ -130,7 +122,6 @@ module.exports = function(grunt) {
node: true,
browser: true,
es5: true,
- "evil":"ignore",
expr: "warn"
},
globals: {}
View
6 package.json
@@ -1,7 +1,7 @@
{
"name": "blanket",
"description": "seamless js code coverage",
- "version": "1.1.4",
+ "version": "1.1.5",
"homepage": "https://github.com/alex-seville/blanket",
"author": {
"name": "Alex-Seville",
@@ -23,18 +23,18 @@
],
"main": "src/index.js",
"engines": {
- "node": "0.8.*"
+ "node": "0.10.7"
},
"dependencies": {
"esprima": "~1.0.2",
"falafel": "~0.1.6",
- "requirejs": "~2.1.4",
"xtend": "~2.0.3"
},
"devDependencies": {
"phantomjs": "1.8.2-0",
"coffee-script": "1.4.0",
"mocha": "1.7.4",
+ "requirejs": "~2.1.4",
"travis-cov": "*",
"grunt": "0.3.17"
},
View
2  src/adapters/jasmine-blanket.js
@@ -83,7 +83,7 @@
jasmine.getEnv().addReporter(new jasmine.BlanketReporter());
window.jasmine.getEnv().currentRunner().execute();
jasmine.getEnv().execute = function () {
- jasmine.getEnv().currentRunner().execute;
+ jasmine.getEnv().currentRunner().execute();
};
}
});
View
4 src/blanket.js
@@ -34,7 +34,6 @@ var parseAndModify = (inBrowser ? window.falafel : require("falafel"));
adapter:null,
filter: null,
customVariable: null,
- orderedLoading: true,
loader: null,
ignoreScriptError: false,
existingRequireJS:false,
@@ -47,7 +46,8 @@ var parseAndModify = (inBrowser ? window.falafel : require("falafel"));
engineOnly:false,
testReadyCallback:null,
commonJS:false,
- instrumentCache:false
+ instrumentCache:false,
+ modulePattern: null
};
if (inBrowser && typeof window.blanket !== 'undefined'){
View
376 src/blanketRequire.js
@@ -1,139 +1,225 @@
(function(_blanket){
_blanket.extend({
utils: {
- normalizeBackslashes: function(str) {
- return str.replace(/\\/g, '/');
- },
- matchPatternAttribute: function(filename,pattern){
- if (typeof pattern === 'string'){
- if (pattern.indexOf("[") === 0){
- //treat as array
- var pattenArr = pattern.slice(1,pattern.length-1).split(",");
- return pattenArr.some(function(elem){
- return _blanket.utils.matchPatternAttribute(filename,_blanket.utils.normalizeBackslashes(elem.slice(1,-1)));
- //return filename.indexOf(_blanket.utils.normalizeBackslashes(elem.slice(1,-1))) > -1;
+ normalizeBackslashes: function(str) {
+ return str.replace(/\\/g, '/');
+ },
+ matchPatternAttribute: function(filename,pattern){
+ if (typeof pattern === 'string'){
+ if (pattern.indexOf("[") === 0){
+ //treat as array
+ var pattenArr = pattern.slice(1,pattern.length-1).split(",");
+ return pattenArr.some(function(elem){
+ return _blanket.utils.matchPatternAttribute(filename,_blanket.utils.normalizeBackslashes(elem.slice(1,-1)));
+ //return filename.indexOf(_blanket.utils.normalizeBackslashes(elem.slice(1,-1))) > -1;
+ });
+ }else if ( pattern.indexOf("//") === 0){
+ var ex = pattern.slice(2,pattern.lastIndexOf('/'));
+ var mods = pattern.slice(pattern.lastIndexOf('/')+1);
+ var regex = new RegExp(ex,mods);
+ return regex.test(filename);
+ }else if (pattern.indexOf("#") === 0){
+ return window[pattern.slice(1)].call(window,filename);
+ }else{
+ return filename.indexOf(_blanket.utils.normalizeBackslashes(pattern)) > -1;
+ }
+ }else if ( pattern instanceof Array ){
+ return pattern.some(function(elem){
+ return _blanket.utils.matchPatternAttribute(filename,elem);
});
- }else if ( pattern.indexOf("//") === 0){
- var ex = pattern.slice(2,pattern.lastIndexOf('/'));
- var mods = pattern.slice(pattern.lastIndexOf('/')+1);
- var regex = new RegExp(ex,mods);
- return regex.test(filename);
- }else if (pattern.indexOf("#") === 0){
- return window[pattern.slice(1)].call(window,filename);
- }else{
- return filename.indexOf(_blanket.utils.normalizeBackslashes(pattern)) > -1;
+ }else if (pattern instanceof RegExp){
+ return pattern.test(filename);
+ }else if (typeof pattern === "function"){
+ return pattern.call(window,filename);
}
- }else if ( pattern instanceof Array ){
- return pattern.some(function(elem){
- return _blanket.utils.matchPatternAttribute(filename,elem);
- });
- }else if (pattern instanceof RegExp){
- return pattern.test(filename);
- }else if (typeof pattern === "function"){
- return pattern.call(window,filename);
- }
- },
- blanketEval: function(data){
- return ( window.execScript || function( data ) {
- //borrowed from jquery
- window[ "eval" ].call( window, data );
- } )( data );
- },
- collectPageScripts: function(){
- console.log("cps1:"+new Date().getTime());
- var toArray = Array.prototype.slice;
- var scripts = toArray.call(document.scripts);
- var selectedScripts=[],scriptNames=[];
- var filter = _blanket.options("filter");
- if(filter != null){
- //global filter in place, data-cover-only
- var antimatch = _blanket.options("antifilter");
- selectedScripts = toArray.call(document.scripts)
- .filter(function(s){
- return toArray.call(s.attributes).filter(function(sn){
- return sn.nodeName === "src" && _blanket.utils.matchPatternAttribute(sn.nodeValue,filter) &&
- (typeof antimatch === "undefined" || !_blanket.utils.matchPatternAttribute(sn.nodeValue,antimatch));
- }).length === 1;
- });
- }else{
- selectedScripts = toArray.call(document.querySelectorAll("script[data-cover]"));
- }
- scriptNames = selectedScripts.map(function(s){
- return _blanket.utils.qualifyURL(
- toArray.call(s.attributes).filter(
- function(sn){
- return sn.nodeName === "src";
- })[0].nodeValue).replace(".js","");
+ },
+ blanketEval: function(data){
+ _blanket._addScript(data);
+ },
+ collectPageScripts: function(){
+ var toArray = Array.prototype.slice;
+ var scripts = toArray.call(document.scripts);
+ var selectedScripts=[],scriptNames=[];
+ var filter = _blanket.options("filter");
+ if(filter != null){
+ //global filter in place, data-cover-only
+ var antimatch = _blanket.options("antifilter");
+ selectedScripts = toArray.call(document.scripts)
+ .filter(function(s){
+ return toArray.call(s.attributes).filter(function(sn){
+ return sn.nodeName === "src" && _blanket.utils.matchPatternAttribute(sn.nodeValue,filter) &&
+ (typeof antimatch === "undefined" || !_blanket.utils.matchPatternAttribute(sn.nodeValue,antimatch));
+ }).length === 1;
});
- if (!filter){
- _blanket.options("filter","['"+scriptNames.join("','")+"']");
- }
- return scriptNames;
- }
-}
-});
-(function(){
- var require = blanket.options("commonJS") ? blanket._commonjs.require : window.require;
- var requirejs = blanket.options("commonJS") ? blanket._commonjs.requirejs : window.requirejs;
- if (!_blanket.options("engineOnly")){
-
- _blanket.utils.oldloader = requirejs.load;
- console.log("cps2:"+new Date().getTime());
-
- requirejs.load = function (context, moduleName, url) {
- _blanket.requiringFile(url);
- requirejs.cget(url, function (content) {
+ }else{
+ selectedScripts = toArray.call(document.querySelectorAll("script[data-cover]"));
+ }
+ scriptNames = selectedScripts.map(function(s){
+ return _blanket.utils.qualifyURL(
+ toArray.call(s.attributes).filter(
+ function(sn){
+ return sn.nodeName === "src";
+ })[0].nodeValue).replace(".js","");
+ });
+ if (!filter){
+ _blanket.options("filter","['"+scriptNames.join("','")+"']");
+ }
+ return scriptNames;
+ },
+ loadAll: function(nextScript,cb,preprocessor){
+ /**
+ * load dependencies
+ * @param {nextScript} factory for priority level
+ * @param {cb} the done callback
+ */
+ var currScript=nextScript();
+ var isLoaded = _blanket.utils.scriptIsLoaded(
+ currScript,
+ _blanket.utils.ifOrdered,
+ nextScript,
+ cb
+ );
+
+ if (!(_blanket.utils.cache[currScript] && _blanket.utils.cache[currScript].loaded)){
+ var attach = function(){
+ if (_blanket.options("debug")) {console.log("BLANKET-Mark script:"+currScript+", as loaded and move to next script.");}
+ isLoaded();
+ };
+ var whenDone = function(result){
+ if (_blanket.options("debug")) {console.log("BLANKET-File loading finished");}
+ if (typeof result !== 'undefined'){
+ if (_blanket.options("debug")) {console.log("BLANKET-Add file to DOM.");}
+ _blanket._addScript(result);
+ }
+ attach();
+ };
- var match = _blanket.options("filter");
- //we check the never matches first
- var antimatch = _blanket.options("antifilter");
- if (typeof antimatch !== "undefined" &&
- _blanket.utils.matchPatternAttribute(url.replace(".js",""),antimatch)
- ){
- _blanket.utils.oldloader(context, moduleName, url);
- if (_blanket.options("debug")) {console.log("BLANKET-File will never be instrumented:"+url);}
- _blanket.requiringFile(url,true);
- }else if (_blanket.utils.matchPatternAttribute(url.replace(".js",""),match)){
- if (_blanket.options("debug")) {console.log("BLANKET-Attempting instrument of:"+url);}
- _blanket.instrument({
- inputFile: content,
- inputFileName: url
- },function(instrumented){
- try{
- _blanket.utils.blanketEval(instrumented);
- context.completeLoad(moduleName);
+ _blanket.utils.attachScript(
+ {
+ url: currScript
+ },
+ function (content){
+ _blanket.utils.processFile(
+ content,
+ currScript,
+ whenDone,
+ whenDone
+ );
+ }
+ );
+ }else{
+ isLoaded();
+ }
+ },
+ attachScript: function(options,cb){
+ var timeout = _blanket.options("timeout") || 3000;
+ setTimeout(function(){
+ if (!_blanket.utils.cache[options.url].loaded){
+ throw new Error("error loading source script");
+ }
+ },timeout);
+ _blanket.utils.getFile(
+ options.url,
+ cb,
+ function(){ throw new Error("error loading source script");}
+ );
+ },
+ ifOrdered: function(nextScript,cb){
+ /**
+ * ordered loading callback
+ * @param {nextScript} factory for priority level
+ * @param {cb} the done callback
+ */
+ var currScript = nextScript(true);
+ if (currScript){
+ _blanket.utils.loadAll(nextScript,cb);
+ }else{
+ cb(new Error("Error in loading chain."));
+ }
+ },
+ scriptIsLoaded: function(url,orderedCb,nextScript,cb){
+ /**
+ * returns a callback that checks a loading list to see if a script is loaded.
+ * @param {orderedCb} callback if ordered loading is being done
+ * @param {nextScript} factory for next priority level
+ * @param {cb} the done callback
+ */
+ if (_blanket.options("debug")) {console.log("BLANKET-Returning function");}
+ return function(){
+ if (_blanket.options("debug")) {console.log("BLANKET-Marking file as loaded: "+url);}
+
+ _blanket.utils.cache[url].loaded=true;
+
+ if (_blanket.utils.allLoaded()){
+ if (_blanket.options("debug")) {console.log("BLANKET-All files loaded");}
+ cb();
+ }else if (orderedCb){
+ //if it's ordered we need to
+ //traverse down to the next
+ //priority level
+ if (_blanket.options("debug")) {console.log("BLANKET-Load next file.");}
+ orderedCb(nextScript,cb);
+ }
+ };
+ },
+ cache: {},
+ allLoaded: function (){
+ /**
+ * check if depdencies are loaded in cache
+ */
+ var cached = Object.keys(_blanket.utils.cache);
+ for (var i=0;i<cached.length;i++){
+ if (!_blanket.utils.cache[cached[i]].loaded){
+ return false;
+ }
+ }
+ return true;
+ },
+ processFile: function (content,url,cb,oldCb) {
+ var match = _blanket.options("filter");
+ //we check the never matches first
+ var antimatch = _blanket.options("antifilter");
+ if (typeof antimatch !== "undefined" &&
+ _blanket.utils.matchPatternAttribute(url.replace(/\.js$/,""),antimatch)
+ ){
+ oldCb(content);
+ if (_blanket.options("debug")) {console.log("BLANKET-File will never be instrumented:"+url);}
+ _blanket.requiringFile(url,true);
+ }else if (_blanket.utils.matchPatternAttribute(url.replace(/\.js$/,""),match)){
+ if (_blanket.options("debug")) {console.log("BLANKET-Attempting instrument of:"+url);}
+ _blanket.instrument({
+ inputFile: content,
+ inputFileName: url
+ },function(instrumented){
+ try{
+ if (_blanket.options("debug")) {console.log("BLANKET-instrument of:"+url+" was successfull.");}
+ _blanket.utils.blanketEval(instrumented);
+ cb();
+ _blanket.requiringFile(url,true);
+ }
+ catch(err){
+ if (_blanket.options("ignoreScriptError")){
+ //we can continue like normal if
+ //we're ignoring script errors,
+ //but otherwise we don't want
+ //to completeLoad or the error might be
+ //missed.
+ if (_blanket.options("debug")) { console.log("BLANKET-There was an error loading the file:"+url); }
+ cb(content);
_blanket.requiringFile(url,true);
+ }else{
+ throw new Error("Error parsing instrumented code: "+err);
}
- catch(err){
- if (_blanket.options("ignoreScriptError")){
- //we can continue like normal if
- //we're ignoring script errors,
- //but otherwise we don't want
- //to completeLoad or the error might be
- //missed.
- if (_blanket.options("debug")) { console.log("BLANKET-There was an error loading the file:"+url); }
- context.completeLoad(moduleName);
- _blanket.requiringFile(url,true);
- }else{
- throw new Error("Error parsing instrumented code: "+err);
- }
- }
- });
- }else{
- if (_blanket.options("debug")) { console.log("BLANKET-Loading (without instrumenting) the file:"+url);}
- _blanket.utils.oldloader(context, moduleName, url);
- _blanket.requiringFile(url,true);
- }
-
- }, function (err) {
- _blanket.requiringFile();
- throw err;
- });
- };
-
+ }
+ });
+ }else{
+ if (_blanket.options("debug")) { console.log("BLANKET-Loading (without instrumenting) the file:"+url);}
+ oldCb(content);
+ _blanket.requiringFile(url,true);
+ }
- requirejs.createXhr = function () {
- //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
+ },
+ createXhr: function(){
var xhr, i, progId;
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
@@ -152,10 +238,8 @@ _blanket.extend({
}
return xhr;
- };
-
-
- requirejs.cget = function (url, callback, errback, onXhr) {
+ },
+ getFile: function(url, callback, errback, onXhr){
var foundInSession = false;
if (_blanket.blanketSession){
var files = Object.keys(_blanket.blanketSession);
@@ -169,7 +253,7 @@ _blanket.extend({
}
}
if (!foundInSession){
- var xhr = requirejs.createXhr();
+ var xhr = _blanket.utils.createXhr();
xhr.open('GET', url, true);
//Allow overrides specified in config
@@ -208,7 +292,37 @@ _blanket.extend({
}
}
}
+ }
+ }
+});
+
+(function(){
+ var require = blanket.options("commonJS") ? blanket._commonjs.require : window.require;
+ var requirejs = blanket.options("commonJS") ? blanket._commonjs.requirejs : window.requirejs;
+ if (!_blanket.options("engineOnly") && _blanket.options("existingRequireJS")){
+
+ _blanket.utils.oldloader = requirejs.load;
+
+ requirejs.load = function (context, moduleName, url) {
+ _blanket.requiringFile(url);
+ _blanket.utils.getFile(url,
+ function(content){
+ _blanket.utils.processFile(
+ content,
+ url,
+ function newLoader(){
+ context.completeLoad(moduleName);
+ },
+ function oldLoader(){
+ _blanket.utils.oldloader(context, moduleName, url);
+ }
+ );
+ }, function (err) {
+ _blanket.requiringFile();
+ throw err;
+ });
};
}
})();
+
})(blanket);
View
66 src/blanket_browser.js
@@ -137,12 +137,15 @@ _blanket.extend({
var request = new XMLHttpRequest();
request.open('GET', path, false);
request.send();
- var script = document.createElement("script");
- script.type = "text/javascript";
- script.text = request.responseText;
- (document.body || document.getElementsByTagName('head')[0]).appendChild(script);
+ _blanket._addScript(request.responseText);
}
},
+ _addScript: function(data){
+ var script = document.createElement("script");
+ script.type = "text/javascript";
+ script.text = data;
+ (document.body || document.getElementsByTagName('head')[0]).appendChild(script);
+ },
hasAdapter: function(callback){
return _blanket.options("adapter") !== null;
},
@@ -165,9 +168,8 @@ _blanket.extend({
delete coverage_data.files.branchFcn;
}
if (typeof _blanket.options("reporter") === "string"){
- require([_blanket.options("reporter").replace(".js","")],function(r){
- r(coverage_data,_blanket.options("reporter_options"));
- });
+ _blanket._loadFile(_blanket.options("reporter"));
+ _blanket.customReporter(coverage_data,_blanket.options("reporter_options"));
}else if (typeof _blanket.options("reporter") === "function"){
_blanket.options("reporter")(coverage_data);
}else if (typeof _blanket.defaultReporter === 'function'){
@@ -184,7 +186,6 @@ _blanket.extend({
}
},
_loadSourceFiles: function(callback){
- console.log("ls1:"+new Date().getTime());
var require = blanket.options("commonJS") ? blanket._commonjs.require : window.require;
function copy(o){
var _copy = Object.create( Object.getPrototypeOf(o) );
@@ -208,38 +209,25 @@ _blanket.extend({
if (sessionStorage["blanketSessionLoader"]){
_blanket.blanketSession = JSON.parse(sessionStorage["blanketSessionLoader"]);
}
-
- var requireConfig = {
- paths: {},
- shim: {},
- waitSeconds: _blanket.options("timeout")
- };
- var lastDep = {
- deps: []
- };
- var isOrdered = _blanket.options("orderedLoading");
- var initialGet=[];
- scripts.forEach(function(file,indx){
- //for whatever reason requirejs
- //prefers when we don't use the full path
- //so we just use a custom name
- var requireKey = "blanket_"+indx;
- initialGet.push(requireKey);
- requireConfig.paths[requireKey] = file;
- if (isOrdered){
- if (indx > 0){
- requireConfig.shim[requireKey] = copy(lastDep);
- }
- lastDep.deps = [requireKey];
- }
- });
- require.config(requireConfig);
- var filt = initialGet;
- require(filt, function(){
- callback();
+
+ scripts.forEach(function(file,indx){
+ _blanket.utils.cache[file+".js"]={
+ loaded:false
+ };
});
+
+ var currScript=-1;
+ _blanket.utils.loadAll(function(test){
+ if (test){
+ return typeof scripts[currScript+1] !== 'undefined';
+ }
+ currScript++;
+ if (currScript >= scripts.length){
+ return null;
+ }
+ return scripts[currScript]+".js";
+ },callback);
}
- console.log("ls2:"+new Date().getTime());
},
beforeStartTestRunner: function(opts){
opts = opts || {};
@@ -263,7 +251,7 @@ _blanket.extend({
if (typeof cb === "function"){
cb(opts.callback);
}else if (typeof cb === "string"){
- eval(cb);
+ _blanket._addScript(cb);
opts.callback();
}
}else{
View
23 src/config.js
@@ -23,6 +23,9 @@
if (es.nodeName === "data-cover-timeout"){
newOptions.timeout = es.nodeValue;
}
+ if (es.nodeName === "data-cover-modulepattern") {
+ newOptions.modulePattern = es.nodeValue;
+ }
if (es.nodeName === "data-cover-reporter-options"){
try{
newOptions.reporter_options = JSON.parse(es.nodeValue);
@@ -40,9 +43,6 @@
}
if (es.nodeName === "data-cover-flags"){
var flags = " "+es.nodeValue+" ";
- if (flags.indexOf(" unordered ") > -1){
- newOptions.order = false;
- }
if (flags.indexOf(" ignoreError ") > -1){
newOptions.ignoreScriptError = true;
}
@@ -78,19 +78,8 @@
blanket.options("existingRequireJS",true);
}
/* setup requirejs loader, if needed */
- if (!blanket.options("existingRequireJS") ){
- if (typeof window["define"] !== "undefined"){
- window["__blanket_old_define"]=window["define"];
- window["define"]=void 0;
- }
- if (blanket.options("commonJS")){
- blanket._commonjs = {};
- blanket.setupRequireJS(blanket._commonjs);
- }else{
- blanket.setupRequireJS(window);
- }
- if (typeof window["__blanket_old_define"] !== "undefined"){
- window["define"] = window["__blanket_old_define"];
- }
+
+ if (blanket.options("commonJS")){
+ blanket._commonjs = {};
}
})();
View
31 src/index.js
@@ -118,7 +118,7 @@ var blanketNode = function (userOptions,cli){
//we check the never matches first
var antipattern = _blanket.options("antifilter");
if (typeof antipattern !== "undefined" &&
- blanket.normalizeBackslashes(url.replace(".js",""),antimatch)
+ blanket.normalizeBackslashes(filename.replace(/\.js$/,""),antipattern)
){
oldLoader(localModule,filename);
if (_blanket.options("debug")) {console.log("BLANKET-File will never be instrumented:"+filename);}
@@ -161,19 +161,24 @@ var blanketNode = function (userOptions,cli){
return blanket;
};
-var args = process.argv;
-if (args[0] === 'node' &&
- args[1].indexOf(join('node_modules','mocha','bin')) > -1 &&
- (args.indexOf('--require') > 1 || args.indexOf('-r') > -1) &&
- args.indexOf('blanket') > 2){
- //using mocha cli
- module.exports = blanketNode(null,true);
+if ((process.env && process.env.BLANKET_COV===1) ||
+ (process.ENV && process.ENV.BLANKET_COV)){
+ module.exports = blanketNode({engineOnly:true},false);
}else{
- //not mocha cli
- module.exports = function(options){
- //we don't want to expose the cli option.
- return blanketNode(options,false);
- };
+ var args = process.argv;
+ if (args[0] === 'node' &&
+ args[1].indexOf(join('node_modules','mocha','bin')) > -1 &&
+ (args.indexOf('--require') > 1 || args.indexOf('-r') > -1) &&
+ args.indexOf('blanket') > 2){
+ //using mocha cli
+ module.exports = blanketNode(null,true);
+ }else{
+ //not mocha cli
+ module.exports = function(options){
+ //we don't want to expose the cli option.
+ return blanketNode(options,false);
+ };
+ }
}
View
2  src/qunit/qunit.js
@@ -61,7 +61,7 @@ if (typeof QUnit !== 'undefined'){
}
});
}else{
- requirejs.load = _blanket.utils.oldloader;
+ if (blanket.options("existingRequireJS")){ requirejs.load = _blanket.utils.oldloader; }
blanket.noConflict().beforeStartTestRunner({
condition: allLoaded,
callback: function(){
View
80 src/qunit/reporter.js
@@ -10,7 +10,7 @@ blanket.defaultReporter = function(coverage){
}),
bodyContent = "<div id='blanket-main'><div class='blanket bl-title'><div class='bl-cl bl-file'><a href='http://alex-seville.github.com/blanket/' target='_blank' class='bl-logo'>Blanket.js</a> results</div><div class='bl-cl rs'>Coverage (%)</div><div class='bl-cl rs'>Covered/Total Smts.</div>"+(hasBranchTracking ? "<div class='bl-cl rs'>Covered/Total Branches</div>":"")+"<div style='clear:both;'></div></div>",
fileTemplate = "<div class='blanket {{statusclass}}'><div class='bl-cl bl-file'><span class='bl-nb'>{{fileNumber}}.</span><a href='javascript:blanket_toggleSource(\"file-{{fileNumber}}\")'>{{file}}</a></div><div class='bl-cl rs'>{{percentage}} %</div><div class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</div>"+( hasBranchTracking ? "<div class='bl-cl rs'>{{passedBranches}}/{{totalBranches}}</div>" : "" )+"<div id='file-{{fileNumber}}' class='bl-source' style='display:none;'>{{source}}</div><div style='clear:both;'></div></div>";
- grandTotalTemplate = "<div class='blanket grand-total {{statusclass}}'><div class='bl-cl'>Totals</div><div class='bl-cl rs'>{{percentage}} %</div><div class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</div>"+( hasBranchTracking ? "<div class='bl-cl rs'>{{passedBranches}}/{{totalBranches}}</div>" : "" ) + "<div style='clear:both;'></div></div>";
+ grandTotalTemplate = "<div class='blanket grand-total {{statusclass}}'><div class='bl-cl'>{{rowTitle}}</div><div class='bl-cl rs'>{{percentage}} %</div><div class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</div>"+( hasBranchTracking ? "<div class='bl-cl rs'>{{passedBranches}}/{{totalBranches}}</div>" : "" ) + "<div style='clear:both;'></div></div>";
function blanket_toggleSource(id) {
var element = document.getElementById(id);
@@ -154,8 +154,17 @@ blanket.defaultReporter = function(coverage){
totalSmts: 0,
numberOfFilesCovered: 0,
passedBranches: 0,
- totalBranches: 0
+ totalBranches: 0,
+ moduleTotalStatements : {},
+ moduleTotalCoveredStatements : {},
+ moduleTotalBranches : {},
+ moduleTotalCoveredBranches : {}
};
+
+ // check if a data-cover-modulepattern was provided for per-module coverage reporting
+ var modulePattern = _blanket.options("modulePattern");
+ var modulePatternRegex = ( modulePattern ? new RegExp(modulePattern) : null );
+
for(var file in files)
{
fileNumber++;
@@ -226,6 +235,29 @@ blanket.defaultReporter = function(coverage){
}
totals.passedBranches += passedBranches;
totals.totalBranches += totalBranches;
+
+ // if "data-cover-modulepattern" was provided,
+ // track totals per module name as well as globally
+ if (modulePatternRegex) {
+ var moduleName = file.match(modulePatternRegex)[1];
+
+ if(!totals.moduleTotalStatements.hasOwnProperty(moduleName)) {
+ totals.moduleTotalStatements[moduleName] = 0;
+ totals.moduleTotalCoveredStatements[moduleName] = 0;
+ }
+
+ totals.moduleTotalStatements[moduleName] += totalSmts;
+ totals.moduleTotalCoveredStatements[moduleName] += numberOfFilesCovered;
+
+ if(!totals.moduleTotalBranches.hasOwnProperty(moduleName)) {
+ totals.moduleTotalBranches[moduleName] = 0;
+ totals.moduleTotalCoveredBranches[moduleName] = 0;
+ }
+
+ totals.moduleTotalBranches[moduleName] += totalBranches;
+ totals.moduleTotalCoveredBranches[moduleName] += passedBranches;
+ }
+
var result = percentage(numberOfFilesCovered, totalSmts);
var output = fileTemplate.replace("{{file}}", file)
@@ -245,16 +277,42 @@ blanket.defaultReporter = function(coverage){
bodyContent += output;
}
- var totalPercent = percentage(totals.numberOfFilesCovered, totals.totalSmts);
- var statusClass = totalPercent < successRate ? "bl-error" : "bl-success";
- var totalsOutput = grandTotalTemplate.replace("{{percentage}}", totalPercent)
- .replace("{{numberCovered}}", totals.numberOfFilesCovered)
- .replace("{{totalSmts}}", totals.totalSmts)
- .replace("{{passedBranches}}", totals.passedBranches)
- .replace("{{totalBranches}}", totals.totalBranches)
- .replace("{{statusclass}}", statusClass);
+ // create temporary function for use by the global totals reporter,
+ // as well as the per-module totals reporter
+ var createAggregateTotal = function(numSt, numCov, numBranch, numCovBr, moduleName) {
+
+ var totalPercent = percentage(numCov, numSt);
+ var statusClass = totalPercent < successRate ? "bl-error" : "bl-success";
+ var rowTitle = ( moduleName ? "Total for module: " + moduleName : "Global total" );
+ var totalsOutput = grandTotalTemplate.replace("{{rowTitle}}", rowTitle)
+ .replace("{{percentage}}", totalPercent)
+ .replace("{{numberCovered}}", numCov)
+ .replace("{{totalSmts}}", numSt)
+ .replace("{{passedBranches}}", numCovBr)
+ .replace("{{totalBranches}}", numBranch)
+ .replace("{{statusclass}}", statusClass);
+
+ bodyContent += totalsOutput;
+ };
+
+ // if "data-cover-modulepattern" was provided,
+ // output the per-module totals alongside the global totals
+ if (modulePatternRegex) {
+ for (var thisModuleName in totals.moduleTotalStatements) {
+ if (totals.moduleTotalStatements.hasOwnProperty(thisModuleName)) {
+
+ var moduleTotalSt = totals.moduleTotalStatements[thisModuleName];
+ var moduleTotalCovSt = totals.moduleTotalCoveredStatements[thisModuleName];
+
+ var moduleTotalBr = totals.moduleTotalBranches[thisModuleName];
+ var moduleTotalCovBr = totals.moduleTotalCoveredBranches[thisModuleName];
+
+ createAggregateTotal(moduleTotalSt, moduleTotalCovSt, moduleTotalBr, moduleTotalCovBr, thisModuleName);
+ }
+ }
+ }
- bodyContent += totalsOutput;
+ createAggregateTotal(totals.totalSmts, totals.numberOfFilesCovered, totals.totalBranches, totals.passedBranches, null);
bodyContent += "</div>"; //closing main
View
13 src/reporters/lcov_reporter.js
@@ -1,10 +1,11 @@
-define([],function lcov_reporter(){
+//lcov_reporter
+(function (){
//takes the option: toHTML {boolean}
-
+
var body = document.body;
var appendHtml = function ( filename,data,toHTML) {
-
+
var str="";
str += 'SF:' + filename + '\n';
@@ -27,8 +28,8 @@ define([],function lcov_reporter(){
window._$blanket_LCOV = str;
}
};
-
- return function(coverageData,options){
+
+ blanket.customReporter=function(coverageData,options){
var toHTML=true;
if (typeof options !== 'undefined' && typeof options.toHTML !== 'undefined'){
toHTML = options.toHTML;
@@ -38,4 +39,4 @@ define([],function lcov_reporter(){
appendHtml(filename,data,toHTML);
}
};
-});
+})();
View
11 src/reporters/simple_json_reporter.js
@@ -1,5 +1,6 @@
-define([],function simple_json_reporter(){
-
+//simple_json_reporter
+(function (){
+
var body = document.body;
var appendHtml = function (el, str) {
@@ -7,8 +8,8 @@ define([],function simple_json_reporter(){
div.innerText = str;
el.appendChild(div);
};
-
- return function(coverageData){
+
+ blanket.customReporter= function(coverageData){
appendHtml(body, JSON.stringify(coverageData,null,"\t"));
};
-});
+})();
View
2  tasks/blanketTests.js
@@ -29,7 +29,7 @@ module.exports = function(grunt) {
if (!err) {
grunt.log.write(result+"\n");
}else{
- //grunt.log.write("\nError:"+err);
+ grunt.log.write("\nError:"+result);
done(false);
}
next();
View
1  test/helpers/phantom_qunit_runner.js
@@ -23,6 +23,7 @@ page.onConsoleMessage = function(msg) {
page.onInitialized = function() {
page.evaluate(addLogging);
};
+
page.open(url, function(status){
if (status !== "success") {
console.log("Unable to access network: " + status);
View
5 test/lib-tests/blanket_test.js
@@ -69,7 +69,6 @@ test( "blanket instrument branch", function() {
test('get/set options', function(){
ok(blanket.options("filter") === null,"get filter");
ok(blanket.options("ignoreScriptError") === false,"get ignore");
- ok(blanket.options("orderedLoading") === true,"get ordered");
ok(blanket.options("existingRequireJS") === false,"get existing");
ok(blanket.options("reporter") === null,"get reporter");
ok(blanket.options("loader") === null,"get loader");
@@ -78,7 +77,6 @@ test('get/set options', function(){
blanket.options({
filter: "test",
ignoreScriptError: true,
- orderedLoading: false,
existingRequireJS: true,
reporter: "test1",
loader: "test2",
@@ -87,7 +85,6 @@ test('get/set options', function(){
ok(blanket.options("filter") === "test","get filter");
ok(blanket.options("ignoreScriptError") === true,"get ignore");
- ok(blanket.options("orderedLoading") === false,"get order");
ok(blanket.options("existingRequireJS") === true,"get existing");
ok(blanket.options("reporter") === "test1","get reporter");
ok(blanket.options("loader") === "test2","get loader");
@@ -95,7 +92,6 @@ test('get/set options', function(){
blanket.options("filter",null);
blanket.options("ignoreScriptError",false);
- blanket.options("orderedLoading",true);
blanket.options("existingRequireJS",false);
blanket.options("reporter",null);
blanket.options("loader",null);
@@ -103,7 +99,6 @@ test('get/set options', function(){
ok(blanket.options("filter") === null,"get filter");
ok(blanket.options("ignoreScriptError") === false,"get ignore");
- ok(blanket.options("orderedLoading") === true,"get ordered");
ok(blanket.options("existingRequireJS") === false,"get existing");
ok(blanket.options("reporter") === null,"get reporter");
ok(blanket.options("loader") === null,"get loader");
View
6 test/requirejs/chutzpah.html
@@ -9,10 +9,10 @@
-->
<link rel="stylesheet" type="text/css" href="../vendor/qunit.css"/>
<script type="text/javascript" src="../vendor/qunit.js"></script>
-<script type="text/javascript" src="../../src/lib/require.js"></script>
- <script type="text/javascript" src="../../dist/qunit/blanket.js" data-cover-flags="ignoreError autoStart"
+<script type="text/javascript" src="../../node_modules/requirejs/require.js"></script>
+ <script type="text/javascript" src="../../dist/qunit/blanket.js" data-cover-flags=" autoStart debug"
data-cover-only="//.*/"
- data-cover-never="['vendor/qunit','lib/require','qunit/blanket']"></script>
+ data-cover-never="['vendor/qunit','require','qunit/blanket']"></script>
<script type="text/javascript">
View
2  test/requirejs/require_runner.html
@@ -7,7 +7,7 @@
<link rel="stylesheet" href="../vendor/qunit.css">
<script src="../vendor/qunit.js"></script>
<!-- qunit -->
- <script type="text/javascript" src="../../src/lib/require.js"></script>
+ <script type="text/javascript" src="../../node_modules/requirejs/require.js"></script>
<script src="../../dist/qunit/blanket.js"
data-cover-only="require_sample"></script>
<script>
View
6 test/test-node/fixture/core_fixtures.js
@@ -1,11 +1,11 @@
fs = require("fs");
//simple file fixture
-exports.simple_test_file_js = fs.readFileSync(__dirname+"/simple_test_file.js","utf-8");
+exports.simple_test_file_js = fs.readFileSync(__dirname+"/simple_test_file.js.js","utf-8");
-exports.simple_test_file_instrumented_js = fs.readFileSync(__dirname+"/simple_test_file_instrumented.js","utf-8");
+exports.simple_test_file_instrumented_js = fs.readFileSync(__dirname+"/simple_test_file_instrumented.js.js","utf-8");
-exports.simple_test_file_instrumented_full_js = fs.readFileSync(__dirname+"/simple_test_file_instrumented_full.js","utf-8");
+exports.simple_test_file_instrumented_full_js = fs.readFileSync(__dirname+"/simple_test_file_instrumented_full.js.js","utf-8");
//Block injection fixtures
exports.blockinjection_test_file_js = fs.readFileSync(__dirname+"/blockinjection_test_file.js","utf-8");
View
0  test/test-node/fixture/simple_test_file.js → .../test-node/fixture/simple_test_file.js.js
File renamed without changes
View
0  .../fixture/simple_test_file_instrumented.js → ...xture/simple_test_file_instrumented.js.js
File renamed without changes
View
0  ...ure/simple_test_file_instrumented_full.js → .../simple_test_file_instrumented_full.js.js
File renamed without changes
Please sign in to comment.
Something went wrong with that request. Please try again.