├── .gitignore ├── unit-testing-jest-enzyme ├── src │ ├── actions │ │ ├── types.js │ │ ├── index.js │ │ └── index.test.js │ ├── reducers │ │ ├── index.js │ │ ├── comments.js │ │ └── comments.test.js │ ├── index.css │ ├── App.css │ ├── components │ │ ├── comment_list.js │ │ ├── comment_list.test.js │ │ ├── comment_box.js │ │ └── comment_box.test.js │ ├── index.js │ ├── App.js │ ├── App.test.js │ ├── logo.svg │ └── registerServiceWorker.js ├── public │ ├── favicon.ico │ ├── manifest.json │ └── index.html ├── .gitignore └── package.json ├── unit-testing-mocha-chai ├── src │ ├── actions │ │ ├── types.js │ │ └── index.js │ ├── reducers │ │ ├── comments.js │ │ └── index.js │ ├── components │ │ ├── comment_list.js │ │ ├── app.js │ │ └── comment_box.js │ ├── index.js │ └── registerServiceWorker.js ├── .babelrc ├── .gitignore ├── favicon.ico ├── manifest.json ├── webpack.config.dev.js ├── webpack.config.prod.js ├── test │ ├── actions │ │ └── index_test.js │ ├── components │ │ ├── app_test.js │ │ ├── comment_list_test.js │ │ └── comment_box_test.js │ ├── reducers │ │ └── comments_test.js │ └── test_helper.js ├── style │ ├── style.css │ └── bootstrap.min.css ├── index.html ├── package.json └── logo.svg ├── LICENSE.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .temp 3 | .idea 4 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/actions/types.js: -------------------------------------------------------------------------------- 1 | export const SAVE_COMMENT = 'save_comment'; -------------------------------------------------------------------------------- /unit-testing-mocha-chai/src/actions/types.js: -------------------------------------------------------------------------------- 1 | export const SAVE_COMMENT = 'save_comment'; -------------------------------------------------------------------------------- /unit-testing-mocha-chai/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .temp 3 | .idea 4 | node_modules 5 | dist -------------------------------------------------------------------------------- /unit-testing-mocha-chai/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/herrkraatz/react-unit-testing/HEAD/unit-testing-mocha-chai/favicon.ico -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/herrkraatz/react-unit-testing/HEAD/unit-testing-jest-enzyme/public/favicon.ico -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import { SAVE_COMMENT } from './types'; 2 | 3 | // action creator: 4 | export function saveComment(comment){ 5 | return { 6 | type: SAVE_COMMENT, 7 | payload: comment 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import commentsReducer from './comments'; 3 | 4 | const rootReducer = combineReducers({ 5 | comments: commentsReducer 6 | }); 7 | 8 | export default rootReducer; 9 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import { SAVE_COMMENT } from './types'; 2 | 3 | // action creator: 4 | export function saveComment(comment){ 5 | return { 6 | type: SAVE_COMMENT, 7 | payload: comment 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | 7 | .Test-container{ 8 | width: 50%; 9 | margin: 10px auto 0; 10 | /*margin-top: 10px;*/ 11 | } 12 | 13 | ul{ 14 | width: 150px; 15 | margin: 10px auto 0; 16 | } 17 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | import { SAVE_COMMENT } from '../actions/types'; 2 | 3 | export default function(state = [], action){ 4 | 5 | switch(action.type){ 6 | case SAVE_COMMENT: 7 | // return state.concat([action.payload]); 8 | // better: 9 | return [ ...state, action.payload]; 10 | } 11 | return state; 12 | } -------------------------------------------------------------------------------- /unit-testing-mocha-chai/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | import { SAVE_COMMENT } from '../actions/types'; 2 | 3 | export default function(state = [], action){ 4 | 5 | switch(action.type){ 6 | case SAVE_COMMENT: 7 | // return state.concat([action.payload]); 8 | // better: 9 | return [ ...state, action.payload]; 10 | } 11 | return state; 12 | } -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import commentsReducer from './comments'; 3 | 4 | const rootReducer = combineReducers({ 5 | // state: (state = {}) => state 6 | // for comment list to work: make an array out of it 7 | // dummy reducer: 8 | // comments: (state = []) => state 9 | comments: commentsReducer 10 | }); 11 | 12 | export default rootReducer; 13 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | mode: 'development', 3 | entry: [ 4 | './src/index.js' 5 | ], 6 | output: { 7 | path: __dirname, 8 | publicPath: '/', 9 | filename: 'bundle.js' 10 | }, 11 | module: { 12 | rules: [{ 13 | exclude: /node_modules/, 14 | loader: 'babel-loader' 15 | }] 16 | }, 17 | resolve: { 18 | extensions: ['.js', '.jsx'] 19 | }, 20 | devServer: { 21 | historyApiFallback: true, 22 | contentBase: './' 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/components/comment_list.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // to turn a component into a container to have access to the state: 4 | import { connect } from 'react-redux'; 5 | 6 | const CommentList = (props) => { 7 | const list = props.comments.map(comment =>
  • {comment}
  • ); 8 | return ( 9 | 10 | ); 11 | }; 12 | 13 | function mapStateToProps(state){ 14 | return { comments: state.comments}; 15 | } 16 | 17 | // to turn a component into a container: 18 | export default connect(mapStateToProps)(CommentList); -------------------------------------------------------------------------------- /unit-testing-mocha-chai/src/components/comment_list.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // to turn a component into a container to have access to the state: 4 | import { connect } from 'react-redux'; 5 | 6 | const CommentList = (props) => { 7 | const list = props.comments.map(comment =>
  • {comment}
  • ); 8 | return ( 9 | 10 | ); 11 | }; 12 | 13 | function mapStateToProps(state){ 14 | return { comments: state.comments}; 15 | } 16 | 17 | // to turn a component into a container: 18 | export default connect(mapStateToProps)(CommentList); -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/reducers/comments.test.js: -------------------------------------------------------------------------------- 1 | import commentReducer from './comments'; 2 | import { SAVE_COMMENT } from '../actions/types'; 3 | 4 | describe('Comments Reducer', () => { 5 | 6 | // in case there is a weird input, we react with the default state 7 | test('handles action with unknown type', () => { 8 | 9 | expect(commentReducer(undefined, {})).toEqual([]); 10 | }); 11 | 12 | test('SAVE_COMMENT', () => { 13 | 14 | const action = { type: SAVE_COMMENT, payload: 'new comment'}; 15 | expect(commentReducer([], action)).toEqual(['new comment']); 16 | 17 | }); 18 | 19 | }); -------------------------------------------------------------------------------- /unit-testing-mocha-chai/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware } from 'redux'; 5 | 6 | import App from './components/app'; 7 | import reducers from './reducers'; 8 | import registerServiceWorker from './registerServiceWorker'; 9 | 10 | const createStoreWithMiddleware = applyMiddleware()(createStore); 11 | 12 | ReactDOM.render( 13 | 14 | 15 | 16 | , document.querySelector('.container')); 17 | 18 | registerServiceWorker(); 19 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware } from 'redux'; 5 | import './index.css'; 6 | import App from './App'; 7 | import reducers from './reducers'; 8 | import registerServiceWorker from './registerServiceWorker'; 9 | 10 | const createStoreWithMiddleware = applyMiddleware()(createStore); 11 | 12 | ReactDOM.render( 13 | 14 | 15 | 16 | , document.getElementById('root')); 17 | 18 | registerServiceWorker(); -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/actions/index.test.js: -------------------------------------------------------------------------------- 1 | import { SAVE_COMMENT } from './types'; 2 | import { saveComment } from './'; 3 | 4 | describe('actions', () => { 5 | describe('saveComment', () => { 6 | test('has the correct type', () => { 7 | 8 | // action creator returns an action 9 | const action = saveComment(); 10 | expect(action.type).toEqual(SAVE_COMMENT); 11 | }); 12 | 13 | test('has the correct payload', () => { 14 | 15 | const action = saveComment('new comment'); 16 | expect(action.payload).toEqual('new comment'); 17 | }); 18 | 19 | }); 20 | 21 | }); -------------------------------------------------------------------------------- /unit-testing-mocha-chai/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | module.exports = { 3 | mode: 'production', 4 | entry: [ 5 | './src/index.js' 6 | ], 7 | output: { 8 | path: path.resolve(__dirname, 'dist'), 9 | publicPath: '/', 10 | filename: 'bundle.js' 11 | }, 12 | module: { 13 | rules: [{ 14 | exclude: /node_modules/, 15 | loader: 'babel-loader' 16 | }] 17 | }, 18 | resolve: { 19 | extensions: ['.js', '.jsx'] 20 | }, 21 | devServer: { 22 | historyApiFallback: true, 23 | contentBase: './' 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/test/actions/index_test.js: -------------------------------------------------------------------------------- 1 | import { expect } from '../test_helper'; 2 | 3 | import { SAVE_COMMENT } from '../../src/actions/types'; 4 | import { saveComment } from '../../src/actions'; 5 | 6 | describe('actions', () => { 7 | describe('saveComment', () => { 8 | it('has the correct type', () => { 9 | 10 | // action creator returns an action 11 | const action = saveComment(); 12 | expect(action.type).to.equal(SAVE_COMMENT); 13 | }); 14 | 15 | it('has the correct payload', () => { 16 | 17 | const action = saveComment('new comment'); 18 | expect(action.payload).to.equal('new comment'); 19 | }); 20 | 21 | }); 22 | 23 | }); -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testing-with-cra-and-jest-enzyme", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "lodash": "^4.17.10", 7 | "react": "^16.4.1", 8 | "react-dom": "^16.4.1", 9 | "react-redux": "^5.0.7", 10 | "react-router": "^4.3.1", 11 | "react-scripts": "1.1.4", 12 | "redux": "^4.0.0" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test --env=jsdom --verbose", 18 | "eject": "react-scripts eject" 19 | }, 20 | "devDependencies": { 21 | "enzyme": "^3.3.0", 22 | "enzyme-adapter-react-16": "^1.1.1", 23 | "redux-mock-store": "^1.5.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import CommentBox from './comment_box'; 3 | import CommentList from './comment_list'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
    9 |
    10 | logo 11 |

    Welcome to React

    12 |
    13 |
    14 | 15 | 16 |
    17 |
    18 | ); 19 | } 20 | } 21 | 22 | export default App; 23 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/App.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import CommentBox from './components/comment_box'; 3 | import CommentList from './components/comment_list'; 4 | import logo from './logo.svg'; 5 | import './App.css'; 6 | 7 | class App extends Component { 8 | render() { 9 | return ( 10 |
    11 |
    12 | logo 13 |

    Welcome to React

    14 |
    15 |
    16 | 17 | 18 |
    19 |
    20 | ); 21 | } 22 | } 23 | 24 | export default App; 25 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/test/components/app_test.js: -------------------------------------------------------------------------------- 1 | import { renderComponent, expect } from '../test_helper'; 2 | import App from '../../src/components/app'; 3 | 4 | // Use 'describe' to group together similar tests 5 | describe('App', () => { 6 | 7 | let component; 8 | 9 | // First create an instance of App 10 | beforeEach(() => { 11 | component = renderComponent(App); 12 | }); 13 | 14 | // Use 'it' to test a single attribute of a target 15 | it('shows comment box', () => { 16 | 17 | // Use 'expect' to make an 'assertion' about a target 18 | expect(component.find('.comment-box')).to.exist; 19 | }); 20 | 21 | it('shows comment list', () =>{ 22 | expect(component.find('.comment-list')).to.exist; 23 | }); 24 | }); 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/style/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | 7 | .App { 8 | text-align: center; 9 | } 10 | 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | height: 80px; 14 | } 15 | 16 | .App-header { 17 | background-color: #222; 18 | height: 150px; 19 | padding: 20px; 20 | color: white; 21 | } 22 | 23 | .App-title { 24 | font-size: 1.5em; 25 | } 26 | 27 | .App-intro { 28 | font-size: large; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { transform: rotate(0deg); } 33 | to { transform: rotate(360deg); } 34 | } 35 | 36 | .Test-container{ 37 | width: 50%; 38 | margin: 10px auto 0; 39 | /*margin-top: 10px;*/ 40 | } 41 | 42 | ul{ 43 | width: 150px; 44 | margin: 10px auto 0; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | React App 16 | 17 | 18 | 21 |
    22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/test/components/comment_list_test.js: -------------------------------------------------------------------------------- 1 | import { renderComponent, expect } from '../test_helper'; 2 | import CommentList from '../../src/components/comment_list'; 3 | 4 | describe('CommentList', () => { 5 | 6 | let component; 7 | 8 | beforeEach(() => { 9 | // renderComponents makes props available 10 | // const props = { comments: ['New Comment', 'New Other Comment'] }; 11 | // component = renderComponent(CommentList, null, props); 12 | const initialState = { comments: ['New Comment', 'New Other Comment'] }; // better call it initialState, not props 13 | component = renderComponent(CommentList, null, initialState); 14 | }); 15 | 16 | it('shows an LI for each comment', () => { 17 | expect(component.find('li').length).to.equal(2); 18 | 19 | }); 20 | 21 | it('shows each comment that is provided', () => { 22 | expect(component).to.contain('New Comment'); 23 | expect(component).to.contain('New Other Comment'); 24 | }); 25 | 26 | }); -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Holger Kraatz 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. -------------------------------------------------------------------------------- /unit-testing-mocha-chai/test/reducers/comments_test.js: -------------------------------------------------------------------------------- 1 | import { expect } from '../test_helper'; 2 | import commentReducer from '../../src/reducers/comments'; 3 | import { SAVE_COMMENT } from '../../src/actions/types'; 4 | 5 | describe('Comments Reducer', () => { 6 | 7 | // in case there is a weird input, we react with the default state 8 | it('handles action with unknown type', () => { 9 | 10 | // expect(commentReducer()).to.be.instanceof(Array); 11 | // better: 12 | // eql compares deeply 13 | // so we are sure the array is really empty 14 | // expect(commentReducer()).to.eql([]); 15 | // failed after we completed the reducer: TypeError: Cannot read property 'type' of undefined 16 | // so we have to pass in values here: 17 | expect(commentReducer(undefined, {})).to.eql([]); 18 | }); 19 | 20 | // it('handles action of type SAVE_COMMENT', () => { 21 | // 22 | // }); 23 | // better: 24 | it('SAVE_COMMENT', () => { 25 | 26 | const action = { type: SAVE_COMMENT, payload: 'new comment'}; 27 | expect(commentReducer([], action)).to.eql(['new comment']); 28 | 29 | }); 30 | 31 | }); -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import App from './App'; 3 | import { mount } from 'enzyme'; 4 | 5 | // We need to wrap CommentBox with tag in first beforeEach(() => {}) below; 6 | // otherwise we receive this error message: 7 | // Invariant Violation: Could not find “store” in either the context or props of “Connect(CommentBox)” 8 | // https://stackoverflow.com/questions/36211739/invariant-violation-could-not-find-store-in-either-the-context-or-props-of-c 9 | // Also see comment_list.test.js 10 | import {configure} from 'enzyme'; 11 | import Adapter from 'enzyme-adapter-react-16'; 12 | import {Provider} from "react-redux"; 13 | import {createStore, applyMiddleware} from 'redux'; 14 | import reducers from './reducers'; 15 | 16 | configure({adapter: new Adapter()}); 17 | const createStoreWithMiddleware = applyMiddleware()(createStore); 18 | 19 | // Use 'describe' to group together similar tests 20 | describe('App', () => { 21 | 22 | let component; 23 | 24 | beforeEach(() => { 25 | component = mount(); 26 | }); 27 | 28 | // Use 'test' or 'it' (both possible) to test a single attribute of a target 29 | test('shows comment box', () => { 30 | 31 | expect(component.find('.comment-box').length).toBe(1); 32 | }); 33 | 34 | test('shows comment list', () => { 35 | expect(component.find('.comment-list').length).toBe(1); 36 | }); 37 | }); 38 | 39 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/test/components/comment_box_test.js: -------------------------------------------------------------------------------- 1 | import { renderComponent, expect } from '../test_helper'; 2 | import CommentBox from '../../src/components/comment_box'; 3 | 4 | describe('CommentBox', () => { 5 | 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = renderComponent(CommentBox); 10 | }); 11 | 12 | it('has the correct class', () => { 13 | expect(component).to.have.class('comment-box'); 14 | }); 15 | 16 | it('has a text area', () => { 17 | expect(component.find('textarea')).to.exist; 18 | }); 19 | 20 | it('has a button', () => { 21 | expect(component.find('button')).to.exist; 22 | }); 23 | 24 | describe('entering some text', () => { 25 | 26 | beforeEach(() => { 27 | component.find('textarea').simulate('change', 'new comment'); 28 | }); 29 | 30 | it('shows that text in the textarea', () => { 31 | expect(component.find('textarea')).to.have.value('new comment'); 32 | }); 33 | 34 | it('when submitted, clears the input', () => { 35 | // console.log(component)'s output: 36 | //
    37 | // 38 | // 39 | //
    40 | component.simulate('submit'); 41 | expect(component.find('textarea')).to.have.value(''); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /unit-testing-mocha-chai/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testing-with-webpack-and-chai-mocha", 3 | "version": "1.0.0", 4 | "description": "Great thanks to Stephen Grider's Redux Simple Starter Repo, and his Udemy Course 'Advanced React and Redux', which were the basis of this code", 5 | "main": "index.js", 6 | "repository": "git@github.com:herrkraatz/react-testing.git", 7 | "scripts": { 8 | "dev": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.config.dev.js", 9 | "prod": "webpack --config webpack.config.prod.js && cp index.html dist && cp manifest.json dist && cp logo.svg dist && cp favicon.ico dist && cp -R style dist", 10 | "test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive ./test", 11 | "test:watch": "npm run test -- --watch" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "babel-core": "^6.26.3", 17 | "babel-loader": "^7.1.4", 18 | "babel-preset-env": "^1.7.0", 19 | "babel-preset-react": "^6.24.1", 20 | "chai": "^4.1.2", 21 | "chai-jquery": "^2.0.0", 22 | "jquery": "^3.3.1", 23 | "jsdom": "^11.11.0", 24 | "mocha": "^5.2.0", 25 | "react-addons-test-utils": "^15.6.2", 26 | "webpack": "^4.10.1", 27 | "webpack-cli": "^2.1.4", 28 | "webpack-dev-server": "^3.1.4" 29 | }, 30 | "dependencies": { 31 | "babel-preset-stage-1": "^6.1.18", 32 | "lodash": "^4.17.10", 33 | "react": "^15.4.2", 34 | "react-dom": "^15.4.2", 35 | "react-redux": "^5.0.7", 36 | "react-router": "^4.3.1", 37 | "redux": "^4.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/components/comment_list.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CommentList from './comment_list'; 3 | import { mount } from 'enzyme'; 4 | 5 | // We need to wrap CommentBox with tag in first beforeEach(() => {}) below; 6 | // otherwise we receive this error message: 7 | // Invariant Violation: Could not find “store” in either the context or props of “Connect(CommentBox)” 8 | // https://stackoverflow.com/questions/36211739/invariant-violation-could-not-find-store-in-either-the-context-or-props-of-c 9 | 10 | // The Provider's Redux store must be our own Redux store, not a mock Redux store as in comment_box.test.js because 11 | // we insert an initial state 12 | import { configure } from 'enzyme'; 13 | import Adapter from 'enzyme-adapter-react-16'; 14 | import { Provider } from "react-redux"; 15 | import { createStore, applyMiddleware } from 'redux'; 16 | import reducers from '../reducers'; 17 | 18 | configure({ adapter: new Adapter() }); 19 | const createStoreWithMiddleware = applyMiddleware()(createStore); 20 | 21 | describe('CommentList', () => { 22 | 23 | let component; 24 | 25 | beforeEach(() => { 26 | 27 | const initialState = { comments: ['New Comment', 'New Other Comment'] }; 28 | component = mount(); 29 | }); 30 | 31 | test('shows an LI for each comment', () => { 32 | 33 | expect(component.find('li').length).toBe(2); 34 | }); 35 | 36 | test('shows each comment that is provided', () => { 37 | 38 | expect(component.find('li').at(0).text()).toEqual('New Comment'); 39 | expect(component.find('li').at(1).text()).toEqual('New Other Comment'); 40 | }); 41 | 42 | }); -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/src/components/comment_box.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | // to turn a component into a container to have access to the state: 4 | import { connect } from 'react-redux'; 5 | // imports ALL action creators and stores them in variable actions 6 | import * as actions from '../actions'; 7 | 8 | // not exporting our component any more, but exporting a container instead: 9 | // export default class CommentBox extends Component { 10 | class CommentBox extends Component { 11 | constructor(props) { 12 | super(props); 13 | 14 | this.state = { comment: '' }; 15 | } 16 | 17 | handleChange(event){ 18 | this.setState({ comment: event.target.value }); 19 | } 20 | 21 | handleSubmit(event){ 22 | // keep the form from submitting to itself 23 | event.preventDefault(); 24 | 25 | // new after having wired up the Container with the action creators 26 | this.props.saveComment(this.state.comment); 27 | this.setState({ comment: ''}); 28 | } 29 | 30 | render() { 31 | return ( 32 |
    33 |

    Add a comment

    34 |