├── .editorconfig ├── .gitignore ├── README.md ├── index.html ├── package.json ├── run-test-animated.gif ├── server.js ├── src ├── __test__ │ └── index.spec.js ├── components │ ├── Hello.js │ └── __test__ │ │ └── hello.specs.js └── index.js ├── testem.json ├── webpack.config.js ├── webpack.production.config.js ├── webpack.test.bootstrap.js └── webpack.test.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log.* 5 | 6 | # Dependency directory 7 | node_modules 8 | 9 | #build 10 | build 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React-Testing-Webpack-Tape 2 | 3 | Boilerplate for bdd / tdd / testing with Tape + Testem + Webpack + React 4 | 5 | recompiles + re-runs test on file updates! 6 | 7 | 8 | ![](run-test-animated.gif) 9 | 10 | 11 | 12 | ## Installation 13 | 14 | ```javascript 15 | npm install //install dependencies 16 | ``` 17 | 18 | 19 | ## Usage 20 | 21 | ```javascript 22 | npm start //start webpack-dev-server with react-hot-loader 23 | ``` 24 | 25 | Open another terminal tab and then : 26 | 27 | ```javascript 28 | npm test //start testem + tape 29 | ``` 30 | 31 | ## Dependencies 32 | 33 | [tape](https://github.com/substack/tape) - tap-producing test harness for node and browsers 34 | 35 | [testem](https://github.com/airportyh/testem) - test runner 36 | 37 | [webpack](https://github.com/airportyh/testem) - a bundler for JavaScript 38 | 39 | [webpack-dev-server](https://github.com/webpack/webpack-dev-server) - updates browsers on changes 40 | 41 | [react](https://github.com/facebook/react) - View for our app 42 | 43 | [react-hot-loader](https://github.com/gaearon/react-hot-loader) - used for hot reloading 44 | 45 | [babel](https://github.com/babel/babel) - compiler for converting ES6 46 | 47 | 48 | ## Not quite right? 49 | 50 | I'm unsure if the use of glob to compile my tests is the fastest way pretty sure there should be a way with webpack. Feel free to contribute or open issues if you spot errors =) 51 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Boilerplate for bdd / tdd / testing with Tape + Webpack + React 6 | 7 | 8 | 9 |
10 |

Boilerplate for bdd / tdd / testing with Tape + Webpack + React

11 |
12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-testing-webpack-tape", 3 | "version": "1.0.0", 4 | "description": "Boilerplate for bdd / tdd / testing with Tape + Webpack + React", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node server.js", 8 | "build": "webpack --progress --colors --config webpack.production.config.js", 9 | "clean": "rm -rf build/", 10 | "test": "testem" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/Cmdv/React-Testing-Webpack-Tape.git" 15 | }, 16 | "keywords": [ 17 | "react", 18 | "webpack", 19 | "tape", 20 | "testem", 21 | "testing", 22 | "bdd", 23 | "babel", 24 | "tdd", 25 | "boilerplate", 26 | "react-hot-loader" 27 | ], 28 | "author": "Vincent Orr", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/Cmdv/React-Testing-Webpack-Tape/issues" 32 | }, 33 | "homepage": "https://github.com/Cmdv/React-Testing-Webpack-Tape#readme", 34 | 35 | "devDependencies": { 36 | "babel-core": "^5.7.4", 37 | "babel-loader": "^5.3.2", 38 | "glob": "^5.0.3", 39 | "install": "^0.1.8", 40 | "node-libs-browser": "^0.5.2", 41 | "path": "^0.11.14", 42 | "react": "0.13", 43 | "react-hot-loader": "^1.1.7", 44 | "tape": "^4.0.1", 45 | "testem": "^0.7.5", 46 | "webpack": "^1.10.1", 47 | "webpack-dev-server": "^1.7.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /run-test-animated.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cmdv/React-Testing-Webpack-Tape/e3b20603a686164ea13ebfc26c070ed7c65859be/run-test-animated.gif -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var WebpackDevServer = require('webpack-dev-server'); 3 | var config = require('./webpack.config'); 4 | 5 | 6 | // Start watching and bundling tests here 7 | var tests = require('./webpack.test.config'), 8 | testsCompiler = webpack(tests); 9 | 10 | testsCompiler.watch({}, function (err) { 11 | if (err) console.log(err); 12 | //console.log('Test file bundled'); 13 | }); 14 | 15 | 16 | // Primary app 17 | new WebpackDevServer(webpack(config), { 18 | publicPath: config.output.publicPath, 19 | hot: true, 20 | historyApiFallback: true, 21 | stats: {colors: true} 22 | }) 23 | .listen(3000, 'localhost', function (err) { 24 | if (err) { 25 | console.log(err); 26 | } 27 | 28 | console.log('Listening at localhost:3000'); 29 | }); 30 | -------------------------------------------------------------------------------- /src/__test__/index.spec.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | 3 | test('basic arithmetic', function(t) { 4 | t.plan(4); 5 | 6 | t.equal(2 + 3, 5); 7 | t.equal(7 * 8 + 9, 65); 8 | t.equal(1 + 2 , 3); 9 | t.equal(3 + 4 , 7); 10 | }); -------------------------------------------------------------------------------- /src/components/Hello.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | var Hello = React.createClass({ 4 | 5 | render() { 6 | return ( 7 |
8 |

Hello Mumm!!

9 |
10 | )} 11 | }); 12 | 13 | module.exports = Hello; -------------------------------------------------------------------------------- /src/components/__test__/hello.specs.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import React from 'react/addons'; 3 | import Hello from '../Hello'; 4 | 5 | const TestUtils = React.addons.TestUtils; 6 | 7 | // http://simonsmith.io/unit-testing-react-components-without-a-dom/ 8 | var createComponent = function (component, props = {}, ...children) { 9 | const renderer = TestUtils.createRenderer(); 10 | renderer.render(React.createElement(component, props, children.length > 1 ? children : children[0])); 11 | return renderer.getRenderOutput(); 12 | }; 13 | 14 | 15 | test('Components:Hello', t => { 16 | 17 | t.plan(1); 18 | 19 | let component = createComponent(Hello), 20 | expected = React.DOM.h1({}, 'Hello Mumm!!'); 21 | 22 | t.deepEqual(component.props.children, expected); 23 | }); 24 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Hello from 'components/Hello' 3 | 4 | React.render( 5 | , 6 | document.getElementById('app') 7 | ); 8 | -------------------------------------------------------------------------------- /testem.json: -------------------------------------------------------------------------------- 1 | { 2 | "framework": "tap", 3 | "src_files": ["build/test.js"], 4 | "launch_in_dev": [ "chrome" ] 5 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | module.exports = { 5 | devtool: 'eval', 6 | 7 | entry: { 8 | app: [ 9 | 'webpack-dev-server/client?http://0.0.0.0:3000', 10 | 'webpack/hot/only-dev-server', 11 | './src/index' 12 | ] 13 | }, 14 | 15 | output: { 16 | filename: '[name].js', 17 | path: path.join(__dirname, './build'), 18 | publicPath: '/build/' 19 | }, 20 | 21 | resolve: { 22 | extensions: ['', '.js', '.jsx'], 23 | modulesDirectories: ['src', 'node_modules'] 24 | }, 25 | 26 | module: { 27 | loaders: [ 28 | { 29 | test: /\.js?$/, 30 | loaders: ['react-hot', 'babel'], 31 | exclude: /node_modules/ 32 | }, 33 | ] 34 | }, 35 | 36 | plugins: [ 37 | new webpack.HotModuleReplacementPlugin(), 38 | new webpack.NoErrorsPlugin() 39 | ] 40 | 41 | }; -------------------------------------------------------------------------------- /webpack.production.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | module.exports = { 5 | entry: { 6 | app: ['./src/index'] 7 | }, 8 | 9 | output: { 10 | path: path.join(__dirname, './build'), 11 | filename: '[name].js' 12 | }, 13 | 14 | module: { 15 | loaders: [ 16 | { 17 | test: /\.jsx?$/, 18 | exclude: /node_modules/, 19 | loader: 'babel' 20 | } 21 | ] 22 | }, 23 | 24 | resolve: { 25 | extensions: ['', '.js', '.jsx'], 26 | modulesDirectories: ['src', 'node_modules'] 27 | }, 28 | 29 | plugins: [ 30 | new webpack.optimize.DedupePlugin(), 31 | new webpack.optimize.UglifyJsPlugin() 32 | ] 33 | }; 34 | -------------------------------------------------------------------------------- /webpack.test.bootstrap.js: -------------------------------------------------------------------------------- 1 | var context = require.context("./src", true, /\S+\/__test__\/\S+\.js$/); 2 | context.keys().forEach(context); 3 | -------------------------------------------------------------------------------- /webpack.test.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | module.exports = { 5 | entry: { 6 | test: [path.join(__dirname, 'webpack.test.bootstrap.js')] 7 | }, 8 | 9 | output: { 10 | path: path.join(__dirname, './build'), 11 | filename: '[name].js' 12 | }, 13 | 14 | module: { 15 | loaders: [ 16 | { 17 | test: /\.jsx?$/, 18 | exclude: /node_modules/, 19 | loader: 'babel' 20 | } 21 | ] 22 | }, 23 | 24 | resolve: { 25 | extensions: ['', '.js', '.jsx'], 26 | modulesDirectories: ['src', 'node_modules'] 27 | }, 28 | 29 | node: { 30 | fs: 'empty' 31 | } 32 | }; 33 | 34 | --------------------------------------------------------------------------------