├── .babelrc ├── .editorconfig ├── .eslintrc ├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── README.md ├── package.json ├── src ├── api │ ├── delay.js │ ├── mockAuthorApi.js │ └── mockCourseApi.js ├── index.html ├── index.js └── index.test.js ├── tools ├── srcServer.js ├── startMessage.js └── testSetup.js └── webpack.config.dev.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015"], 3 | "env": { 4 | "development": { 5 | "presets": ["react-hmre"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "plugin:import/errors", 5 | "plugin:import/warnings" 6 | ], 7 | "plugins": [ 8 | "react" 9 | ], 10 | "parserOptions": { 11 | "ecmaVersion": 6, 12 | "sourceType": "module", 13 | "ecmaFeatures": { 14 | "jsx": true 15 | } 16 | }, 17 | "env": { 18 | "es6": true, 19 | "browser": true, 20 | "node": true, 21 | "jquery": true, 22 | "mocha": true 23 | }, 24 | "rules": { 25 | "quotes": 0, 26 | "no-console": 1, 27 | "no-debugger": 1, 28 | "no-var": 1, 29 | "semi": [1, "always"], 30 | "no-trailing-spaces": 0, 31 | "eol-last": 0, 32 | "no-unused-vars": 0, 33 | "no-underscore-dangle": 0, 34 | "no-alert": 0, 35 | "no-lone-blocks": 0, 36 | "jsx-quotes": 1, 37 | "react/display-name": [ 1, {"ignoreTranspilerName": false }], 38 | "react/forbid-prop-types": [1, {"forbid": ["any"]}], 39 | "react/jsx-boolean-value": 1, 40 | "react/jsx-closing-bracket-location": 0, 41 | "react/jsx-curly-spacing": 1, 42 | "react/jsx-indent-props": 0, 43 | "react/jsx-key": 1, 44 | "react/jsx-max-props-per-line": 0, 45 | "react/jsx-no-bind": 1, 46 | "react/jsx-no-duplicate-props": 1, 47 | "react/jsx-no-literals": 0, 48 | "react/jsx-no-undef": 1, 49 | "react/jsx-pascal-case": 1, 50 | "react/jsx-sort-prop-types": 0, 51 | "react/jsx-sort-props": 0, 52 | "react/jsx-uses-react": 1, 53 | "react/jsx-uses-vars": 1, 54 | "react/no-danger": 1, 55 | "react/no-did-mount-set-state": 1, 56 | "react/no-did-update-set-state": 1, 57 | "react/no-direct-mutation-state": 1, 58 | "react/no-multi-comp": 1, 59 | "react/no-set-state": 0, 60 | "react/no-unknown-property": 1, 61 | "react/prefer-es6-class": 1, 62 | "react/prop-types": 1, 63 | "react/react-in-jsx-scope": 1, 64 | "react/require-extension": 1, 65 | "react/self-closing-comp": 1, 66 | "react/sort-comp": 1, 67 | "react/wrap-multilines": 1 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Wait, try this first... 2 | Before opening an issue, [please try these things first](https://github.com/coryhouse/pluralsight-redux-starter#having-issues-try-these-things-first). 3 | 4 | If that list doesn't help you fix the problem, fill out the info below. 5 | 6 | Node version: 7 | 8 | npm version: 9 | 10 | Operating system: 11 | 12 | Command line used: 13 | 14 | Steps to reproduce: 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | #dist folder 30 | dist 31 | 32 | #Webstorm metadata 33 | .idea 34 | 35 | # Mac files 36 | .DS_Store 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTE: This repo is archived. 2 | 3 | This repo contains code from the previous version of [Building Applications in React and Redux in ES6](http://www.pluralsight.com/author/cory-house). For the latest code, see the exercise files on the course page on Pluralsight. 4 | 5 | # Starter Kit for [Building Applications in React and Redux in ES6](http://www.pluralsight.com/author/cory-house) on Pluralsight 6 | 7 | ## Get Started 8 | 1. **Install [Node 6](https://nodejs.org)**. Need to run multiple versions of Node? Use [nvm](https://github.com/creationix/nvm) or [nvm-windows](https://github.com/coreybutler/nvm-windows) 9 | 2. **Clone this repository.** - `git clone https://github.com/coryhouse/pluralsight-redux-starter.git` or [download the zip](https://github.com/coryhouse/pluralsight-redux-starter/archive/master.zip) 10 | 3. **Make sure you're in the directory you just created.** - `cd pluralsight-redux-starter` 11 | 4. **Install Node Packages.** - `npm install` 12 | 5. **Run the app.** - `npm start -s` 13 | This will run the automated build process, start up a webserver, and open the application in your default browser. When doing development with this kit, this command will continue watching files all your files. Every time you hit save the code is rebuilt, linting runs, and tests run automatically. Note: The -s flag is optional. It enables silent mode which suppresses unnecessary messages during the build. 14 | 6. **[Disable safe write in your editor](https://webpack.js.org/guides/development/#adjusting-your-text-editor)** to assure hot reloading works properly. 15 | 7. **Install [React developer tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) and [Redux Dev Tools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en)** in Chrome. 16 | 8. Having issues? See below. 17 | 18 | ## Having Issues? Try these things first: 19 | 1. Run `npm install` - If you forget to do this, you'll see this: `babel-node: command not found`. 20 | 2. Make sure the path doesn't include any spaces, or install the latest version of eslint-watch which adds support for paths containing spaces: `npm install eslint-watch@2.1.13` 21 | 3. Make sure you're running the latest version of Node. Or, use [Node 5.12.0](https://nodejs.org/download/release/v5.12.0/) if you're having issues on Windows. Node 6 has issues on some Windows machines. 22 | 4. Make sure files with names that begin with a dot (.babelrc, .editorconfig, .eslintrc) are copied to the project directory root. This is easy to overlook if you copy this repository manually. 23 | 5. Don't run the project from a symbolic link. It will cause issues with file watches. 24 | 6. Use path.resolve on all path references in both the dev and prod webpack.config. [See this commit](https://github.com/coryhouse/pluralsight-redux-starter/commit/298848d4332d3bec9eb4e23592e710083acaf340) for an example. 25 | 7. Delete any .eslintrc in your user directory and disable any ESLint plugin / custom rules within your editor since these will conflict with the ESLint rules defined in the course. 26 | 8. On Windows? Open your console as an administrator. This will assure the console has the necessary rights to perform installs. 27 | 9. Try using your OS's native command line instead of an editor's. For some people, an editor's command line configuration may cause issues. 28 | 10. Ensure you do not have NODE_ENV=production in your env variables as it will not install the devDependencies. To check run this on the command line: `set NODE_ENV`. If it comes back as production, you need to clear this env variable. 29 | 11. Make sure you're using the same imports as the course demo. I've seen some people import ES6 code from node_modules via different imports like `import Route from "react-router/es6/Route";` and `import IndexRoute from "react-router/es6/IndexRoute";`. Don't do that. :) Use the exact imports I use in the course. 30 | 12. Reference bundle.js with a leading slash or [you'll get an unexpected token error on reload of deep links](https://github.com/coryhouse/pluralsight-redux-starter/issues/88). 31 | 13. Make sure you have a .babelrc file defined in the root, as provided in this repo. Without it, you'll get a `Unexpected token import` error. 32 | 14. Nothing above work? Delete your node_modules folder and re-run npm install. 33 | 34 | ### Production Dependencies 35 | | **Dependency** | **Use** | 36 | |----------|-------| 37 | |babel-polyfill | Polyfill for Babel features that cannot be transpiled | 38 | |bootstrap|CSS Framework| 39 | |jquery|Only used to support toastr| 40 | |react|React library | 41 | |react-dom|React library for DOM rendering | 42 | |react-redux|Redux library for connecting React components to Redux | 43 | |react-router|React library for routing | 44 | |react-router-redux|Keep React Router in sync with Redux application state| 45 | |redux|Library for unidirectional data flows | 46 | |redux-thunk|Async redux library| 47 | |toastr|Display messages to the user| 48 | 49 | ### Development Dependencies 50 | | **Dependency** | **Use** | 51 | |----------|-------| 52 | |babel-cli|Babel Command line interface | 53 | |babel-core|Babel Core for transpiling the new JavaScript to old | 54 | |babel-loader|Adds Babel support to Webpack | 55 | |babel-plugin-react-display-name| Add displayName to React.createClass calls | 56 | |babel-preset-es2015|Babel preset for ES2015| 57 | |babel-preset-react| Add JSX support to Babel | 58 | |babel-preset-react-hmre|Hot reloading preset for Babel| 59 | |babel-register|Register Babel to transpile our Mocha tests| 60 | |cheerio|Supports querying DOM with jQuery like syntax - Useful in testing and build process for HTML manipulation| 61 | |colors|Adds color support to terminal | 62 | |compression|Add gzip support to Express| 63 | |cross-env|Cross-environment friendly way to handle environment variables| 64 | |css-loader|Add CSS support to Webpack| 65 | |enzyme|Simplified JavaScript Testing utilities for React| 66 | |eslint|Lints JavaScript | 67 | |eslint-plugin-import|Advanced linting of ES6 imports| 68 | |eslint-plugin-react|Adds additional React-related rules to ESLint| 69 | |eslint-watch|Add watch functionality to ESLint | 70 | |eventsource-polyfill|Polyfill to support hot reloading in IE| 71 | |expect|Assertion library for use with Mocha| 72 | |express|Serves development and production builds| 73 | |extract-text-webpack-plugin| Extracts CSS into separate file for production build | 74 | |file-loader| Adds file loading support to Webpack | 75 | |jsdom|In-memory DOM for testing| 76 | |mocha| JavaScript testing library | 77 | |nock| Mock HTTP requests for testing | 78 | |npm-run-all| Display results of multiple commands on single command line | 79 | |open|Open app in default browser| 80 | |react-addons-test-utils| Adds React TestUtils | 81 | |redux-immutable-state-invariant|Warn when Redux state is mutated| 82 | |redux-mock-store|Mock Redux store for testing| 83 | |rimraf|Delete files | 84 | |style-loader| Add Style support to Webpack | 85 | |url-loader| Add url loading support to Webpack | 86 | |webpack| Bundler with plugin system and integrated development server | 87 | |webpack-dev-middleware| Adds middleware support to webpack | 88 | |webpack-hot-middleware| Adds hot reloading to webpack | 89 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pluralsight-redux-starter", 3 | "version": "1.0.0", 4 | "description": "Starter kit for React and Redux Pluralsight course by Cory House", 5 | "scripts": { 6 | "prestart": "babel-node tools/startMessage.js", 7 | "start": "npm-run-all --parallel test:watch open:src lint:watch", 8 | "open:src": "babel-node tools/srcServer.js", 9 | "lint": "node_modules/.bin/esw webpack.config.* src tools", 10 | "lint:watch": "npm run lint -- --watch", 11 | "test": "mocha --reporter progress tools/testSetup.js \"src/**/*.test.js\"", 12 | "test:watch": "npm run test -- --watch" 13 | }, 14 | "author": "Cory House", 15 | "license": "MIT", 16 | "dependencies": { 17 | "babel-polyfill": "6.8.0", 18 | "bootstrap": "3.3.6", 19 | "jquery": "2.2.3", 20 | "react": "15.0.2", 21 | "react-dom": "15.0.2", 22 | "react-redux": "4.4.5", 23 | "react-router": "2.4.0", 24 | "react-router-redux": "4.0.4", 25 | "redux": "3.5.2", 26 | "redux-thunk": "2.0.1", 27 | "toastr": "2.1.2" 28 | }, 29 | "devDependencies": { 30 | "babel-cli": "6.8.0", 31 | "babel-core": "6.8.0", 32 | "babel-loader": "6.2.4", 33 | "babel-plugin-react-display-name": "2.0.0", 34 | "babel-preset-es2015": "6.6.0", 35 | "babel-preset-react": "6.5.0", 36 | "babel-preset-react-hmre": "1.1.1", 37 | "babel-register": "6.8.0", 38 | "cheerio": "0.22.0", 39 | "colors": "1.1.2", 40 | "compression": "1.6.1", 41 | "cross-env": "1.0.7", 42 | "css-loader": "0.23.1", 43 | "enzyme": "2.2.0", 44 | "eslint": "2.9.0", 45 | "eslint-plugin-import": "1.6.1", 46 | "eslint-plugin-react": "5.0.1", 47 | "eslint-watch": "2.1.11", 48 | "eventsource-polyfill": "0.9.6", 49 | "expect": "1.19.0", 50 | "express": "4.13.4", 51 | "extract-text-webpack-plugin": "1.0.1", 52 | "file-loader": "0.8.5", 53 | "jsdom": "8.5.0", 54 | "mocha": "2.4.5", 55 | "nock": "8.0.0", 56 | "npm-run-all": "1.8.0", 57 | "open": "0.0.5", 58 | "react-addons-test-utils": "15.0.2", 59 | "redux-immutable-state-invariant": "1.2.3", 60 | "redux-mock-store": "1.0.2", 61 | "rimraf": "2.5.2", 62 | "style-loader": "0.13.1", 63 | "url-loader": "0.5.7", 64 | "webpack": "1.13.0", 65 | "webpack-dev-middleware": "1.6.1", 66 | "webpack-hot-middleware": "2.10.0" 67 | }, 68 | "repository": { 69 | "type": "git", 70 | "url": "https://github.com/coryhouse/pluralsight-redux-starter" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/api/delay.js: -------------------------------------------------------------------------------- 1 | export default 0; 2 | -------------------------------------------------------------------------------- /src/api/mockAuthorApi.js: -------------------------------------------------------------------------------- 1 | import delay from './delay'; 2 | 3 | // This file mocks a web API by working with the hard-coded data below. 4 | // It uses setTimeout to simulate the delay of an AJAX call. 5 | // All calls return promises. 6 | const authors = [ 7 | { 8 | id: 'cory-house', 9 | firstName: 'Cory', 10 | lastName: 'House' 11 | }, 12 | { 13 | id: 'scott-allen', 14 | firstName: 'Scott', 15 | lastName: 'Allen' 16 | }, 17 | { 18 | id: 'dan-wahlin', 19 | firstName: 'Dan', 20 | lastName: 'Wahlin' 21 | } 22 | ]; 23 | 24 | //This would be performed on the server in a real app. Just stubbing in. 25 | const generateId = (author) => { 26 | return author.firstName.toLowerCase() + '-' + author.lastName.toLowerCase(); 27 | }; 28 | 29 | class AuthorApi { 30 | static getAllAuthors() { 31 | return new Promise((resolve, reject) => { 32 | setTimeout(() => { 33 | resolve(Object.assign([], authors)); 34 | }, delay); 35 | }); 36 | } 37 | 38 | static saveAuthor(author) { 39 | author = Object.assign({}, author); // to avoid manipulating object passed in. 40 | return new Promise((resolve, reject) => { 41 | setTimeout(() => { 42 | // Simulate server-side validation 43 | const minAuthorNameLength = 3; 44 | if (author.firstName.length < minAuthorNameLength) { 45 | reject(`First Name must be at least ${minAuthorNameLength} characters.`); 46 | } 47 | 48 | if (author.lastName.length < minAuthorNameLength) { 49 | reject(`Last Name must be at least ${minAuthorNameLength} characters.`); 50 | } 51 | 52 | if (author.id) { 53 | const existingAuthorIndex = authors.findIndex(a => a.id == author.id); 54 | authors.splice(existingAuthorIndex, 1, author); 55 | } else { 56 | //Just simulating creation here. 57 | //The server would generate ids for new authors in a real app. 58 | //Cloning so copy returned is passed by value rather than by reference. 59 | author.id = generateId(author); 60 | authors.push(author); 61 | } 62 | 63 | resolve(author); 64 | }, delay); 65 | }); 66 | } 67 | 68 | static deleteAuthor(authorId) { 69 | return new Promise((resolve, reject) => { 70 | setTimeout(() => { 71 | const indexOfAuthorToDelete = authors.findIndex(author => { 72 | author.id == authorId; 73 | }); 74 | authors.splice(indexOfAuthorToDelete, 1); 75 | resolve(); 76 | }, delay); 77 | }); 78 | } 79 | } 80 | 81 | export default AuthorApi; 82 | -------------------------------------------------------------------------------- /src/api/mockCourseApi.js: -------------------------------------------------------------------------------- 1 | import delay from './delay'; 2 | 3 | // This file mocks a web API by working with the hard-coded data below. 4 | // It uses setTimeout to simulate the delay of an AJAX call. 5 | // All calls return promises. 6 | const courses = [ 7 | { 8 | id: "react-flux-building-applications", 9 | title: "Building Applications in React and Flux", 10 | watchHref: "http://www.pluralsight.com/courses/react-flux-building-applications", 11 | authorId: "cory-house", 12 | length: "5:08", 13 | category: "JavaScript" 14 | }, 15 | { 16 | id: "clean-code", 17 | title: "Clean Code: Writing Code for Humans", 18 | watchHref: "http://www.pluralsight.com/courses/writing-clean-code-humans", 19 | authorId: "cory-house", 20 | length: "3:10", 21 | category: "Software Practices" 22 | }, 23 | { 24 | id: "architecture", 25 | title: "Architecting Applications for the Real World", 26 | watchHref: "http://www.pluralsight.com/courses/architecting-applications-dotnet", 27 | authorId: "cory-house", 28 | length: "2:52", 29 | category: "Software Architecture" 30 | }, 31 | { 32 | id: "career-reboot-for-developer-mind", 33 | title: "Becoming an Outlier: Reprogramming the Developer Mind", 34 | watchHref: "http://www.pluralsight.com/courses/career-reboot-for-developer-mind", 35 | authorId: "cory-house", 36 | length: "2:30", 37 | category: "Career" 38 | }, 39 | { 40 | id: "web-components-shadow-dom", 41 | title: "Web Component Fundamentals", 42 | watchHref: "http://www.pluralsight.com/courses/web-components-shadow-dom", 43 | authorId: "cory-house", 44 | length: "5:10", 45 | category: "HTML5" 46 | } 47 | ]; 48 | 49 | function replaceAll(str, find, replace) { 50 | return str.replace(new RegExp(find, 'g'), replace); 51 | } 52 | 53 | //This would be performed on the server in a real app. Just stubbing in. 54 | const generateId = (course) => { 55 | return replaceAll(course.title, ' ', '-'); 56 | }; 57 | 58 | class CourseApi { 59 | static getAllCourses() { 60 | return new Promise((resolve, reject) => { 61 | setTimeout(() => { 62 | resolve(Object.assign([], courses)); 63 | }, delay); 64 | }); 65 | } 66 | 67 | static saveCourse(course) { 68 | course = Object.assign({}, course); // to avoid manipulating object passed in. 69 | return new Promise((resolve, reject) => { 70 | setTimeout(() => { 71 | // Simulate server-side validation 72 | const minCourseTitleLength = 1; 73 | if (course.title.length < minCourseTitleLength) { 74 | reject(`Title must be at least ${minCourseTitleLength} characters.`); 75 | } 76 | 77 | if (course.id) { 78 | const existingCourseIndex = courses.findIndex(a => a.id == course.id); 79 | courses.splice(existingCourseIndex, 1, course); 80 | } else { 81 | //Just simulating creation here. 82 | //The server would generate ids and watchHref's for new courses in a real app. 83 | //Cloning so copy returned is passed by value rather than by reference. 84 | course.id = generateId(course); 85 | course.watchHref = `http://www.pluralsight.com/courses/${course.id}`; 86 | courses.push(course); 87 | } 88 | 89 | resolve(course); 90 | }, delay); 91 | }); 92 | } 93 | 94 | static deleteCourse(courseId) { 95 | return new Promise((resolve, reject) => { 96 | setTimeout(() => { 97 | const indexOfCourseToDelete = courses.findIndex(course => { 98 | course.id == courseId; 99 | }); 100 | courses.splice(indexOfCourseToDelete, 1); 101 | resolve(); 102 | }, delay); 103 | }); 104 | } 105 | } 106 | 107 | export default CourseApi; 108 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Pluralsight Admin 5 | 6 | 7 |

React and Redux in ES6 on Pluralsight

8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | console.log('hi'); 3 | -------------------------------------------------------------------------------- /src/index.test.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | 3 | describe('Our first test', () => { 4 | it('should pass', () => { 5 | expect(true).toEqual(true); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /tools/srcServer.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import webpack from 'webpack'; 3 | import path from 'path'; 4 | import config from '../webpack.config.dev'; 5 | import open from 'open'; 6 | 7 | /* eslint-disable no-console */ 8 | 9 | const port = 3000; 10 | const app = express(); 11 | const compiler = webpack(config); 12 | 13 | app.use(require('webpack-dev-middleware')(compiler, { 14 | noInfo: true, 15 | publicPath: config.output.publicPath 16 | })); 17 | 18 | app.use(require('webpack-hot-middleware')(compiler)); 19 | 20 | app.get('*', function(req, res) { 21 | res.sendFile(path.join( __dirname, '../src/index.html')); 22 | }); 23 | 24 | app.listen(port, function(err) { 25 | if (err) { 26 | console.log(err); 27 | } else { 28 | open(`http://localhost:${port}`); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /tools/startMessage.js: -------------------------------------------------------------------------------- 1 | import colors from 'colors'; 2 | 3 | /* eslint-disable no-console */ 4 | 5 | console.log('Starting app in dev mode...'.green); 6 | 7 | -------------------------------------------------------------------------------- /tools/testSetup.js: -------------------------------------------------------------------------------- 1 | // This file is written in ES5 since it's not transpiled by Babel. 2 | // This file does the following: 3 | // 1. Sets Node environment variable 4 | // 2. Registers babel for transpiling our code for testing 5 | // 3. Disables Webpack-specific features that Mocha doesn't understand. 6 | // 4. Requires jsdom so we can test via an in-memory DOM in Node 7 | // 5. Sets up global vars that mimic a browser. 8 | 9 | /* eslint-disable no-var*/ 10 | 11 | /* This setting assures the .babelrc dev config (which includes 12 | hot module reloading code) doesn't apply for tests. 13 | But also, we don't want to set it to production here for 14 | two reasons: 15 | 1. You won't see any PropType validation warnings when 16 | code is running in prod mode. 17 | 2. Tests will not display detailed error messages 18 | when running against production version code 19 | */ 20 | process.env.NODE_ENV = 'test'; 21 | 22 | // Register babel so that it will transpile ES6 to ES5 23 | // before our tests run. 24 | require('babel-register')(); 25 | 26 | // Disable webpack-specific features for tests since 27 | // Mocha doesn't know what to do with them. 28 | require.extensions['.css'] = function () {return null;}; 29 | require.extensions['.png'] = function () {return null;}; 30 | require.extensions['.jpg'] = function () {return null;}; 31 | 32 | // Configure JSDOM and set global variables 33 | // to simulate a browser environment for tests. 34 | var jsdom = require('jsdom').jsdom; 35 | 36 | var exposedProperties = ['window', 'navigator', 'document']; 37 | 38 | global.document = jsdom(''); 39 | global.window = document.defaultView; 40 | Object.keys(document.defaultView).forEach((property) => { 41 | if (typeof global[property] === 'undefined') { 42 | exposedProperties.push(property); 43 | global[property] = document.defaultView[property]; 44 | } 45 | }); 46 | 47 | global.navigator = { 48 | userAgent: 'node.js' 49 | }; 50 | 51 | documentRef = document; //eslint-disable-line no-undef 52 | -------------------------------------------------------------------------------- /webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | import path from 'path'; 3 | 4 | export default { 5 | debug: true, 6 | devtool: 'inline-source-map', 7 | noInfo: false, 8 | entry: [ 9 | 'eventsource-polyfill', // necessary for hot reloading with IE 10 | 'webpack-hot-middleware/client?reload=true', //note that it reloads the page if hot module reloading fails. 11 | path.resolve(__dirname, 'src/index') 12 | ], 13 | target: 'web', 14 | output: { 15 | path: __dirname + '/dist', // Note: Physical files are only output by the production build task `npm run build`. 16 | publicPath: '/', 17 | filename: 'bundle.js' 18 | }, 19 | devServer: { 20 | contentBase: path.resolve(__dirname, 'src') 21 | }, 22 | plugins: [ 23 | new webpack.HotModuleReplacementPlugin(), 24 | new webpack.NoErrorsPlugin() 25 | ], 26 | module: { 27 | loaders: [ 28 | {test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']}, 29 | {test: /(\.css)$/, loaders: ['style', 'css']}, 30 | {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'}, 31 | {test: /\.(woff|woff2)$/, loader: 'url?prefix=font/&limit=5000'}, 32 | {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'}, 33 | {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'} 34 | ] 35 | } 36 | }; 37 | --------------------------------------------------------------------------------