Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

monocart-coverage-reports

Package Overview
Dependencies
Maintainers
1
Versions
91
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

monocart-coverage-reports - npm Package Compare versions

Comparing version 2.3.3 to 2.3.4

5

lib/converter/ast.js

@@ -7,3 +7,2 @@ const {

const { createBranches, collectBranches } = require('./branches.js');
const findInRanges = require('./find-in-ranges.js');

@@ -32,3 +31,3 @@ const getFunctionRange = (start, end, state) => {

// find in functionRanges
return findInRanges(start, end, functionRanges);
return Util.findInRanges(start, end, functionRanges, 'startOffset', 'endOffset');
};

@@ -219,3 +218,3 @@

if (!count) {
const coveredRange = findInRanges(startOffset, endOffset, coveredRanges);
const coveredRange = Util.findInRanges(startOffset, endOffset, coveredRanges, 'startOffset', 'endOffset');
if (coveredRange) {

@@ -222,0 +221,0 @@ count = 1;

63

lib/converter/branches.js
const Util = require('../utils/util.js');
const findInRanges = require('./find-in-ranges.js');

@@ -17,3 +16,3 @@ const findBranchBlock = (start, end, functionInfo) => {

// "a" is in "|| a"
const blockItem = findInRanges(start, end, blockRanges);
const blockItem = Util.findInRanges(start, end, blockRanges, 'startOffset', 'endOffset');
if (blockItem) {

@@ -112,3 +111,3 @@ return blockItem;

const blockItem = findInRanges(start, end, blockRanges);
const blockItem = Util.findInRanges(start, end, blockRanges, 'startOffset', 'endOffset');
if (blockItem) {

@@ -275,4 +274,23 @@ node._state = {

const updateBlockLocations = (locations) => {
const noBlockList = [];
let blockCount = 0;
locations.forEach((item) => {
if (item.block) {
item.count = item.block.count;
blockCount += item.count;
return;
}
noBlockList.push(item);
});
return {
noBlockList,
blockCount
};
};
// const a = tf1 ? 'true' : 'false';
const ConditionalExpression = (group, parentCount, noBlockList, blockCount) => {
const ConditionalExpression = (locations, parentCount) => {
const { noBlockList, blockCount } = updateBlockLocations(locations);
if (!noBlockList.length) {

@@ -288,3 +306,4 @@ return;

const IfStatement = (group, parentCount, noBlockList, blockCount) => {
const IfStatement = (locations, parentCount) => {
const { noBlockList, blockCount } = updateBlockLocations(locations);
if (!noBlockList.length) {

@@ -303,3 +322,4 @@ return;

// const b = tf2 || tf1 || a;
const LogicalExpression = (group, parentCount, noBlockList, blockCount) => {
const LogicalExpression = (locations, parentCount) => {
const { noBlockList, blockCount } = updateBlockLocations(locations);
if (!noBlockList.length) {

@@ -312,11 +332,6 @@ return;

});
// const start = group.start;
// if (start > 7874 && start < 7922) {
// console.log(group.type, parentCount, 'locations', group.locations);
// }
};
const SwitchStatement = (group, parentCount, noBlockList, blockCount) => {
const SwitchStatement = (locations, parentCount) => {
const { noBlockList, blockCount } = updateBlockLocations(locations);
if (!noBlockList.length) {

@@ -331,2 +346,8 @@ return;

const AssignmentPattern = (locations, parentCount) => {
locations.forEach((item) => {
item.count = parentCount;
});
};
// =======================================================================================

@@ -373,13 +394,2 @@

const noBlockList = [];
let blockCount = 0;
locations.forEach((item) => {
if (item.block) {
item.count = item.block.count;
blockCount += item.count;
return;
}
noBlockList.push(item);
});
const handlers = {

@@ -389,3 +399,4 @@ ConditionalExpression,

LogicalExpression,
SwitchStatement
SwitchStatement,
AssignmentPattern
};

@@ -395,3 +406,3 @@

if (handler) {
handler(group, parentCount, noBlockList, blockCount);
handler(locations, parentCount);
}

@@ -398,0 +409,0 @@

@@ -23,3 +23,2 @@ /**

const InfoFunction = require('./info-function.js');
const findInRanges = require('./find-in-ranges.js');

@@ -33,3 +32,3 @@ // ========================================================================================================

}
const range = findInRanges(item.start, item.end, ignoredRanges);
const range = Util.findInRanges(item.start, item.end, ignoredRanges, 'start', 'end');
if (range) {

@@ -44,5 +43,4 @@ // console.log(item, range);

const updateLinesCount = (bytes, locator, lineMap) => {
const applyBytesToLines = (bytes, locator, lineMap) => {
bytes.forEach((range) => {
const {

@@ -52,2 +50,7 @@ start, end, count, ignored

// no need handle ignored and uncovered byte
if (count === 0 && ignored) {
return;
}
const sLoc = locator.offsetToLocation(start);

@@ -60,79 +63,106 @@ const eLoc = locator.offsetToLocation(end);

lines.forEach((it) => {
const line = lineMap.get(it.line);
if (!line) {
const lineItem = lineMap.get(it.line);
if (!lineItem) {
// not found line, could be comment or blank line
return;
}
if (lineItem.ignored) {
return;
}
// from outside into inside, uncovered is certain
// default is covered
if (it.entire) {
line.covered = count > 0;
line.count = count;
it.count = count;
if (ignored) {
if (!line.covered) {
line.ignored = true;
}
}
// default is covered, so only focus on
// 1, last covered count
// 2, uncovered entire and pieces
if (count > 0) {
lineItem.coveredCount = count;
} else {
if (!ignored) {
if (count > 0) {
line.count = count;
} else {
// not covered if any count = 0
line.covered = false;
}
if (it.entire) {
lineItem.uncoveredEntire = it;
} else {
lineItem.uncoveredPieces.push(it);
}
}
// if (!line.history) {
// line.history = [];
// }
// line.history.push(`${it.entire}-${count}`);
});
});
// if (state.sourcePath.endsWith('component.js')) {
// console.log('===========================================', state.sourcePath);
// }
};
const handleLinesCoverage = (bytes, locator) => {
const handleLinesCoverage = (bytes, locator, ignoredRanges) => {
const lines = [];
// line 1 based
const lineMap = new Map();
// init lines
let blankCount = 0;
let commentCount = 0;
locator.lines.forEach((it) => {
// line 1 based
const lineMap = new Map();
locator.lines.forEach((lineItem) => {
// exclude blank and comment
if (it.blank) {
if (lineItem.blank) {
blankCount += 1;
return;
}
if (it.comment) {
if (lineItem.comment) {
commentCount += 1;
return;
}
const ignored = Util.findInRanges(lineItem.start, lineItem.end, ignoredRanges);
if (ignored) {
return;
}
// line 1-base
const line = it.line + 1;
const line = lineItem.line + 1;
lineItem.coveredCount = 1;
lineItem.uncoveredEntire = null;
lineItem.uncoveredPieces = [];
lineMap.set(line, lineItem);
});
applyBytesToLines(bytes, locator, lineMap);
const lines = [];
// data lines for codecov
// https://docs.codecov.com/docs/codecov-custom-coverage-format
const dataLines = {};
// no ignore items
lineMap.forEach((lineItem, line) => {
const {
uncoveredEntire, uncoveredPieces, coveredCount
} = lineItem;
// default count to 1, both js and css
const lineInfo = new InfoLine(line, it.length, 1);
lineMap.set(line, lineInfo);
lines.push(lineInfo);
let count = 1;
// full covered true/false for entire line
let covered = true;
if (uncoveredEntire) {
count = 0;
covered = false;
} else {
count = coveredCount;
const uncoveredLen = uncoveredPieces.length;
if (uncoveredLen > 0) {
covered = false;
// uncovered
count = `1/${uncoveredLen + 1}`;
}
}
// data lines
dataLines[line] = count;
// exclude indent?
const infoLine = new InfoLine(line, lineItem.length, count, covered);
lines.push(infoLine);
});
updateLinesCount(bytes, locator, lineMap);
return {
lines,
dataLines,
blankCount,

@@ -193,7 +223,4 @@ commentCount

// the lines not includes ignored
lines.forEach((ln) => {
if (ln.ignored) {
// console.log(ln);
return;
}
v8Lines.total += 1;

@@ -244,2 +271,4 @@ // full line covered

data.ignores = ignoredRanges;
// data bytes is start/end/count object

@@ -285,5 +314,7 @@ handleIgnoredRanges(data.bytes, ignoredRanges);

const {
lines, blankCount, commentCount
} = handleLinesCoverage(data.bytes, locator);
lines, dataLines, blankCount, commentCount
} = handleLinesCoverage(data.bytes, locator, ignoredRanges);
data.lines = dataLines;
// ==========================================

@@ -312,17 +343,6 @@ // v8 data and summary

// for codecov https://docs.codecov.com/docs/codecov-custom-coverage-format
data.lines = {};
lines.filter((it) => !it.ignored).forEach((line, index) => {
// the lines not includes ignored
lines.forEach((line, index) => {
istanbulData.statementMap[`${index}`] = line.generate();
istanbulData.s[`${index}`] = line.count;
let count = 0;
if (line.covered) {
count = line.count;
} else if (!line.covered && line.count > 0) {
count = '1/2';
}
// 1-base
data.lines[`${line.line}`] = count;
});

@@ -329,0 +349,0 @@

@@ -5,3 +5,3 @@ const Util = require('../utils/util.js');

// v8 ignore next N
// v-8 ignore next N
if (content) {

@@ -24,6 +24,22 @@ const n = parseInt(content);

// v8 ignore next
// v-8 ignore next
return 1;
};
const extendStart = (start, source) => {
// extend left, include
while (start > 0 && Util.isBlank(source[start - 1])) {
start -= 1;
}
return start;
};
const extendEnd = (end, source, maxLength) => {
// extend right, exclude
while (end < maxLength && Util.isBlank(source[end])) {
end += 1;
}
return end;
};
const addNextIgnore = (list, content, item, locator) => {

@@ -33,8 +49,5 @@

const maxLength = source.length;
let startOffset = item.start;
// extend left
while (startOffset > 0 && Util.isBlank(source[startOffset - 1])) {
startOffset -= 1;
}
const start = extendStart(item.start, source);
// findLine 0-base

@@ -49,7 +62,3 @@ const currentLine = lineParser.findLine(item.end);

const endLine = locator.getLine(line + n);
let endOffset = endLine ? endLine.end : maxLength;
// extend right
while (endOffset < maxLength && Util.isBlank(source[endOffset + 1])) {
endOffset += 1;
}
const end = extendEnd(endLine ? endLine.end : maxLength, source, maxLength);

@@ -59,4 +68,4 @@ const nextItem = {

n,
startOffset,
endOffset
start,
end
};

@@ -77,2 +86,3 @@

}
// istanbul ignore has different rules, can not support it
};

@@ -85,3 +95,4 @@

const { lineParser } = locator;
const { lineParser, source } = locator;
const maxLength = source.length;

@@ -111,5 +122,5 @@ const comments = lineParser.comments;

if (ignoreStart) {
// v8 ignore stop
// v-8 ignore stop
if (content === 'stop') {
ignoreStart.endOffset = end;
ignoreStart.end = extendEnd(end, source, maxLength);
ignoreStart = null;

@@ -120,3 +131,3 @@ }

// v8 ignore start
// v-8 ignore start
if (content === 'start') {

@@ -126,4 +137,4 @@ // add first for sort by start

type: 'start-stop',
startOffset: start,
endOffset: start
start: extendStart(start, source),
end: start
};

@@ -134,3 +145,3 @@ list.push(ignoreStart);

// v8 ignore next N
// v-8 ignore next N
const nextKey = 'next';

@@ -146,3 +157,3 @@ if (content.startsWith(nextKey)) {

if (ignoreStart) {
ignoreStart.endOffset = locator.source.length;
ignoreStart.end = locator.source.length;
ignoreStart = null;

@@ -149,0 +160,0 @@ }

module.exports = class InfoLine {
constructor(line, column, count = 1) {
constructor(line, column, count, covered) {
// 1 based

@@ -8,3 +8,3 @@ this.line = line;

// covered full line, could be false even count > 0
this.covered = count > 0;
this.covered = covered;
}

@@ -11,0 +11,0 @@

@@ -251,2 +251,37 @@ const Util = {

findInRanges: (startPos, endPos, rangeList, startKey = 'start', endKey = 'end') => {
if (!Util.isList(rangeList)) {
return;
}
const quickFindRange = (position, ranges) => {
let start = 0;
let end = ranges.length - 1;
while (end - start > 1) {
const i = Math.floor((start + end) * 0.5);
const item = ranges[i];
if (position < item[startKey]) {
end = i;
continue;
}
if (position > item[endKey]) {
start = i;
continue;
}
return ranges[i];
}
// last two items, less is start
const endItem = ranges[end];
if (position < endItem[startKey]) {
return ranges[start];
}
return ranges[end];
};
const range = quickFindRange(startPos, rangeList);
if (startPos >= range[startKey] && endPos <= range[endKey]) {
return range;
}
},
getRangeLines: (sLoc, eLoc) => {

@@ -277,3 +312,3 @@

entire,
range: {
pieces: {
start: sLoc.column,

@@ -294,3 +329,3 @@ end: sLoc.length

entire,
range: {
pieces: {
start: sLoc.column,

@@ -313,3 +348,3 @@ end: eLoc.column

entire,
range: {
pieces: {
start: eLoc.indent,

@@ -339,3 +374,3 @@ end: eLoc.column

entire: true
// no range for entire line
// no pieces for entire line
});

@@ -342,0 +377,0 @@ }

{
"name": "monocart-coverage-reports",
"version": "2.3.3",
"version": "2.3.4",
"description": "Monocart coverage reports",

@@ -5,0 +5,0 @@ "main": "./lib/index.js",

@@ -32,4 +32,4 @@ # Monocart Coverage Reports

- [How Monocart Works](#how-monocart-works)
* [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
* [Integration](#integration) - Playwright, Jest, Vitest, Codecov, Coveralls, Sonar Cloud
* [Istanbul Introduction](#istanbul-introduction)
* [Thanks](#thanks)

@@ -306,3 +306,3 @@

## Manually Resolve the Sourcemap
> If the `js` file is loaded with `addScriptTag` [API](https://playwright.dev/docs/api/class-page#page-add-script-tag), then its sourcemap file may not work. You can try to manually read the sourcemap file before the coverage data is added to the report.
> Sometimes, the sourcemap file cannot be successfully loaded with the `sourceMappingURL`, you can try to manually read the sourcemap file before the coverage data is added to the report.
```js

@@ -375,24 +375,30 @@ const jsCoverage = await page.coverage.stopJSCoverage();

## Multiprocessing Support
The data will be added to `[outputDir]/.cache`, and the cache will be removed after reports generated.
- sub process 1
> The data will be added to `[outputDir]/.cache`, After the generation of the report, this data will be removed unless debugging has been enabled or a raw report has been used, see [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
- Main process, before the start of testing
```js
// clean previous cache before the start of testing (option)
const MCR = require('monocart-coverage-reports');
const options = require('path-to/same-options.js');
const coverageReport = MCR(options);
await coverageReport.add(coverageData1);
MCR(options).cleanCache();
```
- sub process 2
- Sub process 1, testing stage 1
```js
const MCR = require('monocart-coverage-reports');
const options = require('path-to/same-options.js');
const coverageReport = MCR(options);
await coverageReport.add(coverageData2);
await MCR(options).add(coverageData1);
```
- main process
- Sub process 2, testing stage 2
```js
// after all sub processes finished
const MCR = require('monocart-coverage-reports');
const options = require('path-to/same-options.js');
await MCR(options).add(coverageData2);
```
- Main process, after the completion of testing
```js
// generate coverage reports after the completion of testing
const MCR = require('monocart-coverage-reports');
const options = require('path-to/same-options.js');
const coverageReport = MCR(options);

@@ -484,3 +490,3 @@ const coverageResults = await coverageReport.generate();

if (platform === 'linux') {
console.info('hello linux');
console.log('hello linux');
}

@@ -584,2 +590,21 @@ ```

## Debug for Coverage and Sourcemap
> Sometimes, the coverage is not what we expect. The next step is to figure out why, and we can easily find out the answer step by step through debugging.
- Start debugging for v8 report with option `logging: 'debug'`
```js
const coverageOptions = {
logging: 'debug',
reports: [
['v8'],
['console-summary']
]
};
```
When `logging` is `debug`, the raw report data will be preserved in `[outputDir]/.cache` or `[outputDir]/raw` if `raw` report is used. And the dist file will be preserved in the V8 list, and by opening the browser's devtool, it makes data verification visualization effortless.
![](./test/debug-coverage.png)
- Check sourcemap with [Source Map Visualization](https://evanw.github.io/source-map-visualization/)
![](./test/debug-sourcemap.png)
## Integration

@@ -609,2 +634,8 @@ - [monocart-reporter](https://github.com/cenfun/monocart-reporter) - A [Playwright](https://github.com/microsoft/playwright) custom reporter, supports generating [Code Coverage Report](https://github.com/cenfun/monocart-reporter?#code-coverage-report)

- [![Coverage Status](https://coveralls.io/repos/github/cenfun/monocart-coverage-reports/badge.svg?branch=main)](https://coveralls.io/github/cenfun/monocart-coverage-reports?branch=main)
```js
const coverageOptions = {
outputDir: "./coverage-reports",
lcov: true
};
```
- Github Actions example:

@@ -636,11 +667,8 @@ ```yml

```
- Integration with any testing framework
- First, you need to collect coverage data when any stage of the test is completed. Then, add the coverage data to the coverage report.
- Upon the completion of all tests, generate the coverage report.
- see [Multiprocessing Support](#multiprocessing-support)
## Istanbul Introduction
- [Istanbul coverage report](https://istanbul.js.org/) - Instrumenting source codes and generating coverage reports
- [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul)
- [istanbul-reports](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib)
- [Code Coverage Introduction](https://docs.cypress.io/guides/tooling/code-coverage)
## Thanks
- Special thanks to [@edumserrano](https://github.com/edumserrano)

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc