Skip to content

Commit c0586d4

Browse files
committed
initial commit
0 parents  commit c0586d4

25 files changed

+998
-0
lines changed

.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["es2015"]
3+
}

.eslintrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"env": {
3+
"node": true
4+
},
5+
"extends": "meetic"
6+
}

.esnextcoverage.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports = {
2+
only: 'src/**/*.js',
3+
reporters: [
4+
{
5+
formatter: function () {
6+
return require('./src').apply(null, arguments);
7+
},
8+
console: true
9+
}
10+
]
11+
};

.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Compiled files
2+
dist
3+
4+
# Dependencies
5+
node_modules
6+
7+
# Logs
8+
logs
9+
*.log
10+
11+
# Runtime data
12+
pids
13+
*.pid
14+
*.seed
15+
16+
# node-waf configuration
17+
.lock-wscript

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src

.travis.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
sudo: false
2+
language: node_js
3+
node_js:
4+
- 6
5+
- 5
6+
- 4
7+
- 0.12

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# esnext-coverage-format-text
2+
3+
[![NPM version](http://img.shields.io/npm/v/esnext-coverage-format-text.svg)](https://www.npmjs.org/package/esnext-coverage-format-text)
4+
[![Build Status](https://travis-ci.org/olegskl/esnext-coverage-format-text.svg?branch=master)](https://travis-ci.org/olegskl/esnext-coverage-format-text)
5+
6+
Code coverage reporter for [esnext-coverage](https://github.com/esnext-coverage/esnext-coverage).
7+
8+
Similar to other coverage formatters, esnext-coverage-format-text accepts a coverage results object and produces a report as an utf8-encoded string.
9+
10+
## Installation
11+
12+
```bash
13+
npm install esnext-coverage-format-text --save-dev
14+
```
15+
16+
## Usage
17+
18+
### Usage with test frameworks
19+
20+
Add esnext-coverage-format-text to the list of reporters in [esnext-coverage configuration object](https://github.com/esnext-coverage/karma-esnext-coverage-reporter#usage) or to your karma configuration file.
21+
22+
```js
23+
reporters: [
24+
{
25+
formatter: 'text', // require esnext-coverage-format-text
26+
outFile: 'reports/text-report.txt', // write output to file
27+
console: true // output to console
28+
}
29+
]
30+
```
31+
32+
### Usage with esnext-coverage cli
33+
34+
```bash
35+
esnext-coverage format coverage.json -f text -o report.txt
36+
```
37+
38+
### Usage in Node
39+
40+
```js
41+
import fs from 'fs';
42+
import formatter from 'esnext-coverage-format-text';
43+
44+
fs.readFile('coverage.json', 'utf8', (err, data) => {
45+
const coverage = JSON.parse(data);
46+
const report = formatter(coverage);
47+
fs.writeFile('text-report.txt', report);
48+
});
49+
```
50+
51+
## License
52+
53+
[MIT License](http://opensource.org/licenses/MIT)

package.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "esnext-coverage-format-text",
3+
"version": "0.0.0",
4+
"description": "esnext-coverage output formatter to human-readable text",
5+
"main": "dist/index.js",
6+
"scripts": {
7+
"transpile": "babel src --out-dir dist",
8+
"lint": "eslint --ignore-path .gitignore .",
9+
"spec": "mocha --slow 200 -r esnext-coverage test/spec/**/*.spec.js",
10+
"test": "npm run lint && npm run spec",
11+
"prepublish": "npm run test && npm run transpile"
12+
},
13+
"repository": {
14+
"type": "git",
15+
"url": "https://github.com/olegskl/esnext-coverage-format-text.git"
16+
},
17+
"keywords": [
18+
"coverage",
19+
"esnext-coverage",
20+
"text"
21+
],
22+
"author": "Oleg Sklyanchuk <[email protected]> (http://olegskl.com)",
23+
"license": "MIT",
24+
"bugs": {
25+
"url": "https://github.com/olegskl/esnext-coverage-format-text/issues"
26+
},
27+
"homepage": "https://github.com/olegskl/esnext-coverage-format-text",
28+
"dependencies": {
29+
"esnext-coverage-analytics": "^0.0.2",
30+
"chalk": "^1.1.3"
31+
},
32+
"devDependencies": {
33+
"babel-cli": "^6.14.0",
34+
"babel-core": "^6.14.0",
35+
"babel-preset-es2015": "^6.14.0",
36+
"chai": "^3.5.0",
37+
"eslint": "^3.4.0",
38+
"eslint-config-meetic": "^2.0.0",
39+
"esnext-coverage": "^0.0.1",
40+
"mocha": "^3.0.2"
41+
}
42+
}

src/colors.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Color functions for pretty console output.
3+
* @module colors
4+
*/
5+
6+
import chalk from 'chalk';
7+
8+
/**
9+
* Color for failure result.
10+
* @type {Function}
11+
*/
12+
export const failed = chalk.red;
13+
14+
/**
15+
* Color for optimal result.
16+
* @type {Function}
17+
*/
18+
export const optimal = chalk.green;

src/index.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Text reporter.
3+
* @module text-reporter
4+
*/
5+
6+
import createReportSummary from './reporters/report-summary';
7+
import createGlobalReport from './reporters/report-global';
8+
import createLocalFilesReport from './reporters/report-local-files';
9+
import reportWrap from './reporters/report-wrap';
10+
import computeMetrics from './services/compute-metrics';
11+
import {
12+
areMetricsAboveThresholds,
13+
areFilesMetricsAboveThresholds
14+
} from './services/check-against-thresholds';
15+
16+
/**
17+
* Text reporter for esnext-coverage-compatible results.
18+
* @param {Object} coverage - esnext-coverage-compatible code coverage.
19+
* @param {Object} options - Options.
20+
* @param {Object} options.environment - Environment where the tests were run.
21+
* @param {Object} options.thresholds - Thresholds for comparison with coverage metrics.
22+
* @return {String} Report ready to be written to stdout.
23+
*/
24+
module.exports = function textReporter(coverage, options = {}) {
25+
const {environment = {}, thresholds = {global: {}, local: {}}} = options;
26+
const {projectMetrics, filesMetrics} = computeMetrics(coverage);
27+
const isGlobalSuccess = areMetricsAboveThresholds(projectMetrics, thresholds.global);
28+
const isLocalSuccess = areFilesMetricsAboveThresholds(filesMetrics, thresholds.local);
29+
const isOverallSuccess = isGlobalSuccess && isLocalSuccess;
30+
const reportSummary = createReportSummary(isOverallSuccess, environment);
31+
32+
return reportWrap([
33+
reportSummary,
34+
createGlobalReport(projectMetrics, thresholds.global),
35+
createLocalFilesReport(filesMetrics, thresholds.local),
36+
reportSummary
37+
]);
38+
};

src/reporters/report-global.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Global reporter.
3+
* @module reporters/report-global
4+
*/
5+
6+
import reportUnit from './report-unit';
7+
8+
/**
9+
* Creates a global coverage report.
10+
* @param {Object} metrics - Global metrics.
11+
* @param {Object} thresholds - Global thresholds.
12+
* @return {String} Global coverage report as report unit.
13+
*/
14+
export default function createGlobalReport(metrics, thresholds) {
15+
return reportUnit('Overall project coverage', metrics, thresholds);
16+
}

src/reporters/report-local-files.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/**
2+
* Local files reporter.
3+
* @module reporters/report-local-files
4+
*/
5+
6+
import reportUnit from './report-unit';
7+
import findCommonPath from '../services/find-common-path';
8+
import {areMetricsAboveThresholds} from '../services/check-against-thresholds';
9+
10+
/**
11+
* File path separator (may differ depending on OS).
12+
* @private
13+
* @type {RegExp}
14+
*/
15+
const separator = /\\|\//;
16+
17+
/**
18+
* Normalizes file path separators.
19+
* @private
20+
* @param {String} path - File path.
21+
* @return {String} Normalized file path.
22+
* @example
23+
* normalizePath('a\b\c'); // 'a/b/c'
24+
*/
25+
function normalizePath(path) {
26+
return path.replace(separator, '/');
27+
}
28+
29+
/**
30+
* Creates a failed file reporter function.
31+
* @private
32+
* @param {Object} localThresholds - Thresholds to be used in the reporter.
33+
* @return {Function} Failed file reporter.
34+
*/
35+
function failedFileReporterFactory(localThresholds) {
36+
37+
/**
38+
* Failed file reporter.
39+
* @private
40+
* @param {Object} localReport - Report for a given file.
41+
* @param {String} localReport.name - File name.
42+
* @param {Object} localReport.metrics - File coverage metrics.
43+
* @return {String} Unit report.
44+
*/
45+
return function reportFailedFile({name, metrics}) {
46+
return reportUnit(name, metrics, localThresholds);
47+
};
48+
}
49+
50+
/**
51+
* Finds and removes the common path from a list of files.
52+
* @private
53+
* @param {[Object]} failedFiles - List of files.
54+
* @return {[Object]} List of files with common path removed.
55+
*/
56+
function removeCommonPath(failedFiles) {
57+
const filePathList = failedFiles.map(file => file.name);
58+
const commonPath = findCommonPath(filePathList);
59+
if (!commonPath) { return failedFiles; }
60+
return failedFiles.map(file => {
61+
file.name = file.name.slice(commonPath.length + 1);
62+
return file;
63+
});
64+
}
65+
66+
/**
67+
* Finds files that have failed local thresholds.
68+
* @private
69+
* @param {Object} fileMetricsIndex - Index of file metrics.
70+
* @param {Object} thresholds - Local thresholds.
71+
* @return {Array} List of files that have failed local thresholds.
72+
*/
73+
function findFilesFailingThresholds(fileMetricsIndex, thresholds) {
74+
return Object.keys(fileMetricsIndex)
75+
.filter(fileName => {
76+
const fileMetrics = fileMetricsIndex[fileName];
77+
return !areMetricsAboveThresholds(fileMetrics, thresholds);
78+
})
79+
.map(fileName => {
80+
return {
81+
name: normalizePath(fileName),
82+
metrics: fileMetricsIndex[fileName]
83+
};
84+
});
85+
}
86+
87+
/**
88+
* Generates a report displaying files that have failed local thresholds.
89+
* @param {Object} fileIndex - Index of file metrics.
90+
* @param {Object} thresholds - Local thresholds.
91+
* @return {String} Failed files report.
92+
* @example
93+
* Failed report A
94+
*
95+
* Failed report B
96+
*
97+
* Failed report C
98+
*/
99+
export default function createLocalFilesReport(fileIndex, thresholds) {
100+
const failedFiles = findFilesFailingThresholds(fileIndex, thresholds);
101+
const failedFileReporter = failedFileReporterFactory(thresholds);
102+
return removeCommonPath(failedFiles)
103+
.map(failedFileReporter)
104+
.join('\n\n');
105+
}

src/reporters/report-summary.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Report summary.
3+
* @module reporters/report-summary
4+
*/
5+
6+
import {optimal, failed} from '../colors';
7+
8+
/**
9+
* Generates the overall report summary.
10+
* @param {Boolean} isSuccess Indicator of coverage matching threshold limits.
11+
* @param {Object} environment The environment where the test was run.
12+
* @return {String} Report summary.
13+
* @example
14+
* Failed test coverage on Node v5.4.0
15+
*/
16+
export default function createReportSummary(isSuccess, environment) {
17+
const overallResultMessage = isSuccess ? optimal('Passed') : failed('Failed');
18+
const envName = environment.name || `Node ${process.version}`;
19+
return `${overallResultMessage} test coverage on ${envName}`;
20+
}

0 commit comments

Comments
 (0)