├── __styles └── index.styl ├── .gitignore ├── preprocessor.js ├── __app ├── index.js └── components │ └── CheckboxWithLabel.js ├── __web └── index.html ├── __tests__ └── components │ └── CheckboxWithLabel-spec.js ├── package.json ├── README.md └── gulpfile.js /__styles/index.styl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built output 2 | public 3 | build 4 | 5 | # Dependency directory 6 | node_modules 7 | -------------------------------------------------------------------------------- /preprocessor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var ReactTools = require('react-tools'); 4 | module.exports = { 5 | process: function(src) { 6 | return ReactTools.transform(src); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /__app/index.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | var CheckboxWithLabel = require('./components/CheckboxWithLabel'); 3 | var react = require('react'); 4 | var el = document.getElementsByTagName('body')[0]; 5 | react.renderComponent(, el); 6 | -------------------------------------------------------------------------------- /__web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /__app/components/CheckboxWithLabel.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 'use strict'; 3 | 4 | var React = require('react/addons'); 5 | var CheckboxWithLabel = React.createClass({ 6 | getInitialState: function() { 7 | return { isChecked: false }; 8 | }, 9 | onChange: function() { 10 | this.setState({isChecked: !this.state.isChecked}); 11 | }, 12 | render: function() { 13 | return ( 14 | 22 | ); 23 | } 24 | }); 25 | module.exports = CheckboxWithLabel; 26 | -------------------------------------------------------------------------------- /__tests__/components/CheckboxWithLabel-spec.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 'use strict'; 3 | jest.dontMock('./../../__app/components/CheckboxWithLabel'); 4 | describe('CheckboxWithLabel', function() { 5 | it('changes the text after click', function() { 6 | var React = require('react/addons'); 7 | var CheckboxWithLabel = require('./../../__app/components/CheckboxWithLabel'); 8 | var TestUtils = React.addons.TestUtils; 9 | 10 | // Render a checkbox with label in the document 11 | var checkbox = TestUtils.renderIntoDocument( 12 | 13 | ); 14 | 15 | // Verify that it's Off by default 16 | var label = TestUtils.findRenderedDOMComponentWithTag( 17 | checkbox, 'label'); 18 | expect(label.getDOMNode().textContent).toEqual('Off'); 19 | 20 | // Simulate a click and verify that it is now On 21 | var input = TestUtils.findRenderedDOMComponentWithTag( 22 | checkbox, 'input'); 23 | TestUtils.Simulate.change(input); 24 | expect(label.getDOMNode().textContent).toEqual('On'); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jbrg", 3 | "version": "0.0.0", 4 | "description": "JestJS + Browserify + React + gulp", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest", 8 | "dev": "gulp dev", 9 | "build": "gulp build" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/andrew-codes/jbrg.git" 14 | }, 15 | "author": "Andrew Smith ", 16 | "license": "BSD-2-Clause", 17 | "bugs": { 18 | "url": "https://github.com/andrew-codes/jbrg/issues" 19 | }, 20 | "devDependencies": { 21 | "gulp": "~3.8.7", 22 | "jest-cli": "~0.1.18", 23 | "gulp-stylus": "~1.3.0", 24 | "gulp-autoprefixer": "0.0.10", 25 | "gulp-browserify": "~0.5.0", 26 | "gulp-rename": "~1.2.0", 27 | "gulp-shell": "~0.2.9", 28 | "gulp-minify-css": "~0.3.8", 29 | "gulp-uglify": "~1.0.1", 30 | "gulp-jshint": "~1.8.4", 31 | "gulp-connect": "~2.0.6", 32 | "gulp-clean": "~0.3.1", 33 | "browserify-shim": "~3.7.0", 34 | "react": "~0.11.1", 35 | "react-tools": "~0.11.1", 36 | "gulp-react": "~1.0.0" 37 | }, 38 | "jest": { 39 | "unmockedModulePathPatterns": [ 40 | "./node_modules" 41 | ], 42 | "scriptPreprocessor": "./preprocessor.js" 43 | }, 44 | "browserify-shim": { 45 | "underscore": "global:_", 46 | "react": "React" 47 | }, 48 | "browserify": { 49 | "transform": [ 50 | "browserify-shim" 51 | ] 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Front-end Bootstrap with React + Jest + Browserify + Gulp 2 | 3 | This is a bootstrap project to help you get started quickly with a front-end project using React, Jest, Browserify, and gulp. 4 | 5 | ## Quick Start 6 | ```shell 7 | npm install 8 | 9 | # Run tests 10 | npm test 11 | 12 | # Build output 13 | npm run build 14 | 15 | # Build output and then start local server at http://localhost 16 | npm run dev 17 | ``` 18 | 19 | ## Adding Additional Third-Party Dependencies 20 | Third-party dependencies are included via a CDN instead of with Bower. This is done by design to utilize the caching of common libraries in end-users' browsers. In order to include a new dependency, follow the steps below: 21 | 22 | 1. Include a script reference in the `__web/index.html` to their hosted CDN URL. 23 | 2. Include a reference to the library in `package.json` under `browserify-shim`. As an example: if you are using `require('jquery')` in your application, then you must tell browserify where `'jquery'` comes from. The shim in `package.json` gives you the ability to associate a name, `'jquery'` with its reference, `$` found in the global namespace. 24 | 3. [Optional]: By default Jest mocks all dependencies unless otherwise specified. If you wish Jest to not mock a dependency that is a third-party dependnecy, then you must install the dependency as a npm package. The reason why is so that when Jest encounters a `require('underscore')`, for example, and underscore is not mocked, it will look to require it from your npm modules. 25 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var connect = require('gulp-connect'); 5 | var clean = require('gulp-clean'); 6 | var stylus = require('gulp-stylus'); 7 | var browserify = require('gulp-browserify'); 8 | var minifyCss = require('gulp-minify-css'); 9 | var autoPrefix = require('gulp-autoprefixer'); 10 | var rename = require('gulp-rename'); 11 | var uglify = require('gulp-uglify'); 12 | var shell = require('gulp-shell'); 13 | var react = require('gulp-react'); 14 | 15 | var config = { 16 | dest: './public', 17 | html: { 18 | src: './__web/index.html', 19 | dest: './public' 20 | }, 21 | styles: { 22 | src: './__styles/index.styl', 23 | name: 'app.css', 24 | dest: './public/css' 25 | }, 26 | scripts: { 27 | src: './__app/**/*.js', 28 | build: './build', 29 | entry: './build/index.js', 30 | name: 'app.js', 31 | dest: './public/js' 32 | } 33 | }; 34 | 35 | gulp.task('dev', ['build'], function() { 36 | return connect.server({ 37 | root: config.dest, 38 | livereload: true 39 | }); 40 | }); 41 | 42 | gulp.task('build', ['assemble-html', 'assemble-styles', 'assemble-scripts'], function() { 43 | 44 | }); 45 | 46 | gulp.task('assemble-html', ['clean'], function() { 47 | return gulp.src(config.html.src) 48 | .pipe(gulp.dest(config.html.dest)); 49 | }); 50 | 51 | gulp.task('clean', [], function() { 52 | return gulp.src([config.dest, config.scripts.build], { 53 | read: false 54 | }) 55 | .pipe(clean()); 56 | }); 57 | 58 | gulp.task('assemble-styles', ['clean'], function() { 59 | return gulp.src(config.styles.src) 60 | .pipe(stylus()) 61 | .pipe(autoPrefix()) 62 | .pipe(minifyCss()) 63 | .pipe(rename(config.styles.name)) 64 | .pipe(gulp.dest(config.styles.dest)); 65 | }); 66 | 67 | gulp.task('assemble-scripts', ['reactify-scripts'], function() { 68 | return gulp.src(config.scripts.entry) 69 | .pipe(browserify()) 70 | .pipe(uglify()) 71 | .pipe(rename(config.scripts.name)) 72 | .pipe(gulp.dest(config.scripts.dest)); 73 | }); 74 | 75 | gulp.task('reactify-scripts', ['clean'], function() { 76 | return gulp.src(config.scripts.src) 77 | .pipe(react()) 78 | .pipe(gulp.dest(config.scripts.build)); 79 | }); 80 | 81 | gulp.task('test-unit', shell.task(['npm test'])); 82 | --------------------------------------------------------------------------------