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.0.7 to 2.0.8

lib/converter/find-in-ranges.js

5

lib/converter/ast.js

@@ -6,5 +6,4 @@ const {

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

@@ -11,0 +10,0 @@ const getFunctionRange = (start, end, state) => {

38

lib/converter/branches.js
const Util = require('../utils/util.js');
const findInRanges = require('./find-in-ranges.js');
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.startOffset) {
end = i;
continue;
}
if (position > item.endOffset) {
start = i;
continue;
}
return ranges[i];
}
// last two items, less is start
const endItem = ranges[end];
if (position < endItem.startOffset) {
return ranges[start];
}
return ranges[end];
};
const findInRanges = (start, end, ranges) => {
if (!Util.isList(ranges)) {
return;
}
const range = quickFindRange(start, ranges);
if (start >= range.startOffset && end <= range.endOffset) {
return range;
}
};
const findBranchBlock = (start, end, functionInfo) => {

@@ -435,5 +400,4 @@ const { range } = functionInfo;

module.exports = {
findInRanges,
createBranches,
collectBranches
};

@@ -0,1 +1,13 @@

// https://github.com/demurgos/v8-coverage
/**
* @ranges is always non-empty. The first range is called the "root range".
* @isBlockCoverage indicates if the function has block coverage information
* @false means that there is a single range and its count is the number of times the function was called.
* @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
* It detects skipped or repeated statements. The root range counts the number of function calls.
*
* @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
*/
// if you have a line of code that says `var x= 10; console.log(x);` that's one line and 2 statements.
const path = require('path');

@@ -10,2 +22,3 @@

const { getJsAstInfo, getCssAstInfo } = require('./ast.js');
const { getIgnoredRanges } = require('./ignore.js');

@@ -18,5 +31,120 @@ const { dedupeCountRanges } = require('../utils/dedupe.js');

const InfoFunction = require('./info-function.js');
const findInRanges = require('./find-in-ranges.js');
// ========================================================================================================
const handleIgnoredRanges = (list, ignoredRanges) => {
list.forEach((item) => {
if (item.count > 0) {
return;
}
const range = findInRanges(item.start, item.end, ignoredRanges);
if (range) {
// console.log(item, range);
item.ignored = true;
}
});
};
// ========================================================================================================
const updateLinesCount = (bytes, locator, lineMap) => {
bytes.forEach((range) => {
const {
start, end, count, ignored
} = range;
const sLoc = locator.offsetToLocation(start);
const eLoc = locator.offsetToLocation(end);
// update lines coverage
const lines = Util.getRangeLines(sLoc, eLoc);
lines.forEach((it) => {
const line = lineMap.get(it.line);
if (!line) {
return;
}
// from outside into inside, uncovered is certain
// default is covered
if (it.entire) {
line.covered = count > 0;
line.count = count;
if (ignored) {
if (!line.covered) {
line.ignored = true;
}
}
} else {
if (!ignored) {
if (count > 0) {
line.count = count;
} else {
// not covered if any count = 0
line.covered = false;
}
}
}
// if (!line.history) {
// line.history = [];
// }
// line.history.push(`${it.entire}-${count}`);
});
});
// if (state.sourcePath.endsWith('component.js')) {
// console.log('===========================================', state.sourcePath);
// console.log(coverageInfo.lines);
// }
};
const handleLinesCoverage = (bytes, locator) => {
const lines = [];
// line 1 based
const lineMap = new Map();
// init lines
let blankCount = 0;
let commentCount = 0;
locator.lines.forEach((it) => {
// exclude blank and comment
if (it.blank) {
blankCount += 1;
return;
}
if (it.comment) {
commentCount += 1;
return;
}
// line 1-base
const line = it.line + 1;
// default count to 1, both js and css
const lineInfo = new InfoLine(line, it.length, 1);
lineMap.set(line, lineInfo);
lines.push(lineInfo);
});
updateLinesCount(bytes, locator, lineMap);
return {
lines,
blankCount,
commentCount
};
};
// ========================================================================================================
const calculateV8Functions = (functions) => {

@@ -30,2 +158,6 @@

functions.forEach((fn) => {
if (fn.ignored) {
return;
}
v8Functions.total += 1;

@@ -47,8 +179,9 @@ if (fn.count > 0) {

branches.forEach((branch) => {
branch.locations.forEach((location) => {
v8Branches.total += 1;
if (location.count > 0) {
v8Branches.covered += 1;
}
});
if (branch.ignored) {
return;
}
v8Branches.total += 1;
if (branch.count > 0) {
v8Branches.covered += 1;
}
});

@@ -68,2 +201,6 @@

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

@@ -79,38 +216,16 @@ // full line covered

// ========================================================================================================
const createEmptyCoverageInfo = () => {
// data for v8 UI
const data = {
bytes: [],
return {
// v8 UI
data: {
bytes: [],
functions: [],
branches: []
},
// istanbul
functions: [],
branches: []
};
const branches = [];
const functions = [];
const lines = [];
// line 1 based
const lineMap = new Map();
const blankCount = 0;
const commentCount = 0;
return {
// v8
data,
// istanbul
branches,
functions,
lines,
lineMap,
blankCount,
commentCount
};
};

@@ -128,19 +243,11 @@

*/
const collectFileCoverage = (item, coverageInfo, state) => {
const collectFileCoverage = (item, state, coverageData, options) => {
const { sourcePath } = item;
const { coverageInfo, locator } = state;
const {
// v8
data,
// istanbul
branches,
functions,
lines,
blankCount,
commentCount
branches
} = coverageInfo;

@@ -151,6 +258,23 @@

data.bytes = dedupeCountRanges(data.bytes);
const ignoredRanges = getIgnoredRanges(locator, options);
if (ignoredRanges) {
handleIgnoredRanges(data.bytes, ignoredRanges);
handleIgnoredRanges(data.functions, ignoredRanges);
handleIgnoredRanges(data.branches, ignoredRanges);
// console.log(ignoredRanges);
}
// after bytes with ignored, before calculateV8Lines
const {
lines, blankCount, commentCount
} = handleLinesCoverage(data.bytes, locator);
item.data = data;
item.summary = {
functions: calculateV8Functions(functions),
branches: calculateV8Branches(branches),
functions: calculateV8Functions(data.functions),
branches: calculateV8Branches(data.branches),
lines: calculateV8Lines(lines, blankCount, commentCount)

@@ -189,3 +313,3 @@ };

// append to dist file state
state.coverageData[sourcePath] = istanbulCoverage;
coverageData[sourcePath] = istanbulCoverage;

@@ -196,67 +320,10 @@ };

const updateLineCoverage = (start, end, count, lineMap, locator) => {
const sLoc = locator.offsetToLocation(start);
const eLoc = locator.offsetToLocation(end);
// update lines coverage
const lines = Util.getRangeLines(sLoc, eLoc);
lines.forEach((it) => {
const line = lineMap.get(it.line);
if (!line) {
return;
}
// from outside into inside, uncovered is certain
// default is covered
if (it.entire) {
line.covered = count > 0;
line.count = count;
} else {
if (count > 0) {
line.count = count;
} else {
// not covered if any count = 0
line.covered = false;
}
}
// if (!line.history) {
// line.history = [];
// }
// line.history.push(`${it.entire}-${count}`);
});
// if (state.sourcePath.endsWith('component.js')) {
// console.log('===========================================', state.sourcePath);
// console.log(coverageInfo.lines);
// }
};
// https://github.com/demurgos/v8-coverage
/**
* @ranges is always non-empty. The first range is called the "root range".
* @isBlockCoverage indicates if the function has block coverage information
* @false means that there is a single range and its count is the number of times the function was called.
* @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
* It detects skipped or repeated statements. The root range counts the number of function calls.
*
* @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
*/
// if you have a line of code that says `var x= 10; console.log(x);` that's one line and 2 statements.
const addJsLineCoverage = (state, range) => {
const { locator, coverageInfo } = state;
const { data, lineMap } = coverageInfo;
const addJsBytesCoverage = (state, range) => {
const { coverageInfo } = state;
const { data } = coverageInfo;
const {
startOffset, endOffset, count
} = range;
// add bytes range
data.bytes.push({
// index,
start: startOffset,

@@ -266,26 +333,18 @@ end: endOffset,

});
updateLineCoverage(startOffset, endOffset, count, lineMap, locator);
};
const addCssLineCoverage = (state, range) => {
const { coverageInfo, locator } = state;
const { lineMap, data } = coverageInfo;
const addCssBytesCoverage = (state, range) => {
const { coverageInfo } = state;
const { data } = coverageInfo;
const {
start, end, count
} = range;
// add bytes range
data.bytes.push(range);
updateLineCoverage(start, end, count, lineMap, locator);
// add css bytes range, already start, end
data.bytes.push({
start,
end,
count
});
};
// ========================================================================================================
const updateOffsetToLocation = (locator, loc) => {

@@ -304,2 +363,4 @@ const sLoc = locator.offsetToLocation(loc.start);

// ========================================================================================================
const handleFunctionsCoverage = (state) => {

@@ -403,46 +464,190 @@

};
const handleBytesCoverage = (state) => {
const { js, coverageList } = state;
if (js) {
coverageList.forEach((block) => {
block.ranges.forEach((range) => {
addJsBytesCoverage(state, range);
});
});
} else {
coverageList.forEach((range) => {
addCssBytesCoverage(state, range);
});
}
};
const handleLinesCoverage = (state) => {
// ========================================================================================================
const { locator, coverageInfo } = state;
const handleOriginalFunctionsCoverage = (state, originalMap) => {
const lines = coverageInfo.lines;
const lineMap = coverageInfo.lineMap;
// functions only for js
if (!state.js) {
return;
}
// init lines
let blankCount = 0;
let commentCount = 0;
// console.log(state.astInfo.functions);
locator.lines.forEach((it) => {
// exclude blank and comment
if (it.blank) {
blankCount += 1;
// function count
state.astInfo.functions.forEach((it) => {
const {
start, end, wrap
} = it;
// remove webpack wrap functions for functions count, not for ranges here
if (wrap) {
return;
}
if (it.comment) {
commentCount += 1;
// rename to startOffset and endOffset
const range = {
startOffset: start,
endOffset: end
};
const result = findOriginalRange(range, state, originalMap);
if (result.error) {
return;
}
// line 1-base
const line = it.line + 1;
// default count to 1, both js and css
const lineInfo = new InfoLine(line, it.length, 1);
lineMap.set(line, lineInfo);
lines.push(lineInfo);
const { originalRange, originalState } = result;
// add back to original ast
originalState.astInfo.functions.push({
... it,
generatedStart: start,
generatedEnd: end,
start: originalRange.startOffset,
end: originalRange.endOffset
});
// if (originalState.sourcePath.endsWith('store.js')) {
// console.log('==========================================================');
// console.log(it, result.startMapping, result.endMapping);
// }
});
coverageInfo.blankCount = blankCount;
coverageInfo.commentCount = commentCount;
};
const handleRangesCoverage = (state) => {
const handleOriginalBranchesCoverage = (state, originalMap) => {
// branches only for js
if (!state.js) {
return;
}
// console.log(state.astInfo.branches);
// function count
state.astInfo.branches.forEach((it) => {
const {
type, loc, locations
} = it;
// rename to startOffset and endOffset
const bRange = {
startOffset: loc.start,
endOffset: loc.end
};
// start
const result = findOriginalRange(bRange, state, originalMap);
if (result.error) {
// not in the original files
return;
}
const { originalRange, originalState } = result;
const newBranchLoc = {
start: originalRange.startOffset,
end: originalRange.endOffset
};
let hasError;
const newLocations = locations.map((oLoc) => {
const newLoc = {
... oLoc
};
if (newLoc.none) {
return newLoc;
}
const { start, end } = newLoc;
const lRange = {
startOffset: start,
endOffset: end
};
const res = findOriginalRange(lRange, state, originalMap);
if (res.error) {
// It should not happen unless it is minify files, the SourceMap has some order problems
hasError = true;
// console.log('====================================', state.sourcePath, loc);
// console.log(res.errors);
// Util.logError(`Not found original branch. start: ${start}, end: ${end}`);
return newLoc;
}
const oRage = res.originalRange;
newLoc.start = oRage.startOffset;
newLoc.end = oRage.endOffset;
return newLoc;
});
if (hasError) {
return;
}
// add back to original ast
originalState.astInfo.branches.push({
type,
loc: newBranchLoc,
locations: newLocations
});
});
};
const handleOriginalBytesCoverage = (state, originalMap) => {
const { js, coverageList } = state;
// const time_start_mapping = Date.now();
if (js) {
// v8 coverage
coverageList.forEach((block) => {
block.ranges.forEach((range) => {
addJsLineCoverage(state, range);
block.ranges.forEach((range, index) => {
// remove wrap functions for original files
if (range.wrap) {
// console.log(range);
return;
}
const result = findOriginalRange(range, state, originalMap);
if (result.error) {
return;
}
const { originalRange, originalState } = result;
addJsBytesCoverage(originalState, originalRange);
// if (originalRange.startOffset === 110 && originalRange.endOffset === 271) {
// console.log('===============================', originalState.sourcePath);
// console.log(result.startMapping, result.endMapping);
// }
});

@@ -452,5 +657,7 @@ });

} else {
coverageList.forEach((range) => {
addCssLineCoverage(state, range);
});
// support css later
// current css no sourceMap, so never come in
// coverageList.forEach((range) => {
// });
}

@@ -460,14 +667,2 @@

const generateCoverageForDist = (item, state) => {
// handle coverage
handleFunctionsCoverage(state);
handleBranchesCoverage(state);
handleLinesCoverage(state);
handleRangesCoverage(state);
collectFileCoverage(item, state.coverageInfo, state);
};
// ========================================================================================================

@@ -566,2 +761,4 @@

// ========================================================================================================
const initOriginalList = (state, originalDecodedMap, options) => {

@@ -629,3 +826,3 @@

const collectOriginalList = (item, state, originalMap) => {
const collectOriginalList = (item, state, originalMap, options) => {

@@ -640,3 +837,3 @@ const { fileUrls, sourceMap } = state;

const {
js, type, sourcePath, source, coverageInfo
js, type, sourcePath, source
} = originalState;

@@ -659,3 +856,3 @@

// generate coverage, coverageInfo for current file, state for dist file
collectFileCoverage(sourceItem, coverageInfo, state);
collectFileCoverage(sourceItem, originalState, state.coverageData, options);

@@ -668,183 +865,14 @@ sourceList.push(sourceItem);

// =======================================================================================
// ========================================================================================================
const handleOriginalFunctionsCoverage = (state, originalMap) => {
const generateCoverageForDist = (item, state, options) => {
// functions only for js
if (!state.js) {
return;
}
handleFunctionsCoverage(state);
handleBranchesCoverage(state);
handleBytesCoverage(state);
// console.log(state.astInfo.functions);
collectFileCoverage(item, state, state.coverageData, options);
// function count
state.astInfo.functions.forEach((it) => {
const {
start, end, wrap
} = it;
// remove webpack wrap functions for functions count, not for ranges here
if (wrap) {
return;
}
// rename to startOffset and endOffset
const range = {
startOffset: start,
endOffset: end
};
const result = findOriginalRange(range, state, originalMap);
if (result.error) {
return;
}
const { originalRange, originalState } = result;
// add back to original ast
originalState.astInfo.functions.push({
... it,
generatedStart: start,
generatedEnd: end,
start: originalRange.startOffset,
end: originalRange.endOffset
});
// if (originalState.sourcePath.endsWith('store.js')) {
// console.log('==========================================================');
// console.log(it, result.startMapping, result.endMapping);
// }
});
};
const handleOriginalBranchesCoverage = (state, originalMap) => {
// branches only for js
if (!state.js) {
return;
}
// console.log(state.astInfo.branches);
// function count
state.astInfo.branches.forEach((it) => {
const {
type, loc, locations
} = it;
// rename to startOffset and endOffset
const bRange = {
startOffset: loc.start,
endOffset: loc.end
};
// start
const result = findOriginalRange(bRange, state, originalMap);
if (result.error) {
// not in the original files
return;
}
const { originalRange, originalState } = result;
const newBranchLoc = {
start: originalRange.startOffset,
end: originalRange.endOffset
};
let hasError;
const newLocations = locations.map((oLoc) => {
const newLoc = {
... oLoc
};
if (newLoc.none) {
return newLoc;
}
const { start, end } = newLoc;
const lRange = {
startOffset: start,
endOffset: end
};
const res = findOriginalRange(lRange, state, originalMap);
if (res.error) {
// It should not happen unless it is minify files, the SourceMap has some order problems
hasError = true;
// console.log('====================================', state.sourcePath, loc);
// console.log(res.errors);
// Util.logError(`Not found original branch. start: ${start}, end: ${end}`);
return newLoc;
}
const oRage = res.originalRange;
newLoc.start = oRage.startOffset;
newLoc.end = oRage.endOffset;
return newLoc;
});
if (hasError) {
return;
}
// add back to original ast
originalState.astInfo.branches.push({
type,
loc: newBranchLoc,
locations: newLocations
});
});
};
const handleOriginalRangesCoverage = (state, originalMap) => {
const { js, coverageList } = state;
// const time_start_mapping = Date.now();
if (js) {
// v8 coverage
coverageList.forEach((block) => {
block.ranges.forEach((range, index) => {
// remove wrap functions for original files
if (range.wrap) {
// console.log(range);
return;
}
const result = findOriginalRange(range, state, originalMap);
if (result.error) {
return;
}
const { originalRange, originalState } = result;
addJsLineCoverage(originalState, originalRange);
// if (originalRange.startOffset === 110 && originalRange.endOffset === 271) {
// console.log('===============================', originalState.sourcePath);
// console.log(result.startMapping, result.endMapping);
// }
});
});
} else {
// support css later
// current css no sourceMap, so never come in
// coverageList.forEach((range) => {
// });
}
};
const unpackSourceMap = async (item, state, options) => {

@@ -883,11 +911,6 @@

originalMap.forEach((originalState) => {
handleFunctionsCoverage(originalState);
handleBranchesCoverage(originalState);
handleLinesCoverage(originalState);
// console.log(originalState.sourcePath, '================================');
// console.log(originalState.astInfo.functions);
// console.log(originalState.source.length);
// console.log(originalState.coverageInfo.functions);
// if (originalState.sourcePath.endsWith('demo.js')) {

@@ -901,11 +924,9 @@ // console.log('=================================', originalState.sourcePath);

// handle ranges after lines ready
handleOriginalRangesCoverage(state, originalMap);
handleOriginalBytesCoverage(state, originalMap);
// collect coverage for original list
state.sourceList = collectOriginalList(item, state, originalMap);
state.sourceList = collectOriginalList(item, state, originalMap, options);
};
// ========================================================================================================
const unpackDistFile = async (item, state, options) => {

@@ -916,3 +937,4 @@

// js self
generateCoverageForDist(item, state);
item.debug = true;
generateCoverageForDist(item, state, options);
} else {

@@ -928,3 +950,3 @@ item.dedupe = true;

// css/js self
generateCoverageForDist(item, state);
generateCoverageForDist(item, state, options);

@@ -931,0 +953,0 @@ }

@@ -46,2 +46,5 @@ module.exports = {

// [V8 only](Boolean) Enable/Disable ignoring uncovered codes with the special comments: /* v8 ignore next/next N/start/stop */
v8Ignore: true,
// [Istanbul only] defaultSummarizer, sourceFinder

@@ -48,0 +51,0 @@

@@ -130,56 +130,2 @@ const fs = require('fs');

const generateCoverageReports = async (dataList, options) => {
// get first and check v8list or istanbul data
const firstData = dataList[0];
const dataType = firstData.type;
// console.log('data type', dataType);
// init reports
options.reportGroup = getReportGroup(options.reports, options.lcov, dataType);
// console.log('reportGroup', options.reportGroup);
// v8list
if (dataType === 'v8') {
// merge v8list first
const v8list = await mergeV8Coverage(dataList, options);
// console.log('after merge', v8list.map((it) => it.url));
const { coverageData, fileSources } = await convertV8List(v8list, options);
return generateV8ListReports(v8list, coverageData, fileSources, options);
}
// istanbul data
const istanbulData = mergeIstanbulCoverage(dataList, options);
const { coverageData, fileSources } = initIstanbulData(istanbulData, options);
return saveIstanbulReports(coverageData, fileSources, options);
};
// ========================================================================================================
const getCoverageDataList = async (cacheDir) => {
const files = fs.readdirSync(cacheDir).filter((f) => f.startsWith('coverage-'));
if (!files.length) {
return;
}
const dataList = [];
for (const item of files) {
const content = await Util.readFile(path.resolve(cacheDir, item));
if (content) {
dataList.push(JSON.parse(content));
}
}
if (dataList.length) {
return dataList;
}
};
// ========================================================================================================
const capitalizeFirstLetter = (string) => {

@@ -274,11 +220,2 @@ return string.charAt(0).toUpperCase() + string.slice(1);

if (type === 'istanbul') {
columns.splice(4, 0, {
id: 'skipped',
name: 'Skipped',
align: 'right',
formatter: nFormatter
});
}
CG({

@@ -290,6 +227,68 @@ columns,

// ========================================================================================================
const getCoverageResults = async (dataList, options) => {
// get first and check v8list or istanbul data
const firstData = dataList[0];
const dataType = firstData.type;
// console.log('data type', dataType);
// init reports
options.reportGroup = getReportGroup(options.reports, options.lcov, dataType);
// console.log('reportGroup', options.reportGroup);
// v8list
if (dataType === 'v8') {
// merge v8list first
const v8list = await mergeV8Coverage(dataList, options);
// console.log('after merge', v8list.map((it) => it.url));
const { coverageData, fileSources } = await convertV8List(v8list, options);
return generateV8ListReports(v8list, coverageData, fileSources, options);
}
// istanbul data
const istanbulData = mergeIstanbulCoverage(dataList, options);
const { coverageData, fileSources } = initIstanbulData(istanbulData, options);
return saveIstanbulReports(coverageData, fileSources, options);
};
const generateCoverageReports = async (dataList, options) => {
const coverageResults = await getCoverageResults(dataList, options);
// [ 'type', 'reportPath', 'name', 'watermarks', 'summary', 'files' ]
// console.log(Object.keys(coverageResults));
showConsoleSummary(coverageResults, options);
return coverageResults;
};
// ========================================================================================================
const getCoverageDataList = async (cacheDir) => {
const files = fs.readdirSync(cacheDir).filter((f) => f.startsWith('coverage-'));
if (!files.length) {
return;
}
const dataList = [];
for (const item of files) {
const content = await Util.readFile(path.resolve(cacheDir, item));
if (content) {
dataList.push(JSON.parse(content));
}
}
if (dataList.length) {
return dataList;
}
};
module.exports = {
getCoverageDataList,
generateCoverageReports,
showConsoleSummary
generateCoverageReports
};

@@ -126,2 +126,5 @@

// [V8 only](Boolean) Enable/Disable ignoring uncovered codes with the special comments: /* v8 ignore next/next N/start/stop */
v8Ignore?: boolean,
// [Istanbul only] defaultSummarizer, sourceFinder

@@ -128,0 +131,0 @@

@@ -7,5 +7,3 @@ const fs = require('fs');

const { initV8ListAndSourcemap } = require('./v8/v8.js');
const {
getCoverageDataList, generateCoverageReports, showConsoleSummary
} = require('./generate.js');
const { getCoverageDataList, generateCoverageReports } = require('./generate.js');

@@ -113,4 +111,2 @@ class CoverageReport {

showConsoleSummary(coverageResults, this.options);
const onEnd = this.options.onEnd;

@@ -117,0 +113,0 @@ if (typeof onEnd === 'function') {

@@ -47,4 +47,3 @@ const istanbulLibReport = require('istanbul-lib-report');

const item = this.summary[id];
// NOTE: skipped
item.uncovered = item.total - item.covered - item.skipped;
item.uncovered = item.total - item.covered;
});

@@ -51,0 +50,0 @@

@@ -106,3 +106,3 @@ const fs = require('fs');

const report = {
const coverageResults = {
type: 'istanbul',

@@ -116,3 +116,3 @@ reportPath,

return report;
return coverageResults;
};

@@ -119,0 +119,0 @@

@@ -65,7 +65,2 @@

// v8 ranges format
// { startOffset: 0, endOffset: 6, count: 0 },
// { startOffset: 0, endOffset: 6, count: 1 },
// { startOffset: 0, endOffset: 297, count: 1 }
// count ranges format

@@ -72,0 +67,0 @@ // { start: 0, end: 6, count: 0 }

@@ -1,33 +0,8 @@

// https://playwright.dev/docs/api/class-coverage
const Util = require('../utils/util.js');
// url, text, ranges: [ {start, end} ]
const getCssSummaryBytes = (item) => {
// both css and js
const getV8SummaryBytes = (item) => {
const source = item.source;
const total = source.length;
let covered = 0;
const bytes = item.data.bytes;
if (bytes) {
bytes.forEach((range) => {
if (range.count > 0) {
covered += range.end - range.start;
}
});
}
// no functions for css
return {
total,
covered
};
};
// url, source, ranges:[{start,end, count}]
const getJsSummaryBytes = (item) => {
const source = item.source;
const total = source.length;
const uncoveredBytes = item.data.bytes.filter((range) => range.count === 0);

@@ -39,2 +14,6 @@

uncoveredBytes.forEach((range) => {
if (range.ignored) {
return;
}
const { start, end } = range;

@@ -67,11 +46,83 @@

const getV8SummaryBytes = (item) => {
if (item.type === 'css') {
return getCssSummaryBytes(item);
}
return getJsSummaryBytes(item);
// calculate uncovered, pct, status
const calculatePctAndStatus = (item, watermarks) => {
Object.keys(item).forEach((k) => {
const indicateData = item[k];
indicateData.uncovered = indicateData.total - indicateData.covered;
let pct = '';
let status = 'unknown';
if (indicateData.total) {
pct = Util.PNF(indicateData.covered, indicateData.total, 2);
status = Util.getStatus(pct, watermarks[k]);
}
indicateData.pct = pct;
indicateData.status = status;
});
};
const getV8Summary = (v8list, watermarks) => {
// get bytes summary
v8list.forEach((entry) => {
entry.summary.bytes = getV8SummaryBytes(entry);
});
// overall summary
const summary = {
bytes: {
total: 0,
covered: 0
},
functions: {
total: 0,
covered: 0
},
branches: {
total: 0,
covered: 0
},
lines: {
total: 0,
covered: 0,
blank: 0,
comment: 0
}
};
v8list.forEach((entry) => {
const entrySummary = entry.summary;
calculatePctAndStatus(entrySummary, watermarks);
// do NOT add debug file
if (entry.debug) {
return;
}
Object.keys(entrySummary).forEach((k) => {
const indicateData = entrySummary[k];
if (!indicateData) {
return;
}
summary[k].total += indicateData.total;
summary[k].covered += indicateData.covered;
if (k === 'lines') {
summary[k].blank += indicateData.blank;
summary[k].comment += indicateData.comment;
}
});
});
// calculate overall summary
calculatePctAndStatus(summary, watermarks);
return summary;
};
module.exports = {
getV8SummaryBytes
getV8Summary
};
const path = require('path');
const Util = require('../utils/util.js');
const { getV8SummaryBytes } = require('./v8-summary.js');
const { getV8Summary } = require('./v8-summary.js');
const { dedupeRanges } = require('../utils/dedupe.js');

@@ -224,23 +224,4 @@ const { getSourcePath } = require('../utils/source-path.js');

// calculate uncovered, pct, status
const calculatePctAndStatus = (item, watermarks) => {
Object.keys(item).forEach((k) => {
const indicateData = item[k];
indicateData.uncovered = indicateData.total - indicateData.covered;
const saveV8Report = async (v8list, options) => {
let pct = '';
let status = 'unknown';
if (indicateData.total) {
pct = Util.PNF(indicateData.covered, indicateData.total, 2);
status = Util.getStatus(pct, watermarks[k]);
}
indicateData.pct = pct;
indicateData.status = status;
});
};
const saveV8Report = async (v8list, options) => {
const defaultWatermarks = {

@@ -254,48 +235,4 @@ bytes: [50, 80],

// init summary
v8list.forEach((entry) => {
entry.summary.bytes = getV8SummaryBytes(entry);
});
const summary = getV8Summary(v8list, watermarks);
// overall summary
const summaryList = v8list.map((entry) => entry.summary);
const summary = {
bytes: {
total: 0,
covered: 0
},
functions: {
total: 0,
covered: 0
},
branches: {
total: 0,
covered: 0
},
lines: {
total: 0,
covered: 0,
blank: 0,
comment: 0
}
};
summaryList.forEach((item) => {
calculatePctAndStatus(item, watermarks);
Object.keys(item).forEach((k) => {
const indicateData = item[k];
if (!indicateData) {
return;
}
summary[k].total += indicateData.total;
summary[k].covered += indicateData.covered;
if (k === 'lines') {
summary[k].blank += indicateData.blank;
summary[k].comment += indicateData.comment;
}
});
});
calculatePctAndStatus(summary, watermarks);
const reportData = {

@@ -343,3 +280,5 @@ name: options.name,

const report = {
const summaryList = v8list.map((entry) => entry.summary);
const coverageResults = {
type: 'v8',

@@ -353,3 +292,3 @@ reportPath,

return report;
return coverageResults;
};

@@ -356,0 +295,0 @@

{
"name": "monocart-coverage-reports",
"version": "2.0.7",
"version": "2.0.8",
"description": "Monocart coverage reports",

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

@@ -22,2 +22,3 @@ # Monocart Coverage Reports

- [How Monocart Works](#how-monocart-works)
* [Ignoring Uncovered Lines](#ignoring-uncovered-lines)
* [Chromium Coverage API](#chromium-coverage-api)

@@ -170,4 +171,5 @@ * [Istanbul Introduction](#istanbul-introduction)

- For source code: enable `sourcemap` and do not compress/minify:
- Webpack: with `source-map` [devtool](https://webpack.js.org/configuration/devtool/) and `development` [mode](https://webpack.js.org/configuration/mode/), example [webpack.config-v8.js](https://github.com/cenfun/monocart-coverage-reports/blob/main/test/webpack.config-v8.js)
- Rollup: [options](https://rollupjs.org/configuration-options/) `sourcemap: true`
- Webpack: build with `source-map` [devtool](https://webpack.js.org/configuration/devtool/) and `development` [mode](https://webpack.js.org/configuration/mode/), example [webpack.config-v8.js](https://github.com/cenfun/monocart-coverage-reports/blob/main/test/webpack.config-v8.js)
- Rollup: build with [options](https://rollupjs.org/configuration-options/) `sourcemap: true`
- Vite: build with [options](https://vitejs.dev/config/build-options.html) `sourcemap: true` and `minify: false`
- Browser (Chromium Only)

@@ -252,7 +254,5 @@ > Collecting coverage data with [Chromium Coverage API](#chromium-coverage-api), see [example](https://github.com/cenfun/monocart-coverage-reports/blob/main/test/test-v8.js)

// v8-to-istanbul: count range as function here.
// Problem: there is no function name if the function is anonymous or expression.
}
} else if (block.functionName) {
// v8-to-istanbul: count range as function here.
// Problem: same as above function.
}

@@ -278,2 +278,24 @@ }

## Ignoring Uncovered Codes
To ignore codes, use the special comment which starts with `v8 ignore `:
- ignoring all until told
```js
/* v8 ignore start */
function uncovered() {
}
/* v8 ignore stop */
```
- ignoring the next line or next N lines
```js
/* v8 ignore next */
const os = platform === 'wind32' ? 'Windows' : 'Other';
const os = platform === 'wind32' ? 'Windows' /* v8 ignore next */ : 'Other';
/* v8 ignore next 3 */
if (platform === 'linux') {
console.info('hello linux');
}
```
## Chromium Coverage API

@@ -280,0 +302,0 @@ - [V8 coverage report](https://v8.dev/blog/javascript-code-coverage) - Native support for JavaScript code coverage to V8. (Chromium only)

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

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