aboutsummaryrefslogtreecommitdiff
path: root/example_reports/tarpaulin-empty.html
diff options
context:
space:
mode:
authorKevin J Hoerr <kjhoerr@protonmail.com>2019-12-11 11:24:28 -0500
committerKevin J Hoerr <kjhoerr@protonmail.com>2019-12-11 11:24:28 -0500
commit0f7e9dddb3fef9f490d03133f8ea860d4b4da349 (patch)
tree69ca08eef6e5e80390cc1766c14497420a098789 /example_reports/tarpaulin-empty.html
parent3ae4f9352ee73a21581735883b4049327dce07bf (diff)
downloadao-coverage-0f7e9dddb3fef9f490d03133f8ea860d4b4da349.tar.gz
ao-coverage-0f7e9dddb3fef9f490d03133f8ea860d4b4da349.tar.bz2
ao-coverage-0f7e9dddb3fef9f490d03133f8ea860d4b4da349.zip
Finish developing unit tests for formats, logger
Diffstat (limited to 'example_reports/tarpaulin-empty.html')
-rw-r--r--example_reports/tarpaulin-empty.html369
1 files changed, 369 insertions, 0 deletions
diff --git a/example_reports/tarpaulin-empty.html b/example_reports/tarpaulin-empty.html
new file mode 100644
index 0000000..7997d8b
--- /dev/null
+++ b/example_reports/tarpaulin-empty.html
@@ -0,0 +1,369 @@
+<!doctype html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <style>
+ html,
+ body {
+ margin: 0;
+ padding: 0;
+ }
+
+ .app {
+ margin: 10px;
+ padding: 0;
+ }
+
+ .files-list {
+ margin: 10px 0 0;
+ width: 100%;
+ border-collapse: collapse;
+ }
+
+ .files-list__head {
+ border: 1px solid #999;
+ }
+
+ .files-list__head>tr>th {
+ padding: 10px;
+ border: 1px solid #999;
+ text-align: left;
+ font-weight: normal;
+ background: #ddd;
+ }
+
+ .files-list__body {}
+
+ .files-list__file {
+ cursor: pointer;
+ }
+
+ .files-list__file:hover {
+ background: #ccf;
+ }
+
+ .files-list__file>td {
+ padding: 10px;
+ border: 1px solid #999;
+ }
+
+ .files-list__file>td:first-child::before {
+ content: '\01F4C4';
+ margin-right: 1em;
+ }
+
+ .files-list__file_low {
+ background: #fcc;
+ }
+
+ .files-list__file_medium {
+ background: #ffc;
+ }
+
+ .files-list__file_high {
+ background: #cfc;
+ }
+
+ .files-list__file_folder>td:first-child::before {
+ content: '\01F4C1';
+ margin-right: 1em;
+ }
+
+ .file-header {
+ border: 1px solid #999;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .file-header__back {
+ margin: 10px;
+ cursor: pointer;
+ flex-shrink: 0;
+ flex-grow: 0;
+ text-decoration: underline;
+ color: #338;
+ }
+
+ .file-header__name {
+ margin: 10px;
+ flex-shrink: 2;
+ flex-grow: 2;
+ }
+
+ .file-header__stat {
+ margin: 10px;
+ flex-shrink: 0;
+ flex-grow: 0;
+ }
+
+ .file-content {
+ margin: 10px 0 0;
+ border: 1px solid #999;
+ padding: 10px;
+ }
+
+ .code-line {
+ margin: 0;
+ padding: 0.3em;
+ height: 1em;
+ }
+
+ .code-line_covered {
+ background: #cfc;
+ }
+
+ .code-line_uncovered {
+ background: #fcc;
+ }
+ </style>
+</head>
+
+<body>
+ <div id="root"></div>
+ <script>var data = { "files": [] };</script>
+ <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
+ <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
+ <script>const e = React.createElement;
+
+ function pathToString(path) {
+ if (path[0] === '/') {
+ return '/' + path.slice(1).join('/');
+ } else {
+ return path.join('/');
+ }
+ }
+
+ function findCommonPath(files) {
+ if (!files || !files.length) {
+ return [];
+ }
+
+ function isPrefix(arr, prefix) {
+ if (arr.length < prefix.length) {
+ return false;
+ }
+ for (let i = prefix.length - 1; i >= 0; --i) {
+ if (arr[i] !== prefix[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ let commonPath = files[0].path.slice(0, -1);
+ while (commonPath.length) {
+ if (files.every(file => isPrefix(file.path, commonPath))) {
+ break;
+ }
+ commonPath.pop();
+ }
+ return commonPath;
+ }
+
+ function findFolders(files) {
+ if (!files || !files.length) {
+ return [];
+ }
+
+ let folders = files.filter(file => file.path.length > 1).map(file => file.path[0]);
+ folders = [...new Set(folders)]; // unique
+ folders.sort();
+
+ folders = folders.map(folder => {
+ let filesInFolder = files
+ .filter(file => file.path[0] === folder)
+ .map(file => ({
+ ...file,
+ path: file.path.slice(1),
+ parent: [...file.parent, file.path[0]],
+ }));
+
+ const children = findFolders(filesInFolder); // recursion
+
+ return {
+ is_folder: true,
+ path: [folder],
+ parent: files[0].parent,
+ children,
+ covered: children.reduce((sum, file) => sum + file.covered, 0),
+ coverable: children.reduce((sum, file) => sum + file.coverable, 0),
+ };
+ });
+
+ return [
+ ...folders,
+ ...files.filter(file => file.path.length === 1),
+ ];
+ }
+
+ class App extends React.Component {
+ constructor(...args) {
+ super(...args);
+
+ this.state = {
+ current: [],
+ };
+ }
+
+ componentDidMount() {
+ this.updateStateFromLocation();
+ window.addEventListener("hashchange", () => this.updateStateFromLocation(), false);
+ }
+
+ updateStateFromLocation() {
+ if (window.location.hash.length > 1) {
+ const current = window.location.hash.substr(1).split('/');
+ this.setState({ current });
+ } else {
+ this.setState({ current: [] });
+ }
+ }
+
+ getCurrentPath() {
+ let file = this.props.root;
+ let path = [file];
+ for (let p of this.state.current) {
+ file = file.children.find(file => file.path[0] === p);
+ if (!file) {
+ return path;
+ }
+ path.push(file);
+ }
+ return path;
+ }
+
+ render() {
+ const path = this.getCurrentPath();
+ const file = path[path.length - 1];
+
+ let w = null;
+ if (file.is_folder) {
+ w = e(FilesList, {
+ folder: file,
+ onSelectFile: this.selectFile.bind(this),
+ onBack: path.length > 1 ? this.back.bind(this) : null,
+ });
+ } else {
+ w = e(DisplayFile, {
+ file,
+ onBack: this.back.bind(this),
+ });
+ }
+
+ return e('div', { className: 'app' }, w);
+ }
+
+ selectFile(file) {
+ this.setState(({ current }) => {
+ return { current: [...current, file.path[0]] };
+ }, () => this.updateHash());
+ }
+
+ back(file) {
+ this.setState(({ current }) => {
+ return { current: current.slice(0, current.length - 1) };
+ }, () => this.updateHash());
+ }
+
+ updateHash() {
+ if (!this.state.current || !this.state.current.length) {
+ window.location = '#';
+ } else {
+ window.location = '#' + this.state.current.join('/');
+ }
+ }
+ }
+
+ function FilesList({ folder, onSelectFile, onBack }) {
+ let files = folder.children;
+ return e('div', { className: 'display-folder' },
+ e(FileHeader, { file: folder, onBack }),
+ e('table', { className: 'files-list' },
+ e('thead', { className: 'files-list__head' },
+ e('tr', null,
+ e('th', null, "Path"),
+ e('th', null, "Coverage")
+ )
+ ),
+ e('tbody', { className: 'files-list__body' },
+ files.map(file => e(File, { file, onClick: onSelectFile }))
+ )
+ )
+ );
+ }
+
+ function File({ file, onClick }) {
+ const coverage = file.coverable ? file.covered / file.coverable * 100 : -1;
+
+ return e('tr', {
+ className: 'files-list__file'
+ + (coverage >= 0 && coverage < 50 ? ' files-list__file_low' : '')
+ + (coverage >= 50 && coverage < 80 ? ' files-list__file_medium' : '')
+ + (coverage >= 80 ? ' files-list__file_high' : '')
+ + (file.is_folder ? ' files-list__file_folder' : ''),
+ onClick: () => onClick(file),
+ },
+ e('td', null, pathToString(file.path)),
+ e('td', null,
+ file.covered + ' / ' + file.coverable +
+ (coverage >= 0 ? ' (' + coverage.toFixed(2) + '%)' : '')
+ )
+ );
+ }
+
+ function DisplayFile({ file, onBack }) {
+ return e('div', { className: 'display-file' },
+ e(FileHeader, { file, onBack }),
+ e(FileContent, { file })
+ );
+ }
+
+ function FileHeader({ file, onBack }) {
+ return e('div', { className: 'file-header' },
+ onBack ? e('a', { className: 'file-header__back', onClick: onBack }, 'Back') : null,
+ e('div', { className: 'file-header__name' }, pathToString([...file.parent, ...file.path])),
+ e('div', { className: 'file-header__stat' },
+ 'Covered: ' + file.covered + ' of ' + file.coverable +
+ (file.coverable ? ' (' + (file.covered / file.coverable * 100).toFixed(2) + '%)' : '')
+ )
+ );
+ }
+
+ function FileContent({ file }) {
+ return e('div', { className: 'file-content' },
+ file.content.split(/\r?\n/).map((line, index) => {
+ const trace = file.traces.find(trace => trace.line === index + 1);
+ const covered = trace && trace.stats.Line;
+ const uncovered = trace && !trace.stats.Line;
+ return e('pre', {
+ className: 'code-line'
+ + (covered ? ' code-line_covered' : '')
+ + (uncovered ? ' code-line_uncovered' : ''),
+ title: trace ? JSON.stringify(trace.stats, null, 2) : null,
+ }, line);
+ })
+ );
+ }
+
+ (function () {
+ const commonPath = findCommonPath(data.files);
+ const files = data.files.map(file => ({ ...file, path: file.path.slice(commonPath.length), parent: commonPath }));
+ const children = findFolders(files);
+
+ const root = {
+ is_folder: true,
+ children,
+ path: commonPath,
+ parent: [],
+ covered: children.reduce((sum, file) => sum + file.covered, 0),
+ coverable: children.reduce((sum, file) => sum + file.coverable, 0),
+ };
+
+ ReactDOM.render(e(App, { root }), document.getElementById('root'));
+ }());
+ </script>
+</body>
+
+</html> \ No newline at end of file