1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
/*
* JaCoCo Report Viewer, a web-based coverage report viewer
* Copyright (C) 2018 Pacien TRAN-GIRARD
* Adam NAILI
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import React, { Component } from 'react';
export class CoverageListing extends Component {
constructor(props) {
super(props);
this.state = {
listingContent: null,
coverageMap: null
};
}
componentDidMount() {
this._updateState();
}
componentDidUpdate(prevProps) {
if (this.props.fileName === prevProps.fileName &&
this.props.sourceSet === prevProps.sourceSet &&
this.props.coverage === prevProps.coverage) return;
this._updateState();
}
_updateState() {
if (!this.props.sourceSet || !(this.props.fileName in this.props.sourceSet)) {
this.setState({ listingContent: null });
return;
}
this._updateListingContent();
this._updateCoverageMap();
}
_updateCoverageMap() {
const coverageMap = this.props.coverage.reduce(function(map, line) {
map[parseInt(line.$.nr)] = line.$;
return map;
}, {});
this.setState({ coverageMap: coverageMap });
}
_updateListingContent() {
this.props.sourceSet[this.props.fileName]
.async('text')
.then(content => this.setState({ listingContent: content }));
}
_lineCoverageString(coverage) {
const instructionCount = parseInt(coverage.ci) + parseInt(coverage.mi);
const branchCount = parseInt(coverage.cb) + parseInt(coverage.mb);
return coverage.ci + '/' + instructionCount + ' instructions covered, ' +
coverage.cb + '/' + branchCount + ' branches covered';
}
_renderNone() {
return (<div>No source file provided.</div>);
}
_nonEmptyString(str) {
return str ? str : ' '; // workaround for empty <pre> collapsing
}
_renderLine(lineContent, lineNumber) {
if (!(lineNumber in this.state.coverageMap))
return (<li key={lineNumber}><pre>{lineContent}</pre></li>);
const coverage = this.state.coverageMap[lineNumber];
const wellCovered = parseInt(coverage.mi) === 0 && parseInt(coverage.mb) === 0;
return (
<li key={lineNumber} well-covered={wellCovered.toString()} title={this._lineCoverageString(coverage)}>
<pre>{lineContent}</pre>
</li>
);
}
_renderListing() {
const lines = this.state.listingContent
.split('\n')
.map(this._nonEmptyString)
.map((line, index) => this._renderLine(line, index + 1));
return (<div className="listing"><ol>{lines}</ol></div>);
}
render() {
return this.state.listingContent ? this._renderListing() : this._renderNone();
}
}
|