mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge pull request #550 from subtleGradient/subtlegradient/code-coverage
Code coverage grunt tasks.
This commit is contained in:
+2
-1
@@ -23,4 +23,5 @@ docs/js/examples
|
||||
docs/downloads
|
||||
examples/shared/*.js
|
||||
test/the-files-to-test.generated.js
|
||||
sauce_connect.log*
|
||||
*.log*
|
||||
chrome-user-data
|
||||
|
||||
@@ -70,6 +70,11 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('build:transformer', ['jsx:debug', 'browserify:transformer']);
|
||||
grunt.registerTask('build:min', ['jsx:release', 'version-check', 'browserify:min']);
|
||||
grunt.registerTask('build:addons-min', ['jsx:debug', 'browserify:addonsMin']);
|
||||
grunt.registerTask('build:withCodeCoverageLogging', [
|
||||
'jsx:debug',
|
||||
'version-check',
|
||||
'browserify:withCodeCoverageLogging'
|
||||
]);
|
||||
grunt.registerTask('build:test', [
|
||||
'jsx:test',
|
||||
'version-check',
|
||||
@@ -78,11 +83,19 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('webdriver-phantomjs', webdriverPhantomJSTask);
|
||||
|
||||
grunt.registerTask('coverage:parse', require('./grunt/tasks/coverage-parse'));
|
||||
|
||||
grunt.registerTask('test:webdriver:phantomjs', [
|
||||
'connect',
|
||||
'webdriver-phantomjs',
|
||||
'webdriver-jasmine:local'
|
||||
]);
|
||||
grunt.registerTask('test:coverage', [
|
||||
'build:test',
|
||||
'build:withCodeCoverageLogging',
|
||||
'test:webdriver:phantomjs',
|
||||
'coverage:parse'
|
||||
]);
|
||||
grunt.registerTask('test', ['build:test', 'build:basic', 'test:webdriver:phantomjs']);
|
||||
grunt.registerTask('npm:test', ['build', 'npm:pack']);
|
||||
|
||||
|
||||
@@ -95,10 +95,23 @@ var addonsMin = grunt.util._.merge({}, addons, {
|
||||
after: [minify, bannerify]
|
||||
});
|
||||
|
||||
var withCodeCoverageLogging = {
|
||||
entries: [
|
||||
'./build/modules/React.js'
|
||||
],
|
||||
outfile: './build/react.js',
|
||||
debug: true,
|
||||
standalone: 'React',
|
||||
transforms: [
|
||||
require('coverify')
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
basic: basic,
|
||||
min: min,
|
||||
transformer: transformer,
|
||||
addons: addons,
|
||||
addonsMin: addonsMin
|
||||
addonsMin: addonsMin,
|
||||
withCodeCoverageLogging: withCodeCoverageLogging
|
||||
};
|
||||
|
||||
+54
-4
@@ -1,11 +1,62 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function(grunt) {
|
||||
module.exports = function(grunt){
|
||||
var coverageWriteStream;
|
||||
|
||||
grunt.task.registerTask('finalize-coverage-stream', function(){
|
||||
if (!coverageWriteStream) {
|
||||
return;
|
||||
}
|
||||
var done = this.async();
|
||||
coverageWriteStream.once('close', done);
|
||||
coverageWriteStream.end();
|
||||
coverageWriteStream = null;
|
||||
});
|
||||
|
||||
function consoleLoggerMiddleware(req, res, next) {
|
||||
if (!(req.method == 'POST' && req._parsedUrl.pathname.replace(/\//g,'') == 'console' && Array.isArray(req.body))) {
|
||||
return next();
|
||||
}
|
||||
res.write('<!doctype html><meta charset=utf-8>');
|
||||
res.end('Got it, thanks!');
|
||||
|
||||
req.body.forEach(function(log){
|
||||
if (log.message.indexOf('not ok ') === 0) {
|
||||
log.type = 'error';
|
||||
} else if (log.message.indexOf('ok ') === 0) {
|
||||
log.type = 'ok';
|
||||
} else if (log.message.indexOf('COVER') === 0) {
|
||||
log.type = 'coverage';
|
||||
} else if (log.message.indexOf('DONE\t') === 0) {
|
||||
log.type = 'coverage done';
|
||||
}
|
||||
|
||||
if (log.type == 'error') {
|
||||
grunt.log.error(log.message);
|
||||
} else if (log.type == 'ok') {
|
||||
grunt.log.ok(log.message);
|
||||
} else if (log.type == 'log') {
|
||||
grunt.log.writeln(log.message);
|
||||
} else if (log.type == 'coverage') {
|
||||
if (!coverageWriteStream) {
|
||||
coverageWriteStream = require('fs').createWriteStream(__dirname + '/../../coverage.log');
|
||||
}
|
||||
coverageWriteStream.write(log.message + '\n');
|
||||
} else if (log.type == 'coverage done') {
|
||||
grunt.task.run('finalize-coverage-stream');
|
||||
} else {
|
||||
grunt.verbose.writeln(log);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testResultLoggerMiddleware(req, res, next) {
|
||||
if (!(req.method == 'POST' && req._parsedUrl.pathname.indexOf('/reportTestResults') === 0)) {
|
||||
return next();
|
||||
}
|
||||
res.write('<!doctype html><meta charset=utf-8>');
|
||||
res.end('Got it, thanks!');
|
||||
|
||||
var logType = 'writeln';
|
||||
var message = req.body;
|
||||
|
||||
@@ -23,8 +74,6 @@ module.exports = function(grunt) {
|
||||
message = JSON.stringify(message, null, 2);
|
||||
}
|
||||
grunt.log[logType]('[%s][%s]', req.headers['user-agent'], Date.now(), message);
|
||||
res.write('<!doctype html><meta charset=utf-8>');
|
||||
res.end('Got it, thanks!');
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -40,13 +89,14 @@ module.exports = function(grunt) {
|
||||
|
||||
return [
|
||||
connect.json(),
|
||||
consoleLoggerMiddleware,
|
||||
testResultLoggerMiddleware,
|
||||
|
||||
connect.logger({format:'[:user-agent][:timestamp] :method :url', stream:grunt.verbose}),
|
||||
connect.static(options.base),
|
||||
connect.directory(options.base)
|
||||
];
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ module.exports = function() {
|
||||
};
|
||||
|
||||
// TODO: make sure this works, test with this too
|
||||
config.transforms.forEach(bundle.transform, this);
|
||||
config.transforms.forEach(bundle.transform, bundle);
|
||||
|
||||
// Actually bundle it up
|
||||
var _this = this;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
var grunt = require('grunt');
|
||||
|
||||
module.exports = function(){
|
||||
var ROOT = require('path').normalize(__dirname + '/../..');
|
||||
var done = this.async();
|
||||
var uncoveredExpressionCount = 0;
|
||||
var uncoveredLineCount = 0;
|
||||
|
||||
require('fs').createReadStream(ROOT + '/coverage.log')
|
||||
.pipe(require('coverify/parse')(function(error, results){
|
||||
if (error) {
|
||||
grunt.fatal(error);
|
||||
}
|
||||
|
||||
Object.keys(results)
|
||||
.sort(function(a, b){
|
||||
return results[a].length - results[b].length;
|
||||
})
|
||||
.reverse()
|
||||
.forEach(function(path){
|
||||
if (results[path].length === 0) {
|
||||
return;
|
||||
}
|
||||
var relativePath = path.replace(ROOT, '');
|
||||
uncoveredExpressionCount += results[path].length;
|
||||
grunt.log.error(results[path].length + ' expressions not covered ' + relativePath);
|
||||
|
||||
results[path].forEach(function(c){
|
||||
uncoveredLineCount += c.code.split('\n').length;
|
||||
console.log('txmt://open?url=' + encodeURIComponent('file://' + path) + '&line=' + (c.lineNum+1) + '&column=' + (c.column[0]+2));
|
||||
});
|
||||
console.log('');
|
||||
})
|
||||
;
|
||||
|
||||
Object.keys(results).sort().forEach(function(path){
|
||||
if (results[path].length > 0) {
|
||||
return;
|
||||
}
|
||||
var relativePath = path.replace(ROOT, '');
|
||||
grunt.log.ok('100% coverage ' + relativePath);
|
||||
});
|
||||
|
||||
if (uncoveredExpressionCount > 0) {
|
||||
grunt.log.error(uncoveredExpressionCount + ' expressions not covered');
|
||||
}
|
||||
if (uncoveredLineCount > 0) {
|
||||
grunt.log.error(uncoveredLineCount + ' lines not covered');
|
||||
}
|
||||
done();
|
||||
}));
|
||||
};
|
||||
@@ -34,6 +34,6 @@ module.exports = function() {
|
||||
}).then(function(output) {
|
||||
grunt.file.write(config.outfile, output);
|
||||
theFilesToTestScript.end();
|
||||
done();
|
||||
theFilesToTestScript.once('close', done);
|
||||
});
|
||||
};
|
||||
|
||||
+2
-1
@@ -61,7 +61,8 @@
|
||||
"grunt-contrib-connect": "~0.5.0",
|
||||
"es5-shim": "~2.1.0",
|
||||
"wd": "~0.2.2",
|
||||
"sauce-tunnel": "~1.1.0"
|
||||
"sauce-tunnel": "~1.1.0",
|
||||
"coverify": "~0.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
||||
@@ -31,6 +31,8 @@ describe('ReactWebWorker', function() {
|
||||
var data = JSON.parse(e.data);
|
||||
if (data.type == 'error') {
|
||||
error = data.message + "\n" + data.stack;
|
||||
} else if (data.type == 'log') {
|
||||
console.log(data.message);
|
||||
} else {
|
||||
expect(data.type).toBe('done');
|
||||
done = true;
|
||||
@@ -42,7 +44,7 @@ describe('ReactWebWorker', function() {
|
||||
});
|
||||
runs(function() {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
throw new Error(error);
|
||||
}
|
||||
});
|
||||
|
||||
+23
-5
@@ -1,6 +1,26 @@
|
||||
/* jshint worker: true */
|
||||
"use strict";
|
||||
|
||||
if (typeof console == 'undefined') {
|
||||
this.console = {
|
||||
error: function(e){
|
||||
postMessage(JSON.stringify({
|
||||
type: 'error',
|
||||
message: e.message,
|
||||
stack: e.stack
|
||||
}));
|
||||
},
|
||||
log: function(message){
|
||||
postMessage(JSON.stringify({
|
||||
type: 'log',
|
||||
message: message
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('worker BEGIN');
|
||||
|
||||
// The UMD wrapper tries to store on `global` if `window` isn't available
|
||||
var global = {};
|
||||
importScripts("phantomjs-shims.js");
|
||||
@@ -8,13 +28,11 @@ importScripts("phantomjs-shims.js");
|
||||
try {
|
||||
importScripts("../../build/react.js");
|
||||
} catch (e) {
|
||||
postMessage(JSON.stringify({
|
||||
type: 'error',
|
||||
message: e.message,
|
||||
stack: e.stack
|
||||
}));
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
postMessage(JSON.stringify({
|
||||
type: 'done'
|
||||
}));
|
||||
|
||||
console.log('worker END');
|
||||
|
||||
@@ -1,34 +1,44 @@
|
||||
var __DEBUG__ = location.search.substring(1).indexOf('debug') != -1;
|
||||
|
||||
if (typeof console == 'undefined') console = {
|
||||
log: function(){},
|
||||
warn: function(){},
|
||||
error: function(){}
|
||||
};
|
||||
|
||||
var __consoleReport__ = [];
|
||||
|
||||
console._log = console.log;
|
||||
console.log = function(message){
|
||||
console._log(message);
|
||||
postDataToURL({type:'log', message:message}, '/reportTestResults');
|
||||
if (__DEBUG__) postDataToURL({type:'log', message:message}, '/reportTestResults');
|
||||
else __consoleReport__.push({type:'log', message:message});
|
||||
}
|
||||
|
||||
console._error = console.error;
|
||||
console.error = function(message){
|
||||
console._error(message);
|
||||
postDataToURL({type:'error', message:message}, '/reportTestResults');
|
||||
if (__DEBUG__) postDataToURL({type:'error', message:message}, '/reportTestResults');
|
||||
else __consoleReport__.push({type:'error', message:message});
|
||||
}
|
||||
|
||||
console._flush = function(){
|
||||
postDataToURL(__consoleReport__, '/console');
|
||||
__consoleReport__.length = 0;
|
||||
}
|
||||
|
||||
;(function(env){
|
||||
env.addReporter(new jasmine.JSReporter());
|
||||
if (location.search.substring(1).indexOf('debug') != -1){
|
||||
env.addReporter(new TAPReporter(console.log.bind(console)));
|
||||
}
|
||||
env.addReporter(new TAPReporter(console.log.bind(console)));
|
||||
|
||||
function report(){
|
||||
if (typeof jasmine.getJSReport != 'function') {
|
||||
console.log("typeof jasmine.getJSReport != 'function'");
|
||||
return setTimeout(report, 100);
|
||||
}
|
||||
postDataToURL(jasmine.getJSReport(), '/reportTestResults', function(error, results){
|
||||
if (error) return console.error(error);
|
||||
});
|
||||
if (!__DEBUG__) {
|
||||
console.log('DONE\t' + navigator.userAgent);
|
||||
console._flush();
|
||||
}
|
||||
}
|
||||
|
||||
var oldCallback = env.currentRunner().finishCallback;
|
||||
|
||||
Reference in New Issue
Block a user