Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

closes #14 and #17, new files option and function support for replace

  • Loading branch information...
commit d2212fbd5439052a55af8f9c1bea971b9f7a9cc9 1 parent 9fcb73e
@maenu authored
View
14 README.md
@@ -43,13 +43,24 @@ The supported types are:
* [`lcovonly`](http://gotwarlost.github.com/istanbul/public/apidocs/classes/LcovOnlyReport.html)
* [`cobertura`](http://gotwarlost.github.com/istanbul/public/apidocs/classes/CoberturaReport.html)
+### templateOptions.files
+
+Type: `String|Array`
+Default: `**/*`
+
+A globbing pattern or multiple patterns for the source files to instrument.
+All source files that do match will be instrumented, those who don't won't.
+E.g. `['**/*', '!src/main/js/uninteresting.js']` will result in all source files being instrumented except `src/main/js/uninteresting.js`.
+
### templateOptions.replace
-Type: `Boolean`
+Type: `Boolean|Function`
Default: `true`
Whether or not the `src` scripts are replaced by the paths to their instrumented versions.
This is useful when you want the mixed-in template to work with the original sources, and you want to serve the instrumented sources by redirecting request on the server side.
+If you don't want the sources to be replaced, set it to `false`.
+If it is a function, it receives the arguments `ìnstrumentedSource` and `source` which represent the URI to the instrumented file and the uninstrumented file respectively, relative to the directory specified by [`outfile`](https://github.com/gruntjs/grunt-contrib-jasmine#optionsoutfile).
### templateOptions.thresholds
Type: `Object`
@@ -161,6 +172,7 @@ If your mixed-in template simply includes the sources, as the default template d
If your mixed-in template loads the sources differently, e.g. directly from the file system, you may need to reconfigure the mixed-in template.
## Change Log
+ * v0.3.1, 02.02.14, closes #14 and #17, added `files` option and function support for `replace` option
* v0.3.0, 02.02.14, fixes #18 and #26, now requires grunt-contrib-jasmine v0.6.0
* v0.2.6, 02.02.14, merged #13 from @llacroix, windows paths are converted to URIs
* v0.2.5, 10.08.13, reporter is now moved to and loaded from jasmine's temporary directory, fixes #11
View
5 package.json
@@ -1,7 +1,7 @@
{
"name": "grunt-template-jasmine-istanbul",
"description": "Code coverage template mix-in for grunt-contrib-jasmine, using istanbul",
- "version": "0.3.0",
+ "version": "0.3.1",
"keywords": [
"grunt",
"template",
@@ -17,7 +17,8 @@
},
"main": "src/main/js/template.js",
"dependencies": {
- "istanbul": ">=0.1.30"
+ "istanbul": ">=0.1.30",
+ "lodash": ">=2.4.1"
},
"peerDependencies": {
"grunt": ">=0.4.0",
View
78 src/main/js/template.js
@@ -8,6 +8,7 @@
var path = require('path');
var istanbul = require('istanbul');
var grunt = require('grunt');
+var _ = require('lodash');
var REPORTER = __dirname + '/reporter.js';
var TMP_REPORTER = 'grunt-template-jasmine-istanbul/reporter.js';
@@ -28,33 +29,29 @@ var getUri = function (file) {
};
/**
- * Instruments the specified sources and moves the instrumented sources to the
+ * Instruments the specified source and moves the instrumented source to the
* temporary location, recreating the original directory structure.
*
* @private
* @method instrument
*
- * @param {Array} sources The paths of the original sources
+ * @param {String} source The path of the original source
* @param {String} tmp The path to the temporary directory
*
- * @return {Array} The paths to the instrumented sources
+ * @return {String} The path to the instrumented source
*/
-var instrument = function (sources, tmp) {
+var instrument = function (source, tmp) {
var instrumenter = new istanbul.Instrumenter();
- var instrumentedSources = [];
- sources.forEach(function (source) {
- var instrumentedSource = instrumenter.instrumentSync(
- grunt.file.read(source), source);
- var tmpSource = source;
- // don't try to write "C:" as part of a folder name on Windows
- if (process.platform == 'win32') {
- tmpSource = tmpSource.replace(/^([a-z]):/i, '$1');
- }
- tmpSource = path.join(tmp, tmpSource);
- grunt.file.write(tmpSource, instrumentedSource);
- instrumentedSources.push(tmpSource);
- });
- return instrumentedSources;
+ var instrumentedSourceText = instrumenter.instrumentSync(
+ grunt.file.read(source), source);
+ var instrumentedSource = source;
+ // don't try to write "C:" as part of a folder name on Windows
+ if (process.platform == 'win32') {
+ instrumentedSource = instrumentedSource.replace(/^([a-z]):/i, '$1');
+ }
+ instrumentedSource = path.join(tmp, instrumentedSource);
+ grunt.file.write(instrumentedSource, instrumentedSourceText);
+ return instrumentedSource;
};
/**
@@ -127,7 +124,7 @@ var checkThresholds = function (collector, options) {
});
var finalSummary = istanbul.utils.mergeSummaryObjects.apply(null,
summaries);
- grunt.util._.each(options, function (threshold, metric) {
+ _.each(options, function (threshold, metric) {
var actual = finalSummary[metric];
if(!actual) {
grunt.warn('unrecognized metric: ' + metric);
@@ -165,7 +162,7 @@ var processMixedInTemplate = function (grunt, task, context) {
if (template.process) {
return template.process(grunt, task, mixedInContext);
} else {
- return grunt.util._.template(grunt.file.read(template), mixedInContext);
+ return _.template(grunt.file.read(template), mixedInContext);
}
};
@@ -189,18 +186,43 @@ exports.process = function (grunt, task, context) {
grunt.file.copy(REPORTER, tmpReporter);
context.scripts.reporters.unshift(getUri(tmpReporter));
// instrument sources
- var sources = [];
+ var files = context.options.files || '**/*';
+ var replacements = [];
context.scripts.src.forEach(function (source) {
- sources.push(path.join(outputDirectory, source))
- });
- var instrumentedSources = instrument(sources, context.temp);
- instrumentedSources.forEach(function (instrumentedSource, i) {
- instrumentedSources[i] = getUri(path.relative(outputDirectory,
+ var instrumentedSource = path.join(outputDirectory, source);
+ if (!grunt.file.isMatch(files, instrumentedSource)) {
+ return;
+ }
+ instrumentedSource = instrument(instrumentedSource, context.temp);
+ instrumentedSource = getUri(path.relative(outputDirectory,
instrumentedSource));
+ replacements.push({
+ from: source,
+ to: instrumentedSource
+ });
});
// replace sources
- if (context.options.replace == null || context.options.replace) {
- context.scripts.src = instrumentedSources;
+ if (typeof context.options.replace == 'function') {
+ replacements.forEach(function (replacement) {
+ // call replace with the original and the instrumented source paths
+ replacement.to = context.options.replace(replacement.to,
+ replacement.from);
+ });
+ }
+ if (context.options.replace != false) {
+ // replace instrumented sources and keep uninstrumented
+ context.scripts.src = context.scripts.src.map(function (source) {
+ var instrumentedSource = null;
+ replacements.forEach(function (replacement) {
+ if (replacement.from == source) {
+ instrumentedSource = replacement.to;
+ }
+ });
+ if (instrumentedSource) {
+ return instrumentedSource;
+ }
+ return source;
+ });
}
// listen to coverage event dispatched by reporter
task.phantomjs.on('jasmine.coverage', function (coverage) {
View
183 src/test/js/template.js
@@ -81,65 +81,6 @@ exports['template'] = {
test.equal(transited, true, 'should transit template options');
test.done();
},
- 'shouldGenerateUris': function (test) {
- var source = 'C:\\some\\file.js';
- var sourceUri = TEMP + '/C/some/file.js';
- var reporterUri = TEMP + '/grunt-template-jasmine-istanbul/reporter.js';
- this.context.scripts.src.push(source);
- // backup mocks
- var platform = process.platform;
- var read = grunt.file.read;
- var write = grunt.file.write;
- // install mocks
- process.platform = 'win32';
- grunt.file.read = function (file) {
- if (path.normalize(file) == path.normalize(source)) {
- return '';
- }
- return read.apply(this, arguments);
- };
- grunt.file.write = function () {};
- // process
- this.template.process(grunt, this.task, this.context);
- test.equal(this.context.scripts.src[0], sourceUri,
- 'should have generated source URI');
- test.equal(this.context.scripts.reporters[0], reporterUri,
- 'should have generated reporter URI');
- // uninstall mocks
- process.platform = platform;
- grunt.file.read = read;
- grunt.file.write = write;
- test.done();
- },
- 'shouldAccountForOutfile': function (test) {
- var source = 's.js';
- var sourceUri = '../' + TEMP + '/' + source;
- var reporterUri = '../' + TEMP
- + '/grunt-template-jasmine-istanbul/reporter.js';
- this.context.outfile = 'target/SpecRunner.html';
- this.context.scripts.src.push('../' + source);
- // backup mocks
- var read = grunt.file.read;
- var write = grunt.file.write;
- // install mocks
- grunt.file.read = function (file) {
- if (path.normalize(file) == path.normalize(source)) {
- return '';
- }
- return read.apply(this, arguments);
- };
- grunt.file.write = function () {};
- // process
- this.template.process(grunt, this.task, this.context);
- test.equal(this.context.scripts.src[0], sourceUri,
- 'should account for outfile in source URI');
- test.equal(this.context.scripts.reporters[0], reporterUri,
- 'should account for outfile in reporter URI');
- // uninstall mocks
- grunt.file.read = read;
- grunt.file.write = write;
- test.done();
- },
'coverage': {
'setUp': function (callback) {
this.context.options.coverage = TEMP + '/coverage/coverage.json';
@@ -225,16 +166,13 @@ exports['template'] = {
}
},
'instrumentation': {
- 'setUp': function (callback) {
- this.context.scripts.src.push(SRC);
- this.template.process(grunt, this.task, this.context);
- callback();
- },
'tearDown': function (callback) {
grunt.file.delete(TEMP);
callback();
},
'shouldIncludeReporter': function (test) {
+ this.context.scripts.src.push(SRC);
+ this.template.process(grunt, this.task, this.context);
test.equal(this.context.scripts.reporters.length, 2,
'should have added 1 reporter');
test.equal(path.normalize(this.context.scripts.reporters[0]),
@@ -244,6 +182,8 @@ exports['template'] = {
test.done();
},
'shouldInstrumentSource': function (test) {
+ this.context.scripts.src.push(SRC);
+ this.template.process(grunt, this.task, this.context);
test.equal(this.context.scripts.src.length, 1, 'should have 1 src');
test.equal(path.normalize(this.context.scripts.src[0]),
path.join(TEMP, SRC),
@@ -254,6 +194,106 @@ exports['template'] = {
+ '{ __coverage__ = {}; }';
test.equal(found, expected, 'should be instrumented');
test.done();
+ },
+ 'shouldGenerateUris': function (test) {
+ var source = 'C:\\some\\file.js';
+ var sourceUri = TEMP + '/C/some/file.js';
+ var reporterUri = TEMP
+ + '/grunt-template-jasmine-istanbul/reporter.js';
+ this.context.scripts.src.push(source);
+ // backup mocks
+ var platform = process.platform;
+ var read = grunt.file.read;
+ var write = grunt.file.write;
+ // install mocks
+ process.platform = 'win32';
+ grunt.file.read = function (file) {
+ if (path.normalize(file) == path.normalize(source)) {
+ return '';
+ }
+ return read.apply(this, arguments);
+ };
+ grunt.file.write = function () {};
+ // process
+ this.template.process(grunt, this.task, this.context);
+ test.equal(this.context.scripts.src[0], sourceUri,
+ 'should have generated source URI');
+ test.equal(this.context.scripts.reporters[0], reporterUri,
+ 'should have generated reporter URI');
+ // uninstall mocks
+ process.platform = platform;
+ grunt.file.read = read;
+ grunt.file.write = write;
+ test.done();
+ },
+ 'shouldAccountForOutfile': function (test) {
+ var source = 's.js';
+ var sourceUri = '../' + TEMP + '/' + source;
+ var reporterUri = '../' + TEMP
+ + '/grunt-template-jasmine-istanbul/reporter.js';
+ this.context.outfile = 'target/SpecRunner.html';
+ this.context.scripts.src.push('../' + source);
+ // backup mocks
+ var read = grunt.file.read;
+ var write = grunt.file.write;
+ // install mocks
+ grunt.file.read = function (file) {
+ if (path.normalize(file) == path.normalize(source)) {
+ return '';
+ }
+ return read.apply(this, arguments);
+ };
+ grunt.file.write = function () {};
+ // process
+ this.template.process(grunt, this.task, this.context);
+ test.equal(this.context.scripts.src[0], sourceUri,
+ 'should account for outfile in source URI');
+ test.equal(this.context.scripts.reporters[0], reporterUri,
+ 'should account for outfile in reporter URI');
+ // uninstall mocks
+ grunt.file.read = read;
+ grunt.file.write = write;
+ test.done();
+ }
+ },
+ 'files': {
+ 'tearDown': function (callback) {
+ grunt.file.delete(TEMP);
+ callback();
+ },
+ 'shouldInstrumentDeclaredFilesOnly': function (test) {
+ var a = 'a.js';
+ var b = 'b.js';
+ var c = 'c.js';
+ this.context.scripts.src.push(a);
+ this.context.scripts.src.push(b);
+ this.context.scripts.src.push(c);
+ this.context.options.files = ['*', '!a.js']
+ // backup mocks
+ var read = grunt.file.read;
+ var write = grunt.file.write;
+ // install mocks
+ grunt.file.read = function (file) {
+ if (path.normalize(file) == path.normalize(a)
+ || path.normalize(file) == path.normalize(b)
+ || path.normalize(file) == path.normalize(c)) {
+ return '';
+ }
+ return read.apply(this, arguments);
+ };
+ grunt.file.write = function () {};
+ // process
+ this.template.process(grunt, this.task, this.context);
+ test.equal(this.context.scripts.src[0], a,
+ 'should not instrument a');
+ test.equal(this.context.scripts.src[1], path.join(TEMP, b),
+ 'should instrument b');
+ test.equal(this.context.scripts.src[2], path.join(TEMP, c),
+ 'should instrument c');
+ // uninstall mocks
+ grunt.file.read = read;
+ grunt.file.write = write;
+ test.done();
}
},
'replacing': {
@@ -292,7 +332,20 @@ exports['template'] = {
test.equal(path.normalize(after[0]), path.normalize(SRC),
'should be at temp');
test.done();
- }
+ },
+ 'shouldReplaceSourceWithFunction': function (test) {
+ var replacedDirectory = 'replaced';
+ this.context.options.replace = function (source) {
+ return path.join(replacedDirectory, source);
+ };
+ var before = this.context.scripts.src;
+ this.template.process(grunt, this.task, this.context);
+ var after = this.context.scripts.src;
+ test.notEqual(after, before, 'should replace sources');
+ test.equal(after[0], path.join(replacedDirectory, TEMP, SRC),
+ 'should be at replaced directory');
+ test.done();
+ },
},
'thresholds': {
'setUp': function (callback) {
Please sign in to comment.
Something went wrong with that request. Please try again.