Add node modules and new code for release (#39)
Co-authored-by: tbarnes94 <tbarnes94@users.noreply.github.com>
This commit is contained in:
parent
a10d84bc2e
commit
7ad2aa66bb
7655 changed files with 1763577 additions and 14 deletions
3
node_modules/istanbul-reports/lib/html-spa/.babelrc
generated
vendored
Normal file
3
node_modules/istanbul-reports/lib/html-spa/.babelrc
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"presets": [["@babel/preset-env", { "modules": "commonjs" }], "@babel/preset-react"]
|
||||
}
|
30
node_modules/istanbul-reports/lib/html-spa/assets/bundle.js
generated
vendored
Normal file
30
node_modules/istanbul-reports/lib/html-spa/assets/bundle.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
node_modules/istanbul-reports/lib/html-spa/assets/sort-arrow-sprite.png
generated
vendored
Normal file
BIN
node_modules/istanbul-reports/lib/html-spa/assets/sort-arrow-sprite.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 209 B |
298
node_modules/istanbul-reports/lib/html-spa/assets/spa.css
generated
vendored
Normal file
298
node_modules/istanbul-reports/lib/html-spa/assets/spa.css
generated
vendored
Normal file
|
@ -0,0 +1,298 @@
|
|||
/* Base */
|
||||
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
background-color: #fcfcfc;
|
||||
font: 14px/14px -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
|
||||
Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
border: none;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
*,
|
||||
*:after,
|
||||
*:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0074d9;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quiet {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Colors */
|
||||
|
||||
.low {
|
||||
background: #fce1e5;
|
||||
}
|
||||
|
||||
.low--dark {
|
||||
background: #c21f39;
|
||||
}
|
||||
|
||||
.medium {
|
||||
background: #fff4c2;
|
||||
}
|
||||
|
||||
.medium--dark {
|
||||
background: #f9cd0b;
|
||||
}
|
||||
|
||||
.high {
|
||||
background: rgb(230, 245, 208);
|
||||
}
|
||||
|
||||
.high--dark {
|
||||
background: rgb(77, 146, 33);
|
||||
}
|
||||
|
||||
/* App */
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
|
||||
.layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.layout__section {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.layout__section--fill {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.layout__section + .layout__section {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 640px) {
|
||||
.col3 {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
.hide-mobile {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Toolbar */
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.toolbar__item {
|
||||
margin-right: 40px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Toggle */
|
||||
|
||||
.toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.toggle__label {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.toggle__options {
|
||||
display: inline-block;
|
||||
border: 1px solid #0074d9;
|
||||
border-radius: 4px;
|
||||
color: #0074d9;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.toggle__option {
|
||||
padding: 4px 8px;
|
||||
background: #fcfcfc;
|
||||
}
|
||||
|
||||
.toggle__option + .toggle__option {
|
||||
border-left: 1px solid #0074d9;
|
||||
}
|
||||
|
||||
.toggle__option.is-toggled {
|
||||
color: #fff;
|
||||
background: #0074d9;
|
||||
border-left-color: #fcfcfc;
|
||||
}
|
||||
|
||||
/* Expand */
|
||||
|
||||
.expandbutton {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
margin-right: 0.25em;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Fraction */
|
||||
|
||||
.fraction {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Coverage */
|
||||
|
||||
.coverage-summary {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.coverage-summary tbody tr {
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
.coverage-summary td,
|
||||
.coverage-summary th {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.coverage-summary th {
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.coverage-summary th.abs,
|
||||
.coverage-summary td.pct,
|
||||
.coverage-summary td.abs {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.coverage-summary th.file {
|
||||
min-width: 300px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.coverage-summary td.file {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.coverage-summary td.pct {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.coverage-summary td.abs {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.coverage-summary td.empty {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.coverage-summary .headercell {
|
||||
border-top: 1px solid #eee;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.coverage-summary .headercell:nth-child(4n - 2),
|
||||
.coverage-summary td:nth-child(4n - 2) {
|
||||
border-left: 2px solid #fcfcfc;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.filetab {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
/* Sorter */
|
||||
|
||||
.sorter {
|
||||
display: inline-block;
|
||||
width: 7px;
|
||||
height: 10px;
|
||||
margin-left: 0.5em;
|
||||
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
|
||||
}
|
||||
|
||||
.sorted .sorter {
|
||||
background-position: 0 -20px;
|
||||
}
|
||||
|
||||
.sorted-desc .sorter {
|
||||
background-position: 0 -10px;
|
||||
}
|
||||
|
||||
.sortable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Bar */
|
||||
|
||||
.bar {
|
||||
width: 50px;
|
||||
height: 5px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.bar__data {
|
||||
height: 100%;
|
||||
}
|
175
node_modules/istanbul-reports/lib/html-spa/index.js
generated
vendored
Normal file
175
node_modules/istanbul-reports/lib/html-spa/index.js
generated
vendored
Normal file
|
@ -0,0 +1,175 @@
|
|||
'use strict';
|
||||
/*
|
||||
Copyright 2012-2015, Yahoo Inc.
|
||||
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { ReportBase } = require('istanbul-lib-report');
|
||||
const HtmlReport = require('../html');
|
||||
|
||||
const standardLinkMapper = {
|
||||
getPath(node) {
|
||||
if (typeof node === 'string') {
|
||||
return node;
|
||||
}
|
||||
let filePath = node.getQualifiedName();
|
||||
if (node.isSummary()) {
|
||||
if (filePath !== '') {
|
||||
filePath += '/index.html';
|
||||
} else {
|
||||
filePath = 'index.html';
|
||||
}
|
||||
} else {
|
||||
filePath += '.html';
|
||||
}
|
||||
return filePath;
|
||||
},
|
||||
|
||||
relativePath(source, target) {
|
||||
const targetPath = this.getPath(target);
|
||||
const sourcePath = path.dirname(this.getPath(source));
|
||||
return path.relative(sourcePath, targetPath);
|
||||
},
|
||||
|
||||
assetPath(node, name) {
|
||||
return this.relativePath(this.getPath(node), name);
|
||||
}
|
||||
};
|
||||
|
||||
class HtmlSpaReport extends ReportBase {
|
||||
constructor(opts = {}) {
|
||||
super({
|
||||
// force the summarizer to nested for html-spa
|
||||
summarizer: 'nested'
|
||||
});
|
||||
|
||||
this.verbose = opts.verbose || false;
|
||||
this.linkMapper = opts.linkMapper || standardLinkMapper;
|
||||
this.subdir = opts.subdir || '';
|
||||
this.date = Date();
|
||||
this.skipEmpty = opts.skipEmpty;
|
||||
this.htmlReport = new HtmlReport(opts);
|
||||
this.htmlReport.getBreadcrumbHtml = function() {
|
||||
return '<a href="javascript:history.back()">Back</a>';
|
||||
};
|
||||
|
||||
this.metricsToShow = opts.metricsToShow || [
|
||||
'lines',
|
||||
'branches',
|
||||
'functions'
|
||||
];
|
||||
}
|
||||
|
||||
getWriter(context) {
|
||||
if (!this.subdir) {
|
||||
return context.writer;
|
||||
}
|
||||
return context.writer.writerForDir(this.subdir);
|
||||
}
|
||||
|
||||
onStart(root, context) {
|
||||
this.htmlReport.onStart(root, context);
|
||||
|
||||
const writer = this.getWriter(context);
|
||||
const srcDir = path.resolve(__dirname, './assets');
|
||||
fs.readdirSync(srcDir).forEach(f => {
|
||||
const resolvedSource = path.resolve(srcDir, f);
|
||||
const resolvedDestination = '.';
|
||||
const stat = fs.statSync(resolvedSource);
|
||||
let dest;
|
||||
|
||||
if (stat.isFile()) {
|
||||
dest = resolvedDestination + '/' + f;
|
||||
if (this.verbose) {
|
||||
console.log('Write asset: ' + dest);
|
||||
}
|
||||
writer.copyFile(resolvedSource, dest);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onDetail(node, context) {
|
||||
this.htmlReport.onDetail(node, context);
|
||||
}
|
||||
|
||||
getMetric(metric, type, context) {
|
||||
const isEmpty = metric.total === 0;
|
||||
return {
|
||||
total: metric.total,
|
||||
covered: metric.covered,
|
||||
skipped: metric.skipped,
|
||||
pct: isEmpty ? 0 : metric.pct,
|
||||
classForPercent: isEmpty
|
||||
? 'empty'
|
||||
: context.classForPercent(type, metric.pct)
|
||||
};
|
||||
}
|
||||
|
||||
toDataStructure(node, context) {
|
||||
const coverageSummary = node.getCoverageSummary();
|
||||
const metrics = {
|
||||
statements: this.getMetric(
|
||||
coverageSummary.statements,
|
||||
'statements',
|
||||
context
|
||||
),
|
||||
branches: this.getMetric(
|
||||
coverageSummary.branches,
|
||||
'branches',
|
||||
context
|
||||
),
|
||||
functions: this.getMetric(
|
||||
coverageSummary.functions,
|
||||
'functions',
|
||||
context
|
||||
),
|
||||
lines: this.getMetric(coverageSummary.lines, 'lines', context)
|
||||
};
|
||||
|
||||
return {
|
||||
file: node.getRelativeName(),
|
||||
isEmpty: coverageSummary.isEmpty(),
|
||||
metrics,
|
||||
children:
|
||||
node.isSummary() &&
|
||||
node
|
||||
.getChildren()
|
||||
.map(child => this.toDataStructure(child, context))
|
||||
};
|
||||
}
|
||||
|
||||
onEnd(rootNode, context) {
|
||||
const data = this.toDataStructure(rootNode, context);
|
||||
|
||||
const cw = this.getWriter(context).writeFile(
|
||||
this.linkMapper.getPath(rootNode)
|
||||
);
|
||||
|
||||
cw.write(
|
||||
`<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="spa.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" class="app"></div>
|
||||
<script>
|
||||
window.data = ${JSON.stringify(data)};
|
||||
window.generatedDatetime = ${JSON.stringify(
|
||||
String(Date())
|
||||
)};
|
||||
window.metricsToShow = ${JSON.stringify(
|
||||
this.metricsToShow
|
||||
)};
|
||||
</script>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>`
|
||||
);
|
||||
cw.close();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HtmlSpaReport;
|
31
node_modules/istanbul-reports/lib/html-spa/src/fileBreadcrumbs.js
generated
vendored
Normal file
31
node_modules/istanbul-reports/lib/html-spa/src/fileBreadcrumbs.js
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
const React = require('react');
|
||||
|
||||
module.exports = function FileBreadcrumbs({ fileFilter = '', setFileFilter }) {
|
||||
const parts = fileFilter.split('/');
|
||||
const breadcrumbs = [
|
||||
{
|
||||
path: '',
|
||||
name: 'all files'
|
||||
},
|
||||
...parts.map((part, i) => ({
|
||||
path: parts.slice(0, i + 1).join('/'),
|
||||
name: part
|
||||
}))
|
||||
];
|
||||
|
||||
return breadcrumbs.map(({ path, name }) =>
|
||||
path === fileFilter ? (
|
||||
name
|
||||
) : (
|
||||
<>
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
onClick={() => setFileFilter(path)}
|
||||
>
|
||||
{name}
|
||||
</a>
|
||||
/
|
||||
</>
|
||||
)
|
||||
);
|
||||
};
|
50
node_modules/istanbul-reports/lib/html-spa/src/filterToggle.js
generated
vendored
Normal file
50
node_modules/istanbul-reports/lib/html-spa/src/filterToggle.js
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
const React = require('react');
|
||||
|
||||
function ToggleOption({ children, filter, activeFilters, setFilters }) {
|
||||
return (
|
||||
<button
|
||||
className={
|
||||
'toggle__option ' + (activeFilters[filter] ? 'is-toggled' : '')
|
||||
}
|
||||
onClick={() =>
|
||||
setFilters({
|
||||
...activeFilters,
|
||||
[filter]: !activeFilters[filter]
|
||||
})
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = function FilterToggle({ activeFilters, setFilters }) {
|
||||
return (
|
||||
<div className="toggle">
|
||||
<div className="toggle__label">Filter:</div>
|
||||
<div className="toggle__options">
|
||||
<ToggleOption
|
||||
filter="low"
|
||||
activeFilters={activeFilters}
|
||||
setFilters={setFilters}
|
||||
>
|
||||
Low
|
||||
</ToggleOption>
|
||||
<ToggleOption
|
||||
filter="medium"
|
||||
activeFilters={activeFilters}
|
||||
setFilters={setFilters}
|
||||
>
|
||||
Medium
|
||||
</ToggleOption>
|
||||
<ToggleOption
|
||||
filter="high"
|
||||
activeFilters={activeFilters}
|
||||
setFilters={setFilters}
|
||||
>
|
||||
High
|
||||
</ToggleOption>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
25
node_modules/istanbul-reports/lib/html-spa/src/flattenToggle.js
generated
vendored
Normal file
25
node_modules/istanbul-reports/lib/html-spa/src/flattenToggle.js
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
const React = require('react');
|
||||
|
||||
module.exports = function FlattenButton({ setIsFlat, isFlat }) {
|
||||
return (
|
||||
<div className="toggle">
|
||||
<div className="toggle__label">Files:</div>
|
||||
<div className="toggle__options">
|
||||
<button
|
||||
onClick={() => setIsFlat(!isFlat)}
|
||||
className={
|
||||
'toggle__option ' + (!isFlat ? 'is-toggled' : '')
|
||||
}
|
||||
>
|
||||
Tree
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsFlat(!isFlat)}
|
||||
className={'toggle__option ' + (isFlat ? 'is-toggled' : '')}
|
||||
>
|
||||
Flat
|
||||
</button>
|
||||
</div>{' '}
|
||||
</div>
|
||||
);
|
||||
};
|
155
node_modules/istanbul-reports/lib/html-spa/src/getChildData.js
generated
vendored
Normal file
155
node_modules/istanbul-reports/lib/html-spa/src/getChildData.js
generated
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
function addPath(node, parentPath) {
|
||||
if (!parentPath) {
|
||||
return node;
|
||||
}
|
||||
return { ...node, file: parentPath + '/' + node.file };
|
||||
}
|
||||
|
||||
function flatten(nodes, parentPath) {
|
||||
let children = [];
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const child = nodes[i];
|
||||
if (child.children) {
|
||||
children = [
|
||||
...children,
|
||||
...flatten(
|
||||
child.children,
|
||||
(parentPath ? parentPath + '/' : '') + child.file
|
||||
)
|
||||
];
|
||||
} else {
|
||||
children.push(addPath(child, parentPath));
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
function filterByFile(nodes, fileFilter, parentPath) {
|
||||
let children = [];
|
||||
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const child = nodes[i];
|
||||
const childFullPath = (parentPath ? parentPath + '/' : '') + child.file;
|
||||
|
||||
const isChildUnderFilter =
|
||||
fileFilter === childFullPath ||
|
||||
fileFilter.indexOf(childFullPath + '/') === 0;
|
||||
const isChildAboveFilter =
|
||||
childFullPath.indexOf(fileFilter + '/') === 0;
|
||||
|
||||
if (isChildUnderFilter) {
|
||||
// flatten and continue looking underneath
|
||||
children = [
|
||||
...children,
|
||||
...filterByFile(child.children, fileFilter, childFullPath)
|
||||
];
|
||||
} else if (isChildAboveFilter) {
|
||||
// remove the parent path and add everything underneath
|
||||
const charsToRemoveFromFile =
|
||||
fileFilter.length - (parentPath ? parentPath.length : 0);
|
||||
let childFilename = child.file.slice(charsToRemoveFromFile);
|
||||
if (childFilename[0] === '/') {
|
||||
childFilename = childFilename.slice(1);
|
||||
}
|
||||
children.push({
|
||||
...child,
|
||||
file: childFilename
|
||||
});
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
function sort(childData, activeSort) {
|
||||
const top = activeSort.order === 'asc' ? 1 : -1;
|
||||
const bottom = activeSort.order === 'asc' ? -1 : 1;
|
||||
childData.sort((a, b) => {
|
||||
let valueA;
|
||||
let valueB;
|
||||
if (activeSort.sortKey === 'file') {
|
||||
valueA = a.file;
|
||||
valueB = b.file;
|
||||
} else {
|
||||
const [metricType, valueType] = activeSort.sortKey.split('.');
|
||||
valueA = a.metrics[metricType][valueType];
|
||||
valueB = b.metrics[metricType][valueType];
|
||||
}
|
||||
|
||||
if (valueA === valueB) {
|
||||
return 0;
|
||||
}
|
||||
return valueA < valueB ? top : bottom;
|
||||
});
|
||||
|
||||
for (let i = 0; i < childData.length; i++) {
|
||||
const child = childData[i];
|
||||
if (child.children) {
|
||||
childData[i] = {
|
||||
...child,
|
||||
children: sort(child.children, activeSort)
|
||||
};
|
||||
}
|
||||
}
|
||||
return childData;
|
||||
}
|
||||
|
||||
function filter(nodes, metricsMap, activeFilters) {
|
||||
const children = [];
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let child = nodes[i];
|
||||
if (child.children) {
|
||||
const newSubChildren = filter(
|
||||
child.children,
|
||||
metricsMap,
|
||||
activeFilters
|
||||
);
|
||||
if (newSubChildren.length) {
|
||||
child = { ...child, children: newSubChildren };
|
||||
children.push(child);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
(metricsMap.statements &&
|
||||
activeFilters[child.metrics.statements.classForPercent]) ||
|
||||
(metricsMap.branches &&
|
||||
activeFilters[child.metrics.branches.classForPercent]) ||
|
||||
(metricsMap.functions &&
|
||||
activeFilters[child.metrics.functions.classForPercent]) ||
|
||||
(metricsMap.lines &&
|
||||
activeFilters[child.metrics.lines.classForPercent])
|
||||
) {
|
||||
children.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
module.exports = function getChildData(
|
||||
sourceData,
|
||||
metricsToShow,
|
||||
activeSort,
|
||||
isFlat,
|
||||
activeFilters,
|
||||
fileFilter
|
||||
) {
|
||||
let childData = sourceData.children;
|
||||
|
||||
if (isFlat) {
|
||||
childData = flatten(childData.slice(0));
|
||||
}
|
||||
|
||||
if (fileFilter) {
|
||||
childData = filterByFile(childData, fileFilter);
|
||||
}
|
||||
|
||||
if (activeFilters.low) {
|
||||
activeFilters = { ...activeFilters, empty: true };
|
||||
}
|
||||
childData = filter(childData, metricsToShow, activeFilters);
|
||||
|
||||
if (activeSort) {
|
||||
childData = sort(childData, activeSort);
|
||||
}
|
||||
return childData;
|
||||
};
|
156
node_modules/istanbul-reports/lib/html-spa/src/index.js
generated
vendored
Normal file
156
node_modules/istanbul-reports/lib/html-spa/src/index.js
generated
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
// The index file for the spa running on the summary page
|
||||
const React = require('react');
|
||||
const ReactDOM = require('react-dom');
|
||||
const SummaryTableHeader = require('./summaryTableHeader');
|
||||
const SummaryTableLine = require('./summaryTableLine');
|
||||
const SummaryHeader = require('./summaryHeader');
|
||||
const getChildData = require('./getChildData');
|
||||
const FlattenToggle = require('./flattenToggle');
|
||||
const FilterToggle = require('./filterToggle');
|
||||
const FileBreadcrumbs = require('./fileBreadcrumbs');
|
||||
const { setLocation, decodeLocation } = require('./routing');
|
||||
|
||||
const { useState, useMemo, useEffect } = React;
|
||||
|
||||
const sourceData = window.data;
|
||||
const metricsToShow = {};
|
||||
for (let i = 0; i < window.metricsToShow.length; i++) {
|
||||
metricsToShow[window.metricsToShow[i]] = true;
|
||||
}
|
||||
|
||||
let firstMount = true;
|
||||
|
||||
function App() {
|
||||
const routingDefaults = decodeLocation();
|
||||
|
||||
const [activeSort, setSort] = useState(
|
||||
(routingDefaults && routingDefaults.activeSort) || {
|
||||
sortKey: 'file',
|
||||
order: 'desc'
|
||||
}
|
||||
);
|
||||
const [isFlat, setIsFlat] = useState(
|
||||
(routingDefaults && routingDefaults.isFlat) || false
|
||||
);
|
||||
const [activeFilters, setFilters] = useState(
|
||||
(routingDefaults && routingDefaults.activeFilters) || {
|
||||
low: true,
|
||||
medium: true,
|
||||
high: true
|
||||
}
|
||||
);
|
||||
const [expandedLines, setExpandedLines] = useState(
|
||||
(routingDefaults && routingDefaults.expandedLines) || []
|
||||
);
|
||||
const [fileFilter, setFileFilter] = useState(
|
||||
(routingDefaults && routingDefaults.fileFilter) || ''
|
||||
);
|
||||
const childData = useMemo(
|
||||
() =>
|
||||
getChildData(
|
||||
sourceData,
|
||||
metricsToShow,
|
||||
activeSort,
|
||||
isFlat,
|
||||
activeFilters,
|
||||
fileFilter
|
||||
),
|
||||
[activeSort, isFlat, activeFilters, fileFilter]
|
||||
);
|
||||
const overallMetrics = sourceData.metrics;
|
||||
|
||||
useEffect(() => {
|
||||
setLocation(
|
||||
firstMount,
|
||||
activeSort,
|
||||
isFlat,
|
||||
activeFilters,
|
||||
fileFilter,
|
||||
expandedLines
|
||||
);
|
||||
firstMount = false;
|
||||
}, [activeSort, isFlat, activeFilters, fileFilter, expandedLines]);
|
||||
|
||||
useEffect(() => {
|
||||
window.onpopstate = () => {
|
||||
const routingState = decodeLocation();
|
||||
if (routingState) {
|
||||
// make sure all the state is set before rendering to avoid url updates
|
||||
// alternative is to merge all the states into one so it can be set in one go
|
||||
// https://github.com/facebook/react/issues/14259
|
||||
ReactDOM.unstable_batchedUpdates(() => {
|
||||
setFilters(routingState.activeFilters);
|
||||
setSort(routingState.activeSort);
|
||||
setIsFlat(routingState.isFlat);
|
||||
setExpandedLines(routingState.expandedLines);
|
||||
setFileFilter(routingState.fileFilter);
|
||||
});
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="layout">
|
||||
<div className="layout__section">
|
||||
<SummaryHeader
|
||||
metrics={overallMetrics}
|
||||
metricsToShow={metricsToShow}
|
||||
/>
|
||||
</div>
|
||||
<div className="layout__section">
|
||||
<div className="toolbar">
|
||||
<div className="toolbar__item">
|
||||
<FlattenToggle setIsFlat={setIsFlat} isFlat={isFlat} />
|
||||
</div>
|
||||
<div className="toolbar__item">
|
||||
<FilterToggle
|
||||
activeFilters={activeFilters}
|
||||
setFilters={setFilters}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="layout__section">
|
||||
<h1>
|
||||
<FileBreadcrumbs
|
||||
fileFilter={fileFilter}
|
||||
setFileFilter={setFileFilter}
|
||||
/>
|
||||
</h1>
|
||||
</div>
|
||||
<div className="layout__section layout__section--fill">
|
||||
<table className="coverage-summary">
|
||||
<SummaryTableHeader
|
||||
onSort={newSort => {
|
||||
setSort(newSort);
|
||||
}}
|
||||
activeSort={activeSort}
|
||||
metricsToShow={metricsToShow}
|
||||
/>
|
||||
<tbody>
|
||||
{childData.map(child => (
|
||||
<SummaryTableLine
|
||||
{...child}
|
||||
key={child.file}
|
||||
metricsToShow={metricsToShow}
|
||||
expandedLines={expandedLines}
|
||||
setExpandedLines={setExpandedLines}
|
||||
fileFilter={fileFilter}
|
||||
setFileFilter={setFileFilter}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="layout__section center small quiet">
|
||||
Code coverage generated by{' '}
|
||||
<a href="https://istanbul.js.org/" target="_blank">
|
||||
istanbul
|
||||
</a>{' '}
|
||||
at {window.generatedDatetime}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('app'));
|
52
node_modules/istanbul-reports/lib/html-spa/src/routing.js
generated
vendored
Normal file
52
node_modules/istanbul-reports/lib/html-spa/src/routing.js
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
exports.setLocation = function setLocation(
|
||||
isReplace,
|
||||
activeSort,
|
||||
isFlat,
|
||||
activeFilters,
|
||||
fileFilter,
|
||||
expandedLines
|
||||
) {
|
||||
const params = [
|
||||
activeSort.sortKey,
|
||||
activeSort.order,
|
||||
isFlat,
|
||||
activeFilters.low,
|
||||
activeFilters.medium,
|
||||
activeFilters.high,
|
||||
encodeURIComponent(fileFilter),
|
||||
expandedLines.map(encodeURIComponent).join(',')
|
||||
];
|
||||
const newUrl = `#${params.join('/')}`;
|
||||
|
||||
if (newUrl === location.hash) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.history[isReplace ? 'replaceState' : 'pushState'](null, '', newUrl);
|
||||
};
|
||||
|
||||
exports.decodeLocation = function decodeLocation() {
|
||||
const items = location.hash.substr(1).split('/');
|
||||
if (items.length !== 8) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return {
|
||||
activeSort: {
|
||||
sortKey: items[0],
|
||||
order: items[1]
|
||||
},
|
||||
isFlat: JSON.parse(items[2]),
|
||||
activeFilters: {
|
||||
low: JSON.parse(items[3]),
|
||||
medium: JSON.parse(items[4]),
|
||||
high: JSON.parse(items[5])
|
||||
},
|
||||
fileFilter: decodeURIComponent(items[6]),
|
||||
expandedLines: items[7].split(',').map(decodeURIComponent)
|
||||
};
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
63
node_modules/istanbul-reports/lib/html-spa/src/summaryHeader.js
generated
vendored
Normal file
63
node_modules/istanbul-reports/lib/html-spa/src/summaryHeader.js
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
const React = require('react');
|
||||
|
||||
function Ignores({ metrics, metricsToShow }) {
|
||||
const metricKeys = Object.keys(metricsToShow);
|
||||
const result = [];
|
||||
|
||||
for (let i = 0; i < metricKeys.length; i++) {
|
||||
const metricKey = metricKeys[i];
|
||||
if (metricsToShow[metricKey]) {
|
||||
const skipped = metrics[metricKey].skipped;
|
||||
if (skipped > 0) {
|
||||
result.push(
|
||||
`${skipped} ${metricKey}${
|
||||
skipped === 1 ? '' : metricKey === 'branch' ? 'es' : 's'
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="toolbar__item">
|
||||
<span className="strong">{result.join(', ')}</span>
|
||||
<span className="quiet">Ignored</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StatusMetric({ data, name }) {
|
||||
return (
|
||||
<div className="toolbar__item">
|
||||
<span className="strong">{data.pct}%</span>{' '}
|
||||
<span className="quiet">{name}</span>{' '}
|
||||
<span className={'fraction ' + data.classForPercent}>
|
||||
{data.covered}/{data.total}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = function SummaryHeader({ metrics, metricsToShow }) {
|
||||
return (
|
||||
<div className="toolbar">
|
||||
{metricsToShow.statements && (
|
||||
<StatusMetric data={metrics.statements} name="Statements" />
|
||||
)}
|
||||
{metricsToShow.branches && (
|
||||
<StatusMetric data={metrics.branches} name="Branches" />
|
||||
)}
|
||||
{metricsToShow.functions && (
|
||||
<StatusMetric data={metrics.functions} name="Functions" />
|
||||
)}
|
||||
{metricsToShow.lines && (
|
||||
<StatusMetric data={metrics.lines} name="Lines" />
|
||||
)}
|
||||
<Ignores metrics={metrics} metricsToShow={metricsToShow} />
|
||||
</div>
|
||||
);
|
||||
};
|
124
node_modules/istanbul-reports/lib/html-spa/src/summaryTableHeader.js
generated
vendored
Normal file
124
node_modules/istanbul-reports/lib/html-spa/src/summaryTableHeader.js
generated
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
const React = require('react');
|
||||
|
||||
function getSortDetails(sortKey, activeSort) {
|
||||
let newSort = { sortKey, order: 'desc' };
|
||||
let sortClass = '';
|
||||
if (activeSort && activeSort.sortKey === sortKey) {
|
||||
sortClass = 'sorted';
|
||||
if (activeSort.order === 'desc') {
|
||||
sortClass += '-desc';
|
||||
newSort.order = 'asc';
|
||||
} else {
|
||||
if (sortKey !== 'file') {
|
||||
newSort = { sortKey: 'file', order: 'desc' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
newSort,
|
||||
sortClass
|
||||
};
|
||||
}
|
||||
|
||||
function SummaryTableHeaderCell({ name, onSort, sortKey, activeSort }) {
|
||||
const { newSort, sortClass } = getSortDetails(sortKey, activeSort);
|
||||
return (
|
||||
<th
|
||||
className={'sortable headercell ' + sortClass}
|
||||
onClick={() => onSort(newSort)}
|
||||
>
|
||||
{name}
|
||||
<span className="sorter" />
|
||||
</th>
|
||||
);
|
||||
}
|
||||
|
||||
function FileHeaderCell({ onSort, activeSort }) {
|
||||
const { newSort, sortClass } = getSortDetails('file', activeSort);
|
||||
|
||||
return (
|
||||
<th
|
||||
className={'sortable file ' + sortClass}
|
||||
onClick={() => onSort(newSort)}
|
||||
>
|
||||
File
|
||||
<span className="sorter" />
|
||||
</th>
|
||||
);
|
||||
}
|
||||
|
||||
function SubHeadings({ sortKeyPrefix, onSort, activeSort }) {
|
||||
return (
|
||||
<>
|
||||
<SummaryTableHeaderCell
|
||||
name="%"
|
||||
onSort={onSort}
|
||||
sortKey={sortKeyPrefix + '.pct'}
|
||||
activeSort={activeSort}
|
||||
/>
|
||||
<th className="headercell"></th>
|
||||
<SummaryTableHeaderCell
|
||||
name="Covered"
|
||||
onSort={onSort}
|
||||
sortKey={sortKeyPrefix + '.covered'}
|
||||
activeSort={activeSort}
|
||||
/>
|
||||
<SummaryTableHeaderCell
|
||||
name="Total"
|
||||
onSort={onSort}
|
||||
sortKey={sortKeyPrefix + '.total'}
|
||||
activeSort={activeSort}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = function SummaryTableHeader({
|
||||
onSort,
|
||||
activeSort,
|
||||
metricsToShow
|
||||
}) {
|
||||
return (
|
||||
<thead>
|
||||
<tr className="topheading">
|
||||
<th></th>
|
||||
{metricsToShow.statements && <th colSpan={4}>Statements</th>}
|
||||
{metricsToShow.branches && <th colSpan={4}>Branches</th>}
|
||||
{metricsToShow.functions && <th colSpan={4}>Functions</th>}
|
||||
{metricsToShow.lines && <th colSpan={4}>Lines</th>}
|
||||
</tr>
|
||||
<tr className="subheading">
|
||||
<FileHeaderCell onSort={onSort} activeSort={activeSort} />
|
||||
{metricsToShow.statements && (
|
||||
<SubHeadings
|
||||
sortKeyPrefix="statements"
|
||||
onSort={onSort}
|
||||
activeSort={activeSort}
|
||||
/>
|
||||
)}
|
||||
{metricsToShow.branches && (
|
||||
<SubHeadings
|
||||
sortKeyPrefix="branches"
|
||||
onSort={onSort}
|
||||
activeSort={activeSort}
|
||||
/>
|
||||
)}
|
||||
{metricsToShow.functions && (
|
||||
<SubHeadings
|
||||
sortKeyPrefix="functions"
|
||||
onSort={onSort}
|
||||
activeSort={activeSort}
|
||||
/>
|
||||
)}
|
||||
{metricsToShow.lines && (
|
||||
<SubHeadings
|
||||
sortKeyPrefix="lines"
|
||||
onSort={onSort}
|
||||
activeSort={activeSort}
|
||||
/>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
);
|
||||
};
|
158
node_modules/istanbul-reports/lib/html-spa/src/summaryTableLine.js
generated
vendored
Normal file
158
node_modules/istanbul-reports/lib/html-spa/src/summaryTableLine.js
generated
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
const React = require('react');
|
||||
|
||||
function MetricCells({ metrics }) {
|
||||
const { classForPercent, pct, covered, total } = metrics;
|
||||
|
||||
return (
|
||||
<>
|
||||
<td className={'pct ' + classForPercent}>{Math.round(pct)}% </td>
|
||||
<td className={classForPercent}>
|
||||
<div className="bar">
|
||||
<div
|
||||
className={`bar__data ${classForPercent} ${classForPercent}--dark`}
|
||||
style={{ width: pct + '%' }}
|
||||
></div>
|
||||
</div>
|
||||
</td>
|
||||
<td className={'abs ' + classForPercent}>{covered}</td>
|
||||
<td className={'abs ' + classForPercent}>{total}</td>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FileCell({
|
||||
file,
|
||||
prefix,
|
||||
expandedLines,
|
||||
setExpandedLines,
|
||||
hasChildren,
|
||||
setFileFilter
|
||||
}) {
|
||||
if (hasChildren) {
|
||||
const expandedIndex = expandedLines.indexOf(prefix + file);
|
||||
const isExpanded = expandedIndex >= 0;
|
||||
const newExpandedLines = isExpanded
|
||||
? [
|
||||
...expandedLines.slice(0, expandedIndex),
|
||||
...expandedLines.slice(expandedIndex + 1)
|
||||
]
|
||||
: [...expandedLines, prefix + file];
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setExpandedLines(newExpandedLines)}
|
||||
className="expandbutton"
|
||||
>
|
||||
{isExpanded ? String.fromCharCode(0x2013) : '+'}
|
||||
</button>
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
onClick={() => setFileFilter(prefix + file)}
|
||||
>
|
||||
{file}
|
||||
</a>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return <a href={`./${prefix}${file}.html`}>{file}</a>;
|
||||
}
|
||||
}
|
||||
|
||||
function getWorstMetricClassForPercent(metricsToShow, metrics) {
|
||||
let classForPercent = 'none';
|
||||
for (const metricToShow in metricsToShow) {
|
||||
if (metricsToShow[metricToShow]) {
|
||||
const metricClassForPercent = metrics[metricToShow].classForPercent;
|
||||
|
||||
// ignore none metrics so they don't change whats shown
|
||||
if (metricClassForPercent === 'none') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the metric low or lower than whats currently being used, replace it
|
||||
if (
|
||||
metricClassForPercent == 'low' ||
|
||||
(metricClassForPercent === 'medium' &&
|
||||
classForPercent !== 'low') ||
|
||||
(metricClassForPercent === 'high' &&
|
||||
classForPercent !== 'low' &&
|
||||
classForPercent !== 'medium')
|
||||
) {
|
||||
classForPercent = metricClassForPercent;
|
||||
}
|
||||
}
|
||||
}
|
||||
return classForPercent;
|
||||
}
|
||||
|
||||
module.exports = function SummaryTableLine({
|
||||
prefix,
|
||||
metrics,
|
||||
file,
|
||||
children,
|
||||
tabSize,
|
||||
metricsToShow,
|
||||
expandedLines,
|
||||
setExpandedLines,
|
||||
fileFilter,
|
||||
setFileFilter
|
||||
}) {
|
||||
tabSize = tabSize || 0;
|
||||
if (children && tabSize > 0) {
|
||||
tabSize--;
|
||||
}
|
||||
prefix = (fileFilter ? fileFilter + '/' : '') + (prefix || '');
|
||||
|
||||
return (
|
||||
<>
|
||||
<tr>
|
||||
<td
|
||||
className={
|
||||
'file ' +
|
||||
getWorstMetricClassForPercent(metricsToShow, metrics)
|
||||
}
|
||||
>
|
||||
{/* eslint-disable-line prefer-spread */ Array.apply(null, {
|
||||
length: tabSize
|
||||
}).map((nothing, index) => (
|
||||
<span className="filetab" key={index} />
|
||||
))}
|
||||
<FileCell
|
||||
file={file}
|
||||
prefix={prefix}
|
||||
expandedLines={expandedLines}
|
||||
setExpandedLines={setExpandedLines}
|
||||
hasChildren={Boolean(children)}
|
||||
setFileFilter={setFileFilter}
|
||||
/>
|
||||
</td>
|
||||
{metricsToShow.statements && (
|
||||
<MetricCells metrics={metrics.statements} />
|
||||
)}
|
||||
{metricsToShow.branches && (
|
||||
<MetricCells metrics={metrics.branches} />
|
||||
)}
|
||||
{metricsToShow.functions && (
|
||||
<MetricCells metrics={metrics.functions} />
|
||||
)}
|
||||
{metricsToShow.lines && <MetricCells metrics={metrics.lines} />}
|
||||
</tr>
|
||||
{children &&
|
||||
expandedLines.indexOf(prefix + file) >= 0 &&
|
||||
children.map(child => (
|
||||
<SummaryTableLine
|
||||
{...child}
|
||||
tabSize={tabSize + 2}
|
||||
key={child.file}
|
||||
prefix={prefix + file + '/'}
|
||||
metricsToShow={metricsToShow}
|
||||
expandedLines={expandedLines}
|
||||
setExpandedLines={setExpandedLines}
|
||||
setFileFilter={setFileFilter}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
22
node_modules/istanbul-reports/lib/html-spa/webpack.config.js
generated
vendored
Normal file
22
node_modules/istanbul-reports/lib/html-spa/webpack.config.js
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: path.resolve(__dirname, 'src/index.js'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'assets'),
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue