Skip to content

Commit ee3e68e

Browse files
committed
feat(config): instrumenter override option
Enable fine-tuning which preprocessor should be used for which files Add README.md section Add tests Update existing tests to comply with new dependency requirement
1 parent b0580ee commit ee3e68e

File tree

4 files changed

+95
-15
lines changed

4 files changed

+95
-15
lines changed

README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ module.exports = function(config) {
6565
preprocessors: {
6666
// source files, that you wanna generate coverage for
6767
// do not include tests or libraries
68-
// (these files will be instrumented by Istanbul via Ibrik)
68+
// (these files will be instrumented by Istanbul via Ibrik unless
69+
// specified otherwise in coverageReporter.instrumenter)
6970
'src/*.coffee': ['coverage'],
7071

7172
// note: project files will already be converted to
@@ -127,6 +128,27 @@ coverageReporter: {
127128
}
128129
```
129130

131+
#### instrumenter
132+
Karma-coverage infers the instrumenter regarding of the file extension.
133+
The .coffee files are by default covered using
134+
[Ibrik](https://github.com/Constellation/ibrik) (an
135+
[Istanbul](https://github.com/gotwarlost/istanbul) analog for
136+
CoffeeScript files). It is possible to override this behavior and point out an
137+
instrumenter for the files matching a specific pattern.
138+
To do so, you need to declare an object under with the keys representing the
139+
pattern to match, and the instrumenter to apply. The matching will be done
140+
using [minimatch](https://github.com/isaacs/minimatch).
141+
If two patterns match, the last one will take the precedence.
142+
143+
```javascript
144+
coverageReporter: {
145+
instrumenter: {
146+
'**/*.coffee': 'istanbul' // Force the use of the Istanbul instrumenter to cover CoffeeScript files
147+
},
148+
// ...
149+
}
150+
```
151+
130152
----
131153

132154
For more information on Karma see the [homepage].

lib/preprocessor.js

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
var istanbul = require('istanbul'),
2-
ibrik = require('ibrik');
1+
var istanbul = require('istanbul'),
2+
ibrik = require('ibrik'),
3+
minimatch = require('minimatch');
34

4-
var createCoveragePreprocessor = function(logger, basePath, reporters) {
5+
var createCoveragePreprocessor = function(logger, basePath, reporters, coverageReporter) {
56
var log = logger.create('preprocessor.coverage');
6-
var jsInstrumenter = new istanbul.Instrumenter();
7-
var coffeeInstrumenter = new ibrik.Instrumenter();
7+
var instrumenterOverrides = coverageReporter.instrumenter || {};
8+
var instrumenters = {istanbul: istanbul, ibrik: ibrik};
89

910
// if coverage reporter is not used, do not preprocess the files
1011
if (reporters.indexOf('coverage') === -1) {
@@ -13,23 +14,55 @@ var createCoveragePreprocessor = function(logger, basePath, reporters) {
1314
};
1415
}
1516

17+
// check instrumenter override requests
18+
function checkInstrumenters() {
19+
var literal;
20+
for (var pattern in instrumenterOverrides) {
21+
literal = String(instrumenterOverrides[pattern]).toLowerCase();
22+
if (literal !== 'istanbul' && literal !== 'ibrik') {
23+
log.error('Unknown instrumenter: %s', literal);
24+
return false;
25+
}
26+
}
27+
return true;
28+
}
29+
if (!checkInstrumenters()) {
30+
return function(content, _, done) {
31+
return done(1);
32+
};
33+
}
34+
1635
return function(content, file, done) {
1736
log.debug('Processing "%s".', file.originalPath);
1837

1938
var jsPath = file.originalPath.replace(basePath + '/', './');
20-
var instrumenter = jsPath.match(/\.coffee$/) ? coffeeInstrumenter : jsInstrumenter;
39+
var instrumenterLiteral = jsPath.match(/\.coffee$/) ? 'ibrik' : 'istanbul';
40+
41+
for (var pattern in instrumenterOverrides) {
42+
if (minimatch(file.originalPath, pattern, {dot: true})) {
43+
instrumenterLiteral = String(instrumenterOverrides[pattern]).toLowerCase();
44+
}
45+
}
46+
47+
var instrumenter = new instrumenters[instrumenterLiteral].Instrumenter();
2148

2249
instrumenter.instrument(content, jsPath, function(err, instrumentedCode) {
23-
if(err) {
50+
if (err) {
2451
log.error('%s\n at %s', err.message, file.originalPath);
2552
}
2653

27-
file.path = file.path.replace(/\.coffee$/, '.js');
54+
if (instrumenterLiteral === 'ibrik') {
55+
file.path = file.path.replace(/\.coffee$/, '.js');
56+
}
57+
2858
done(instrumentedCode);
2959
});
3060
};
3161
};
3262

33-
createCoveragePreprocessor.$inject = ['logger', 'config.basePath', 'config.reporters'];
63+
createCoveragePreprocessor.$inject = ['logger',
64+
'config.basePath',
65+
'config.reporters',
66+
'config.coverageReporter'];
3467

3568
module.exports = createCoveragePreprocessor;

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
],
2020
"author": "SATO taichi <ryushi@gmail.com>",
2121
"dependencies": {
22+
"dateformat": "~1.0.6",
23+
"ibrik": "~1.1.1",
2224
"istanbul": "~0.2.3",
23-
"ibrik": "~1.1.1",
24-
"dateformat": "~1.0.6"
25+
"minimatch": "~0.3.0"
2526
},
2627
"peerDependencies": {
2728
"karma": ">=0.9"

test/preprocessor.spec.coffee

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ describe 'preprocessor', ->
3535

3636

3737
it 'should not do anything if coverage reporter is not used', (done) ->
38-
process = createPreprocessor mockLogger, null, ['dots', 'progress']
38+
process = createPreprocessor mockLogger, null, ['dots', 'progress'], {}
3939
file = new File '/base/path/file.js'
4040

4141
process ORIGINAL_CODE, file, (preprocessedCode) ->
@@ -45,7 +45,7 @@ describe 'preprocessor', ->
4545

4646

4747
it 'should preprocess the code', (done) ->
48-
process = createPreprocessor mockLogger, '/base/path', ['coverage', 'progress']
48+
process = createPreprocessor mockLogger, '/base/path', ['coverage', 'progress'], {}
4949
file = new File '/base/path/file.js'
5050

5151
process ORIGINAL_CODE, file, (preprocessedCode) ->
@@ -58,7 +58,7 @@ describe 'preprocessor', ->
5858
done()
5959

6060
it 'should preprocess the coffee code', (done) ->
61-
process = createPreprocessor mockLogger, '/base/path', ['coverage', 'progress']
61+
process = createPreprocessor mockLogger, '/base/path', ['coverage', 'progress'], {}
6262
file = new File '/base/path/file.coffee'
6363

6464
process ORIGINAL_COFFEE_CODE, file, (preprocessedCode) ->
@@ -70,3 +70,27 @@ describe 'preprocessor', ->
7070
expect(file.path).to.equal '/base/path/file.js'
7171
expect(sandbox.__coverage__).to.have.ownProperty './file.coffee'
7272
done()
73+
74+
it 'should not preprocess the coffee code', (done) ->
75+
process = createPreprocessor mockLogger, '/base/path', ['coverage', 'progress'],
76+
instrumenter:
77+
'**/*.coffee': 'istanbul'
78+
file = new File '/base/path/file.coffee'
79+
80+
process ORIGINAL_CODE, file, (preprocessedCode) ->
81+
sandbox =
82+
a: true
83+
something: ->
84+
85+
vm.runInNewContext preprocessedCode, sandbox
86+
expect(file.path).to.equal '/base/path/file.coffee'
87+
expect(sandbox.__coverage__).to.have.ownProperty './file.coffee'
88+
done()
89+
90+
it 'should fail if invalid instrumenter provided', (done) ->
91+
work = ->
92+
createPreprocessor mockLogger, '/base/path', ['coverage', 'progress'],
93+
instrumenter:
94+
'**/*.coffee': 'madeup'
95+
expect(work).to.throw()
96+
done()

0 commit comments

Comments
 (0)