From 59a67dce175714d28b606818361f0aca9c14f7ee Mon Sep 17 00:00:00 2001 From: Abdella Date: Thu, 2 Feb 2017 17:54:25 -0500 Subject: [PATCH 1/3] before class --- .gitignore | 1 + src/App.js | 31 ++++++++++++------------------- src/actions/index.js | 16 +++++++++++----- src/constants/api-url.js | 2 +- src/index.js | 7 +++++-- src/reducers/index.js | 17 ++--------------- src/reducers/index.test.js | 16 ---------------- src/reducers/pokemon.js | 17 +++++++++++++++++ src/utils/data.js | 15 --------------- 9 files changed, 49 insertions(+), 73 deletions(-) delete mode 100644 src/reducers/index.test.js create mode 100644 src/reducers/pokemon.js delete mode 100644 src/utils/data.js diff --git a/.gitignore b/.gitignore index 6c96c5c..edfc119 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ build .DS_Store .env npm-debug.log +.idea \ No newline at end of file diff --git a/src/App.js b/src/App.js index 781b373..25076c8 100644 --- a/src/App.js +++ b/src/App.js @@ -1,37 +1,30 @@ import React, { Component } from 'react'; -import logo from './logo.svg'; -import './App.css'; import { connect } from 'react-redux' -import { addProduct } from './actions'; +import { favouritePokemon } from './actions'; +import { POKEAPI_BASE_URL } from './constants/api-url'; -import { API_BASE_URL } from './constants/api-url'; +//https://img.pokemondb.net/artwork/${pokemon}.jpg <-- use for pictures const mapStateToProps = state => ({ - products: state.products, -}) + pokemon: state.pokemon, +}); const mapDispatchToProps = { - addProduct, -} + favouritePokemon, +}; class App extends Component { componentDidMount() { - this.props.addProduct({ - name: 'Table', - department: 'Furniture', - price: '300.00', - stock: 5, - }); + //get initial pokemon here, and update state with an action! } render() { - const { products, addProduct } = this.props; + const { pokemon, favouritePokemon } = this.props; // go over destructuring again return ( -
- {products.map(product =>
{product.name}
)} - -
+

Pokemon App!

+ //create SelectedPokemon here + //create PokemonList Here ); } } diff --git a/src/actions/index.js b/src/actions/index.js index 507fd00..e7500d5 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,12 +1,18 @@ export const ACTION_TYPES = { - addProduct: 'ADD_PRODUCT', -} + favouritePokemon: 'FAVOURITE_POKEMON', + setPokemon: 'SET_POKEMON' +}; -export function addProduct(product) { +export function favouritePokemon(pokemon) { return { - type: ACTION_TYPES.addProduct, + type: ACTION_TYPES.favouritePokemon, payload: { - product, + pokemon, } } } + + +export function getPokemon() { + //thunk here! +} diff --git a/src/constants/api-url.js b/src/constants/api-url.js index 18eceee..924dcdd 100644 --- a/src/constants/api-url.js +++ b/src/constants/api-url.js @@ -1 +1 @@ -export const API_BASE_URL = 'https://instgram.com'; +export const POKEAPI_BASE_URL = 'https://pokeapi.coa/pi/v2/'; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 4ae73f8..865f477 100644 --- a/src/index.js +++ b/src/index.js @@ -1,13 +1,16 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { createStore } from 'redux'; +import { createStore, applyMiddleware } from 'redux'; import { Provider } from 'react-redux'; +import thunk from 'redux-thunk'; import App from './App'; import './index.css'; import reducer from './reducers'; -const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); +const store = createStore(reducer, + applyMiddleware(thunk), // this is how think is integrated into the redux library + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); ReactDOM.render( diff --git a/src/reducers/index.js b/src/reducers/index.js index aa23634..a4f7478 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,20 +1,7 @@ import { combineReducers } from 'redux'; +import {pokemon} from "./pokemon"; -import { generateProducts } from '../utils/data'; -import { ACTION_TYPES } from '../actions'; - -const INITIAL_STATE = { - products: generateProducts(10), -}; - -export const products = (state = INITIAL_STATE.products, { type, payload }) => { - if (type === ACTION_TYPES.addProduct) { - return [...state, payload.product]; - } - - return state; -}; export default combineReducers({ - products, + pokemon, }); diff --git a/src/reducers/index.test.js b/src/reducers/index.test.js deleted file mode 100644 index dd671fd..0000000 --- a/src/reducers/index.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import { ACTION_TYPES } from '../actions'; -import { products } from './index'; - - it('adds a product on ADD_PRODUCT', () => { - const action = { - type: ACTION_TYPES.addProduct, - payload: { - product: { - name: 'Sofa', - } - } - }; - expect(products([], action)).toEqual([{ - name: 'Sofa', - }]); - }); diff --git a/src/reducers/pokemon.js b/src/reducers/pokemon.js new file mode 100644 index 0000000..cd940c8 --- /dev/null +++ b/src/reducers/pokemon.js @@ -0,0 +1,17 @@ +import {ACTION_TYPES} from "../actions/index"; + + +const INITIAL_STATE = { + pokemon: [], + favouritePokemon: null +}; + +export const pokemon = (state = INITIAL_STATE, { type, payload }) => { + + switch(type){ + case ACTION_TYPES.favouritePokemon: + return [...state, {favouritePokemon: payload.pokemon}] + } + + return state; +}; diff --git a/src/utils/data.js b/src/utils/data.js deleted file mode 100644 index ed7297a..0000000 --- a/src/utils/data.js +++ /dev/null @@ -1,15 +0,0 @@ -import faker from 'faker'; - -export function generateProducts(numberOfProducts, products = []) { - - if (numberOfProducts === 0) return products; - - products.push({ - name: faker.commerce.productName(), - department: faker.commerce.department(), - price: faker.commerce.price(), - stock: Math.floor(Math.random()*(10 - 2) + 0), - type: faker.commerce.product(), - }); - return generateProducts(numberOfProducts - 1, products); -} From a9fc564f4f9795e3f04c33227fd3f34de11ea6c7 Mon Sep 17 00:00:00 2001 From: Abdella Date: Thu, 2 Feb 2017 20:21:43 -0500 Subject: [PATCH 2/3] debugging code in --- package.json | 10 ++++++-- src/App.js | 24 ++++++++++++++----- src/App.test.js | 8 +++---- src/actions/index.js | 24 ++++++++++++++++++- src/components/pokemon-view.js | 10 ++++++++ src/components/pokemon-view.test.js | 36 +++++++++++++++++++++++++++++ src/constants/api-url.js | 4 +++- src/index.js | 2 +- src/reducers/pokemon.js | 20 +++++++++++----- 9 files changed, 117 insertions(+), 21 deletions(-) create mode 100644 src/components/pokemon-view.js create mode 100644 src/components/pokemon-view.test.js diff --git a/package.json b/package.json index befd1f8..a7c668b 100644 --- a/package.json +++ b/package.json @@ -3,14 +3,20 @@ "version": "0.1.0", "private": true, "devDependencies": { - "react-scripts": "0.8.5" + "chai": "^3.5.0", + "enzyme": "^2.7.1", + "react-addons-test-utils": "^15.4.2", + "react-scripts": "0.8.5", + "sinon": "^1.17.7" }, "dependencies": { "faker": "^3.1.0", + "jquery": "^3.1.1", "react": "^15.4.2", "react-dom": "^15.4.2", "react-redux": "^5.0.2", - "redux": "^3.6.0" + "redux": "^3.6.0", + "redux-thunk": "^2.2.0" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.js b/src/App.js index 25076c8..60e165d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,29 +1,41 @@ import React, { Component } from 'react'; import { connect } from 'react-redux' -import { favouritePokemon } from './actions'; +import { favouritePokemon, getPokemon } from './actions'; -import { POKEAPI_BASE_URL } from './constants/api-url'; +import {PokemonView} from './components/pokemon-view'; + +import { GET_ALL_POKEMON_URL } from './constants/api-url'; //https://img.pokemondb.net/artwork/${pokemon}.jpg <-- use for pictures const mapStateToProps = state => ({ - pokemon: state.pokemon, + pokemon: state.pokemon.list, }); const mapDispatchToProps = { favouritePokemon, + getPokemon }; class App extends Component { componentDidMount() { - //get initial pokemon here, and update state with an action! + debugger; + this.props.getPokemon(); } render() { + const { pokemon, favouritePokemon } = this.props; // go over destructuring again + debugger; return ( -

Pokemon App!

- //create SelectedPokemon here + +
+

Pokemon App!

+ + {pokemon.map(poke =>

{poke.name}

)} + + {/* console.log(name)} pokeData={{name: 'Della', height: '180cm'}} />*/} +
//create PokemonList Here ); } diff --git a/src/App.test.js b/src/App.test.js index e80f4e4..1f9aafe 100644 --- a/src/App.test.js +++ b/src/App.test.js @@ -1,7 +1,7 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - +// import React from 'react'; +// import ReactDOM from 'react-dom'; +// import App from './App'; +// // it('renders without crashing', () => { // const div = document.createElement('div'); // ReactDOM.render(, div); diff --git a/src/actions/index.js b/src/actions/index.js index e7500d5..c4e9471 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,3 +1,8 @@ +import $ from 'jquery'; + +import {GET_ALL_POKEMON_URL} from '../constants/api-url'; + + export const ACTION_TYPES = { favouritePokemon: 'FAVOURITE_POKEMON', setPokemon: 'SET_POKEMON' @@ -14,5 +19,22 @@ export function favouritePokemon(pokemon) { export function getPokemon() { - //thunk here! + + debugger; + + return function (dispatch) { + debugger; + $.get(GET_ALL_POKEMON_URL) + .then(response => { + debugger; + dispatch({ + type: ACTION_TYPES.setPokemon, + payload: { + pokemon: response.results + } + }) + }); + + }; + } diff --git a/src/components/pokemon-view.js b/src/components/pokemon-view.js new file mode 100644 index 0000000..7e9a002 --- /dev/null +++ b/src/components/pokemon-view.js @@ -0,0 +1,10 @@ +import React from 'react'; + +export const PokemonView = ({pokeData, favourite}) =>
+ +

{pokeData.name}

+

Height: {pokeData.height}

+ + + +
; diff --git a/src/components/pokemon-view.test.js b/src/components/pokemon-view.test.js new file mode 100644 index 0000000..a88b92e --- /dev/null +++ b/src/components/pokemon-view.test.js @@ -0,0 +1,36 @@ +import React from 'react'; +import { expect } from 'chai'; +import { shallow } from 'enzyme'; +import {PokemonView} from './pokemon-view'; +import sinon from 'sinon'; + + +describe('', () => { + + it('Should display the name in an H2', () => { + + const wrapper = shallow(); + + expect(wrapper.find('h2')).to.have.length(1); + expect(wrapper.find('h2').text()).to.contain('Bob'); + + }); + + it('should favourite a pokemon on button click', () => { + + let mySpy = sinon.spy(); + + const wrapper = shallow(); + + + wrapper.find('button').simulate('click'); + expect(mySpy.calledOnce).to.equal(false); + + }); + +}); diff --git a/src/constants/api-url.js b/src/constants/api-url.js index 924dcdd..0dea808 100644 --- a/src/constants/api-url.js +++ b/src/constants/api-url.js @@ -1 +1,3 @@ -export const POKEAPI_BASE_URL = 'https://pokeapi.coa/pi/v2/'; \ No newline at end of file +const POKEAPI_BASE_URL = 'https://pokeapi.co/api/v2/'; + +export const GET_ALL_POKEMON_URL = POKEAPI_BASE_URL + 'pokemon'; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 865f477..879c7de 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,7 @@ import './index.css'; import reducer from './reducers'; const store = createStore(reducer, - applyMiddleware(thunk), // this is how think is integrated into the redux library + applyMiddleware(thunk), // this is how thunk is integrated into the redux library window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); ReactDOM.render( diff --git a/src/reducers/pokemon.js b/src/reducers/pokemon.js index cd940c8..ed4eaeb 100644 --- a/src/reducers/pokemon.js +++ b/src/reducers/pokemon.js @@ -2,16 +2,24 @@ import {ACTION_TYPES} from "../actions/index"; const INITIAL_STATE = { - pokemon: [], + list: [], favouritePokemon: null }; -export const pokemon = (state = INITIAL_STATE, { type, payload }) => { +export const pokemon = (state = INITIAL_STATE, {type, payload}) => { + debugger; - switch(type){ + switch (type) { case ACTION_TYPES.favouritePokemon: - return [...state, {favouritePokemon: payload.pokemon}] + return {...state, ...{favouritePokemon: payload.pokemon}}; + + case ACTION_TYPES.setPokemon: + debugger; + + return {...state, ...{list: payload.pokemon}}; + + default: + return state; } - return state; -}; +}; \ No newline at end of file From f132494bff42691e911151effc8024b9e627b0a5 Mon Sep 17 00:00:00 2001 From: Abdella Date: Thu, 2 Feb 2017 20:55:11 -0500 Subject: [PATCH 3/3] assert and testing stuff --- src/App.js | 6 ++---- src/actions/index.js | 3 --- src/components/pokemon-view.js | 1 + src/components/pokemon-view.test.js | 9 ++++++--- src/reducers/pokemon.js | 2 -- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/App.js b/src/App.js index 60e165d..a3e9429 100644 --- a/src/App.js +++ b/src/App.js @@ -19,22 +19,20 @@ const mapDispatchToProps = { class App extends Component { componentDidMount() { - debugger; this.props.getPokemon(); } render() { const { pokemon, favouritePokemon } = this.props; // go over destructuring again - debugger; return (

Pokemon App!

+ console.log(name)} pokeData={{name: 'Della', height: '180cm'}} /> - {pokemon.map(poke =>

{poke.name}

)} + {pokemon.map(poke =>

{poke.name}

)} - {/* console.log(name)} pokeData={{name: 'Della', height: '180cm'}} />*/}
//create PokemonList Here ); diff --git a/src/actions/index.js b/src/actions/index.js index c4e9471..2b3eed3 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -20,13 +20,10 @@ export function favouritePokemon(pokemon) { export function getPokemon() { - debugger; return function (dispatch) { - debugger; $.get(GET_ALL_POKEMON_URL) .then(response => { - debugger; dispatch({ type: ACTION_TYPES.setPokemon, payload: { diff --git a/src/components/pokemon-view.js b/src/components/pokemon-view.js index 7e9a002..def3284 100644 --- a/src/components/pokemon-view.js +++ b/src/components/pokemon-view.js @@ -3,6 +3,7 @@ import React from 'react'; export const PokemonView = ({pokeData, favourite}) =>

{pokeData.name}

+

Height: {pokeData.height}

diff --git a/src/components/pokemon-view.test.js b/src/components/pokemon-view.test.js index a88b92e..f269e44 100644 --- a/src/components/pokemon-view.test.js +++ b/src/components/pokemon-view.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { expect } from 'chai'; +import { expect, assert } from 'chai'; import { shallow } from 'enzyme'; import {PokemonView} from './pokemon-view'; import sinon from 'sinon'; @@ -23,13 +23,16 @@ describe('', () => { let mySpy = sinon.spy(); const wrapper = shallow(); - wrapper.find('button').simulate('click'); expect(mySpy.calledOnce).to.equal(false); + wrapper.find('button').simulate('click'); + expect(mySpy.calledOnce).to.equal(true); + + assert(mySpy.calledWith('Jon'), 'I expect the pokemon name that is passed in to be what is called when the button is clicked'); }); diff --git a/src/reducers/pokemon.js b/src/reducers/pokemon.js index ed4eaeb..dd4da40 100644 --- a/src/reducers/pokemon.js +++ b/src/reducers/pokemon.js @@ -7,14 +7,12 @@ const INITIAL_STATE = { }; export const pokemon = (state = INITIAL_STATE, {type, payload}) => { - debugger; switch (type) { case ACTION_TYPES.favouritePokemon: return {...state, ...{favouritePokemon: payload.pokemon}}; case ACTION_TYPES.setPokemon: - debugger; return {...state, ...{list: payload.pokemon}};