Skip to content
This repository was archived by the owner on Feb 19, 2020. It is now read-only.

Commit a3f841a

Browse files
committed
Fixed wrong JS coverage reporting
1 parent ecc496e commit a3f841a

File tree

9 files changed

+215
-14
lines changed

9 files changed

+215
-14
lines changed

lib/impl/lcov.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@
5050

5151
//TODO: Convert to reduce function
5252
stats.lines.details.forEach(function (detail) {
53-
// If a line is not sent to the service then it is considered to be 0, so no need to be redundant in the payload.
53+
// Codacy needs the 0s to know failed coverage data
5454
// We also can't have a negative number of hits on a line, so exclude those.
55-
if (detail.hit >= 1) {
55+
if (detail.hit >= 0) {
5656
fileStats.coverage[detail.line] = detail.hit;
5757
}
5858
});

lib/reporter.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
fileReports: Joi.array().required().items(Joi.object({
1212
filename: Joi.string().required().min(1),
1313
total: Joi.number().integer().required().min(0).max(100),
14-
coverage: Joi.object().pattern(/\d/, Joi.number().integer().min(1))
14+
coverage: Joi.object().pattern(/\d/, Joi.number().integer().min(0))
1515
}).required())
1616
}).example({total: 50, fileReports: [{filename: 'filename', total: 10, coverage: {1: 1, 2: 3}}]});
1717

@@ -21,14 +21,15 @@
2121
ts: 'typescript',
2222
tsx: 'typescript',
2323
coffee: 'coffeescript'
24-
}
24+
};
2525

2626
function sendByLanguage(endpoint, commitId, token, data) {
2727
var reportsByLanguage = lodash.groupBy(data.fileReports, function(elem) {
2828
return languageMap[lodash.head(lodash.takeRight(elem.filename.split('.'), 1))] || 'javascript';
2929
});
3030

3131
var languageResponses = lodash.map(reportsByLanguage, function(fileReports, language) {
32+
3233
var weighedCoverage = lodash.reduce(fileReports, function(accom, elem) {
3334
return accom + (elem.total * Object.keys(elem.coverage).length);
3435
}, 0);

test/handleInput.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,15 @@
6161
39: 1,
6262
40: 3,
6363
44: 3,
64+
45: 0,
6465
48: 3,
6566
50: 3,
6667
52: 3,
6768
54: 3,
6869
55: 3,
6970
61: 3,
7071
63: 3,
72+
64: 0,
7173
67: 3,
7274
73: 2,
7375
74: 1,
@@ -104,13 +106,15 @@
104106
39: 1,
105107
40: 3,
106108
44: 3,
109+
45: 0,
107110
48: 3,
108111
50: 3,
109112
52: 3,
110113
54: 3,
111114
55: 3,
112115
61: 3,
113116
63: 3,
117+
64: 0,
114118
67: 3,
115119
73: 2,
116120
74: 1,

test/handleMultiLangInput.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
(function (handleInput, helper, Joi, request, fs, path, Promise) {
2+
'use strict';
3+
/*eslint new-cap: ["error", { "newIsCap": false }]*/
4+
5+
var expect = helper.chai.expect;
6+
var lcov2Data = fs.readFileSync(__dirname + '/mock/lcov2.info').toString();
7+
var lcovMultiData = fs.readFileSync(__dirname + '/mock/lcov-multilang.info').toString();
8+
var originalCodacyToken = process.env.CODACY_PROJECT_TOKEN || process.env.CODACY_REPO_TOKEN;
9+
10+
describe('Handle Input', function () {
11+
beforeEach(function () {
12+
helper.clearEnvironmentVariables();
13+
process.env.CODACY_PROJECT_TOKEN = originalCodacyToken;
14+
});
15+
it('should be able to parse multiple files lcov data', function () {
16+
var expectedCoverage = {
17+
total: 30,
18+
fileReports: Joi.array().items(Joi.compile({
19+
filename: path.normalize('FileA.js'),
20+
coverage: {
21+
1: 0,
22+
2: 0,
23+
9: 0,
24+
19: 0
25+
},
26+
total: 0
27+
}),
28+
Joi.compile({
29+
filename: path.normalize('FileB.js'),
30+
coverage: {
31+
1: 0,
32+
2: 0
33+
},
34+
total: 0
35+
}),
36+
Joi.compile({
37+
filename: path.normalize('FileC.js'),
38+
coverage: {
39+
1: 1,
40+
2: 1,
41+
3: 1,
42+
7: 0
43+
},
44+
total: 75
45+
}))
46+
};
47+
48+
return helper.setupMockEndpoint('1234', '4321', Joi.compile(expectedCoverage))
49+
.then(function () {
50+
return expect(handleInput(lcov2Data, {
51+
token: '1234',
52+
commit: '4321'
53+
})).to.eventually.be.fulfilled();
54+
});
55+
});
56+
it('should be able to parse multiple lang files lcov data', function () {
57+
var expectedCoverageJS = {
58+
total: 30,
59+
fileReports: Joi.array().items(Joi.compile({
60+
filename: path.normalize('FileA.js'),
61+
coverage: {
62+
1: 0,
63+
2: 0,
64+
3: 0,
65+
4: 0,
66+
9: 0,
67+
19: 0
68+
},
69+
total: 0
70+
}),
71+
Joi.compile({
72+
filename: path.normalize('FileC.js'),
73+
coverage: {
74+
1: 1,
75+
2: 1,
76+
3: 1,
77+
7: 0
78+
},
79+
total: 75
80+
}))
81+
};
82+
var expectedCoverageTS = {
83+
total: 40,
84+
fileReports: Joi.array().items(Joi.compile({
85+
filename: path.normalize('FileB.ts'),
86+
coverage: {
87+
1: 1,
88+
2: 1,
89+
3: 0,
90+
4: 0
91+
},
92+
total: 50
93+
}),
94+
Joi.compile({
95+
filename: path.normalize('FileB2.ts'),
96+
coverage: {
97+
1: 0
98+
},
99+
total: 0
100+
}))
101+
};
102+
103+
return new Promise.all(
104+
[
105+
helper.setupLangMockEndpoint('1234', '4321', Joi.compile(expectedCoverageJS), 'javascript'),
106+
helper.setupLangMockEndpoint('1234', '4321', Joi.compile(expectedCoverageTS), 'typescript')
107+
]
108+
).then(function () {
109+
return expect(handleInput(lcovMultiData, {
110+
token: '1234',
111+
commit: '4321'
112+
})).to.eventually.be.fulfilled();
113+
});
114+
});
115+
});
116+
117+
}(require('../lib/handleInput'), require('./helper'), require('joi'),
118+
require('request-promise'), require('fs'), require('path'), require('bluebird')));

test/helper.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,35 @@
1919
return resolve(nock('https://api.codacy.com')
2020
.post('/2.0/coverage/' + commitId + '/javascript', function (body) {
2121
var result = bodyValidator.validate(body);
22-
return result.error ? false : true;
22+
23+
return !result.error;
2324
})
2425
.reply(statusCode || 200));
2526
});
2627
}
2728

29+
function setupLangMockEndpoint(token, commitId, bodyValidator, language) {
30+
return new Promise(function (resolve) {
31+
expect(token).to.be.ok();
32+
expect(commitId).to.be.ok();
33+
expect(bodyValidator).to.be.ok();
34+
35+
return resolve(nock('https://api.codacy.com')
36+
.post('/2.0/coverage/' + commitId + '/' + language, function (body) {
37+
38+
console.error('<BODY>');
39+
console.error(body);
40+
console.error('</BODY>');
41+
42+
var result = bodyValidator.validate(body);
43+
return !(result.error);
44+
}).reply(200));
45+
});
46+
}
47+
2848
module.exports = {
2949
setupMockEndpoint: setupMockEndpoint,
50+
setupLangMockEndpoint: setupLangMockEndpoint,
3051
chai: chai,
3152
clearEnvironmentVariables: function () {
3253
process.env.CODACY_GIT_COMMIT = '';
@@ -38,4 +59,4 @@
3859
process.env.WERCKER_GIT_COMMIT = '';
3960
}
4061
};
41-
}(require('nock'), require('chai'), require('bluebird')));
62+
}(require('nock'), require('chai'), require('bluebird')));

test/lcov.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
39: 1,
2121
40: 3,
2222
44: 3,
23+
45: 0,
2324
48: 3,
2425
50: 3,
2526
52: 3,
2627
54: 3,
2728
55: 3,
2829
61: 3,
2930
63: 3,
31+
64: 0,
3032
67: 3,
3133
73: 2,
3234
74: 1,
@@ -61,13 +63,15 @@
6163
39: 1,
6264
40: 3,
6365
44: 3,
66+
45: 0,
6467
48: 3,
6568
50: 3,
6669
52: 3,
6770
54: 3,
6871
55: 3,
6972
61: 3,
7073
63: 3,
74+
64: 0,
7175
67: 3,
7276
73: 2,
7377
74: 1,

test/mock/lcov-multilang.info

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
TN:
2+
SF:FileA.js
3+
FN:1,(anonymous_0)
4+
FN:8,(anonymous_1)
5+
FNF:2
6+
FNH:0
7+
FNDA:0,(anonymous_0)
8+
FNDA:0,(anonymous_1)
9+
DA:1,0
10+
DA:2,0
11+
DA:3,0
12+
DA:4,0
13+
DA:9,0
14+
DA:19,0
15+
LF:6
16+
LH:0
17+
BRF:0
18+
BRH:0
19+
end_of_record
20+
TN:
21+
SF:FileB.ts
22+
FN:1,(anonymous_0)
23+
FNF:1
24+
FNH:0
25+
FNDA:0,(anonymous_0)
26+
DA:1,1
27+
DA:2,1
28+
DA:3,0
29+
DA:4,0
30+
LF:4
31+
LH:2
32+
BRF:0
33+
BRH:0
34+
end_of_record
35+
TN:
36+
SF:FileB2.ts
37+
FN:1,(anonymous_0)
38+
FNF:1
39+
FNH:0
40+
FNDA:0,(anonymous_0)
41+
DA:1,0
42+
LF:1
43+
LH:0
44+
BRF:0
45+
BRH:0
46+
end_of_record
47+
TN:
48+
SF:FileC.js
49+
FNF:0
50+
FNH:0
51+
DA:1,1
52+
DA:2,1
53+
DA:3,1
54+
DA:7,0
55+
LF:4
56+
LH:3
57+
BRF:0
58+
BRH:0
59+
end_of_record
60+
TN:

test/mock/lcov2.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ BRF:0
2929
BRH:0
3030
end_of_record
3131
TN:
32-
SF:FileC.jsx
32+
SF:FileC.js
3333
FNF:0
3434
FNH:0
3535
DA:1,1

test/reporter.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,6 @@
4949
});
5050
});
5151
});
52-
it('shouldn\'t be able to send coverage with 0 hits on a line', function () {
53-
sampleCoverageData.fileReports[0].coverage['3'] = 0;
54-
55-
return expect(reporter({})
56-
.sendCoverage('1234', '4321', 'javascript', sampleCoverageData))
57-
.to.eventually.be.rejectedWith(Error, 'child "fileReports" fails because ["fileReports" does not contain 1 required value(s)]');
58-
});
5952
it('shouldn\'t be able to create a reporter with invalid options', function () {
6053
return expect(function () {
6154
reporter({endpoint: 1});

0 commit comments

Comments
 (0)