-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/issue#1 redux test #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
f17d2cd
6f2cef5
397791a
6b0e4b7
9b112c0
4c660a4
cf5045a
442991d
749a4ed
7c5bb0e
e740fee
766e2ed
e4be787
95ea157
bfcc460
f13b690
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,9 @@ | ||
| import * as React from 'react'; | ||
| import { MessagesSection } from './components'; | ||
| import { MyComponent } from './components/myComponent'; | ||
| import './styles.less'; | ||
|
|
||
| export const App: React.FunctionComponent = props => ( | ||
| export const App: React.FunctionComponent = (props) => ( | ||
| <div> | ||
| <MessagesSection /> | ||
| <MyComponent nameFromProps="Fruit User" /> | ||
| </div> | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { MyComponent, Posts } from './myComponent'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: () => <div />, | ||
| })); | ||
|
|
||
| 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( | ||
| <Provider store={mockStore}> | ||
| <MyComponent nameFromProps={name} /> | ||
| </Provider> | ||
| ); | ||
|
|
||
| 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); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| import { useSelector, useDispatch } from 'react-redux'; | ||
| import { fetchPosts, deletePost, addPost } from './../../redux/actions/index'; | ||
| import './styles.less'; | ||
|
|
||
| import Button from '@material-ui/core/Button'; | ||
| import Chip from '@material-ui/core/Chip'; | ||
|
|
||
| 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> = (props) => { | ||
| const { nameFromProps } = props; | ||
| const dispatch = useDispatch(); | ||
| const posts = useSelector((state) => state.posts.posts); | ||
|
|
||
| return ( | ||
| <> | ||
| <div className="container"> | ||
| <h1>Hello {nameFromProps}!</h1> | ||
| <Button | ||
| variant="contained" | ||
| color="primary" | ||
| onClick={() => dispatch(fetchPosts())} | ||
| > | ||
| Get post from API | ||
| </Button> | ||
| <div className="chip-container"> | ||
| {!!posts | ||
| ? posts.map((el: Posts) => ( | ||
| <Chip | ||
| color="primary" | ||
| label={el.title} | ||
| key={el.id.toString()} | ||
| onDelete={() => dispatch(deletePost(el.id))} | ||
| /> | ||
| )) | ||
| : null} | ||
| </div> | ||
| <MyInputComponent | ||
| addPost={(newPost) => | ||
| dispatch( | ||
| addPost({ | ||
| id: Math.floor(Math.random() * 1000), | ||
| userId: 1, | ||
| title: newPost, | ||
| body: newPost, | ||
| }) | ||
| ) | ||
| } | ||
| /> | ||
| </div> | ||
| </> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| .container { | ||
| text-align: center; | ||
| .chip-container { | ||
| display: block; | ||
| position: relative; | ||
| margin-top: 25px; | ||
| .MuiChip-root { | ||
| margin-left: 5px; | ||
| margin-top: 5px; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { MyInputComponent } from './myInputComponent'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import * as React from 'react'; | ||
| import TextField from '@material-ui/core/TextField'; | ||
| import { Add } from '@material-ui/icons'; | ||
| import './styles.less'; | ||
|
|
||
| export interface Props { | ||
| addPost: Function; | ||
| } | ||
|
|
||
| export const MyInputComponent: React.FunctionComponent<Props> = (props) => { | ||
| const { addPost } = props; | ||
| const [name, setName] = React.useState(''); | ||
|
|
||
| return ( | ||
| <div className="input-component"> | ||
| <TextField | ||
| label="Add post" | ||
| value={name} | ||
| onChange={(e) => setName(e.target.value)} | ||
| /> | ||
| {!!name ? ( | ||
| <Add | ||
| onClick={() => { | ||
| addPost(name); | ||
| setName(''); | ||
| }} | ||
| /> | ||
| ) : null} | ||
| </div> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| .input-component { | ||
| .MuiFormControl-root { | ||
| margin-top: 10px; | ||
| } | ||
| .MuiSvgIcon-root { | ||
| margin-top: 35px; | ||
| color: #00ff00; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,14 @@ | ||
| import * as React from 'react'; | ||
| import * as ReactDOM from 'react-dom'; | ||
| import { App } from './app'; | ||
| import { Provider } from 'react-redux' | ||
| import { createStore, compose, applyMiddleware } from 'redux' | ||
| import {MessagesReducer} from './redux/reducers/MessagesReducer' | ||
| import thunk from 'redux-thunk' | ||
| import { Provider } from 'react-redux'; | ||
| import store from './redux/store'; | ||
|
|
||
| const MessagesStore = createStore(MessagesReducer,compose(applyMiddleware(thunk))); | ||
| import { App } from './app'; | ||
| import 'babel-polyfill' | ||
|
|
||
| ReactDOM.render( | ||
| <Provider store={MessagesStore}> | ||
| <Provider store={store}> | ||
| <App /> | ||
| </Provider>, | ||
|
|
||
| document.getElementById('root')); | ||
| </Provider>, | ||
| document.getElementById('root') | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { getListOfFruit, getPosts } from './myApi'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { getListOfFruit, getPosts } 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', | ||
| ]); | ||
| }); | ||
| it('should fecth some post from the api', () => { | ||
| expect(getPosts()).rejects.toThrowError('Error fetching'); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test is not semantic, please fix it |
||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import * as BEApi from './myBackEndApiEndpoint'; | ||
| import axios from 'axios'; | ||
| import { Posts } from '../components/myComponent/index'; | ||
|
|
||
| export const getListOfFruit = (): Promise<string[]> => { | ||
| 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???'); | ||
| }; | ||
| export const getPosts = (): Promise<Posts[]> => { | ||
| return axios | ||
| .get('https://jsonplaceholder.typicode.com/posts') | ||
| .then(resolvePosts) | ||
| .catch(handlePostError); | ||
| }; | ||
| const resolvePosts = (posts: any) => { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This posts is not typed |
||
| console.log('resolvePosts -> posts', posts); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Delete this comment |
||
| return posts.data; | ||
| }; | ||
| const handlePostError = () => { | ||
| throw new Error('Error fetching'); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| export const getFruits = (_url: string) => { | ||
| return Promise.resolve([ | ||
| 'grape', | ||
| 'pineapple', | ||
| 'watermelon', | ||
| 'orange', | ||
| 'lemon', | ||
| 'strawberry', | ||
| 'cherry', | ||
| 'peach', | ||
| ]); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please delete all comented code
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try to increase the coverage here
