From f17d2cd5f83967c32dea6cc17157af0d4f86cc57 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Sun, 5 Apr 2020 20:51:18 +0200 Subject: [PATCH 01/14] fetching data into store --- 00 Base/package.json | 7 ++++++- 00 Base/src/index.tsx | 11 ++++++++++- 00 Base/src/myComponent/myComponent.tsx | 7 ++++++- 00 Base/src/redux/actions/fruitsActions.tsx | 14 ++++++++++++++ 00 Base/src/redux/constants.ts | 1 + 00 Base/src/redux/reducers/fruitReducer.tsx | 19 +++++++++++++++++++ 00 Base/src/redux/reducers/index.js | 6 ++++++ 00 Base/src/redux/store.js | 12 ++++++++++++ 8 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 00 Base/src/redux/actions/fruitsActions.tsx create mode 100644 00 Base/src/redux/constants.ts create mode 100644 00 Base/src/redux/reducers/fruitReducer.tsx create mode 100644 00 Base/src/redux/reducers/index.js create mode 100644 00 Base/src/redux/store.js diff --git a/00 Base/package.json b/00 Base/package.json index c70f345..94df324 100644 --- a/00 Base/package.json +++ b/00 Base/package.json @@ -15,9 +15,13 @@ "dependencies": { "@material-ui/core": "^4.1.3", "axios": "^0.19.0", + "babel-polyfill": "^6.26.0", "react": "^16.8.6", "react-dom": "^16.8.6", - "react-router-dom": "^5.0.1" + "react-redux": "^7.2.0", + "react-router-dom": "^5.0.1", + "redux": "^4.0.5", + "redux-thunk": "^2.3.0" }, "devDependencies": { "@babel/cli": "^7.4.4", @@ -31,6 +35,7 @@ "awesome-typescript-loader": "^5.2.1", "html-webpack-plugin": "^3.2.0", "jest": "^24.8.0", + "redux-devtools-extension": "^2.13.8", "rimraf": "^2.6.3", "ts-jest": "^24.0.2", "typescript": "^3.5.2", diff --git a/00 Base/src/index.tsx b/00 Base/src/index.tsx index ded7936..2c35ff9 100644 --- a/00 Base/src/index.tsx +++ b/00 Base/src/index.tsx @@ -1,5 +1,14 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; +import { Provider } from 'react-redux'; +import store from './redux/store'; + import { App } from './app'; +import 'babel-polyfill' -ReactDOM.render(, document.getElementById('root')); +ReactDOM.render( + + + , + document.getElementById('root') +); diff --git a/00 Base/src/myComponent/myComponent.tsx b/00 Base/src/myComponent/myComponent.tsx index ea44068..7fec1db 100644 --- a/00 Base/src/myComponent/myComponent.tsx +++ b/00 Base/src/myComponent/myComponent.tsx @@ -1,15 +1,20 @@ import * as React from 'react'; +import {useSelector, useDispatch} from 'react-redux' +import {fetchfruits} from './../redux/actions/fruitsActions' + export interface Props { nameFromProps: string; } export const MyComponent: React.FunctionComponent = props => { const { nameFromProps } = props; - + const dispatch = useDispatch() + return ( <>

Hello {nameFromProps}!

+ ); }; \ No newline at end of file diff --git a/00 Base/src/redux/actions/fruitsActions.tsx b/00 Base/src/redux/actions/fruitsActions.tsx new file mode 100644 index 0000000..258f7b7 --- /dev/null +++ b/00 Base/src/redux/actions/fruitsActions.tsx @@ -0,0 +1,14 @@ +import { GET_ALL_FRUITS } from './../constants'; +import { getListOfFruit } from '../../myApi/index'; + +export const getAllFruits = (res) => { + return { + type: GET_ALL_FRUITS, + payload: res, + }; +}; +export const fetchfruits = () => { + return (dispatch) => { + return getListOfFruit().then((res) => dispatch(getAllFruits(res))); + }; +}; diff --git a/00 Base/src/redux/constants.ts b/00 Base/src/redux/constants.ts new file mode 100644 index 0000000..207ec14 --- /dev/null +++ b/00 Base/src/redux/constants.ts @@ -0,0 +1 @@ +export const GET_ALL_FRUITS = 'GET_ALL_FRUITS' \ No newline at end of file diff --git a/00 Base/src/redux/reducers/fruitReducer.tsx b/00 Base/src/redux/reducers/fruitReducer.tsx new file mode 100644 index 0000000..add19c6 --- /dev/null +++ b/00 Base/src/redux/reducers/fruitReducer.tsx @@ -0,0 +1,19 @@ +import { GET_ALL_FRUITS } from './../constants'; +const initialState = { + fruitList: [], +}; +export default function (state = initialState, action) { + switch (action.type) { + case GET_ALL_FRUITS: { + return { + ...state, + fruitList: action.payload, + }; + } + default: { + return { + ...state, + }; + } + } +} diff --git a/00 Base/src/redux/reducers/index.js b/00 Base/src/redux/reducers/index.js new file mode 100644 index 0000000..4b26bf6 --- /dev/null +++ b/00 Base/src/redux/reducers/index.js @@ -0,0 +1,6 @@ +import { combineReducers } from 'redux'; +import fruitsReducer from './fruitReducer'; + +export default combineReducers({ + fruits: fruitsReducer, +}); diff --git a/00 Base/src/redux/store.js b/00 Base/src/redux/store.js new file mode 100644 index 0000000..e7c2c33 --- /dev/null +++ b/00 Base/src/redux/store.js @@ -0,0 +1,12 @@ +import { createStore, applyMiddleware, compose } from 'redux'; +import thunk from 'redux-thunk'; +import rootReducer from './reducers/index'; + +const initialState = {}; +const middleware = [thunk]; +const store=createStore(rootReducer,initialState,compose( + applyMiddleware(thunk), + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() + +)) +export default store; From 6f2cef5855336a53eb9ee2719fe33e26f2e43236 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Mon, 6 Apr 2020 20:37:53 +0200 Subject: [PATCH 02/14] new packages and webpack updated to be able to use scss and css --- 00 Base/config/webpack/base.js | 17 ++++++++++++++++- 00 Base/package.json | 10 ++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/00 Base/config/webpack/base.js b/00 Base/config/webpack/base.js index 116fcaf..d46e520 100644 --- a/00 Base/config/webpack/base.js +++ b/00 Base/config/webpack/base.js @@ -8,7 +8,7 @@ module.exports = merge( { context: helpers.resolveFromRootPath('src'), resolve: { - extensions: ['.js', '.ts', '.tsx'], + extensions: ['.js', '.ts', '.tsx', '.css', '.scss'], }, entry: { app: ['./index.tsx'], @@ -25,6 +25,21 @@ module.exports = merge( babelCore: '@babel/core', }, }, + { + test: /\.css$/, + loaders: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.s[ac]ss$/i, + loaders: [ + 'style-loader', + 'css-loader', + 'sass-loader', + ], + }, ], }, optimization: { diff --git a/00 Base/package.json b/00 Base/package.json index 94df324..ad735e4 100644 --- a/00 Base/package.json +++ b/00 Base/package.json @@ -13,7 +13,8 @@ "author": "arp82", "license": "MIT", "dependencies": { - "@material-ui/core": "^4.1.3", + "@material-ui/core": "^4.9.9", + "@material-ui/icons": "^4.9.1", "axios": "^0.19.0", "babel-polyfill": "^6.26.0", "react": "^16.8.6", @@ -21,7 +22,8 @@ "react-redux": "^7.2.0", "react-router-dom": "^5.0.1", "redux": "^4.0.5", - "redux-thunk": "^2.3.0" + "redux-thunk": "^2.3.0", + "sass-loader": "^8.0.2" }, "devDependencies": { "@babel/cli": "^7.4.4", @@ -33,10 +35,14 @@ "@types/react-dom": "^16.8.4", "@types/react-router-dom": "^4.3.4", "awesome-typescript-loader": "^5.2.1", + "css-loader": "^3.4.2", "html-webpack-plugin": "^3.2.0", "jest": "^24.8.0", + "node-sass": "^4.13.1", "redux-devtools-extension": "^2.13.8", "rimraf": "^2.6.3", + "sass-loader": "^7.2.0", + "style-loader": "^1.1.3", "ts-jest": "^24.0.2", "typescript": "^3.5.2", "webpack": "^4.32.2", From 397791ae9dae158f12a4112c87e7318a16c33092 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Mon, 6 Apr 2020 20:38:41 +0200 Subject: [PATCH 03/14] delete and add a fruit --- 00 Base/src/myComponent/myComponent.tsx | 50 ++++++++++++++++---- 00 Base/src/myComponent/myInputComponent.tsx | 30 ++++++++++++ 00 Base/src/myComponent/styles.scss | 21 ++++++++ 00 Base/src/redux/actions/fruitsActions.tsx | 16 ++++++- 00 Base/src/redux/constants.ts | 4 +- 00 Base/src/redux/reducers/fruitReducer.tsx | 14 +++++- 6 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 00 Base/src/myComponent/myInputComponent.tsx create mode 100644 00 Base/src/myComponent/styles.scss diff --git a/00 Base/src/myComponent/myComponent.tsx b/00 Base/src/myComponent/myComponent.tsx index 7fec1db..867f59a 100644 --- a/00 Base/src/myComponent/myComponent.tsx +++ b/00 Base/src/myComponent/myComponent.tsx @@ -1,20 +1,54 @@ import * as React from 'react'; -import {useSelector, useDispatch} from 'react-redux' -import {fetchfruits} from './../redux/actions/fruitsActions' +import { useSelector, useDispatch } from 'react-redux'; +import { + fetchfruits, + deleteFruit, + addFruit, +} from './../redux/actions/fruitsActions'; +import './styles.scss'; +import Button from '@material-ui/core/Button'; +import Chip from '@material-ui/core/Chip'; + +import { MyInputComponent } from './myInputComponent'; export interface Props { nameFromProps: string; } -export const MyComponent: React.FunctionComponent = props => { +export const MyComponent: React.FunctionComponent = (props) => { const { nameFromProps } = props; - const dispatch = useDispatch() - + const dispatch = useDispatch(); + const fruitList = useSelector((state) => state.fruits.fruitList); + console.log('fruitList', fruitList); + return ( <> -

Hello {nameFromProps}!

- +
+

Hello {nameFromProps}!

+ +
+ {!!fruitList + ? fruitList.map((el: string) => ( + dispatch(deleteFruit(el))} + /> + )) + : null} +
+ dispatch(addFruit(newFruit))} + /> +
); -}; \ No newline at end of file +}; diff --git a/00 Base/src/myComponent/myInputComponent.tsx b/00 Base/src/myComponent/myInputComponent.tsx new file mode 100644 index 0000000..b3d2818 --- /dev/null +++ b/00 Base/src/myComponent/myInputComponent.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import TextField from '@material-ui/core/TextField'; +import { Add } from '@material-ui/icons'; + +export interface Props { + addFruit: Function; +} + +export const MyInputComponent: React.FunctionComponent = (props) => { + const { addFruit } = props; + const [name, setName] = React.useState(''); + + return ( +
+ setName(e.target.value)} + /> + {!!name ? ( + { + addFruit(name); + setName(''); + }} + /> + ) : null} +
+ ); +}; diff --git a/00 Base/src/myComponent/styles.scss b/00 Base/src/myComponent/styles.scss new file mode 100644 index 0000000..f42639a --- /dev/null +++ b/00 Base/src/myComponent/styles.scss @@ -0,0 +1,21 @@ +.container { + text-align: center; + .chip-container { + display: block; + position: relative; + margin-top: 25px; + .MuiChip-root { + margin-left: 5px; + margin-top: 5px; + } + } + .input-component { + .MuiFormControl-root { + margin-top: 10px; + } + .MuiSvgIcon-root { + margin-top: 35px; + color: #00ff00; + } + } +} diff --git a/00 Base/src/redux/actions/fruitsActions.tsx b/00 Base/src/redux/actions/fruitsActions.tsx index 258f7b7..850f984 100644 --- a/00 Base/src/redux/actions/fruitsActions.tsx +++ b/00 Base/src/redux/actions/fruitsActions.tsx @@ -1,4 +1,4 @@ -import { GET_ALL_FRUITS } from './../constants'; +import { GET_ALL_FRUITS, DELETE_FRUIT, ADD_FRUIT } from './../constants'; import { getListOfFruit } from '../../myApi/index'; export const getAllFruits = (res) => { @@ -12,3 +12,17 @@ export const fetchfruits = () => { return getListOfFruit().then((res) => dispatch(getAllFruits(res))); }; }; + +export const deleteFruit = (name) => { + return { + type: DELETE_FRUIT, + payload: name, + }; +}; + +export const addFruit = (name) => { + return { + type: ADD_FRUIT, + payload: name, + }; +}; diff --git a/00 Base/src/redux/constants.ts b/00 Base/src/redux/constants.ts index 207ec14..06549a2 100644 --- a/00 Base/src/redux/constants.ts +++ b/00 Base/src/redux/constants.ts @@ -1 +1,3 @@ -export const GET_ALL_FRUITS = 'GET_ALL_FRUITS' \ No newline at end of file +export const GET_ALL_FRUITS = 'GET_ALL_FRUITS' +export const DELETE_FRUIT = 'DELETE_FRUIT' +export const ADD_FRUIT = 'ADD_FRUIT' \ No newline at end of file diff --git a/00 Base/src/redux/reducers/fruitReducer.tsx b/00 Base/src/redux/reducers/fruitReducer.tsx index add19c6..a3cfbec 100644 --- a/00 Base/src/redux/reducers/fruitReducer.tsx +++ b/00 Base/src/redux/reducers/fruitReducer.tsx @@ -1,4 +1,4 @@ -import { GET_ALL_FRUITS } from './../constants'; +import { GET_ALL_FRUITS, DELETE_FRUIT, ADD_FRUIT } from './../constants'; const initialState = { fruitList: [], }; @@ -10,6 +10,18 @@ export default function (state = initialState, action) { fruitList: action.payload, }; } + case DELETE_FRUIT: { + return { + ...state, + fruitList: state.fruitList.filter((e) => e !== action.payload), + }; + } + case ADD_FRUIT: { + return { + ...state, + fruitList: state.fruitList.concat([action.payload]), + }; + } default: { return { ...state, From 6b0e4b7a9cf7cd19462bfb589474c3216089f4c4 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Tue, 7 Apr 2020 19:43:26 +0200 Subject: [PATCH 04/14] new component folder --- 00 Base/src/app.tsx | 2 +- 00 Base/src/{ => components}/myComponent/index.ts | 0 00 Base/src/{ => components}/myComponent/myComponent.tsx | 4 ++-- 00 Base/src/{ => components}/myComponent/styles.scss | 9 --------- 00 Base/src/components/myInputComponent/index.ts | 1 + .../myInputComponent}/myInputComponent.tsx | 1 + 00 Base/src/components/myInputComponent/styles.scss | 9 +++++++++ 00 Base/src/redux/actions/fruitsActions.tsx | 8 ++++---- 00 Base/src/redux/reducers/fruitReducer.tsx | 2 +- 9 files changed, 19 insertions(+), 17 deletions(-) rename 00 Base/src/{ => components}/myComponent/index.ts (100%) rename 00 Base/src/{ => components}/myComponent/myComponent.tsx (91%) rename 00 Base/src/{ => components}/myComponent/styles.scss (56%) create mode 100644 00 Base/src/components/myInputComponent/index.ts rename 00 Base/src/{myComponent => components/myInputComponent}/myInputComponent.tsx (96%) create mode 100644 00 Base/src/components/myInputComponent/styles.scss diff --git a/00 Base/src/app.tsx b/00 Base/src/app.tsx index f201da0..b427eff 100644 --- a/00 Base/src/app.tsx +++ b/00 Base/src/app.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { MyComponent } from './myComponent'; +import { MyComponent } from './components/myComponent'; export const App: React.FunctionComponent = props => (
diff --git a/00 Base/src/myComponent/index.ts b/00 Base/src/components/myComponent/index.ts similarity index 100% rename from 00 Base/src/myComponent/index.ts rename to 00 Base/src/components/myComponent/index.ts diff --git a/00 Base/src/myComponent/myComponent.tsx b/00 Base/src/components/myComponent/myComponent.tsx similarity index 91% rename from 00 Base/src/myComponent/myComponent.tsx rename to 00 Base/src/components/myComponent/myComponent.tsx index 867f59a..bcd59bc 100644 --- a/00 Base/src/myComponent/myComponent.tsx +++ b/00 Base/src/components/myComponent/myComponent.tsx @@ -5,13 +5,13 @@ import { fetchfruits, deleteFruit, addFruit, -} from './../redux/actions/fruitsActions'; +} from './../../redux/actions/fruitsActions'; import './styles.scss'; import Button from '@material-ui/core/Button'; import Chip from '@material-ui/core/Chip'; -import { MyInputComponent } from './myInputComponent'; +import { MyInputComponent } from '../myInputComponent/myInputComponent'; export interface Props { nameFromProps: string; } diff --git a/00 Base/src/myComponent/styles.scss b/00 Base/src/components/myComponent/styles.scss similarity index 56% rename from 00 Base/src/myComponent/styles.scss rename to 00 Base/src/components/myComponent/styles.scss index f42639a..3ec5f71 100644 --- a/00 Base/src/myComponent/styles.scss +++ b/00 Base/src/components/myComponent/styles.scss @@ -9,13 +9,4 @@ margin-top: 5px; } } - .input-component { - .MuiFormControl-root { - margin-top: 10px; - } - .MuiSvgIcon-root { - margin-top: 35px; - color: #00ff00; - } - } } diff --git a/00 Base/src/components/myInputComponent/index.ts b/00 Base/src/components/myInputComponent/index.ts new file mode 100644 index 0000000..3b0b11d --- /dev/null +++ b/00 Base/src/components/myInputComponent/index.ts @@ -0,0 +1 @@ +export { MyInputComponent } from './myInputComponent'; \ No newline at end of file diff --git a/00 Base/src/myComponent/myInputComponent.tsx b/00 Base/src/components/myInputComponent/myInputComponent.tsx similarity index 96% rename from 00 Base/src/myComponent/myInputComponent.tsx rename to 00 Base/src/components/myInputComponent/myInputComponent.tsx index b3d2818..6f9bf2b 100644 --- a/00 Base/src/myComponent/myInputComponent.tsx +++ b/00 Base/src/components/myInputComponent/myInputComponent.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import TextField from '@material-ui/core/TextField'; import { Add } from '@material-ui/icons'; +import './styles.scss'; export interface Props { addFruit: Function; diff --git a/00 Base/src/components/myInputComponent/styles.scss b/00 Base/src/components/myInputComponent/styles.scss new file mode 100644 index 0000000..0af11b8 --- /dev/null +++ b/00 Base/src/components/myInputComponent/styles.scss @@ -0,0 +1,9 @@ +.input-component { + .MuiFormControl-root { + margin-top: 10px; + } + .MuiSvgIcon-root { + margin-top: 35px; + color: #00ff00; + } +} diff --git a/00 Base/src/redux/actions/fruitsActions.tsx b/00 Base/src/redux/actions/fruitsActions.tsx index 850f984..81d68bf 100644 --- a/00 Base/src/redux/actions/fruitsActions.tsx +++ b/00 Base/src/redux/actions/fruitsActions.tsx @@ -1,10 +1,10 @@ import { GET_ALL_FRUITS, DELETE_FRUIT, ADD_FRUIT } from './../constants'; import { getListOfFruit } from '../../myApi/index'; -export const getAllFruits = (res) => { +export const getAllFruits = (fruits: String[]) => { return { type: GET_ALL_FRUITS, - payload: res, + payload: fruits, }; }; export const fetchfruits = () => { @@ -13,14 +13,14 @@ export const fetchfruits = () => { }; }; -export const deleteFruit = (name) => { +export const deleteFruit = (name: string) => { return { type: DELETE_FRUIT, payload: name, }; }; -export const addFruit = (name) => { +export const addFruit = (name: string) => { return { type: ADD_FRUIT, payload: name, diff --git a/00 Base/src/redux/reducers/fruitReducer.tsx b/00 Base/src/redux/reducers/fruitReducer.tsx index a3cfbec..e260a37 100644 --- a/00 Base/src/redux/reducers/fruitReducer.tsx +++ b/00 Base/src/redux/reducers/fruitReducer.tsx @@ -13,7 +13,7 @@ export default function (state = initialState, action) { case DELETE_FRUIT: { return { ...state, - fruitList: state.fruitList.filter((e) => e !== action.payload), + fruitList: state.fruitList.filter((e: string) => e !== action.payload), }; } case ADD_FRUIT: { From 9b112c08fd7f49f9efd479d848db07cd0165523d Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Wed, 8 Apr 2020 17:45:21 +0200 Subject: [PATCH 05/14] fix --- 00 Base/config/webpack/base.js | 17 +++++++---------- 00 Base/package.json | 4 +++- 00 Base/src/app.tsx | 3 ++- .../src/components/myComponent/myComponent.tsx | 5 ++--- .../myComponent/{styles.scss => styles.less} | 0 .../myInputComponent/myInputComponent.tsx | 2 +- .../{styles.scss => styles.less} | 0 00 Base/src/redux/actions/index.ts | 6 ++++++ 00 Base/src/styles.less | 3 +++ 9 files changed, 24 insertions(+), 16 deletions(-) rename 00 Base/src/components/myComponent/{styles.scss => styles.less} (100%) rename 00 Base/src/components/myInputComponent/{styles.scss => styles.less} (100%) create mode 100644 00 Base/src/redux/actions/index.ts create mode 100644 00 Base/src/styles.less diff --git a/00 Base/config/webpack/base.js b/00 Base/config/webpack/base.js index d46e520..d4fc9eb 100644 --- a/00 Base/config/webpack/base.js +++ b/00 Base/config/webpack/base.js @@ -8,7 +8,7 @@ module.exports = merge( { context: helpers.resolveFromRootPath('src'), resolve: { - extensions: ['.js', '.ts', '.tsx', '.css', '.scss'], + extensions: ['.js', '.ts', '.tsx', '.css', '.scss', '.less'], }, entry: { app: ['./index.tsx'], @@ -27,18 +27,15 @@ module.exports = merge( }, { test: /\.css$/, - loaders: [ - 'style-loader', - 'css-loader' - ] + loaders: ['style-loader', 'css-loader'], }, { test: /\.s[ac]ss$/i, - loaders: [ - 'style-loader', - 'css-loader', - 'sass-loader', - ], + loaders: ['style-loader', 'css-loader', 'sass-loader'], + }, + { + test: /\.less$/, + use: ['style-loader', 'css-loader', 'less-loader'], }, ], }, diff --git a/00 Base/package.json b/00 Base/package.json index ad735e4..2e335f0 100644 --- a/00 Base/package.json +++ b/00 Base/package.json @@ -35,9 +35,11 @@ "@types/react-dom": "^16.8.4", "@types/react-router-dom": "^4.3.4", "awesome-typescript-loader": "^5.2.1", - "css-loader": "^3.4.2", + "css-loader": "^3.5.1", "html-webpack-plugin": "^3.2.0", "jest": "^24.8.0", + "less": "^3.11.1", + "less-loader": "^5.0.0", "node-sass": "^4.13.1", "redux-devtools-extension": "^2.13.8", "rimraf": "^2.6.3", diff --git a/00 Base/src/app.tsx b/00 Base/src/app.tsx index b427eff..f234558 100644 --- a/00 Base/src/app.tsx +++ b/00 Base/src/app.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; import { MyComponent } from './components/myComponent'; +import './styles.less'; -export const App: React.FunctionComponent = props => ( +export const App: React.FunctionComponent = (props) => (
diff --git a/00 Base/src/components/myComponent/myComponent.tsx b/00 Base/src/components/myComponent/myComponent.tsx index bcd59bc..8b9ba4c 100644 --- a/00 Base/src/components/myComponent/myComponent.tsx +++ b/00 Base/src/components/myComponent/myComponent.tsx @@ -5,8 +5,8 @@ import { fetchfruits, deleteFruit, addFruit, -} from './../../redux/actions/fruitsActions'; -import './styles.scss'; +} from './../../redux/actions/index'; +import './styles.less'; import Button from '@material-ui/core/Button'; import Chip from '@material-ui/core/Chip'; @@ -20,7 +20,6 @@ export const MyComponent: React.FunctionComponent = (props) => { const { nameFromProps } = props; const dispatch = useDispatch(); const fruitList = useSelector((state) => state.fruits.fruitList); - console.log('fruitList', fruitList); return ( <> diff --git a/00 Base/src/components/myComponent/styles.scss b/00 Base/src/components/myComponent/styles.less similarity index 100% rename from 00 Base/src/components/myComponent/styles.scss rename to 00 Base/src/components/myComponent/styles.less diff --git a/00 Base/src/components/myInputComponent/myInputComponent.tsx b/00 Base/src/components/myInputComponent/myInputComponent.tsx index 6f9bf2b..20b7d79 100644 --- a/00 Base/src/components/myInputComponent/myInputComponent.tsx +++ b/00 Base/src/components/myInputComponent/myInputComponent.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import TextField from '@material-ui/core/TextField'; import { Add } from '@material-ui/icons'; -import './styles.scss'; +import './styles.less'; export interface Props { addFruit: Function; diff --git a/00 Base/src/components/myInputComponent/styles.scss b/00 Base/src/components/myInputComponent/styles.less similarity index 100% rename from 00 Base/src/components/myInputComponent/styles.scss rename to 00 Base/src/components/myInputComponent/styles.less diff --git a/00 Base/src/redux/actions/index.ts b/00 Base/src/redux/actions/index.ts new file mode 100644 index 0000000..3cb5666 --- /dev/null +++ b/00 Base/src/redux/actions/index.ts @@ -0,0 +1,6 @@ +export { + addFruit, + deleteFruit, + fetchfruits, + getAllFruits, +} from './fruitsActions'; diff --git a/00 Base/src/styles.less b/00 Base/src/styles.less new file mode 100644 index 0000000..af8d565 --- /dev/null +++ b/00 Base/src/styles.less @@ -0,0 +1,3 @@ +body { + background-color: #afafdc; +} From 4c660a4b547cb8631f1d1ca1b7b588ab62274f6e Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Wed, 8 Apr 2020 19:51:28 +0200 Subject: [PATCH 06/14] reducer and action test --- .../src/redux/actions/fruitsActions.spec.tsx | 31 +++++++++++ .../src/redux/reducers/fruitReducer.spec.tsx | 55 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 00 Base/src/redux/actions/fruitsActions.spec.tsx create mode 100644 00 Base/src/redux/reducers/fruitReducer.spec.tsx diff --git a/00 Base/src/redux/actions/fruitsActions.spec.tsx b/00 Base/src/redux/actions/fruitsActions.spec.tsx new file mode 100644 index 0000000..fa277fc --- /dev/null +++ b/00 Base/src/redux/actions/fruitsActions.spec.tsx @@ -0,0 +1,31 @@ +import { addFruit, deleteFruit, getAllFruits } from './index'; +import { GET_ALL_FRUITS, DELETE_FRUIT, ADD_FRUIT } from '../constants'; + +describe('actions', () => { + it('should create an action to add a fruit', () => { + const fruit = 'grape'; + const expectedAction = { + type: ADD_FRUIT, + payload: fruit, + }; + expect(addFruit(fruit)).toEqual(expectedAction); + }); + + it('should create an action to delete a fruit', () => { + const fruit = 'grape'; + const expectedAction = { + type: DELETE_FRUIT, + payload: fruit, + }; + expect(deleteFruit(fruit)).toEqual(expectedAction); + }); + + it('should create an action to fetch', () => { + const fruit = ['grape','banana']; + const expectedAction = { + type: GET_ALL_FRUITS, + payload: fruit, + }; + expect(getAllFruits(fruit)).toEqual(expectedAction); + }); +}); diff --git a/00 Base/src/redux/reducers/fruitReducer.spec.tsx b/00 Base/src/redux/reducers/fruitReducer.spec.tsx new file mode 100644 index 0000000..64ec3e7 --- /dev/null +++ b/00 Base/src/redux/reducers/fruitReducer.spec.tsx @@ -0,0 +1,55 @@ +import reducer from './fruitReducer'; +import { ADD_FRUIT, DELETE_FRUIT } from '../constants'; + +const initialState = { + fruitList: [], +}; + +describe('fruit reducer', () => { + it('should return the initial state', () => { + expect(reducer(undefined, {})).toEqual({ + fruitList: [], + }); + }); + + it('should handle ADD_FRUIT', () => { + const grape = 'grape'; + expect( + reducer(initialState, { + type: ADD_FRUIT, + payload: grape, + }) + ).toEqual({ + fruitList: [grape], + }); + + expect( + reducer( + { + fruitList: ['apple'], + }, + { + type: ADD_FRUIT, + payload: grape, + } + ) + ).toEqual({ + fruitList: ['apple', grape], + }); + }); + + it('should handle DELETE_FRUIT', () => { + const grape = 'grape'; + expect( + reducer( + { fruitList: [grape, 'apple'] }, + { + type: DELETE_FRUIT, + payload: grape, + } + ) + ).toEqual({ + fruitList: ['apple'], + }); + }); +}); From cf5045ac777a7e76fe2428ca2569d46da5867abe Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Thu, 9 Apr 2020 13:03:09 +0200 Subject: [PATCH 07/14] api test --- 00 Base/src/myApi/myApi.spec.tsx | 16 ++++++++++++++++ 00 Base/src/redux/actions/fruitsActions.spec.tsx | 6 +++--- 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 00 Base/src/myApi/myApi.spec.tsx diff --git a/00 Base/src/myApi/myApi.spec.tsx b/00 Base/src/myApi/myApi.spec.tsx new file mode 100644 index 0000000..d2a61e5 --- /dev/null +++ b/00 Base/src/myApi/myApi.spec.tsx @@ -0,0 +1,16 @@ +import { getListOfFruit } from './myApi'; + +describe('myApi tests', () => { + it('getListOfFruit should return an array of string', () => { + expect(getListOfFruit()).resolves.toEqual([ + 'grape', + 'pineapple', + 'watermelon', + 'orange', + 'lemon', + 'strawberry', + 'cherry', + 'peach', + ]); + }); +}); diff --git a/00 Base/src/redux/actions/fruitsActions.spec.tsx b/00 Base/src/redux/actions/fruitsActions.spec.tsx index fa277fc..fecba83 100644 --- a/00 Base/src/redux/actions/fruitsActions.spec.tsx +++ b/00 Base/src/redux/actions/fruitsActions.spec.tsx @@ -19,9 +19,9 @@ describe('actions', () => { }; expect(deleteFruit(fruit)).toEqual(expectedAction); }); - - it('should create an action to fetch', () => { - const fruit = ['grape','banana']; + + it('should create an action to get all fruits', () => { + const fruit = ['grape', 'banana']; const expectedAction = { type: GET_ALL_FRUITS, payload: fruit, From 442991d68a879f0a8f340ddf7c85370d74f82edc Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Fri, 10 Apr 2020 20:53:00 +0200 Subject: [PATCH 08/14] changed mocked fruits to fake posts api --- 00 Base/package.json | 2 +- .../components/myComponent/myComponent.tsx | 27 ++++++------- .../myInputComponent/myInputComponent.tsx | 8 ++-- 00 Base/src/myApi/index.ts | 2 +- 00 Base/src/myApi/myApi.ts | 15 +++++-- 00 Base/src/redux/actions/index.ts | 1 + 00 Base/src/redux/actions/postActions.tsx | 28 +++++++++++++ 00 Base/src/redux/constants.ts | 10 +++-- 00 Base/src/redux/reducers/index.js | 2 + 00 Base/src/redux/reducers/postReducer.tsx | 39 +++++++++++++++++++ 10 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 00 Base/src/redux/actions/postActions.tsx create mode 100644 00 Base/src/redux/reducers/postReducer.tsx diff --git a/00 Base/package.json b/00 Base/package.json index 2e335f0..d91fccd 100644 --- a/00 Base/package.json +++ b/00 Base/package.json @@ -15,7 +15,7 @@ "dependencies": { "@material-ui/core": "^4.9.9", "@material-ui/icons": "^4.9.1", - "axios": "^0.19.0", + "axios": "^0.19.2", "babel-polyfill": "^6.26.0", "react": "^16.8.6", "react-dom": "^16.8.6", diff --git a/00 Base/src/components/myComponent/myComponent.tsx b/00 Base/src/components/myComponent/myComponent.tsx index 8b9ba4c..529195e 100644 --- a/00 Base/src/components/myComponent/myComponent.tsx +++ b/00 Base/src/components/myComponent/myComponent.tsx @@ -2,9 +2,12 @@ import * as React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { - fetchfruits, + /* fetchfruits, deleteFruit, - addFruit, + addFruit, */ + fetchPosts, + deletePost, + addPost, } from './../../redux/actions/index'; import './styles.less'; @@ -19,7 +22,7 @@ export interface Props { export const MyComponent: React.FunctionComponent = (props) => { const { nameFromProps } = props; const dispatch = useDispatch(); - const fruitList = useSelector((state) => state.fruits.fruitList); + const posts = useSelector((state) => state.posts.posts); return ( <> @@ -28,25 +31,23 @@ export const MyComponent: React.FunctionComponent = (props) => {
- {!!fruitList - ? fruitList.map((el: string) => ( + {!!posts + ? posts.map((el /* : Object */) => ( dispatch(deleteFruit(el))} + label={el.title} + key={el.id} + onDelete={() => dispatch(deletePost(el.id))} /> )) : null}
- dispatch(addFruit(newFruit))} - /> + dispatch(addPost(newPost))} />
); diff --git a/00 Base/src/components/myInputComponent/myInputComponent.tsx b/00 Base/src/components/myInputComponent/myInputComponent.tsx index 20b7d79..bd63ca7 100644 --- a/00 Base/src/components/myInputComponent/myInputComponent.tsx +++ b/00 Base/src/components/myInputComponent/myInputComponent.tsx @@ -4,24 +4,24 @@ import { Add } from '@material-ui/icons'; import './styles.less'; export interface Props { - addFruit: Function; + addPost: Function; } export const MyInputComponent: React.FunctionComponent = (props) => { - const { addFruit } = props; + const { addPost } = props; const [name, setName] = React.useState(''); return (
setName(e.target.value)} /> {!!name ? ( { - addFruit(name); + addPost(name); setName(''); }} /> diff --git a/00 Base/src/myApi/index.ts b/00 Base/src/myApi/index.ts index 3e74d70..3cbca37 100644 --- a/00 Base/src/myApi/index.ts +++ b/00 Base/src/myApi/index.ts @@ -1 +1 @@ -export { getListOfFruit } from './myApi'; \ No newline at end of file +export { getListOfFruit, getPosts } from './myApi'; diff --git a/00 Base/src/myApi/myApi.ts b/00 Base/src/myApi/myApi.ts index 988d0c5..8cd6d3d 100644 --- a/00 Base/src/myApi/myApi.ts +++ b/00 Base/src/myApi/myApi.ts @@ -1,15 +1,24 @@ import * as BEApi from './myBackEndApiEndpoint'; +import axios from 'axios'; export const getListOfFruit = (): Promise => { return BEApi.getFruits('http://fruityfruit.com') .then(resolveFruits) .catch(handleError); -} +}; const resolveFruits = (fruits: string[]) => { return fruits; -} +}; const handleError = () => { throw new Error('Where is my fruit???'); -} \ No newline at end of file +}; +export const getPosts = (): any => { + return axios + .get('https://jsonplaceholder.typicode.com/posts') + .then(resolvePosts); +}; +const resolvePosts = (posts: any) => { + return posts; +}; diff --git a/00 Base/src/redux/actions/index.ts b/00 Base/src/redux/actions/index.ts index 3cb5666..af7b50e 100644 --- a/00 Base/src/redux/actions/index.ts +++ b/00 Base/src/redux/actions/index.ts @@ -4,3 +4,4 @@ export { fetchfruits, getAllFruits, } from './fruitsActions'; +export { fetchPosts, deletePost,addPost } from './postActions'; diff --git a/00 Base/src/redux/actions/postActions.tsx b/00 Base/src/redux/actions/postActions.tsx new file mode 100644 index 0000000..0345d8e --- /dev/null +++ b/00 Base/src/redux/actions/postActions.tsx @@ -0,0 +1,28 @@ +import { GET_POST_FROM_API,DELETE_POST,ADD_POST } from './../constants'; +import { getPosts } from '../../myApi/index'; + +export const getPostFromApi = ( posts: Object[]) => { + return { + type: GET_POST_FROM_API, + payload: posts, + }; +}; +export const fetchPosts = () => { + return (dispatch) => { + return getPosts().then((res) => dispatch(getPostFromApi(res))); + }; +}; + + export const deletePost = (id: Number) => { + return { + type: DELETE_POST, + payload: id, + }; +}; + +export const addPost = (name: string) => { + return { + type: ADD_POST, + payload: name, + }; +}; diff --git a/00 Base/src/redux/constants.ts b/00 Base/src/redux/constants.ts index 06549a2..1e7fd44 100644 --- a/00 Base/src/redux/constants.ts +++ b/00 Base/src/redux/constants.ts @@ -1,3 +1,7 @@ -export const GET_ALL_FRUITS = 'GET_ALL_FRUITS' -export const DELETE_FRUIT = 'DELETE_FRUIT' -export const ADD_FRUIT = 'ADD_FRUIT' \ No newline at end of file +export const GET_ALL_FRUITS = 'GET_ALL_FRUITS'; +export const DELETE_FRUIT = 'DELETE_FRUIT'; +export const ADD_FRUIT = 'ADD_FRUIT'; + +export const GET_POST_FROM_API = 'GET_POST_FROM_API'; +export const DELETE_POST = 'DELETE_POST'; +export const ADD_POST = 'ADD_POST'; diff --git a/00 Base/src/redux/reducers/index.js b/00 Base/src/redux/reducers/index.js index 4b26bf6..2026315 100644 --- a/00 Base/src/redux/reducers/index.js +++ b/00 Base/src/redux/reducers/index.js @@ -1,6 +1,8 @@ import { combineReducers } from 'redux'; import fruitsReducer from './fruitReducer'; +import postReducer from './postReducer' export default combineReducers({ fruits: fruitsReducer, + posts: postReducer }); diff --git a/00 Base/src/redux/reducers/postReducer.tsx b/00 Base/src/redux/reducers/postReducer.tsx new file mode 100644 index 0000000..92442cb --- /dev/null +++ b/00 Base/src/redux/reducers/postReducer.tsx @@ -0,0 +1,39 @@ +import { GET_POST_FROM_API, DELETE_POST, ADD_POST } from './../constants'; +const initialState = { + posts: [], +}; +export default function (state = initialState, action) { + switch (action.type) { + case GET_POST_FROM_API: { + return { + ...state, + posts: action.payload.data, + }; + } + case DELETE_POST: { + return { + ...state, + posts: state.posts.filter((e) => e.id !== action.payload), + }; + } + + case ADD_POST: { + let tmpPost = { + id: Math.floor(Math.random() * 1000), + userId: 1, + title: action.payload, + body: action.payload, + }; + + return { + ...state, + posts: state.posts.concat([tmpPost]), + }; + } + default: { + return { + ...state, + }; + } + } +} From 749a4ed7f1dc0aef84a808c8233d390b671da590 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Mon, 13 Apr 2020 18:34:21 +0200 Subject: [PATCH 09/14] updated tsconfig file --- 00 Base/src/redux/reducers/{index.js => index.ts} | 0 00 Base/tsconfig.json | 6 ++++-- 2 files changed, 4 insertions(+), 2 deletions(-) rename 00 Base/src/redux/reducers/{index.js => index.ts} (100%) diff --git a/00 Base/src/redux/reducers/index.js b/00 Base/src/redux/reducers/index.ts similarity index 100% rename from 00 Base/src/redux/reducers/index.js rename to 00 Base/src/redux/reducers/index.ts diff --git a/00 Base/tsconfig.json b/00 Base/tsconfig.json index 8a26838..3e07872 100644 --- a/00 Base/tsconfig.json +++ b/00 Base/tsconfig.json @@ -11,7 +11,9 @@ "allowJs": true, "suppressImplicitAnyIndexErrors": true, "skipLibCheck": true, - "esModuleInterop": true + "esModuleInterop": true, + "outDir": "generated", }, - "include": ["./src/**/*"] + "include": ["./src/**/*"], + "exclude": ["node_modules", "**/*.test.ts", "dist"] } From 766e2edae65a69845ba60cf0f66aa84c206fa40b Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Mon, 13 Apr 2020 19:21:16 +0200 Subject: [PATCH 10/14] post reducer added and changed data model --- .../components/myComponent/myComponent.tsx | 13 ++- 00 Base/src/redux/actions/postActions.tsx | 4 +- .../src/redux/reducers/fruitReducer.spec.tsx | 55 ------------ .../src/redux/reducers/postReducer.spec.tsx | 86 +++++++++++++++++++ 00 Base/src/redux/reducers/postReducer.tsx | 8 +- 5 files changed, 101 insertions(+), 65 deletions(-) delete mode 100644 00 Base/src/redux/reducers/fruitReducer.spec.tsx create mode 100644 00 Base/src/redux/reducers/postReducer.spec.tsx diff --git a/00 Base/src/components/myComponent/myComponent.tsx b/00 Base/src/components/myComponent/myComponent.tsx index 529195e..747535f 100644 --- a/00 Base/src/components/myComponent/myComponent.tsx +++ b/00 Base/src/components/myComponent/myComponent.tsx @@ -47,7 +47,18 @@ export const MyComponent: React.FunctionComponent = (props) => { )) : null}
- dispatch(addPost(newPost))} /> + + dispatch( + addPost({ + id: Math.floor(Math.random() * 1000), + userId: 1, + title: newPost, + body:newPost, + }) + ) + } + /> ); diff --git a/00 Base/src/redux/actions/postActions.tsx b/00 Base/src/redux/actions/postActions.tsx index 0345d8e..192b91d 100644 --- a/00 Base/src/redux/actions/postActions.tsx +++ b/00 Base/src/redux/actions/postActions.tsx @@ -20,9 +20,9 @@ export const fetchPosts = () => { }; }; -export const addPost = (name: string) => { +export const addPost = (post: Object) => { return { type: ADD_POST, - payload: name, + payload: post, }; }; diff --git a/00 Base/src/redux/reducers/fruitReducer.spec.tsx b/00 Base/src/redux/reducers/fruitReducer.spec.tsx deleted file mode 100644 index 64ec3e7..0000000 --- a/00 Base/src/redux/reducers/fruitReducer.spec.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import reducer from './fruitReducer'; -import { ADD_FRUIT, DELETE_FRUIT } from '../constants'; - -const initialState = { - fruitList: [], -}; - -describe('fruit reducer', () => { - it('should return the initial state', () => { - expect(reducer(undefined, {})).toEqual({ - fruitList: [], - }); - }); - - it('should handle ADD_FRUIT', () => { - const grape = 'grape'; - expect( - reducer(initialState, { - type: ADD_FRUIT, - payload: grape, - }) - ).toEqual({ - fruitList: [grape], - }); - - expect( - reducer( - { - fruitList: ['apple'], - }, - { - type: ADD_FRUIT, - payload: grape, - } - ) - ).toEqual({ - fruitList: ['apple', grape], - }); - }); - - it('should handle DELETE_FRUIT', () => { - const grape = 'grape'; - expect( - reducer( - { fruitList: [grape, 'apple'] }, - { - type: DELETE_FRUIT, - payload: grape, - } - ) - ).toEqual({ - fruitList: ['apple'], - }); - }); -}); diff --git a/00 Base/src/redux/reducers/postReducer.spec.tsx b/00 Base/src/redux/reducers/postReducer.spec.tsx new file mode 100644 index 0000000..2cfeed2 --- /dev/null +++ b/00 Base/src/redux/reducers/postReducer.spec.tsx @@ -0,0 +1,86 @@ +import reducer from './postReducer'; +import { + ADD_FRUIT, + DELETE_FRUIT, + GET_POST_FROM_API, + ADD_POST, + DELETE_POST, +} from '../constants'; + +const initialState = { + posts: [], +}; + +describe('post reducer', () => { + const testPost = { + userId: 1, + id: 1, + title: + 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', + body: + 'quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est autem sunt rem eveniet architecto', + }; + const testPost2 = { + userId: 2, + id: 2, + title: 'another Title', + body: 'another Title', + }; + it('should return the initial state', () => { + expect(reducer(undefined, {})).toEqual({ + posts: [], + }); + }); + + it('should handle ADD_POST', () => { + expect( + reducer(initialState, { + type: ADD_POST, + payload: testPost, + }) + ).toEqual({ + posts: [testPost], + }); + + expect( + reducer( + { + posts: [testPost], + }, + { + type: ADD_POST, + payload: { + id: 7, + userId: 1, + title: 'newPost', + body: 'newPost', + }, + } + ) + ).toEqual({ + posts: [ + testPost, + { + id: 7, + userId: 1, + title: 'newPost', + body: 'newPost', + }, + ], + }); + }); + + it('should handle DELETE_POST', () => { + expect( + reducer( + { posts: [testPost, testPost2] }, + { + type: DELETE_POST, + payload: testPost2.id, + } + ) + ).toEqual({ + posts: [testPost], + }); + }); +}); diff --git a/00 Base/src/redux/reducers/postReducer.tsx b/00 Base/src/redux/reducers/postReducer.tsx index 92442cb..91950cc 100644 --- a/00 Base/src/redux/reducers/postReducer.tsx +++ b/00 Base/src/redux/reducers/postReducer.tsx @@ -18,16 +18,10 @@ export default function (state = initialState, action) { } case ADD_POST: { - let tmpPost = { - id: Math.floor(Math.random() * 1000), - userId: 1, - title: action.payload, - body: action.payload, - }; return { ...state, - posts: state.posts.concat([tmpPost]), + posts: state.posts.concat([action.payload]), }; } default: { From e4be787d6127071ef2379ca672e88a9e1910762a Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Mon, 13 Apr 2020 19:40:29 +0200 Subject: [PATCH 11/14] actions test done --- .../src/redux/actions/fruitsActions.spec.tsx | 31 -------------- .../src/redux/actions/postActions.spec.tsx | 42 +++++++++++++++++++ 2 files changed, 42 insertions(+), 31 deletions(-) delete mode 100644 00 Base/src/redux/actions/fruitsActions.spec.tsx create mode 100644 00 Base/src/redux/actions/postActions.spec.tsx diff --git a/00 Base/src/redux/actions/fruitsActions.spec.tsx b/00 Base/src/redux/actions/fruitsActions.spec.tsx deleted file mode 100644 index fecba83..0000000 --- a/00 Base/src/redux/actions/fruitsActions.spec.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { addFruit, deleteFruit, getAllFruits } from './index'; -import { GET_ALL_FRUITS, DELETE_FRUIT, ADD_FRUIT } from '../constants'; - -describe('actions', () => { - it('should create an action to add a fruit', () => { - const fruit = 'grape'; - const expectedAction = { - type: ADD_FRUIT, - payload: fruit, - }; - expect(addFruit(fruit)).toEqual(expectedAction); - }); - - it('should create an action to delete a fruit', () => { - const fruit = 'grape'; - const expectedAction = { - type: DELETE_FRUIT, - payload: fruit, - }; - expect(deleteFruit(fruit)).toEqual(expectedAction); - }); - - it('should create an action to get all fruits', () => { - const fruit = ['grape', 'banana']; - const expectedAction = { - type: GET_ALL_FRUITS, - payload: fruit, - }; - expect(getAllFruits(fruit)).toEqual(expectedAction); - }); -}); diff --git a/00 Base/src/redux/actions/postActions.spec.tsx b/00 Base/src/redux/actions/postActions.spec.tsx new file mode 100644 index 0000000..8322e8d --- /dev/null +++ b/00 Base/src/redux/actions/postActions.spec.tsx @@ -0,0 +1,42 @@ +import { addPost, deletePost, fetchPosts } from './index'; +import { ADD_POST, DELETE_POST, GET_POST_FROM_API } from '../constants'; +import { getPostFromApi } from './postActions'; + +describe('actions', () => { + const testPost = { + id: 7, + userId: 1, + title: 'newPost', + body: 'newPost', + }; + const testPost2 = { + id: 8, + userId: 1, + title: 'newPost2', + body: 'newPost2', + }; + it('should create an action to add a post', () => { + const expectedAction = { + type: ADD_POST, + payload: testPost, + }; + expect(addPost(testPost)).toEqual(expectedAction); + }); + + it('should create an action to delete a post', () => { + const expectedAction = { + type: DELETE_POST, + payload: testPost.id, + }; + expect(deletePost(testPost.id)).toEqual(expectedAction); + }); + + it('should create an action to get all posts', () => { + const arrayOfPosts=[testPost,testPost2] + const expectedAction = { + type: GET_POST_FROM_API, + payload: arrayOfPosts, + }; + expect(getPostFromApi(arrayOfPosts)).toEqual(expectedAction); + }); +}); From 95ea157a06ee22cba3a17f396d2d00aa8757d9e3 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Mon, 13 Apr 2020 20:58:28 +0200 Subject: [PATCH 12/14] added a component test --- 00 Base/package.json | 12 ++-- .../myComponent/myComponent.spec.tsx | 59 +++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 00 Base/src/components/myComponent/myComponent.spec.tsx diff --git a/00 Base/package.json b/00 Base/package.json index acf78fd..ed52777 100644 --- a/00 Base/package.json +++ b/00 Base/package.json @@ -46,22 +46,22 @@ "@types/react-dom": "^16.8.4", "@types/react-router-dom": "^4.3.4", "awesome-typescript-loader": "^5.2.1", + "babel-jest": "^25.2.6", + "css-loader": "^3.4.2", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", "html-webpack-plugin": "^3.2.0", "jest": "^24.8.0", "less": "^3.11.1", "less-loader": "^5.0.0", "node-sass": "^4.13.1", + "react-addons-test-utils": "^15.6.2", "redux-devtools-extension": "^2.13.8", + "redux-mock-store": "^1.5.4", "rimraf": "^2.6.3", "sass-loader": "^7.2.0", "style-loader": "^1.1.3", "ts-jest": "^24.0.2", - "babel-jest": "^25.2.6", - "css-loader": "^3.4.2", - "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.2", - "react-addons-test-utils": "^15.6.2", - "redux-mock-store": "^1.5.4", "typescript": "^3.5.2", "webpack": "^4.32.2", "webpack-cli": "^3.3.2", diff --git a/00 Base/src/components/myComponent/myComponent.spec.tsx b/00 Base/src/components/myComponent/myComponent.spec.tsx new file mode 100644 index 0000000..decd453 --- /dev/null +++ b/00 Base/src/components/myComponent/myComponent.spec.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +// import { render, cleanup } from '@testing-library/react'; +import { + render, + fireEvent, + waitForElement, + act, + RenderResult, +} from '@testing-library/react'; +//import * as myApi from '../myApi'; +import { MyComponent, Props } from './myComponent'; +import { Provider } from 'react-redux'; +import * as redux from 'react-redux'; +import { createStore } from 'redux'; +import Enzyme, { mount } from 'enzyme'; +import EnzymeAdapter from 'enzyme-adapter-react-16'; +import { fetchPosts } from '../../redux/actions/index'; + +import reducer from '../../redux/reducers/index'; +jest.mock('./MyComponent.tsx', () => ({ + MyComponent: () =>
, +})); + +const baseProps: Props = { + nameFromProps: null, +}; +Enzyme.configure({ adapter: new EnzymeAdapter() }); + +//afterEach(cleanup); +describe('My component', () => { + let props: Props; + beforeEach(() => { + props = { ...baseProps }; + }); + + const name = 'Title'; + const getWrapper = ( + mockStore = createStore(reducer, { posts: { posts: [] } }) + ) => + mount( + + + + ); + + it('should display the title provided', () => { + const wrapper = getWrapper(); + expect(wrapper.find('h1').text()).toEqual(`Hello ${name}!`); + }); + + it('should dispatch the get post action', () => { + const mockStore = createStore(reducer, { posts: { posts: [] } }); + mockStore.dispatch = jest.fn(); + + const wrapper = getWrapper(mockStore); + wrapper.find('button').simulate('click'); + expect(mockStore.dispatch).toHaveBeenCalledTimes(1); + }); +}); From bfcc460ee9bdba7cc02bee96bfaac5668aa5e772 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Tue, 14 Apr 2020 18:18:51 +0200 Subject: [PATCH 13/14] types added and comments removed --- 00 Base/src/components/myComponent/index.ts | 2 +- .../components/myComponent/myComponent.tsx | 21 +++++++++---------- 00 Base/src/redux/actions/postActions.tsx | 9 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/00 Base/src/components/myComponent/index.ts b/00 Base/src/components/myComponent/index.ts index bcc7da0..84cbb30 100644 --- a/00 Base/src/components/myComponent/index.ts +++ b/00 Base/src/components/myComponent/index.ts @@ -1 +1 @@ -export { MyComponent } from './myComponent'; \ No newline at end of file +export { MyComponent, Posts } from './myComponent'; diff --git a/00 Base/src/components/myComponent/myComponent.tsx b/00 Base/src/components/myComponent/myComponent.tsx index 747535f..c8e3ab6 100644 --- a/00 Base/src/components/myComponent/myComponent.tsx +++ b/00 Base/src/components/myComponent/myComponent.tsx @@ -1,14 +1,7 @@ import * as React from 'react'; import { useSelector, useDispatch } from 'react-redux'; -import { - /* fetchfruits, - deleteFruit, - addFruit, */ - fetchPosts, - deletePost, - addPost, -} from './../../redux/actions/index'; +import { fetchPosts, deletePost, addPost } from './../../redux/actions/index'; import './styles.less'; import Button from '@material-ui/core/Button'; @@ -18,6 +11,12 @@ import { MyInputComponent } from '../myInputComponent/myInputComponent'; export interface Props { nameFromProps: string; } +export interface Posts { + id: Number; + userId: Number; + title: string; + body: string; +} export const MyComponent: React.FunctionComponent = (props) => { const { nameFromProps } = props; @@ -37,11 +36,11 @@ export const MyComponent: React.FunctionComponent = (props) => {
{!!posts - ? posts.map((el /* : Object */) => ( + ? posts.map((el: Posts) => ( dispatch(deletePost(el.id))} /> )) @@ -54,7 +53,7 @@ export const MyComponent: React.FunctionComponent = (props) => { id: Math.floor(Math.random() * 1000), userId: 1, title: newPost, - body:newPost, + body: newPost, }) ) } diff --git a/00 Base/src/redux/actions/postActions.tsx b/00 Base/src/redux/actions/postActions.tsx index 192b91d..7831de9 100644 --- a/00 Base/src/redux/actions/postActions.tsx +++ b/00 Base/src/redux/actions/postActions.tsx @@ -1,7 +1,8 @@ -import { GET_POST_FROM_API,DELETE_POST,ADD_POST } from './../constants'; +import { GET_POST_FROM_API, DELETE_POST, ADD_POST } from './../constants'; import { getPosts } from '../../myApi/index'; +import { Posts } from '../../components/myComponent/index'; -export const getPostFromApi = ( posts: Object[]) => { +export const getPostFromApi = (posts: Posts[]) => { return { type: GET_POST_FROM_API, payload: posts, @@ -13,14 +14,14 @@ export const fetchPosts = () => { }; }; - export const deletePost = (id: Number) => { +export const deletePost = (id: Number) => { return { type: DELETE_POST, payload: id, }; }; -export const addPost = (post: Object) => { +export const addPost = (post: Posts) => { return { type: ADD_POST, payload: post, From f13b690faca47582283b66f1f1268beabb44a9ad Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Ortiz Date: Tue, 14 Apr 2020 20:08:10 +0200 Subject: [PATCH 14/14] new tesapi test added --- 00 Base/src/myApi/myApi.spec.tsx | 5 ++++- 00 Base/src/myApi/myApi.ts | 12 +++++++++--- 00 Base/src/redux/reducers/postReducer.tsx | 3 +-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/00 Base/src/myApi/myApi.spec.tsx b/00 Base/src/myApi/myApi.spec.tsx index d2a61e5..49dbe83 100644 --- a/00 Base/src/myApi/myApi.spec.tsx +++ b/00 Base/src/myApi/myApi.spec.tsx @@ -1,4 +1,4 @@ -import { getListOfFruit } from './myApi'; +import { getListOfFruit, getPosts } from './myApi'; describe('myApi tests', () => { it('getListOfFruit should return an array of string', () => { @@ -13,4 +13,7 @@ describe('myApi tests', () => { 'peach', ]); }); + it('should fecth some post from the api', () => { + expect(getPosts()).rejects.toThrowError('Error fetching'); + }); }); diff --git a/00 Base/src/myApi/myApi.ts b/00 Base/src/myApi/myApi.ts index 8cd6d3d..8ebc456 100644 --- a/00 Base/src/myApi/myApi.ts +++ b/00 Base/src/myApi/myApi.ts @@ -1,5 +1,6 @@ import * as BEApi from './myBackEndApiEndpoint'; import axios from 'axios'; +import { Posts } from '../components/myComponent/index'; export const getListOfFruit = (): Promise => { return BEApi.getFruits('http://fruityfruit.com') @@ -14,11 +15,16 @@ const resolveFruits = (fruits: string[]) => { const handleError = () => { throw new Error('Where is my fruit???'); }; -export const getPosts = (): any => { +export const getPosts = (): Promise => { return axios .get('https://jsonplaceholder.typicode.com/posts') - .then(resolvePosts); + .then(resolvePosts) + .catch(handlePostError); }; const resolvePosts = (posts: any) => { - return posts; + console.log('resolvePosts -> posts', posts); + return posts.data; +}; +const handlePostError = () => { + throw new Error('Error fetching'); }; diff --git a/00 Base/src/redux/reducers/postReducer.tsx b/00 Base/src/redux/reducers/postReducer.tsx index 91950cc..e037c8f 100644 --- a/00 Base/src/redux/reducers/postReducer.tsx +++ b/00 Base/src/redux/reducers/postReducer.tsx @@ -7,7 +7,7 @@ export default function (state = initialState, action) { case GET_POST_FROM_API: { return { ...state, - posts: action.payload.data, + posts: action.payload, }; } case DELETE_POST: { @@ -18,7 +18,6 @@ export default function (state = initialState, action) { } case ADD_POST: { - return { ...state, posts: state.posts.concat([action.payload]),