diff --git a/.gitignore b/.gitignore index e9aeae37a1..927b40333d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ static _SpecRunner.html __benchmarks__ build/ +coverage/ .module-cache *.gem docs/.bundle diff --git a/grunt/tasks/jest.js b/grunt/tasks/jest.js index d964a8c03c..ca8dda4a81 100644 --- a/grunt/tasks/jest.js +++ b/grunt/tasks/jest.js @@ -6,25 +6,87 @@ 'use strict'; +var assign = require('object-assign'); +var async = require('async'); +var fs = require('fs'); +var glob = require('glob'); var grunt = require('grunt'); var path = require('path'); +var rootPath = path.resolve('.'); +var buildPath = path.join(rootPath, 'build'); +var tempConfigPath = path.join(buildPath, 'jest-config.json'); + +var config = require(path.join(rootPath, 'package.json')).jest; + +function getCollectCoverageOnlyFrom(callback) { + var coverageFrom = config.collectCoverageOnlyFrom; + var patterns = Object.keys((config.collectCoverage && coverageFrom) || {}); + var result = {}; + + async.each(patterns, function(pattern) { + var options = assign({ nodir: true }, coverageFrom[pattern]); + glob(pattern, options, function(err, files) { + (files || []).reduce(function(object, key) { + object[key] = true; + return object; + }, result); + + callback(err); + }); + }, function(err) { + callback(err, result); + }); +} + +function getJestConfig(callback) { + var rootDir = path.resolve(buildPath, path.resolve(config.rootDir)); + getCollectCoverageOnlyFrom(function(err, data) { + callback(err, assign({}, config, { + rootDir: rootDir, + collectCoverageOnlyFrom: data, + })); + }); +} + +function onError(err) { + grunt.log.error('jest failed'); + grunt.log.error(err); +} + +function writeTempConfig(callback) { + getJestConfig(function(err, data) { + if (err) { + callback(err); + } else { + fs.writeFile(tempConfigPath, JSON.stringify(data, null, ' '), 'utf8', callback); + } + }); +} + module.exports = function() { var done = this.async(); - grunt.log.writeln('running jest (this may take a while)'); - grunt.util.spawn({ - cmd: 'node', - args: ['--harmony', path.join('node_modules', 'jest-cli', 'bin', 'jest')], - opts: {stdio: 'inherit', env: {NODE_ENV: 'test'}}, - }, function(err, result, code) { - if (err) { - grunt.log.error('jest failed'); - grunt.log.error(err); - } else { - grunt.log.ok('jest passed'); - } - grunt.log.writeln(result.stdout); - done(code === 0); + grunt.log.writeln('running jest (this may take a while)'); + + writeTempConfig(function(writeErr) { + if (writeErr) { + onError(writeErr); + return; + } + grunt.util.spawn({ + cmd: 'node', + args: ['--harmony', path.join('node_modules', 'jest-cli', 'bin', 'jest'), '--config', tempConfigPath], + opts: { stdio: 'inherit', env: { NODE_ENV: 'test' } }, + }, function(spawnErr, result, code) { + if (spawnErr) { + onError(spawnErr); + } else { + grunt.log.ok('jest passed'); + } + grunt.log.writeln(result.stdout); + + done(code === 0); + }); }); }; diff --git a/package.json b/package.json index 0fd7f94d12..78ee20c332 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,14 @@ "private": true, "version": "0.15.0-alpha", "devDependencies": { + "async": "^1.5.0", "babel": "^5.8.29", "babel-eslint": "4.1.5", "benchmark": "^1.0.0", "browserify": "^12.0.1", "bundle-collapser": "^1.1.1", "coffee-script": "^1.8.0", + "coveralls": "^2.11.6", "del": "^2.0.2", "derequire": "^2.0.3", "envify": "^3.0.0", @@ -17,6 +19,7 @@ "eslint-plugin-react-internal": "file:eslint-rules", "fbjs": "^0.4.0", "fbjs-scripts": "^0.5.0", + "glob": "^6.0.1", "grunt": "^0.4.5", "grunt-cli": "^0.1.13", "grunt-compare-size": "^0.4.0", @@ -54,6 +57,16 @@ "test": "jest" }, "jest": { + "collectCoverage": true, + "collectCoverageOnlyFrom": { + "src/**/*.js": { + "ignore": [ + "src/**/__tests__/*.js", + "src/shared/vendor/third_party/*.js", + "src/test/*.js" + ] + } + }, "modulePathIgnorePatterns": [ "/.module-cache/", "/react/build/"