Fix #13: Add testing #22

Merged
alexis.drai merged 3 commits from tests/add-testing into main 2 years ago

@ -11,9 +11,12 @@ to [instructions here](https://react-native-courses.clubinfo-clermont.fr/docs/no
- [Detail](#detail)
- [Creating](#creating)
- [Updating](#updating)
- [Some business logic](#some-business-logic)
- [Using the app](#using-the-app)
- [Running the backend](#running-the-backend)
- [Connecting to the backend locally](#connecting-to-the-backend-locally)
- [Running this app](#running-this-app)
- [Testing the app](#testing-the-app)
- [Known limitations](#known-limitations)
- [Sparse](#sparse)
- [Hardcoded enums](#hardcoded-enums)
@ -29,7 +32,7 @@ a [backend API](https://github.com/draialexis/pokemong_api) that provides the da
* [x] Documentation (6 pts)
- [x] Application sketches (4 pts)
- [x] A Readme describing your project/application. (2 pts)
* [x] Basics (20 pts)
* [x] Basics (20 pts (- 2))
- [x] Navigation (3 pts)
+ [x] Tab bottom navigation (2 pts) AND at least one button (1 pts)
- [x] Redux Store (10 pts)
@ -42,14 +45,14 @@ a [backend API](https://github.com/draialexis/pokemong_api) that provides the da
- [x] Binding child component props (1 pts)
- [x] Handle a TextInput correctly (2 pts)
+ [x] Beware of keyboard management
* [ ] Application features (14 pts)
* [x] Application features (14 pts (- 2))
- [x] Retrieve data using the Web API (6 pts)
+ [x] Handle fetch success callback (3 pts)
+ [x] Handle fetch error callback (3 pts)
- [ ] Store favorite data into phone storage (2 pts)
- [ ] Write Tests (6 pts)
+ [ ] all actions payload (1 pts)
+ [ ] all reducers case (2 pts)
- [ ] ~~Store favorite data into phone storage (2 pts)~~
- [x] Write Tests (6 pts (- 1))
+ [ ] ~~all actions payload (1 pts)~~
+ [x] all reducers case (2 pts)
+ [x] one UI Component (3 pts)
## Sketches
@ -133,6 +136,16 @@ yarn start
The app should launch successfully, and instructions should be provided in terminal to open it on a number of devices.
## Testing the app
You can run some partial automated tests on `moveReducer.ts`, on `TypeTacticsInfoList.tsx`, and
on `MoveDetailScreen.tsx`
by running the command
```bash
yarn run test
```
## Known limitations
Beside whatever items may not have been checked off the [notation checklist](#notation-checklist), there are also

@ -1,9 +1,9 @@
// components/TypeTacticsInfoList.test.ts
// components/__tests__/TypeTacticsInfoList.test.ts
import React from 'react';
import { render } from '@testing-library/react-native';
import TypeTacticsInfoList from './TypeTacticsInfoList';
import { TypeName } from "../entities/TypeName";
import TypeTacticsInfoList from '../TypeTacticsInfoList';
import { TypeName } from "../../entities/TypeName";
describe('TypeTacticsInfoList component', () => {
it('renders types correctly', () => {
@ -17,12 +17,12 @@ describe('TypeTacticsInfoList component', () => {
it('renders "Nothing" when types array is empty', () => {
const { getByText } = render(<TypeTacticsInfoList isWeakness={false} types={[]}/>);
expect(getByText('Nothing')).toBeTruthy();
expect(getByText('NOTHING')).toBeTruthy();
});
it('renders "Nothing" when types is undefined', () => {
// @ts-ignore
const { getByText } = render(<TypeTacticsInfoList isWeakness={true} types={undefined}/>);
expect(getByText('Nothing')).toBeTruthy();
expect(getByText('NOTHING')).toBeTruthy();
});
});

@ -56,6 +56,7 @@
"react-native-web": "~0.18.11",
"react-redux": "^8.0.7",
"redux": "^4.2.1",
"redux-mock-store": "^1.5.4",
"redux-thunk": "^2.4.2",
"typescript": "^4.9.4"
},
@ -63,6 +64,7 @@
"@babel/core": "^7.20.0",
"@types/jest": "^29.5.1",
"@types/react-native": "~0.64.12",
"@types/redux-mock-store": "^1.0.3",
"jest": "^29.2.1",
"jest-expo": "^48.0.0"
},

@ -0,0 +1,100 @@
// redux/reducers/__tests__/moveReducer.test.ts
import moveReducer from '../moveReducer';
import { CREATE_MOVE, DELETE_MOVE, GET_MOVES, MOVE_ERROR, UPDATE_MOVE } from '../../constants';
import { Move } from "../../../entities/Move";
import { MoveCategoryName } from "../../../entities/MoveCategoryName";
import { TypeName } from "../../../entities/TypeName";
describe('moveReducer', () => {
const initialState = {
moves: [],
error: null
};
it('returns the initial state when an action type is not passed', () => {
// @ts-ignore
const reducer = moveReducer(undefined, { type: null });
expect(reducer).toEqual(initialState);
});
it('handles GET_MOVES action', () => {
const moves: Move[] = [{
id: '1',
name: 'Test Move',
category: MoveCategoryName.PHYSICAL,
power: 100,
accuracy: 100,
type: { name: TypeName.NORMAL, weakAgainst: [], effectiveAgainst: [] },
schemaVersion: 2
}];
const reducer = moveReducer(
initialState,
{ type: GET_MOVES, payload: moves }
);
expect(reducer).toEqual({ ...initialState, moves });
});
it('handles CREATE_MOVE action', () => {
const move: Move = {
id: '1',
name: 'Test Move',
category: MoveCategoryName.PHYSICAL,
power: 100,
accuracy: 100,
type: { name: TypeName.NORMAL, weakAgainst: [], effectiveAgainst: [] },
schemaVersion: 2
};
const reducer = moveReducer(
initialState,
{ type: CREATE_MOVE, payload: move }
);
expect(reducer).toEqual({ ...initialState, moves: [move] });
});
it('handles UPDATE_MOVE action', () => {
const initialMove: Move = {
id: '1',
name: 'Test Move',
category: MoveCategoryName.PHYSICAL,
power: 100,
accuracy: 100,
type: { name: TypeName.NORMAL, weakAgainst: [], effectiveAgainst: [] },
schemaVersion: 2
};
const updatedMove: Move = { ...initialMove, name: 'Updated Move' };
const reducer = moveReducer(
{ ...initialState, moves: [initialMove] },
{ type: UPDATE_MOVE, payload: updatedMove }
);
expect(reducer).toEqual({ ...initialState, moves: [updatedMove] });
});
it('handles DELETE_MOVE action', () => {
const move: Move = {
id: '1',
name: 'Test Move',
category: MoveCategoryName.PHYSICAL,
power: 100,
accuracy: 100,
type: { name: TypeName.NORMAL, weakAgainst: [], effectiveAgainst: [] },
schemaVersion: 2
};
const reducer = moveReducer(
{ ...initialState, moves: [move] },
// @ts-ignore
{ type: DELETE_MOVE, payload: move.id }
);
expect(reducer).toEqual(initialState);
});
it('handles MOVE_ERROR action', () => {
const reducer = moveReducer(initialState, { type: MOVE_ERROR, payload: 'Error message' });
expect(reducer).toEqual({ ...initialState, error: 'Error message' });
});
});

@ -0,0 +1,71 @@
// screens/moves/__tests__/MoveDetailScreen.test.tsx
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';
import MoveDetailScreen from '../MoveDetailScreen';
import { MOVE_FORM } from "../../../navigation/constants";
const mockStore = configureStore([]);
describe('MoveDetailScreen', () => {
let store;
let component: JSX.Element;
// @ts-ignore
let navigation;
beforeEach(() => {
const mockMove = {
id: '1',
name: 'Test Move',
category: 'PHYSICAL',
power: '100',
accuracy: '100',
type: {
name: 'NORMAL',
weakAgainst: [],
effectiveAgainst: [],
},
};
store = mockStore({
move: {
moves: [mockMove],
error: null,
},
});
navigation = { navigate: jest.fn(), setOptions: jest.fn() };
const route = { params: { move: mockMove } };
component = (
<Provider store={store}>
{/* @ts-ignore */}
<MoveDetailScreen navigation={navigation} route={route} />
</Provider>
);
});
it('renders correctly', () => {
const { getByText } = render(component);
expect(getByText('Name: Test Move')).toBeTruthy();
expect(getByText('Category: PHYSICAL')).toBeTruthy();
expect(getByText('Power: 100')).toBeTruthy();
expect(getByText('Accuracy: 100')).toBeTruthy();
expect(getByText('Type: NORMAL')).toBeTruthy();
});
it('navigates to the form screen when the edit button is pressed', () => {
const { getByText } = render(component);
fireEvent.press(getByText('Edit Move'));
// @ts-ignore
expect(navigation.navigate).toHaveBeenCalledWith(MOVE_FORM, { move: expect.any(Object) });
});
it('sets the navigation options correctly', () => {
render(component);
// @ts-ignore
expect(navigation.setOptions).toHaveBeenCalledWith({ title: 'Test Move' });
});
});

@ -2478,6 +2478,13 @@
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/redux-mock-store@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@types/redux-mock-store/-/redux-mock-store-1.0.3.tgz#895de4a364bc4836661570aec82f2eef5989d1fb"
integrity sha512-Wqe3tJa6x9MxMN4DJnMfZoBRBRak1XTPklqj4qkVm5VBpZnC8PSADf4kLuFQ9NAdHaowfWoEeUMz7NWc2GMtnA==
dependencies:
redux "^4.0.5"
"@types/retry@0.12.0":
version "0.12.0"
resolved "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz"
@ -6752,6 +6759,11 @@ lodash.debounce@^4.0.8:
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz"
@ -8648,12 +8660,19 @@ recast@^0.20.4:
source-map "~0.6.1"
tslib "^2.0.1"
redux-mock-store@^1.5.4:
version "1.5.4"
resolved "https://registry.yarnpkg.com/redux-mock-store/-/redux-mock-store-1.5.4.tgz#90d02495fd918ddbaa96b83aef626287c9ab5872"
integrity sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==
dependencies:
lodash.isplainobject "^4.0.6"
redux-thunk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b"
integrity sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==
redux@^4.2.1:
redux@^4.0.5, redux@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==

Loading…
Cancel
Save