Skip to content

Commit

Permalink
feat(thresholds): allow overriding per file thresholds
Browse files Browse the repository at this point in the history
Closes #20
  • Loading branch information
Matt Lewis committed May 26, 2017
1 parent 2de647c commit 1a894f0
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 16 deletions.
7 changes: 6 additions & 1 deletion README.md
Expand Up @@ -75,7 +75,12 @@ module.exports = function (config) {
statements: 100,
lines: 100,
branches: 100,
functions: 100
functions: 100,
overrides: {
'baz/component/**/*.js': {
statements: 98
}
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -37,7 +37,8 @@
},
"homepage": "https://github.com/mattlewis92/karma-coverage-istanbul-reporter#readme",
"dependencies": {
"istanbul-api": "^1.1.8"
"istanbul-api": "^1.1.8",
"minimatch": "^3.0.4"
},
"devDependencies": {
"@types/chai": "^3.4.34",
Expand Down
9 changes: 6 additions & 3 deletions src/reporter.js
Expand Up @@ -93,7 +93,8 @@ function CoverageIstanbulReporter(baseReporterDecorator, logger, config) {
statements: 0,
lines: 0,
branches: 0,
functions: 0
functions: 0,
overrides: {}
}
};

Expand Down Expand Up @@ -130,15 +131,17 @@ function CoverageIstanbulReporter(baseReporterDecorator, logger, config) {
});

remappedCoverageMap.files().forEach(file => {
const fileThresholds = Object.assign({}, thresholds.each, util.overrideThresholds(file, thresholds.each.overrides, config.basePath));
delete fileThresholds.overrides;
const fileSummary = remappedCoverageMap.fileCoverageFor(file).toSummary().data;
const failedFileTypes = checkThresholds(thresholds.each, fileSummary);
const failedFileTypes = checkThresholds(fileThresholds, fileSummary);

failedFileTypes.forEach(type => {
thresholdCheckFailed = true;
if (coverageIstanbulReporter.fixWebpackSourcePaths) {
file = util.fixWebpackFilePath(file);
}
logThresholdMessage(`Coverage for ${type} (${fileSummary[type].pct}%) in file ${file} does not meet per file threshold (${thresholds.each[type]}%)`);
logThresholdMessage(`Coverage for ${type} (${fileSummary[type].pct}%) in file ${file} does not meet per file threshold (${fileThresholds[type]}%)`);
});
});

Expand Down
36 changes: 36 additions & 0 deletions src/util.js
@@ -1,3 +1,6 @@
const path = require('path');
const minimatch = require('minimatch');

function fixWebpackFilePath(filePath) {
const isWin = process.platform.startsWith('win');

Expand Down Expand Up @@ -29,5 +32,38 @@ function fixWebpackSourcePaths(sourceMap) {
});
}

function isAbsolute(file) {
if (path.isAbsolute) {
return path.isAbsolute(file);
}

return path.resolve(file) === path.normalize(file);
}

function normalize(key, basePath) {
// Exclude keys will always be relative, but covObj keys can be absolute or relative
let excludeKey = isAbsolute(key) ? path.relative(basePath, key) : key;
// Also normalize for files that start with `./`, etc.
excludeKey = path.normalize(excludeKey);

return excludeKey;
}

function overrideThresholds(key, overrides, basePath) {
let thresholds = {};

// First match wins
Object.keys(overrides).some(pattern => {
if (minimatch(normalize(key, basePath), pattern, {dot: true})) {
thresholds = overrides[pattern];
return true;
}
return false;
});

return thresholds;
}

module.exports.fixWebpackSourcePaths = fixWebpackSourcePaths;
module.exports.fixWebpackFilePath = fixWebpackFilePath;
module.exports.overrideThresholds = overrideThresholds;
49 changes: 49 additions & 0 deletions test/reporter.spec.js
Expand Up @@ -261,5 +261,54 @@ describe('karma-coverage-istanbul-reporter', () => {
setTimeout(checkOutput, fileReadTimeout); // Hacky workaround to make sure the output file has been written
});
});

it('should allow per file thresholds to be overridden', done => {
const server = createServer({
coverageIstanbulReporter: {
reports: ['json-summary'],
dir: path.join(__dirname, 'fixtures', 'outputs'),
fixWebpackSourcePaths: true,
thresholds: {
global: {
statements: 50,
lines: 50,
branches: 50,
functions: 50
},
each: {
statements: 80,
lines: 80,
branches: 80,
functions: 60,
overrides: {
'fixtures/typescript/src/example.ts': {
statements: 90,
lines: 100
},
'fixtures/typescript/src/*.ts': {
functions: 90
}
}
}
}
}
});
server.start();

function checkOutput() {
const output = fs.readFileSync(OUTPUT_LOG_FILE).toString();
expect(Boolean(output.match(/\[ERROR\] reporter\.coverage-istanbul - Coverage for statements \(85\.71%\) in file \/.+test\/fixtures\/typescript\/src\/example\.ts does not meet per file threshold \(90%\)/))).to.equal(true);
expect(Boolean(output.match(/\[ERROR\] reporter\.coverage-istanbul - Coverage for lines \(85\.71%\) in file \/.+test\/fixtures\/typescript\/src\/example\.ts does not meet per file threshold \(100%\)/))).to.equal(true);
expect(Boolean(output.match(/\[ERROR\] reporter\.coverage-istanbul - Coverage for functions \(66\.67%\) in file \/.+test\/fixtures\/typescript\/src\/example\.ts does not meet per file threshold \(60%\)/))).to.equal(false);
expect(Boolean(output.match(/\[ERROR\] reporter\.coverage-istanbul - Coverage for statements \(75%\) in file \/.+test\/fixtures\/typescript\/src\/another-file\.ts does not meet per file threshold \(80%\)/))).to.equal(true);
expect(Boolean(output.match(/\[ERROR\] reporter\.coverage-istanbul - Coverage for lines \(75%\) in file \/.+test\/fixtures\/typescript\/src\/another-file\.ts does not meet per file threshold \(80%\)/))).to.equal(true);
expect(Boolean(output.match(/\[ERROR\] reporter\.coverage-istanbul - Coverage for functions \(50%\) in file \/.+test\/fixtures\/typescript\/src\/another-file\.ts does not meet per file threshold \(90%\)/))).to.equal(true);
done();
}

server.on('run_complete', () => {
setTimeout(checkOutput, fileReadTimeout); // Hacky workaround to make sure the output file has been written
});
});
});
});
19 changes: 8 additions & 11 deletions yarn.lock
Expand Up @@ -405,7 +405,7 @@ boxen@^1.0.0:
term-size "^0.1.0"
widest-line "^1.0.0"

brace-expansion@^1.0.0:
brace-expansion@^1.0.0, brace-expansion@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
dependencies:
Expand Down Expand Up @@ -3175,6 +3175,12 @@ minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3:
dependencies:
brace-expansion "^1.0.0"

minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
brace-expansion "^1.1.7"

minimist@0.0.8, minimist@~0.0.1:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
Expand Down Expand Up @@ -4643,16 +4649,7 @@ typescript@^2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.3.tgz#9639f3c3b40148e8ca97fe08a51dd1891bb6be22"

uglify-js@^2.6:
version "2.8.22"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
optionalDependencies:
uglify-to-browserify "~1.0.0"

uglify-js@^2.8.27:
uglify-js@^2.6, uglify-js@^2.8.27:
version "2.8.27"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.27.tgz#47787f912b0f242e5b984343be8e35e95f694c9c"
dependencies:
Expand Down

0 comments on commit 1a894f0

Please sign in to comment.