From e3e4585b96941dd0e4637832a424b0cd1f7aa4f3 Mon Sep 17 00:00:00 2001 From: Aries McRae Date: Fri, 17 Mar 2017 22:18:22 +1100 Subject: [PATCH 01/55] Change build system to create-react-app --- .babelrc | 16 - .editorconfig | 31 - .eslintrc.yaml | 72 - .gitignore | 22 +- LICENSE | 22 - package.json | 69 +- public/favicon.ico | Bin 0 -> 24838 bytes public/index.html | 15 + scripts/build.js | 34 - scripts/serverDev.js | 35 - scripts/serverProd.js | 30 - scripts/startMessage.js | 3 - scripts/testSetup.js | 39 - src/favicon.ico | Bin 26238 -> 0 bytes src/index.html | 16 - src/index.js | 2 +- src/vendor.js | 27 - test/action/ApiAction.test.js | 31 - test/action/AuthorAction.test.js | 65 - test/action/CourseAction.test.js | 215 -- test/components/About.test.js | 16 - test/components/App.test.js | 24 - test/components/common/FieldInput.test.js | 23 - test/components/common/PageNotFound.test.js | 14 - test/components/common/SelectInput.test.js | 22 - test/components/common/Spinner.test.js | 13 - .../course/AddOrEditCourseContainer.test.js | 39 - test/components/course/CourseForm.test.js | 41 - test/components/course/CourseList.test.js | 22 - .../course/CourseListContainer.test.js | 32 - test/components/course/CourseListRow.test.js | 19 - test/components/landing/Footer.test.js | 21 - test/components/landing/Header.test.js | 21 - .../landing/HeaderNavContainer.test.js | 18 - test/components/landing/Home.test.js | 18 - test/components/landing/Section.test.js | 17 - test/reducer/apiReducer.test.js | 48 - test/reducer/authorReducer.test.js | 36 - test/reducer/coursesReducer.test.js | 63 - test/selectors/Selectors.test.js | 21 - webpack.config.dev.js | 55 - webpack.config.prod.js | 88 - yarn.lock | 2478 +++++++++-------- 43 files changed, 1333 insertions(+), 2560 deletions(-) delete mode 100644 .babelrc delete mode 100644 .editorconfig delete mode 100644 .eslintrc.yaml delete mode 100644 LICENSE create mode 100644 public/favicon.ico create mode 100644 public/index.html delete mode 100644 scripts/build.js delete mode 100644 scripts/serverDev.js delete mode 100644 scripts/serverProd.js delete mode 100644 scripts/startMessage.js delete mode 100644 scripts/testSetup.js delete mode 100644 src/favicon.ico delete mode 100644 src/index.html delete mode 100644 src/vendor.js delete mode 100644 test/action/ApiAction.test.js delete mode 100644 test/action/AuthorAction.test.js delete mode 100644 test/action/CourseAction.test.js delete mode 100644 test/components/About.test.js delete mode 100644 test/components/App.test.js delete mode 100644 test/components/common/FieldInput.test.js delete mode 100644 test/components/common/PageNotFound.test.js delete mode 100644 test/components/common/SelectInput.test.js delete mode 100644 test/components/common/Spinner.test.js delete mode 100644 test/components/course/AddOrEditCourseContainer.test.js delete mode 100644 test/components/course/CourseForm.test.js delete mode 100644 test/components/course/CourseList.test.js delete mode 100644 test/components/course/CourseListContainer.test.js delete mode 100644 test/components/course/CourseListRow.test.js delete mode 100644 test/components/landing/Footer.test.js delete mode 100644 test/components/landing/Header.test.js delete mode 100644 test/components/landing/HeaderNavContainer.test.js delete mode 100644 test/components/landing/Home.test.js delete mode 100644 test/components/landing/Section.test.js delete mode 100644 test/reducer/apiReducer.test.js delete mode 100644 test/reducer/authorReducer.test.js delete mode 100644 test/reducer/coursesReducer.test.js delete mode 100644 test/selectors/Selectors.test.js delete mode 100644 webpack.config.dev.js delete mode 100644 webpack.config.prod.js diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 20c8880..0000000 --- a/.babelrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "presets": [ - ["latest", {"modules": false}], - "react" - ], - - "plugins": ["transform-object-rest-spread"], - - "env": { - "development": { - "presets": ["react-hmre"] - } - } - - -} diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 60ed390..0000000 --- a/.editorconfig +++ /dev/null @@ -1,31 +0,0 @@ -# Go to editorconfig.org to install the plugin for your appropriate editor. - - -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -end_of_line = lf -insert_final_newline = true -trim_training_whitespace = true - -# Matches multiple files with brace expansion notation -# Set default charset -[*.{js,java}] -charset = utf-8 - -# 4 space indentation -[*.{js,java}] -indent_style = space -indent_size = 4 - -# Indentation override for all JS under lib directory -[lib/**.js] -indent_style = space -indent_size = 4 - -# Matches the exact files either package.json or .travis.yml -[{package.json}] -indent_style = space -indent_size = 4 diff --git a/.eslintrc.yaml b/.eslintrc.yaml deleted file mode 100644 index 50fc55a..0000000 --- a/.eslintrc.yaml +++ /dev/null @@ -1,72 +0,0 @@ -root: true - -extends: - - eslint:recommended - - plugin:import/errors - - plugin:import/warnings - -plugins: [ react, jsx-a11y ] - - -parserOptions: - ecmaVersion: 7 - sourceType: module - ecmaFeatures: - jsx: true - -env: - es6: true - browser: true - node: true - mocha: true - -parser: 'babel-eslint' - -rules: - quotes: 0 - no-console: 1 - no-debugger: 1 - no-var: 1 - semi: [1, "always"] - no-trailing-spaces: 0 - eol-last: 0 - no-unused-vars: 1 - no-underscore-dangle: 0 - no-alert: 0 - no-lone-blocks: 0 - jsx-quotes: 1 - react/display-name: [ 1, ignoreTranspilerName: false ] - react/forbid-prop-types: [1, forbid: [any]] - react/jsx-boolean-value: 1 - react/jsx-closing-bracket-location: 0 - react/jsx-curly-spacing: 1 - react/jsx-indent-props: 0 - react/jsx-key: 1 - react/jsx-max-props-per-line: 0 - react/jsx-no-bind: 1 - react/jsx-no-duplicate-props: 1 - react/jsx-no-literals: 0 - react/jsx-no-undef: 1 - react/jsx-pascal-case: 1 - react/jsx-sort-prop-types: 0 - react/jsx-sort-props: 0 - react/jsx-uses-react: 1 - react/jsx-uses-vars: 1 - jsx-a11y/img-has-alt: 1 - react/no-danger: 1 - react/no-did-mount-set-state: 1 - react/no-did-update-set-state: 1 - react/no-direct-mutation-state: 1 - react/no-multi-comp: 1 - react/no-set-state: 0 - react/no-unknown-property: 1 - react/prefer-es6-class: 1 - react/prop-types: 1 - react/react-in-jsx-scope: 1 - import/extensions: 1 - react/self-closing-comp: 1 - react/sort-comp: 1 - react/jsx-wrap-multilines: 1 - eqeqeq: 1 - array-callback-return: 1 - no-unused-expressions: 1 \ No newline at end of file diff --git a/.gitignore b/.gitignore index e76eabf..927d17b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,18 @@ -# Logs -npm-debug.log* +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# dependencies +/node_modules + +# testing +/coverage -# Dependency directories -node_modules -src/api/db.json +# production +/build + +# misc +.DS_Store +.env +npm-debug.log* +yarn-debug.log* +yarn-error.log* -dist/ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 24fd4c2..0000000 --- a/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright for portions of this project are held by Cory House 2016 as part of project 'javascript-development-environment'. -All other copyright for this project are held by Aries McRae, 2017. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/package.json b/package.json index c45dc97..f457ac6 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "reactjs-crud-starterkit", - "description": "ReactJS CRUD Starter Kit", + "name": "reactjs-crud-boilerplate", + "description": "ReactJS CRUD Boilerplate", "version": "0.0.2", - "main": "index.js", - "repository": "https://github.com/ariesmcrae/reactjs-crud-starter-kit.git", + "private": false, + "repository": "https://github.com/ariesmcrae/reactjs-crud-boilerplate.git", "author": "Aries McRae ", "license": "MIT", "keywords": [ @@ -12,20 +12,6 @@ "Starter Project", "Seed" ], - "scripts": { - "prestart": "babel-node scripts/startMessage.js", - "start": "npm-run-all --parallel security-check lint:watch test:watch startServerDev", - "startServerDev": "babel-node ./scripts/serverDev.js", - "security-check": "nsp check", - "lint": "esw webpack.config.* src scripts --color", - "lint:watch": "yarn lint -- --watch", - "test": "mocha --reporter spec --compilers scripts/testSetup.js --recursive test", - "test:watch": "yarn test -- --watch", - "clean-dist": "node_modules/.bin/rimraf dist && mkdir dist", - "prebuild": "npm-run-all clean-dist test lint", - "build": "babel-node scripts/build.js", - "postbuild": "babel-node scripts/serverProd.js" - }, "dependencies": { "bootstrap": "4.0.0-alpha.6", "font-awesome": "^4.7.0", @@ -42,43 +28,12 @@ "toastr": "^2.1.2" }, "devDependencies": { - "babel-cli": "^6.24.0", - "babel-core": "^6.24.0", - "babel-eslint": "^7.1.1", - "babel-loader": "^6.4.1", - "babel-plugin-transform-object-rest-spread": "^6.23.0", - "babel-preset-latest": "^6.24.0", - "babel-preset-react": "^6.23.0", - "babel-preset-react-hmre": "^1.1.1", - "babel-register": "^6.24.0", - "chai": "^3.5.0", - "chalk": "^1.1.3", - "compression": "^1.6.2", - "css-loader": "^0.27.3", - "enzyme": "^2.7.1", - "eslint": "^3.15.0", - "eslint-plugin-import": "^2.2.0", - "eslint-plugin-jsx-a11y": "^4.0.0", - "eslint-plugin-react": "^6.9.0", - "eslint-watch": "^3.0.0", - "express": "^4.14.1", - "extract-text-webpack-plugin": "^2.0.0", - "file-loader": "^0.10.0", - "html-webpack-plugin": "^2.28.0", - "jsdom": "^9.12.0", - "mocha": "^3.2.0", - "nock": "^9.0.9", - "npm-run-all": "^4.0.1", - "nsp": "^2.6.2", - "open": "^0.0.5", - "react-addons-test-utils": "^15.4.2", - "redux-mock-store": "^1.2.2", - "rimraf": "^2.5.4", - "style-loader": "^0.14.1", - "url-loader": "^0.5.7", - "webpack": "^2.2.1", - "webpack-dev-middleware": "^1.10.0", - "webpack-hot-middleware": "^2.16.1", - "webpack-md5-hash": "^0.0.5" + "react-scripts": "0.9.5" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" } -} +} \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5c125de5d897c1ff5692a656485b3216123dcd89 GIT binary patch literal 24838 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 + + + + + + ReactJS CRUD Boilerplate + + +
+ + + + + diff --git a/scripts/build.js b/scripts/build.js deleted file mode 100644 index adff3fe..0000000 --- a/scripts/build.js +++ /dev/null @@ -1,34 +0,0 @@ -/*eslint-disable no-console */ -import webpack from 'webpack'; -import webpackConfig from '../webpack.config.prod'; -import chalk from 'chalk'; - - -process.env.NODE_ENV = 'production'; // this assures the Babel dev config (for hot reloading) doesn't apply. - -console.log(chalk.blue('Generating minified bundle for production. This will take a moment...')); - -webpack(webpackConfig).run((err, stats) => { - if (err) { - console.log(chalk.red(err)); - return 1; - } - - const jsonStats = stats.toJson(); - - if (jsonStats.hasErrors) { - return jsonStats.errors.map(error => console.log(chalk.red(error))); - } - - if (jsonStats.hasWarnings) { - console.log(chalk.yellow('Webpack generated the following warnings: ')); - jsonStats.warnings.map(warning => console.log(chalk.yellow(warning))); - } - - console.log(`Webpack stats: ${stats}`); - - // if we got this far, the build succeeded. - console.log(chalk.green('Your app has been built for production and written to /dist!')); - - return 0; -}); diff --git a/scripts/serverDev.js b/scripts/serverDev.js deleted file mode 100644 index 608a915..0000000 --- a/scripts/serverDev.js +++ /dev/null @@ -1,35 +0,0 @@ -import express from 'express'; -import path from 'path'; -import open from 'open'; -import webpack from 'webpack'; -import webpackConfig from '../webpack.config.dev'; -import chalk from 'chalk'; - - -/* eslint-disable no-console */ -const port = 3000; -const app = express(); -const compiler = webpack(webpackConfig); - - -app.use(require('webpack-dev-middleware')(compiler,{ - noInfo: true, - publicPath: webpackConfig.output.publicPath -})); - -app.use(require("webpack-hot-middleware")(compiler)); - -app.get('*', function(request, response) { - response.sendFile(path.join(__dirname, '../src/index.html')); -}); - - -app.listen(port, function(err) { - if (err) { - console.log(err); - } else { - const uri = `http://localhost:${port}`; - console.log(chalk.green(`Server started on ${uri}`)); //eslint-disable-line no-console - open(uri); - } -}); diff --git a/scripts/serverProd.js b/scripts/serverProd.js deleted file mode 100644 index 822f591..0000000 --- a/scripts/serverProd.js +++ /dev/null @@ -1,30 +0,0 @@ -import express from 'express'; -import path from 'path'; -import open from 'open'; -import compression from 'compression'; - - -/* eslint-disable no-console */ -const port = 3000; -const app = express(); - -//gzip -app.use(compression()); - -//Express to serve static files -app.use(express.static('dist')); - - -app.get('*', function(request, response) { - response.sendFile(path.join(__dirname, '../dist/index.html')); -}); - - - -app.listen(port, function(err) { - if (err) { - console.log(err); - } else { - open(`http://localhost:${port}`); - } -}); diff --git a/scripts/startMessage.js b/scripts/startMessage.js deleted file mode 100644 index 8c1100e..0000000 --- a/scripts/startMessage.js +++ /dev/null @@ -1,3 +0,0 @@ -import chalk from 'chalk'; - -console.log(chalk.green('Starting app in dev mode...')); //eslint-disable-line no-console diff --git a/scripts/testSetup.js b/scripts/testSetup.js deleted file mode 100644 index 72928c5..0000000 --- a/scripts/testSetup.js +++ /dev/null @@ -1,39 +0,0 @@ -// This file is written in ES5/CommonJS sice it's not transpiled by Babel. - -/* eslint-disable no-var*/ - -/* This setting assures the .babelrc dev config doesn't apply for tests. - Also, we don't want to set it to production here for two reasons: - 1. You won't see any PropType validation warnings when code is running in prod mode. - 2. Tests will not display detailed error messages when running against production version code - */ -process.env.NODE_ENV = 'test'; - -// Register babel so that it will transpile ES6 to ES5 before our tests run. -require('babel-register')(); - -// Disable Webpack features that Mocha doesn't understand. -// If Mocha sees this, then just treat it as an empty function. -require.extensions['.css'] = function() {}; -require.extensions['.png'] = function() {}; -require.extensions['.jpg'] = function() {}; - -// Configure JSDOM and set global variables to simulate a browser environment for tests. -var jsdom = require('jsdom').jsdom; - -var exposedProperties = ['window', 'navigator', 'document']; - -global.document = jsdom(''); -global.window = document.defaultView; -Object.keys(document.defaultView).forEach((property) => { - if (typeof global[property] === 'undefined') { - exposedProperties.push(property); - global[property] = document.defaultView[property]; - } -}); - -global.navigator = { - userAgent: 'node.js' -}; - -documentRef = document; //eslint-disable-line no-undef diff --git a/src/favicon.ico b/src/favicon.ico deleted file mode 100644 index 6621f9f7c947b439e6aa5999a71dc908309da83a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26238 zcmeHPZHQIJ8J=}@*R>{VO>M32y{Tdl2p{TyX0SF(Oo{dh>JA1qO7bhMej z2)auzC^a_L%)h)9^y`#*nLH4HruiaLV}1N>hqGt@s`~pI>d~Vo>ej6XYUj@1sijMQ zsczr?TJ7I|ORZS(w%W7j6ZOg~zg7bSzffDZeyE0ruc@0i|EmrkzO7E2_)N{rJcfS1 zQkO4(rRw!})b{PaRhKS(sWxtWUv1j-zFN2LU3K8Vr|R0ZY2&rF;AQPrZg({R0}Gik|>fnf5fk``VjU&{{Hvs^}dmn_4=w>|F@7|U1L~=!u~L8`5lX9zwzyPUYB5k4nP+81AZ_c7-977f;s81s9)VZ(b54Ls72 zejUP$Q66JGz*4})psA1Kv8J@jQ1=Ldw5J45V!>w~>yqZhGOSZ3J=3JUA#@T8J=Q=? z%O9*?HZAj{y(@GQ3%w9y9n^YAy%CevOHVxdjevF4C7-lj{Y4JeU(G}EMoe0-|FFKt z^f>|Rwo5)~z3rz7@k8CQ53uQ_{n!WE`VaOAF=aDge__)}Uiwdn{ww{s?D!FS#vG&6 zjlQLg3{11EWBkfI)4*uTJI@f;oM*5FR2vbv4cOL&ndeM33Ue&XYgXOb50M&n;G*O`Q;8Ivb@vpvl6 zR@%j%^ZmVh-)R1K?|$Q&zgqMOZ}0kP^1pE5@7mWlZv02{#`9Io`Oc?XQcm8teK;on zmP3*R=U&IUXUik+j(#KZ()d%%`SW*des-R`bMcq{gJ;87)-B3lUi5LqQ+UhlV=#WhM{ul(~~~I{J}0zsWrJ+H1eh z>NAu@X=IP3>2Hie{D+t_^kQW2fEMpyUT(r9Ei8`Vlsx@j_4Xa5ts2ZwYjbq2ekQW4> zwB$iv)3UY0IP88E1Iu}s3=mMU3AUfCu*`fn@r-9x- za~=`=&@p*qkM4v4)ZOyQw%1JNZQO$gKW$r1-+1E>9XL%HZAZb0GXDJrlSR({F_mH+f^4L#BayqT@5HB1f6?** z6B*A&F8N%?rQ8|Y_KSR>yMF!OEgkml`;(K0;3ly#28;JUTfTX&V4Vy5bZLn9p-<*o zn`J-G8wBtU(_qd0=}H9ClL6|$^A3~(=1~haOMx_d1P`hj>r4rCrTZGF#K(`a+scF9v0=+t%Kvm~B3o_d>$-FD1pA0h;+y2FMt z5G@5Q_uo}@c-r)|0k#x{2=A85*`9W$%euUL&9i@fsA2r@d^YF%ILbR&%=!rL@XGi5 z5cZpQ9u2cwNzXfApKm!1U{hYucRqZ)GRv#lZ{Epl8Ehmn-a-5HyOhuRXnmEo2W`hY zbwhPsM;u?^9k+>z*>`RxEz>#Pf%|x~55Tr8(9f1W9=Xb^w12=c@6z>rhV|UzmbpvU zCabLdS!2Gy9e_4{jJ^ij()Pys+|5UuyS$A3T^jQ)opHA41OMG$!-p=OZDmF6&okz8 z-0g1DAw^%@L3RSqEQ6fe6}4afdt}db%on(Klh=OO=sHV{Hl_G1FK>-k#Qq+Pd6(|6 z)dqdf*o9lTEX{sb8~e%%-a9Iy=RVtdwEd}Gw7<_*yPWHMz%g(8=B&eh-mkXtO65be zKkxnJyzf*-N7!mZbaO7*&;G#wBk_Nsq4YBNz*Za5?+F>Snfioie;E(#2fPPbM1Bt3 zDcgF`;C1@k>HlIs;{taN^ZE(4+Rz*O**8o-^Pby|9XC^-dHCNs$N!4k_?SF%q+Rx- zPjtWiZTm$g|I>K<_>|e~ZRtaY{#?ago7UC;KN4N4#%bf_PsvxD%j(*C~w&;Ou^j{?N6cJ_Zh6NXs>tJu%~;JU!`U63+9c>vpS&gFtI z?>NiakME7SOxI;O@1N)K2j7i)!2j)lB7Lri{oLDb+xB66@!~(cwsY>sH+AyZmIr6I z$9NP+_@YsS{!winOtar>WJ*QA{V#2UjcHK*U3WkLalpNf z=;vDVeGZ@x_&o}tEfklrpU*c(kN%~|JMAJm!Iq++zooU+j1+aL6NI3IjK9ZSx4nZ6kU?_lqVy3n7v$AOMr1@p2> z3VG)@%ZK{^O~KxoRPYUTsQO>nEMq0b`?i;=+Vpn zMNk%G&Na~YMsd%u`WXs%*!_TK7v#Nhu37EShwB8!q`pg7>KOvGwEtehgX6o~^SZ-~ zP(}LtQ~b}=S%e!&Fy{_+`@PgUmIXNjt>bi zCMQIw)(8(7ufat<#={z26Ev9b*JPTISr9&H#z!OJEp|yPc1tXN(e9;##}xn$Z!m@*B^EzxM)134uqAFf_DDS2PLoNy0Rh#l LXtt|Pw|@Q)9Za7u diff --git a/src/index.html b/src/index.html deleted file mode 100644 index ef16aa2..0000000 --- a/src/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - ReactJS CRUD Boilerplate - - - - - -
- - - - diff --git a/src/index.js b/src/index.js index 6b39be5..4e16fcf 100644 --- a/src/index.js +++ b/src/index.js @@ -20,5 +20,5 @@ render( , - document.getElementById('app') + document.getElementById('root') ); diff --git a/src/vendor.js b/src/vendor.js deleted file mode 100644 index 3171f0f..0000000 --- a/src/vendor.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - This contains references to all vendor libs, so that they can be cached until one of them change. - This is used by webpack in production build only. - These vendor libs are unlikely to change as often as the app code. -*/ - -/* eslint-disable no-unused-vars*/ - -import React, {PropTypes} from 'react'; - -import {BrowserRouter, Route, Switch, withRouter, Link, NavLink} from 'react-router-dom'; - -import {bindActionCreators, applyMiddleware, createStore} from 'redux'; - -import {connect, Provider} from 'react-redux'; - -import {render} from 'react-dom'; - -import _ from 'lodash'; - -import toastr from 'toastr'; - - - - - - diff --git a/test/action/ApiAction.test.js b/test/action/ApiAction.test.js deleted file mode 100644 index 573808e..0000000 --- a/test/action/ApiAction.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import {expect} from 'chai'; -import * as ApiActions from '../../src/action/ApiAction'; -import * as ActionType from '../../src/action/ActionType'; - - - -describe('ApiAction.test.js', () => { - - describe('ApiCallBeginActionCreator', () => { - it(`should create action ${ActionType.API_CALL_BEGIN}`, () => { - const expectedAction = {type: ActionType.API_CALL_BEGIN}; - - const actualAction = ApiActions.ApiCallBeginAction(); - - expect(actualAction).to.deep.equal(expectedAction); - }); - }); - - - describe('ApiCallErrorActionCreator', () => { - it(`should create action ${ActionType.API_CALL_ERROR}`, () => { - const expectedAction = {type: ActionType.API_CALL_ERROR}; - - const actualAction = ApiActions.ApiCallErrorAction(); - - expect(actualAction).to.deep.equal(expectedAction); - }); - }); - - -}); \ No newline at end of file diff --git a/test/action/AuthorAction.test.js b/test/action/AuthorAction.test.js deleted file mode 100644 index 8197891..0000000 --- a/test/action/AuthorAction.test.js +++ /dev/null @@ -1,65 +0,0 @@ -import { expect } from 'chai'; -import * as AuthorActions from '../../src/action/AuthorAction'; -import * as ActionType from '../../src/action/ActionType'; -import thunk from 'redux-thunk'; -import nock from 'nock'; -import configureMockStore from 'redux-mock-store'; - - - -describe('AuthorAction.test.js', () => { - - describe('getAuthorsResponseActionCreator', () => { - it(`should create action ${ActionType.GET_AUTHORS_RESPONSE}`, () => { - const authors = { id: 'scott-allen', firstName: 'Scott', lastName: 'Allen' }; - const expectedAction = { - type: ActionType.GET_AUTHORS_RESPONSE, - authors: authors - }; - - const actualAction = AuthorActions.getAuthorsResponse(authors); - - expect(actualAction).to.deep.equal(expectedAction); - }); - }); - - - const thunkMiddleware = [thunk]; - const mockStore = configureMockStore(thunkMiddleware); - - - describe('getCoursesActionThunk', () => { - afterEach(() => { - nock.cleanAll(); - }); - - it('should get authors', (done) => { - const expectedActions = [ - { type: ActionType.API_CALL_BEGIN }, - { - type: ActionType.GET_AUTHORS_RESPONSE, - body: { - authors: [ - { id: 1, firstName: 'Allen', lastName: 'Holub' } - ] - } - } - ]; - - const store = mockStore({ authors: [] }, expectedActions, done); - store.dispatch(AuthorActions.getAuthorsAction()) - .then(() => { - const actions = store.getActions(); - - expect(actions[0].type).to.equal(ActionType.API_CALL_BEGIN); - expect(actions[1].type).to.equal(ActionType.GET_AUTHORS_RESPONSE); - done(); - }); - }); - - }); - - - - -}); \ No newline at end of file diff --git a/test/action/CourseAction.test.js b/test/action/CourseAction.test.js deleted file mode 100644 index 3fec879..0000000 --- a/test/action/CourseAction.test.js +++ /dev/null @@ -1,215 +0,0 @@ -import { expect } from 'chai'; -import thunk from 'redux-thunk'; -import nock from 'nock'; -import configureMockStore from 'redux-mock-store'; -import * as CourseActions from '../../src/action/CourseAction'; -import * as ActionType from '../../src/action/ActionType'; - - - -describe('CourseAction.test.js', () => { - - describe('getCoursesResponseActionCreator', () => { - it(`should create action ${ActionType.GET_COURSES_RESPONSE}`, () => { - const courses = [{ title: 'Learn reactjs redux' }]; - const expectedAction = { - type: ActionType.GET_COURSES_RESPONSE, - courses: courses - }; - - const actualAction = CourseActions.getCoursesResponse(courses); - - expect(actualAction).to.deep.equal(expectedAction); - }); - }); - - - describe('addNewCourseResponseActionCreator', () => { - it(`should create action ${ActionType.ADD_NEW_COURSE_RESPONSE}`, () => { - const course = { title: 'Learn reactjs redux' }; - const expectedAction = { - type: ActionType.ADD_NEW_COURSE_RESPONSE, - course: course - }; - - const actualAction = CourseActions.addNewCourseResponse(course); - - expect(actualAction).to.deep.equal(expectedAction); - }); - }); - - - describe('updateExistingCourseResponseActionCreator', () => { - it(`should create action ${ActionType.UPDATE_EXISTING_COURSE_RESPONSE}`, () => { - const course = { title: 'Learn reactjs redux' }; - const expectedAction = { - type: ActionType.UPDATE_EXISTING_COURSE_RESPONSE, - course: course - }; - - const actualAction = CourseActions.updateExistingCourseResponse(course); - - expect(actualAction).to.deep.equal(expectedAction); - }); - }); - - - const thunkMiddleware = [thunk]; - const mockStore = configureMockStore(thunkMiddleware); - - - describe('getCoursesActionThunk', () => { - afterEach(() => { - nock.cleanAll(); - }); - - it('should get all courses', (done) => { - // nock Example (note: our API is a mock, so no need to use nock here) : - // nock('http://example.com') - // .get('/courses') - // .reply(200, { body: - // { - // course: [ { id: 1, firstName: 'Ben', lastName: 'Stuart' } ] - // } - // }); - - const expectedActions = [ - { type: ActionType.API_CALL_BEGIN }, - { - type: ActionType.GET_COURSES_RESPONSE, - body: { - courses: [ - { id: 1, title: 'Java Clean Code' } - ] - } - } - ]; - - const store = mockStore({ courses: [] }, expectedActions, done); - store.dispatch(CourseActions.getCoursesAction()) - .then(() => { - const actions = store.getActions(); - - expect(actions[0].type).to.equal(ActionType.API_CALL_BEGIN); - expect(actions[1].type).to.equal(ActionType.GET_COURSES_RESPONSE); - done(); - }); - }); - - }); - - - describe('saveCourseActionThunk', () => { - afterEach(() => { - nock.cleanAll(); - }); - - it('should update existing course', (done) => { - const expectedActions = [ - { type: ActionType.API_CALL_BEGIN }, - { - type: ActionType.UPDATE_EXISTING_COURSE_RESPONSE, - body: { - course: [ - { id: 1, title: 'Java Clean Code' } - ] - } - } - ]; - - const store = mockStore({ course: [] }, expectedActions, done); - const course = { id: 1, title: 'Learn reactjs redux' }; - store.dispatch(CourseActions.saveCourseAction(course)) - .then(() => { - const actions = store.getActions(); - - expect(actions[0].type).to.equal(ActionType.API_CALL_BEGIN); - expect(actions[1].type).to.equal(ActionType.UPDATE_EXISTING_COURSE_RESPONSE); - done(); - }); - }); - - - it('should add a new course', (done) => { - const expectedActions = [ - { type: ActionType.API_CALL_BEGIN }, - { - type: ActionType.ADD_NEW_COURSE_RESPONSE, - body: { - course: [ - { title: 'Java Clean Code' } - ] - } - } - ]; - - const store = mockStore({ course: [] }, expectedActions, done); - const course = { title: 'Learn reactjs redux' }; - store.dispatch(CourseActions.saveCourseAction(course)) - .then(() => { - const actions = store.getActions(); - - expect(actions[0].type).to.equal(ActionType.API_CALL_BEGIN); - expect(actions[1].type).to.equal(ActionType.ADD_NEW_COURSE_RESPONSE); - done(); - }); - }); - - }); - - - - - describe('getCourseResponseActionCreator', () => { - it(`should create action ${ActionType.GET_COURSE_RESPONSE}`, () => { - const course = { title: 'Learn reactjs redux' }; - const expectedAction = { - type: ActionType.GET_COURSE_RESPONSE, - course: course - }; - - const actualAction = CourseActions.getCourseResponse(course); - - expect(actualAction).to.deep.equal(expectedAction); - }); - }); - - - - describe('getCourseActionThunk', () => { - afterEach(() => { - nock.cleanAll(); - }); - - it('should get a specific courses', (done) => { - const findThisCourse = { id: 1, title: 'Java Clean Code' }; - - const expectedActions = [ - { - type: ActionType.API_CALL_BEGIN - }, - { - type: ActionType.GET_COURSE_RESPONSE, - body: { - course: findThisCourse - } - } - ]; - - const store = mockStore({ course: {} }, expectedActions, done); - store.dispatch(CourseActions.getCourseAction(1)) - .then(() => { - const actions = store.getActions(); - - expect(actions[0].type).to.equal(ActionType.API_CALL_BEGIN); - expect(actions[1].type).to.equal(ActionType.GET_COURSE_RESPONSE); - done(); - }); - }); - - }); - -}); - - - diff --git a/test/components/About.test.js b/test/components/About.test.js deleted file mode 100644 index c34f71c..0000000 --- a/test/components/About.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import {shallow} from 'enzyme'; -import {expect} from 'chai'; -import About from '../../src/components/About'; - - -describe('About.test.js', () => { - - it('renders', () => { - const wrapper = shallow(); - - expect(wrapper).to.have.length(1); - - expect(wrapper.find('.container')).to.have.length(1); - }); -}); diff --git a/test/components/App.test.js b/test/components/App.test.js deleted file mode 100644 index f2711a8..0000000 --- a/test/components/App.test.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import {shallow} from 'enzyme'; -import {expect} from 'chai'; -import createBrowserHistory from 'history/createBrowserHistory'; -import App from '../../src/components/App'; - - -describe('App.test.js', () => { - let history; - - beforeEach(() => { - history = createBrowserHistory(); - }); - - it('renders', () => { - const props = { - history: history - }; - - const wrapper = shallow(); - - expect(wrapper).to.have.length(1); - }); -}); diff --git a/test/components/common/FieldInput.test.js b/test/components/common/FieldInput.test.js deleted file mode 100644 index 3895101..0000000 --- a/test/components/common/FieldInput.test.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; -import {expect} from 'chai'; -import {shallow} from 'enzyme'; -import FieldInput from '../../../src/components/common/FieldInput'; - - -describe('FieldInput.test.js', () => { - it('renders', () => { - const props = { - input: {}, - type: 'text', - name: 'category', - label: 'Category', - placeholder: 'Category', - meta: {touched: false, error:{}, warning: {}}, - onChange: () => {} - }; - - const wrapper = shallow(); - - expect(wrapper.length).to.equal(1); - }); -}); diff --git a/test/components/common/PageNotFound.test.js b/test/components/common/PageNotFound.test.js deleted file mode 100644 index 2c973b7..0000000 --- a/test/components/common/PageNotFound.test.js +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import {expect} from 'chai'; -import {shallow} from 'enzyme'; -import PageNotFound from '../../../src/components/common/PageNotFound'; - - -describe('PageNotFound.test.js', () => { - it('render', () => { - const props = { location:{pathName: '/blah'}}; - const wrapper = shallow(); - expect(wrapper.length).to.equal(1); - expect(wrapper.find('.display-1')).to.have.length(1); - }); -}); diff --git a/test/components/common/SelectInput.test.js b/test/components/common/SelectInput.test.js deleted file mode 100644 index ed2fffc..0000000 --- a/test/components/common/SelectInput.test.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import {expect} from 'chai'; -import {shallow} from 'enzyme'; -import SelectInput from '../../../src/components/common/SelectInput'; - - -describe('SelectInput.test.js', () => { - it('renders', () => { - const props = { - input:{}, - name: 'category', - label: 'Category', - defaultOption: '', - options:[{value: 'Josh', text: 'Bloch'}], - meta: {touched: false, error:{}, warning: {}}, - }; - - const wrapper = shallow(); - - expect(wrapper.length).to.equal(1); - }); -}); diff --git a/test/components/common/Spinner.test.js b/test/components/common/Spinner.test.js deleted file mode 100644 index e7e89ab..0000000 --- a/test/components/common/Spinner.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import {expect} from 'chai'; -import {shallow} from 'enzyme'; -import Spinner from '../../../src/components/common/Spinner'; - - -describe('Spinner.test.js', () => { - it('renders', () => { - const wrapper = shallow(); - expect(wrapper.length).to.equal(1); - expect(wrapper.find('h3')).to.have.length(1); - }); -}); diff --git a/test/components/course/AddOrEditCourseContainer.test.js b/test/components/course/AddOrEditCourseContainer.test.js deleted file mode 100644 index 6c72f4c..0000000 --- a/test/components/course/AddOrEditCourseContainer.test.js +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; -import {expect} from 'chai'; -import {shallow} from 'enzyme'; -import configureMockStore from 'redux-mock-store'; -import thunk from 'redux-thunk'; -import {AddOrEditCourseContainer} from '../../../src/components/course/AddOrEditCourseContainer'; - - -describe('AddOrEditCourseContainer.test.js', () => { - let store; - - beforeEach(() => { - const thunkMiddleware = [thunk]; - const mockStore = configureMockStore(thunkMiddleware); - const initialState = {course:{}}; - store = mockStore(initialState); - }); - - it('sets an error message when trying to save empty title', () => { - const props = { - action: { - getCourseAction: () => {return Promise.resolve();}, - getAuthorsAction: () => {return Promise.resolve();} - }, - authors:[], - initialValues: {id: '', watchHref: '', title: '', authorId: '', length: '', category: ''}, - match: {params: {id:'1'}} - }; - - const wrapper = shallow(); - expect(wrapper.length).to.equal(1); - }); - -}); - - - - - \ No newline at end of file diff --git a/test/components/course/CourseForm.test.js b/test/components/course/CourseForm.test.js deleted file mode 100644 index d66539f..0000000 --- a/test/components/course/CourseForm.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import {expect} from 'chai'; -import {shallow} from 'enzyme'; -import {CourseForm} from '../../../src/components/course/CourseForm'; - - - -function setup(heading) { - const props = { - handleSubmit: () => {}, - pristine: true, - reset: () => {}, - submitting: false, - heading: heading, - authors: [], - handleSave: () => {}, - handleCancel: () => {}, - }; - - return shallow(); -} - - -describe('CourseForm.test.js', () => { - - it('renders form and display "Add" in h1', () => { - const wrapper = setup('Add'); - expect(wrapper.length).to.equal(1); - expect(wrapper.find('form').length).to.equal(1); - expect(wrapper.find('h1').text()).to.equal('Add'); - }); - - - it('displays "Edit" in h1', () => { - const wrapper = setup('Edit'); - expect(wrapper.find('h1').text()).to.equal('Edit'); - }); - - -}); - diff --git a/test/components/course/CourseList.test.js b/test/components/course/CourseList.test.js deleted file mode 100644 index 70c4caa..0000000 --- a/test/components/course/CourseList.test.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import {shallow} from 'enzyme'; -import {expect} from 'chai'; -import CourseList from '../../../src/components/course/CourseList'; - - -describe('CourseList.test.js', () => { - - it('renders', () => { - const props = { - courses: [ - { id: 1, title: 'Java Clean Code' }, - { id: 2, title: 'Java The Good Pards' }, - ] - }; - - const wrapper = shallow(); - - expect(wrapper.length).to.equal(1); - expect(wrapper.find('CourseListRow')).to.have.length(2); - }); -}); diff --git a/test/components/course/CourseListContainer.test.js b/test/components/course/CourseListContainer.test.js deleted file mode 100644 index 3b92a75..0000000 --- a/test/components/course/CourseListContainer.test.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import {shallow} from 'enzyme'; -import {expect} from 'chai'; -import createBrowserHistory from 'history/createBrowserHistory'; -import {CourseListContainer} from '../../../src/components/course/CourseListContainer'; - - -describe('CourseListContainer.test.js', () => { - let history; - - beforeEach(() => { - history = createBrowserHistory(); - }); - - - it('renders', () => { - const props = { - courses:[ - {title: 'Java The Good Pards'} - ], - action: { getCoursesAction: () => {return Promise.resolve();} }, - history: history - }; - - const wrapper = shallow(); - - expect(wrapper).to.have.length(1); - - expect(wrapper.find('button')).to.have.length(1); - expect(wrapper.find('CourseList')).to.have.length(1); - }); -}); diff --git a/test/components/course/CourseListRow.test.js b/test/components/course/CourseListRow.test.js deleted file mode 100644 index 6cf7816..0000000 --- a/test/components/course/CourseListRow.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import {shallow} from 'enzyme'; -import {expect} from 'chai'; -import CourseListRow from '../../../src/components/course/CourseListRow'; - - -describe('CourseListRow.test.js', () => { - - it('renders', () => { - const props = { - course: { id: 1, title: 'Java Clean Code' } - }; - - const wrapper = shallow(); - - expect(wrapper.length).to.equal(1); - expect(wrapper.find('tr')).to.have.length(1); - }); -}); diff --git a/test/components/landing/Footer.test.js b/test/components/landing/Footer.test.js deleted file mode 100644 index c5dbf36..0000000 --- a/test/components/landing/Footer.test.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import {shallow} from 'enzyme'; -import {expect} from 'chai'; -import Footer from '../../../src/components/landing/Footer'; - - -describe('Footer.test.js', () => { - - it('renders', () => { - - const wrapper = shallow(