-
Notifications
You must be signed in to change notification settings - Fork 274
Redux Integration #292
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
Merged
Redux Integration #292
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
539a40f
Redux example
cross19xx 7d20b52
Reviews implemented
cross19xx e51a2cb
Redux integration example
cross19xx 48b17f8
Update docs/ReduxIntegration.md
thymikee 60c9ba5
Update docs/ReduxIntegration.md
thymikee 4807969
Resolution of reviews put in by @thymikee
cross19xx ee9e305
Merge conflict resolution
cross19xx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
--- | ||
id: redux-integration | ||
title: Redux Integration | ||
--- | ||
|
||
This section deals with testing RN applications developed with Redux. We will be developing a simple TODO application capable of adding and removing an item. Once included, the timestamp is included. | ||
|
||
## Setting up | ||
|
||
An example of setting up can be found [here](https://github.com/callstack/react-native-testing-library/tree/master/examples/redux). | ||
|
||
## Test cases | ||
|
||
Our test is on the components that either dispatch actions on the redux store or read some data from the redux store. This means we will test `./components/TodoElem.js` and `./components/TodoList.js`. Thus we will create `./components/AddTodo.test.js` and `./components/TodoList.test.js` | ||
|
||
For `./components/AddTodo.test.js` | ||
|
||
```jsx | ||
import React from 'react'; | ||
import { Provider } from 'react-redux'; | ||
import { cleanup, fireEvent, render } from 'react-native-testing-library'; | ||
import configureStore from '../store'; | ||
import AddTodo from './AddTodo'; | ||
|
||
describe('AddTodo component test', () => { | ||
test('adds a new TODO when the button is pressed', () => { | ||
const store = configureStore(); | ||
|
||
const component = ( | ||
<Provider store={store}> | ||
<AddTodo /> | ||
</Provider> | ||
); | ||
|
||
const { getByPlaceholder, getByText } = render(component); | ||
|
||
// There is a TextInput. | ||
// https://github.com/callstack/react-native-testing-library/blob/ae3d4af370487e1e8fedd8219f77225690aefc59/examples/redux/components/AddTodo.js#L24 | ||
const input = getByPlaceholder(/repository/i); | ||
expect(input).toBeTruthy(); | ||
|
||
const textToEnter = 'This is a random element'; | ||
fireEvent.changeText(input, textToEnter); | ||
fireEvent.press(getByText('Submit form')); | ||
|
||
const todosState = store.getState().todos; | ||
|
||
expect(todosState.length).toEqual(1); | ||
|
||
expect(todosState).toEqual( | ||
expect.arrayContaining([ | ||
expect.objectContaining({ | ||
id: 1, | ||
text: textToEnter, | ||
date: expect.any(Date), | ||
}), | ||
]) | ||
); | ||
}); | ||
}); | ||
``` | ||
|
||
For the `./components/TodoList.js` | ||
|
||
```jsx | ||
import React from 'react'; | ||
import { Provider } from 'react-redux'; | ||
import { fireEvent, render } from 'react-native-testing-library'; | ||
import configureStore from '../store'; | ||
import TodoList from './TodoList'; | ||
|
||
describe('TodoList component test', () => { | ||
test('it should execute with a store with 4 elements', () => { | ||
const initialState = { | ||
todos: [ | ||
{ id: 1, text: 'Sing something', date: new Date() }, | ||
{ id: 2, text: 'Dance something', date: new Date() }, | ||
{ id: 3, text: 'Sleep something', date: new Date() }, | ||
{ id: 4, text: 'Sleep something', date: new Date() }, | ||
], | ||
}; | ||
const store = configureStore(initialState); | ||
|
||
const component = ( | ||
<Provider store={store}> | ||
<TodoList /> | ||
</Provider> | ||
); | ||
|
||
const { getAllByText } = render(component); | ||
const todoElems = getAllByText(/something/i); | ||
|
||
expect(todoElems.length).toEqual(4); | ||
}); | ||
|
||
test('should execute with 2 elements and end up with 1 after delete', () => { | ||
const initialState = { | ||
todos: [ | ||
{ id: 1, text: 'Sing something', date: new Date() }, | ||
{ id: 2, text: 'Dance something', date: new Date() }, | ||
], | ||
}; | ||
const store = configureStore(initialState); | ||
|
||
const component = ( | ||
<Provider store={store}> | ||
<TodoList /> | ||
</Provider> | ||
); | ||
|
||
const { getAllByText } = render(component); | ||
const todoElems = getAllByText(/something/i); | ||
|
||
expect(todoElems.length).toBe(2); | ||
|
||
const buttons = getAllByText('Delete'); | ||
expect(buttons.length).toBe(2); | ||
|
||
fireEvent.press(buttons[0]); | ||
expect(getAllByText('Delete').length).toBe(1); | ||
}); | ||
}); | ||
``` | ||
|
||
## Running tests | ||
|
||
To run the tests, place a test script inside your package.json | ||
|
||
```json | ||
{ | ||
"scripts": { | ||
"test": "jest" | ||
} | ||
} | ||
``` | ||
|
||
And run the test script with npm test or yarn test. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React from 'react'; | ||
cross19xx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import { StyleSheet, View, StatusBar } from 'react-native'; | ||
import { Provider } from 'react-redux'; | ||
import configureStore from './store'; | ||
import AddTodo from './components/AddTodo'; | ||
import TodoList from './components/TodoList'; | ||
|
||
const store = configureStore(); | ||
|
||
export default function App() { | ||
return ( | ||
<Provider store={store}> | ||
<View style={styles.container}> | ||
<StatusBar barStyle="dark-content" /> | ||
<AddTodo /> | ||
<TodoList /> | ||
</View> | ||
</Provider> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
paddingTop: 32, | ||
}, | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export const actions = { | ||
ADD: '@ADD_TODO', | ||
REMOVE: '@REMOVE_TODO', | ||
MODIFY: '@MODIFY_TODO', | ||
CLEAR: '@CLEAR_TODO', | ||
}; | ||
|
||
export const addTodo = (todo) => ({ | ||
type: actions.ADD, | ||
payload: todo, | ||
}); | ||
|
||
export const removeTodo = (id) => ({ | ||
type: actions.REMOVE, | ||
payload: { id }, | ||
}); | ||
|
||
export const modifyTodo = (todo) => ({ | ||
type: actions.MODIFY, | ||
payload: todo, | ||
}); | ||
|
||
export const clearTodos = () => ({ | ||
type: actions.CLEAR, | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = function (api) { | ||
api.cache(true); | ||
return { | ||
presets: ['module:metro-react-native-babel-preset'], | ||
}; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import React from 'react'; | ||
import { Button, StyleSheet, Text, View, TextInput } from 'react-native'; | ||
import { bindActionCreators } from 'redux'; | ||
import { connect } from 'react-redux'; | ||
import { addTodo } from '../actions/todoActions'; | ||
|
||
export function AddTodo(props) { | ||
const [text, setText] = React.useState(''); | ||
|
||
const submitForm = () => { | ||
const todo = { | ||
id: props.todoLength + 1, | ||
text, | ||
date: new Date(), | ||
}; | ||
|
||
props.addTodo(todo); | ||
setText(''); | ||
}; | ||
|
||
return ( | ||
<View style={styles.container}> | ||
<Text style={styles.header}>Enter a text below to add a new todo</Text> | ||
<TextInput | ||
autoFocus | ||
value={text} | ||
style={styles.input} | ||
returnKeyType="search" | ||
onSubmitEditing={submitForm} | ||
onChangeText={(t) => setText(t)} | ||
placeholder="Enter the name of the repository here" | ||
/> | ||
|
||
<Button onPress={submitForm} title="Submit form" /> | ||
</View> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
minHeight: 156, | ||
display: 'flex', | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
borderBottomColor: '#EEEEEE', | ||
borderBottomWidth: 2, | ||
marginBottom: 16, | ||
padding: 16, | ||
}, | ||
header: { | ||
fontSize: 20, | ||
fontWeight: 'bold', | ||
marginBottom: 8, | ||
}, | ||
input: { | ||
borderColor: '#DDDDDD', | ||
borderWidth: 1, | ||
paddingVertical: 8, | ||
width: '100%', | ||
textAlign: 'center', | ||
borderRadius: 4, | ||
}, | ||
}); | ||
|
||
const mapStateToProps = ({ todos }) => ({ | ||
todoLength: todos.length, | ||
}); | ||
|
||
const mapDispatchToProps = (dispatch) => | ||
bindActionCreators({ addTodo }, dispatch); | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(AddTodo); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react'; | ||
import { Provider } from 'react-redux'; | ||
import { cleanup, fireEvent, render } from 'react-native-testing-library'; | ||
import configureStore from '../store'; | ||
import AddTodo from './AddTodo'; | ||
|
||
describe('Application test', () => { | ||
afterEach(cleanup); | ||
|
||
test('adds a new test when entry has been included', () => { | ||
const store = configureStore(); | ||
|
||
const component = ( | ||
<Provider store={store}> | ||
<AddTodo /> | ||
</Provider> | ||
); | ||
|
||
const { getByPlaceholder, getByText } = render(component); | ||
|
||
const input = getByPlaceholder(/repository/i); | ||
expect(input).toBeTruthy(); | ||
|
||
const textToEnter = 'This is a random element'; | ||
fireEvent.changeText(input, textToEnter); | ||
fireEvent.press(getByText('Submit form')); | ||
|
||
const todosState = store.getState().todos; | ||
|
||
expect(todosState.length).toEqual(1); | ||
|
||
expect(todosState).toEqual( | ||
expect.arrayContaining([ | ||
expect.objectContaining({ | ||
id: 1, | ||
text: textToEnter, | ||
date: expect.any(Date), | ||
}), | ||
]) | ||
); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React from 'react'; | ||
import { StyleSheet, Button, Text, View } from 'react-native'; | ||
|
||
export default function TodoElem({ todo, onDelete }) { | ||
return ( | ||
<View style={styles.container}> | ||
<View style={styles.textContainer}> | ||
<Text style={styles.text}>{todo.text}</Text> | ||
<Text style={styles.date}>{new Date(todo.date).toDateString()}</Text> | ||
</View> | ||
<View style={styles.buttonContainer}> | ||
<Button onPress={() => onDelete(todo.id)} title="Delete" /> | ||
</View> | ||
</View> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
display: 'flex', | ||
flexDirection: 'row', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
}, | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from 'react'; | ||
import { FlatList, Text } from 'react-native'; | ||
import { connect } from 'react-redux'; | ||
import { bindActionCreators } from 'redux'; | ||
import { removeTodo } from '../actions/todoActions'; | ||
import TodoElem from './TodoElem'; | ||
|
||
export function TodoList(props) { | ||
const onDeleteTodo = (id) => props.removeTodo(id); | ||
|
||
return ( | ||
<FlatList | ||
data={props.todos} | ||
keyExtractor={(todo) => todo.id.toString()} | ||
renderItem={({ item }) => ( | ||
<TodoElem todo={item} onDelete={onDeleteTodo} /> | ||
)} | ||
/> | ||
); | ||
} | ||
|
||
const mapStateToProps = (state) => ({ | ||
todos: state.todos, | ||
}); | ||
|
||
const mapDispatchToProps = (dispatch) => | ||
bindActionCreators({ removeTodo }, dispatch); | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(TodoList); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.