Skip to content

Commit 5e78818

Browse files
Added comments & screenshots
1 parent caea2c6 commit 5e78818

32 files changed

+82
-21
lines changed

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
# testing-app
1+
# Testing App
2+
23
Demo for react native testing library
4+
5+
Please don't judge me for coding practices using this code base. I am better than this; might be.

app/screens/LoginScreen/EmailPasswordForm/tests/index.test.tsx

+23
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,53 @@ import {
1212

1313
describe('<EmailPasswordForm />', () => {
1414
it('Expect to show password required', async () => {
15+
// Dummy email value
1516
const email = 'email@email.com';
1617

18+
// Grabbing our parent component
1719
const { getByTestId } = render(
1820
<EmailPasswordForm
1921
onSubmit={() => null}
2022
onForgotPasswordPress={() => null}
2123
/>,
2224
);
25+
26+
// Grabbing our input & button components
2327
const emailInput = getByTestId(TEST_ID_EMAIL_INPUT);
2428
const button = getByTestId(TEST_ID_SUBMIT_BUTTON);
2529

30+
/**
31+
* We are changing text in inputs here; that requires a state change
32+
* Since setState is async in react we have to execute this tests
33+
* in async way. RNTL give waitFor API for this.
34+
*/
2635
await waitFor(() => {
2736
fireEvent.changeText(emailInput, email);
37+
// Just making sure that value is updated in input
2838
expect(emailInput.props.value).toBe(email);
2939
fireEvent.press(button);
40+
41+
// We have passwordInput_ERROR component that only renders when error is there
3042
expect(getByTestId('passwordInput_ERROR')).toBeDefined();
3143
});
3244
});
3345

3446
it('Expect to call handle submit with email & password', async () => {
47+
// Dummy inputs
3548
const email = 'email@email.com';
3649
const password = 'qwerty1234';
50+
51+
// Expected output
3752
const expectedOutput = {
3853
email,
3954
password,
4055
};
4156
let output = {};
57+
58+
// Mock onSubmit method that we are expecting will be executed
4259
const onSubmit = jest.fn((data) => (output = data));
4360

61+
// Rendering our component & grabbing required nodes.
4462
const { getByTestId } = render(
4563
<EmailPasswordForm
4664
onSubmit={onSubmit}
@@ -51,13 +69,18 @@ describe('<EmailPasswordForm />', () => {
5169
const emailInput = getByTestId(TEST_ID_EMAIL_INPUT);
5270
const passwordInput = getByTestId(TEST_ID_PASSWORD_INPUT);
5371

72+
// Testing behaviors
5473
await waitFor(() => {
5574
fireEvent.changeText(emailInput, email);
5675
expect(emailInput.props.value).toBe(email);
5776

5877
fireEvent.changeText(passwordInput, password);
5978
expect(passwordInput.props.value).toBe(password);
6079

80+
/**
81+
* Here we are asserting that onSubmit is not just called
82+
* but it is called with expected output.
83+
*/
6184
fireEvent.press(button);
6285
expect(onSubmit).toHaveBeenCalledTimes(1);
6386
expect(output).toEqual(expectedOutput);

app/screens/LoginScreen/tests/index.test.tsx

+21-6
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,32 @@ import {
2020
} from '../constants';
2121

2222
describe('Login Screen', () => {
23-
afterEach(() => {
24-
fetchMock.reset();
25-
fetchMock.restore();
26-
});
27-
28-
it('Expect to save token in AsyncStorage & navigate to home screen on successful login', async () => {
23+
// Setting up fetch mock before execution of any test
24+
beforeAll(() => {
2925
const endPoint = `${API_URL}${LOGIN_ENDPOINT}`;
3026
fetchMock.post(endPoint, {
3127
status: 200,
3228
body: JSON.stringify(LOGIN_EXPECTED_RESPONSE),
3329
});
30+
});
3431

32+
// Testing complete flow
33+
it('Expect to save token in AsyncStorage & navigate to home screen on successful login', async () => {
34+
// Mocking navigate method
3535
const navigate = jest.fn();
36+
const endPoint = `${API_URL}${LOGIN_ENDPOINT}`;
3637

38+
// Dummy data to supply to form
3739
const email = 'email@email.com';
3840
const password = 'password';
3941

42+
// Getting element
4043
const screen = render(<LoginScreen navigation={{ navigate }} />);
4144
const emailInput = screen.getByTestId(TEST_ID_EMAIL_INPUT);
4245
const passwordInput = screen.getByTestId(TEST_ID_PASSWORD_INPUT);
4346
const button = screen.getByTestId(TEST_ID_SUBMIT_BUTTON);
4447

48+
// Formik requires all state changes to be wrapper in async method.
4549
await waitFor(() => {
4650
fireEvent.changeText(emailInput, email);
4751
fireEvent.changeText(passwordInput, password);
@@ -51,16 +55,27 @@ describe('Login Screen', () => {
5155
fireEvent.press(button);
5256
});
5357

58+
// Asserting that API has been called
5459
expect(fetchMock).toHaveBeenCalledWith(endPoint, {
5560
body: `{"email":"${email}","password":"${password}"}`,
5661
headers: { 'Content-Type': 'application/json' },
5762
method: 'POST',
5863
});
64+
65+
// Asserting screen navigation
5966
expect(navigate).toHaveBeenCalledTimes(1);
6067
expect(navigate).toHaveBeenCalledWith(HOME, {});
68+
69+
// Asserting token storage in local storage.
6170
expect(AsyncStorage.setItem).toHaveBeenCalledWith(
6271
AUTH_TOKEN_KEY,
6372
LOGIN_EXPECTED_RESPONSE.data.tokens.jwtToken,
6473
);
6574
});
75+
76+
// Cleaning up fetch mock
77+
afterEach(() => {
78+
fetchMock.reset();
79+
fetchMock.restore();
80+
});
6681
});

app/theme/Button/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import React, { useEffect, useRef } from 'react';
77
import { Animated } from 'react-native';
88

99
import Text from 'theme/Text';
10-
import TouchFeedback from 'theme/TouchFeedback';
10+
import TouchFeedback, { TouchFeedbackProps } from 'theme/TouchFeedback';
1111

1212
import style from './style';
1313

@@ -22,7 +22,7 @@ const typeForeground = {
2222
tertiary: style.tertiaryForeground,
2323
};
2424

25-
interface ButtonProps {
25+
interface ButtonProps extends TouchFeedbackProps {
2626
onPress: (...args: any[]) => any;
2727
label: string | React.ReactNode;
2828
mini?: boolean;

app/theme/Button/tests/index.test.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,31 @@ import { fireEvent } from '@testing-library/react-native';
55
import { render } from 'utils/testWrapper';
66
import Button from '../index';
77

8+
// Describing a test suite
89
describe('<Button />', () => {
10+
// Describing our test
911
it('Calls onPress', async () => {
12+
// Mocking onPress method so we can check if its called or not
1013
const onPress = jest.fn();
14+
15+
// test id to be applied on our button component
1116
const testID = 'button';
17+
18+
// Rendering Button component using react-native-test-renderer.
1219
const { getByTestId } = await render(
1320
<Button testID={testID} onPress={onPress} label="Button" />,
1421
);
22+
23+
// Grabbing our button component to perform actions on it.
1524
const button = getByTestId(testID);
25+
26+
/**
27+
* RNTL gives us API to fire events on node
28+
* Here we are firing on press event
29+
*/
1630
fireEvent.press(button);
31+
32+
// Asserting if given mock method is called or not.
1733
expect(onPress).toHaveBeenCalledTimes(1);
1834
});
1935
});

app/theme/TouchFeedback/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ const AnimatedNative = Animated.createAnimatedComponent(
1313
);
1414
const RIPPLE = Platform.OS === 'android' && Platform.Version >= 21;
1515

16-
type TouchFeedbackProps = {
16+
export interface TouchFeedbackProps {
1717
style?: number | any[];
1818
ripple?: boolean;
1919
animated?: boolean;
2020
onPress: (...args: any[]) => any;
2121
testID?: string;
22-
};
22+
}
2323

2424
const TouchFeedback: React.SFC<TouchFeedbackProps> = ({
2525
children,

app/utils/delay.ts

-5
This file was deleted.

0 commit comments

Comments
 (0)