From d6d216d05dd303560bded922e0715aa51604c80a Mon Sep 17 00:00:00 2001 From: Simon Bailey Date: Thu, 15 May 2014 19:52:23 +0100 Subject: [PATCH] Squashed commit of the following: commit 25ef9a176ee9bab902579f79415bd6047a77a62f Author: Simon Bailey Date: Thu May 15 19:51:45 2014 +0100 Updated README Signed-off-by: Simon Bailey commit 1b0020c8fd248bc0dc892bed1f3e315867378274 Merge: d8fd494 c468b98 Author: Edd Date: Sat Apr 26 11:13:52 2014 +0100 Merged with Master commit d8fd494478cb7fd0d97a47a90986f4c1b29eb996 Author: Edd Date: Thu Apr 24 22:09:19 2014 +0100 Trimming redundant options from Gruntfile commit b5015ae42b0beb770ae1b146f152b5f38764987e Author: Edd Date: Sun Mar 30 21:32:14 2014 +0100 Moved development mode to webpack-dev-server to imrove rebuild times commit 7d31ade8085a8d415b95c67dba69ae5157ebf9b4 Author: Edd Date: Wed Feb 26 00:18:56 2014 +0000 Changed JSX filenames to .jsx over .js commit 00faa6182b6cb4ae46b05dd12db1e73da4b47953 Author: Edd Date: Mon Feb 24 23:39:18 2014 +0000 Updated engines & Travis build targets commit e58e0d70639f3c3e9acc7d085b6a795365a140a6 Author: Edd Date: Mon Feb 24 23:26:04 2014 +0000 Added auto generation of a template CSS file for a component commit f6c67351aead570224b2457261d457a1954277dc Author: Edd Date: Mon Feb 24 00:06:42 2014 +0000 Updated default app test commit 996d769685d1a4f20ae2c4117422790bbc347594 Author: Edd Date: Sun Feb 23 23:32:37 2014 +0000 Added test for default main component (currently identical to any other component tests) commit 31dfcbaff6ee9aef339886897e053a339f98021b Author: Edd Date: Sun Feb 23 22:54:04 2014 +0000 Moved webpack configuration to a separate file - Added webpack config file - Added Uglify to webpack config - Added source maps in webpack config Moved entry file back in to Gruntfile commit 6b3a3e92b80f3121e1128e4f166cf36aa32cfa26 Author: Edd Date: Sun Feb 23 17:23:07 2014 +0000 Added distribution folder & Grunt tasks to deal with it - Created Distribution build folder (script link broken) - Added grunt-contrib-copy - Added grunt-uglify - Bumped React version number - Switched source map types Signed-off-by: Simon Bailey --- .gitignore | 1 + .travis.yml | 1 - README.md | 18 +- component/index.js | 1 + main/index.js | 4 +- package.json | 3 +- script-base.js | 28 +++- templates/common/Gruntfile.js | 158 ++++++++---------- templates/common/_package.json | 18 +- templates/common/gitignore | 1 + templates/common/index.html | 2 +- templates/common/karma.conf.js | 2 +- templates/common/root/webpack.config.js | 49 ++++++ templates/common/root/webpack.dist.config.js | 60 +++++++ templates/javascript/{App.js => App.jsx} | 0 .../{Component.js => Component.jsx} | 1 + templates/spec/App.js | 18 ++ templates/{javascript => }/spec/Component.js | 2 +- templates/styles/Component.css | 3 + test/test-creation.js | 8 +- 20 files changed, 262 insertions(+), 116 deletions(-) create mode 100644 templates/common/root/webpack.config.js create mode 100644 templates/common/root/webpack.dist.config.js rename templates/javascript/{App.js => App.jsx} (100%) rename templates/javascript/{Component.js => Component.jsx} (87%) create mode 100644 templates/spec/App.js rename templates/{javascript => }/spec/Component.js (92%) create mode 100644 templates/styles/Component.css diff --git a/.gitignore b/.gitignore index cae3194..5a2ac84 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ $RECYCLE.BIN/ # App specific node_modules/ +/test/temp-test/ /test/temp/ diff --git a/.travis.yml b/.travis.yml index 3f16ce8..92d91d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: node_js node_js: - - '0.8' - '0.10' before_install: - currentfolder=${PWD##*/} diff --git a/README.md b/README.md index 1406758..e2e46a0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# generator-react-webpack [![Build Status](https://secure.travis-ci.org/newtriks/generator-react-webpack.png?branch=master)](https://travis-ci.org/newtriks/generator-react-webpack) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) +# generator-react-webpack [![Build Status](https://secure.travis-ci.org/eddhannay/generator-react-webpack.png?branch=master)](https://travis-ci.org/eddhannay/generator-react-webpack) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) > Yeoman generator for [ReactJS](http://facebook.github.io/react/) - lets you quickly set up a project including karma test runner and [Webpack](http://webpack.github.io/) module system. @@ -54,7 +54,7 @@ Example: yo react-webpack:component foo ``` -Produces `src/scripts/components/Foo.js` (*javascript - JSX*): +Produces `src/scripts/components/Foo.jsx` (*javascript - JSX*): ``` /** * @jsx React.DOM @@ -98,6 +98,14 @@ describe('Foo', function () { }); ``` +And `src/styles/Foo.css`: +``` + +.Foo{ + border: 1px dashed #f00; +} +``` + ## Testing Running `grunt test` will run the unit tests with karma. Tests are written using [Jasmine](http://pivotal.github.io/jasmine/) by default. @@ -148,7 +156,7 @@ Each component is a module and can be required using the [Webpack](http://webpac Out the box the [Gruntfile](http://gruntjs.com/api/grunt.file) is configured with the following: 1. **webpack**: uses the [grunt-webpack](https://github.com/webpack/grunt-webpack) plugin to load all required modules and output to a single JS file `src/scripts/main.js`. This is included in the `src/index.html` file by default and will reload in the browser as and when it is recompiled. -2. **watch**: uses the [grunt-watch](https://github.com/gruntjs/grunt-contrib-watch) plugin and watches for file changes. Livereload support is included by default and thus on file change the *webpack* task is run and the browser will auto update. +2. **webpack-dev-server**: uses the [webpack-dev-server](https://github.com/webpack/webpack-dev-server) to watch for file changes and also serve the webpack app in development. 3. **connect**: uses the [grunt-connect](https://github.com/gruntjs/grunt-contrib-connect) plugin to start a webserver at [localhost](http://localhost:8000). 4. **karma**: uses the [grunt-karma](https://github.com/karma-runner/grunt-karma) plugin to load the Karma configuration file `karma.conf.js` located in the project root. This will run all tests using [PhantomJS](http://phantomjs.org/) by default but supports many other browsers. @@ -167,7 +175,3 @@ Contributions are welcomed. When submitting a bugfix, write a test that exposes ## License [BSD license](http://opensource.org/licenses/bsd-license.php) - - -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/newtriks/generator-react-webpack/trend.png)](https://bitdeli.com/free "Bitdeli Badge") - diff --git a/component/index.js b/component/index.js index a5b6541..5e37c8f 100644 --- a/component/index.js +++ b/component/index.js @@ -12,6 +12,7 @@ ComponentGenerator.prototype.createComponentFile = function createComponentFile( this.generateSourceAndTest( 'Component', 'spec/Component', + 'styles/Component', 'components' ); }; diff --git a/main/index.js b/main/index.js index 96e85c5..fde7d63 100644 --- a/main/index.js +++ b/main/index.js @@ -1,4 +1,5 @@ 'use strict'; + var util = require('util'); var ScriptBase = require('../script-base.js'); @@ -9,5 +10,6 @@ var MainGenerator = module.exports = function MainGenerator(args, options, confi util.inherits(MainGenerator, ScriptBase); MainGenerator.prototype.createAppFile = function createAppFile() { - this.appTemplate('App', 'scripts/components/'+this.scriptAppName); + this.appTemplate('App', 'scripts/components/' + this.scriptAppName); + this.testTemplate('spec/App', 'components/' + this.scriptAppName); }; diff --git a/package.json b/package.json index 6935b2c..2cb43b7 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,7 @@ "yo": ">=1.0.0" }, "engines": { - "node": ">=0.8.0", - "npm": ">=1.2.10" + "node": ">=0.10.0" }, "licenses": [ { diff --git a/script-base.js b/script-base.js index f0510b3..8b4029d 100644 --- a/script-base.js +++ b/script-base.js @@ -8,7 +8,8 @@ var Generator = module.exports = function Generator() { yeoman.generators.NamedBase.apply(this, arguments); // Add capitalize mixin - this._.mixin({ 'capitalize': generalUtils.capitalize }); + this._.mixin({ 'capitalize': generalUtils.capitalize }); + this._.mixin({ 'lowercase': generalUtils.lowercase }); this.appname = path.basename(process.cwd()); @@ -24,8 +25,16 @@ var Generator = module.exports = function Generator() { this.env.options.testPath = this.env.options.testPath || 'test/spec'; } - var sourceRoot = '/templates/javascript'; + if (typeof this.env.options.stylesPath === 'undefined') { + this.env.options.stylesPath = this.env.options.stylesPath || 'src/styles'; + } + + var sourceRoot = '/templates/'; this.scriptSuffix = '.js'; + this.reactSuffix = '.jsx'; + + var stylesRoot = '/templates/styles'; + this.stylesSuffix = '.css'; this.sourceRoot(path.join(__dirname, sourceRoot)); }; @@ -34,8 +43,8 @@ util.inherits(Generator, yeoman.generators.NamedBase); Generator.prototype.appTemplate = function (src, dest) { yeoman.generators.Base.prototype.template.apply(this, [ - src + this.scriptSuffix, - path.join(this.env.options.appPath, dest) + this.scriptSuffix + path.join('javascript', src + this.reactSuffix), + path.join(this.env.options.appPath, dest) + this.reactSuffix ]); }; @@ -46,6 +55,14 @@ Generator.prototype.testTemplate = function (src, dest) { ]); }; +Generator.prototype.stylesTemplate = function (src, dest) { + console.log(src); + yeoman.generators.Base.prototype.template.apply(this, [ + src + this.stylesSuffix, + path.join(this.env.options.stylesPath, dest) + this.stylesSuffix + ]); +}; + Generator.prototype.htmlTemplate = function (src, dest) { yeoman.generators.Base.prototype.template.apply(this, [ src, @@ -53,7 +70,8 @@ Generator.prototype.htmlTemplate = function (src, dest) { ]); }; -Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, targetDirectory) { +Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, stylesTemplate, targetDirectory) { this.appTemplate(appTemplate, path.join('scripts', targetDirectory, this._.capitalize(this.name))); this.testTemplate(testTemplate, path.join(targetDirectory, this._.capitalize(this.name))); + this.stylesTemplate(stylesTemplate, path.join(this._.capitalize(this.name))); }; diff --git a/templates/common/Gruntfile.js b/templates/common/Gruntfile.js index 03ef33d..0840e42 100644 --- a/templates/common/Gruntfile.js +++ b/templates/common/Gruntfile.js @@ -1,101 +1,51 @@ 'use strict'; -var LIVERELOAD_PORT = 35729; -var lrSnippet = require('connect-livereload')({ - port: LIVERELOAD_PORT -}); + var mountFolder = function (connect, dir) { return connect.static(require('path').resolve(dir)); }; +var webpackDistConfig = require('./webpack.dist.config.js'), + webpackDevConfig = require('./webpack.config.js'); + module.exports = function (grunt) { // Let *load-grunt-tasks* require everything require('load-grunt-tasks')(grunt); + // Read configuration from package.json var pkgConfig = grunt.file.readJSON('package.json'); - var jshintConfig = grunt.file.readJSON('.jshintrc'); - - var loaders = [{ - test: /\.css$/, - loader: 'style!css' - }, { - test: /\.gif/, - loader: 'url-loader?limit=10000&minetype=image/gif' - }, { - test: /\.jpg/, - loader: 'url-loader?limit=10000&minetype=image/jpg' - }, { - test: /\.png/, - loader: 'url-loader?limit=10000&minetype=image/png' - }, { - test: /\.js$/, - loader: 'jsx-loader' - }]; - + grunt.initConfig({ pkg: pkgConfig, + webpack: { - development: { - entry: './<%= pkg.src %>/scripts/components/<%= pkg.mainInput %>.js', - output: { - path: '<%= pkg.src %>/scripts/', - filename: '<%= pkg.mainOutput %>.js' - }, - debug: true, - cache: true, - stats: { - colors: true, - reasons: true - }, - jshint: grunt.util._.merge(jshintConfig, { - emitErrors: false, - failOnHint: false - }), - module: { - preLoaders: [{ - test: '\\.js$', - exclude: 'node_modules', - loader: 'jshint' - }], - loaders: loaders - } + options: webpackDistConfig, + + dist: { + cache: false } }, - watch: { - webpack: { - files: ['<%= pkg.src %>/scripts/{,*/}*.js', - '<%= pkg.src %>/styles/{,*/}*.css', - '!<%= pkg.src %>/scripts/<%= pkg.mainOutput %>.js' - ], - tasks: ['webpack:development'] - }, - livereload: { - options: { - livereload: LIVERELOAD_PORT - }, - files: [ - '<%= pkg.src %>/{,*/}*.html', - '<%= pkg.src %>/scripts/<%= pkg.mainOutput %>.js' - ] - } - }, - connect: { + + 'webpack-dev-server': { options: { port: 8000, - // Change this to '0.0.0.0' to access the server from outside. - hostname: 'localhost' + webpack: webpackDevConfig, + publicPath: '/scripts/', + contentBase: './<%= pkg.src %>/', }, - livereload: { - options: { - middleware: function (connect) { - return [ - lrSnippet, - mountFolder(connect, pkgConfig.src) - ]; - } - } + + start: { + keepAlive: true, + } + }, + + connect: { + options: { + port: 8000 }, + dist: { options: { + keepalive: true, middleware: function (connect) { return [ mountFolder(connect, pkgConfig.dist) @@ -104,34 +54,72 @@ module.exports = function (grunt) { } } }, + open: { - server: { - url: 'http://localhost:<%= connect.options.port %>' + options: { + delay: 500 + }, + dev: { + path: 'http://localhost:<%= connect.options.port %>/webpack-dev-server/' + }, + dist: { + path: 'http://localhost:<%= connect.options.port %>/' } }, + karma: { unit: { configFile: 'karma.conf.js' } + }, + + copy: { + dist: { + files: [ + // includes files within path + { + flatten: true, + expand: true, + src: ['<%= pkg.src %>/*'], + dest: '<%= pkg.dist %>/', + filter: 'isFile' + }, + { + flatten: true, + expand: true, + src: ['<%= pkg.src %>/images/*'], + dest: '<%= pkg.dist %>/images/' + }, + ] + } + }, + + clean: { + dist: { + files: [{ + dot: true, + src: [ + '<%= pkg.dist %>' + ] + }] + } } }); grunt.registerTask('serve', function (target) { if (target === 'dist') { - return grunt.task.run(['build', 'open', 'connect:dist:keepalive']); + return grunt.task.run(['build', 'open:dist', 'connect:dist']); } grunt.task.run([ - 'connect:livereload', - 'webpack:development', - 'open', - 'watch' + 'open:dev', + 'webpack-dev-server' ]); }); grunt.registerTask('test', ['karma']); - grunt.registerTask('build', []); + grunt.registerTask('build', ['clean', 'copy', 'webpack']); grunt.registerTask('default', []); }; diff --git a/templates/common/_package.json b/templates/common/_package.json index 1442665..106ef8f 100644 --- a/templates/common/_package.json +++ b/templates/common/_package.json @@ -11,15 +11,13 @@ }, "devDependencies": { "grunt": "~0.4.4", - "load-grunt-tasks": "~0.2.1", - "grunt-contrib-watch": "~0.5.3", - "grunt-contrib-connect": "~0.6.0", - "connect-livereload": "~0.3.1", + "load-grunt-tasks": "~0.4.0", + "grunt-contrib-connect": "~0.7.1", "webpack": "~1.1.2", "jsx-loader": "~0.9.0", "grunt-webpack": "~1.0.0", - "style-loader": "~0.6.0", - "url-loader": "~0.5.2", + "style-loader": "~0.6.3", + "url-loader": "~0.5.4", "css-loader": "~0.6.6", "karma-script-launcher": "~0.1.0", "karma-chrome-launcher": "~0.1.2", @@ -29,8 +27,10 @@ "karma": "~0.10.9", "grunt-karma": "~0.6.2", "karma-webpack-plugin": "~1.0.0", - "webpack-dev-server": "~1.0.2", - "grunt-open": "~0.2.2", - "jshint-loader": "~0.6.0" + "webpack-dev-server": "~1.2.4", + "grunt-open": "~0.2.3", + "jshint-loader": "~0.6.0", + "grunt-contrib-copy": "~0.5.0", + "grunt-contrib-clean": "~0.5.0" } } diff --git a/templates/common/gitignore b/templates/common/gitignore index cfb1a09..e6a2bd4 100644 --- a/templates/common/gitignore +++ b/templates/common/gitignore @@ -29,4 +29,5 @@ $RECYCLE.BIN/ node_modules/ .tmp +dist /src/scripts/main.js diff --git a/templates/common/index.html b/templates/common/index.html index 71fa2a1..654d53a 100644 --- a/templates/common/index.html +++ b/templates/common/index.html @@ -12,7 +12,7 @@

You are using an outdated browser. Please upgrade your browser to improve your experience.

-

If you can see this, something is broken (or JS is not enabled).

+

If you can see this, something is broken (or JS is not enabled)!!.

diff --git a/templates/common/karma.conf.js b/templates/common/karma.conf.js index 3d7cfa4..96ebff7 100644 --- a/templates/common/karma.conf.js +++ b/templates/common/karma.conf.js @@ -27,7 +27,7 @@ module.exports = function (config) { test: /\.png/, loader: 'url-loader?limit=10000&minetype=image/png' }, { - test: /\.js$/, + test: /\.jsx$/, loader: 'jsx-loader' }] } diff --git a/templates/common/root/webpack.config.js b/templates/common/root/webpack.config.js new file mode 100644 index 0000000..1c68c44 --- /dev/null +++ b/templates/common/root/webpack.config.js @@ -0,0 +1,49 @@ +/* + * Webpack development server configuration + * + * This file is set up for serving the webpak-dev-server, which will watch for changes and recompile as required if + * the subfolder /webpack-dev-server/ is visited. Visiting the root will not automatically reload. + */ + +'use strict'; + +module.exports = { + output: { + filename: 'main.js' + }, + + cache: true, + debug: true, + devtool: false, + entry: './src/scripts/components/<%= pkg.mainInput %>.jsx', + + stats: { + colors: true, + reasons: true + }, + + module: { + preLoaders: [{ + test: '\\.js$', + exclude: 'node_modules', + loader: 'jshint' + }], + + loaders: [{ + test: /\.css$/, + loader: 'style!css' + }, { + test: /\.gif/, + loader: 'url-loader?limit=10000&minetype=image/gif' + }, { + test: /\.jpg/, + loader: 'url-loader?limit=10000&minetype=image/jpg' + }, { + test: /\.png/, + loader: 'url-loader?limit=10000&minetype=image/png' + }, { + test: /\.jsx$/, + loader: 'jsx-loader' + }] + } +}; \ No newline at end of file diff --git a/templates/common/root/webpack.dist.config.js b/templates/common/root/webpack.dist.config.js new file mode 100644 index 0000000..6659974 --- /dev/null +++ b/templates/common/root/webpack.dist.config.js @@ -0,0 +1,60 @@ +/* + * Webpack distribution configuration + * + * This file is set up for serving the distribution version. It will be compiled to dist/ by default + */ + +'use strict'; + +var webpack = require('webpack'); + +module.exports = { + output: { + publicPatch: 'dist/', + path: 'dist/scripts/', + filename: 'main.js' + }, + + debug: false, + devtool: false, + entry: './src/scripts/components/<%= pkg.mainInput %>.jsx', + + stats: { + colors: true, + reasons: false + }, + + plugins: [ + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin(), + new webpack.optimize.OccurenceOrderPlugin(), + new webpack.optimize.AggressiveMergingPlugin() + ], + + module: { + preLoaders: [{ + test: '\\.js$', + exclude: 'node_modules', + loader: 'jshint' + }], + + loaders: [ + { + test: /\.css$/, + loader: 'style!css' + }, { + test: /\.gif/, + loader: 'url-loader?limit=10000&minetype=image/gif' + }, { + test: /\.jpg/, + loader: 'url-loader?limit=10000&minetype=image/jpg' + }, { + test: /\.png/, + loader: 'url-loader?limit=10000&minetype=image/png' + }, { + test: /\.jsx$/, + loader: 'jsx-loader' + } + ] + } +}; \ No newline at end of file diff --git a/templates/javascript/App.js b/templates/javascript/App.jsx similarity index 100% rename from templates/javascript/App.js rename to templates/javascript/App.jsx diff --git a/templates/javascript/Component.js b/templates/javascript/Component.jsx similarity index 87% rename from templates/javascript/Component.js rename to templates/javascript/Component.jsx index 2b12147..2418a4b 100644 --- a/templates/javascript/Component.js +++ b/templates/javascript/Component.jsx @@ -5,6 +5,7 @@ 'use strict'; var React = require('react/addons'); +require('../../styles/<%= classedName %>.css'); var <%= classedName %> = React.createClass({ /*jshint ignore:start */ diff --git a/templates/spec/App.js b/templates/spec/App.js new file mode 100644 index 0000000..50cbda1 --- /dev/null +++ b/templates/spec/App.js @@ -0,0 +1,18 @@ +'use strict'; + +describe('<%= classedName %>', function () { + var <%= scriptAppName %>, component; + + beforeEach(function () { + var container = document.createElement('div'); + container.id = 'content'; + document.body.appendChild(container); + + <%= scriptAppName %> = require('../../../src/scripts/components/<%= scriptAppName %>.jsx'); + component = <%= scriptAppName %>(); + }); + + it('should create a new instance of <%= scriptAppName %>', function () { + expect(component).toBeDefined(); + }); +}); diff --git a/templates/javascript/spec/Component.js b/templates/spec/Component.js similarity index 92% rename from templates/javascript/spec/Component.js rename to templates/spec/Component.js index 7f03497..93e72b2 100644 --- a/templates/javascript/spec/Component.js +++ b/templates/spec/Component.js @@ -4,7 +4,7 @@ describe('<%= classedName %>', function () { var <%= classedName %>, component; beforeEach(function () { - <%= classedName %> = require('../../../src/scripts/components/<%= classedName %>'); + <%= classedName %> = require('../../../src/scripts/components/<%= classedName %>.jsx'); component = <%= classedName %>(); }); diff --git a/templates/styles/Component.css b/templates/styles/Component.css new file mode 100644 index 0000000..2bb362b --- /dev/null +++ b/templates/styles/Component.css @@ -0,0 +1,3 @@ +.<%= classedName %>{ + border: 1px dashed #f00; +} \ No newline at end of file diff --git a/test/test-creation.js b/test/test-creation.js index f365a7b..61a23de 100644 --- a/test/test-creation.js +++ b/test/test-creation.js @@ -39,12 +39,14 @@ describe('react-webpack generator', function () { 'src/styles/main.css', 'src/index.html', 'Gruntfile.js', + 'webpack.config.js', 'karma.conf.js', 'package.json', 'package.json', - 'src/scripts/components/TempTestApp.js', + 'src/scripts/components/TempTestApp.jsx', 'test/helpers/phantomjs-shims.js', - 'test/helpers/react/addons.js' + 'test/helpers/react/addons.js', + 'test/spec/components/TempTestApp.js', ]; react.run({}, function () { @@ -84,7 +86,7 @@ describe('react-webpack generator', function () { //var Foo = React.createClass({ reactGenerator.run([], function () { helpers.assertFiles([ - [path.join('src/scripts', targetDirectory, name + '.js'), new RegExp('var ' + scriptNameFn(name) + suffix, 'g')], + [path.join('src/scripts', targetDirectory, name + '.jsx'), new RegExp('var ' + scriptNameFn(name) + suffix, 'g')], [path.join('test/spec', targetDirectory, name + '.js'), new RegExp('describe\\(\'' + specNameFn(name) + suffix + '\'', 'g')] ]); done();