Skip to content

Commit

Permalink
a couple of basic jest tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fourhtyoz committed Jan 25, 2025
1 parent 350c5e1 commit 071bd59
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 5 deletions.
3 changes: 3 additions & 0 deletions components/buttons/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Props = {
pressedBorderColor?: string,
textColor?: string,
pressedTextColor?: string,
testID?: string
}


Expand All @@ -26,10 +27,12 @@ export default function Button({
pressedBorderColor = COLORS.blackTransparentBorder,
textColor = COLORS.white,
pressedTextColor = COLORS.black,
testID = '',
} : Props) {

return (
<Pressable
testID={testID}
onPress={onPress}
disabled={disabled}
style={({ pressed }) => [
Expand Down
38 changes: 38 additions & 0 deletions screens/AddExerciseScreen.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import AddExerciseScreen from './AddExerciseScreen'

jest.mock('mobx-react-lite', () => ({
observer: jest.fn((component) => component),
}));

jest.mock('react-native-toast-message', () => ({
show: jest.fn(),
}));

// Mock external dependencies
jest.mock('../services/db', () => ({
addExercise: jest.fn(),
}));

describe('<AddExerciseScreen />', () => {
let navigation: any;

beforeEach(() => {
navigation = { navigate: jest.fn() };
});

it('renders correctly', () => {
const { getByTestId } = render(<AddExerciseScreen navigation={navigation} route={navigation.route} />);
expect(getByTestId('result-muscle')).toBeTruthy();
expect(getByTestId('result-title')).toBeTruthy();
expect(getByTestId('result-createExercise')).toBeTruthy();
});

it('disables the save button when fields are empty', () => {
const { getByTestId } = render(<AddExerciseScreen navigation={navigation} route={navigation.route} />);
const saveButton = getByTestId('result-createExercise');
expect(saveButton.props.accessibilityState.disabled).toBe(true);
});

});
5 changes: 3 additions & 2 deletions screens/AddExerciseScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const AddExerciseScreen = observer(({ navigation }: Props) => {
<SafeAreaView style={globalStyles.wrapper}>
{error && <View style={{ marginTop: 25 }}><ErrorMessage message={error} setError={setError} /></View>}
<View style={globalStyles.itemWrapper}>
<Text style={[globalStyles.inputLabel, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black }]}>{t('result.options.muscle')}:</Text>
<Text testID='result-muscle' style={[globalStyles.inputLabel, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black }]}>{t('result.options.muscle')}:</Text>
<SelectDropdown
data={MUSCLES}
onSelect={(selectedItem, _) => setMuscleGroup(selectedItem.title)}
Expand Down Expand Up @@ -102,7 +102,7 @@ const AddExerciseScreen = observer(({ navigation }: Props) => {
/>
</View>
<View style={globalStyles.itemWrapper}>
<Text style={[globalStyles.inputLabel, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black }]}>{t('result.options.title')}:</Text>
<Text testID='result-title' style={[globalStyles.inputLabel, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black }]}>{t('result.options.title')}:</Text>
<TextInput
onChangeText={(value) => handleChangeTitle(value)}
defaultValue={title}
Expand All @@ -112,6 +112,7 @@ const AddExerciseScreen = observer(({ navigation }: Props) => {
/>
</View>
<Button
testID='result-createExercise'
onPress={handleCreateExercise}
text={t('result.options.createExercise')}
pressedBgColor={COLORS.orange}
Expand Down
89 changes: 89 additions & 0 deletions screens/EditResultScreen.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';
import { render, fireEvent, waitFor, act } from '@testing-library/react-native';
import EditResultScreen from './EditResultScreen';
import { Alert } from 'react-native';

// Mocking modules
jest.mock('../services/db', () => ({
updateResult: jest.fn(),
}));

jest.mock('../services/db', () => ({
fetchExercises: jest.fn(() => Promise.resolve([{ title: 'Squats', type: 'Legs' }])),
}));

jest.mock('react-native-toast-message', () => ({
Toast: {
show: jest.fn(),
},
}));

jest.spyOn(Alert, 'alert');

describe('EditResultScreen', () => {
const mockNavigation = { navigate: jest.fn() };
const mockRoute = {
params: {
id: '1',
date: new Date().toISOString(),
exercise: 'Squats',
muscleGroup: 'Legs',
reps: 10,
weight: 50,
units: 'kg',
},
};

afterEach(() => {
jest.clearAllMocks();
});

it('renders correctly and fetches exercises', async () => {
const { findByText } = render(
<EditResultScreen navigation={mockNavigation} route={mockRoute} />
);

expect(await findByText('Legs')).toBeTruthy(); // Muscle group dropdown
expect(await findByText('Squats')).toBeTruthy(); // Exercise dropdown
expect(await findByText('kg')).toBeTruthy(); // Exercise dropdown
});

it('displays an error for invalid reps input', async () => {
const { getByTestId, getByText } = render(
<EditResultScreen navigation={mockNavigation} route={mockRoute} />
);

await waitFor(() => {
const repsInput = getByTestId('input-reps')
expect(repsInput).toBeTruthy()
})

act(() => {
fireEvent.changeText(getByTestId('input-reps'), '-5')

})

await waitFor(() => {
expect(getByText('Error: Repetitions must be greater than 0')).toBeTruthy();
});
});

it('displays an error for invalid weight input', async () => {
const { getByTestId, getByText } = render(
<EditResultScreen navigation={mockNavigation} route={mockRoute} />
);

await waitFor(() => {
const weightInput = getByTestId('input-weight')
expect(weightInput).toBeTruthy()
})

act(() => {
fireEvent.changeText(getByTestId('input-weight'), 'abc');
})

await waitFor(() => {
expect(getByText('Error: Weight must be a number')).toBeTruthy();
});
});
});
7 changes: 4 additions & 3 deletions screens/EditResultScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import Loader from '@/components/Loader';


const EditResultScreen = observer(({ navigation, route }: any) => {

const [exercises, setExercises] = useState<Exercise[]>([])
const [newDate, setNewDate] = useState(new Date())
const [newGroup, setNewGroup] = useState<any>(null)
Expand Down Expand Up @@ -206,7 +205,8 @@ const EditResultScreen = observer(({ navigation, route }: any) => {
</View>
<View style={globalStyles.itemWrapper}>
<Text style={[globalStyles.inputLabel, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black }]}>{t('result.options.weight')}:</Text>
<TextInput
<TextInput
testID='input-weight'
style={[globalStyles.inputWithOption, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black, borderColor: settingsStore.isDark ? COLORS.orange : COLORS.gray }]}
value={`${newWeight}`}
placeholder={t('result.options.whatWeight')}
Expand Down Expand Up @@ -234,7 +234,8 @@ const EditResultScreen = observer(({ navigation, route }: any) => {
</View>
<View style={globalStyles.itemWrapper}>
<Text style={[globalStyles.inputLabel, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black }]}>{t('result.options.reps')}:</Text>
<TextInput
<TextInput
testID='input-reps'
style={[globalStyles.input, { color: settingsStore.isDark ? COLORS.textDarkScreen : COLORS.black, borderColor: settingsStore.isDark ? COLORS.orange : COLORS.gray }]}
value={`${newReps}`}
placeholder={t('result.options.howManyReps')}
Expand Down

0 comments on commit 071bd59

Please sign in to comment.