test: improve and add missings tests
parent
5de377f0c3
commit
8c4ee87622
|
|
@ -3,6 +3,8 @@
|
|||
# dependencies
|
||||
node_modules/
|
||||
|
||||
coverage/
|
||||
|
||||
# Expo
|
||||
.expo/
|
||||
dist/
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ export default function Timer() {
|
|||
}
|
||||
};
|
||||
|
||||
const handleContine = () => {
|
||||
const handleContinue = () => {
|
||||
setIsRunning(true);
|
||||
};
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ export default function Timer() {
|
|||
previousRep={previousRep}
|
||||
handleReset={handleReset}
|
||||
handleStop={handleStop}
|
||||
handleContine={handleContine}
|
||||
handleContinue={handleContinue}
|
||||
/>
|
||||
)}
|
||||
</Container>
|
||||
|
|
|
|||
|
|
@ -10,13 +10,15 @@ jest.mock('../TimerStore', () => ({
|
|||
saveWorkTime: jest.fn(),
|
||||
saveRestTime: jest.fn(),
|
||||
saveState: jest.fn(),
|
||||
savePreparationTime: jest.fn(),
|
||||
}
|
||||
}));
|
||||
|
||||
const mockTimerState = {
|
||||
reps: 5,
|
||||
workTime: 30,
|
||||
restTime: 10
|
||||
restTime: 10,
|
||||
preparationTime: 3
|
||||
};
|
||||
|
||||
describe('TimerContext', () => {
|
||||
|
|
@ -169,6 +171,158 @@ describe('TimerContext', () => {
|
|||
expect(result.current.timerState.restTime).toBe(15);
|
||||
});
|
||||
|
||||
it('should handle errors when updating rest time', async () => {
|
||||
// Simulate an error
|
||||
(timerStore.saveRestTime as jest.Mock<Promise<void>>).mockRejectedValueOnce(new Error('Saving error'));
|
||||
|
||||
// Spy on console.error
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { result } = renderHook(() => useTimerContext(), {
|
||||
wrapper: TimerProvider
|
||||
});
|
||||
|
||||
// Wait for initial loading to complete
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
// Attempt to update rest time
|
||||
await act(async () => {
|
||||
await result.current.updateRestTime(15);
|
||||
});
|
||||
|
||||
// Verify error was logged
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'Error updating rest time:',
|
||||
expect.any(Error)
|
||||
);
|
||||
|
||||
// Restore console.error
|
||||
(console.error as jest.MockedFunction<typeof console.error>).mockRestore();
|
||||
});
|
||||
|
||||
it('should handle errors when updating work time', async () => {
|
||||
// Simulate an error
|
||||
(timerStore.saveWorkTime as jest.Mock<Promise<void>>).mockRejectedValueOnce(new Error('Saving error'));
|
||||
|
||||
// Spy on console.error
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { result } = renderHook(() => useTimerContext(), {
|
||||
wrapper: TimerProvider
|
||||
});
|
||||
|
||||
// Wait for initial loading to complete
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
// Attempt to update work time
|
||||
await act(async () => {
|
||||
await result.current.updateWorkTime(45);
|
||||
});
|
||||
|
||||
// Verify error was logged
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'Error updating work time:',
|
||||
expect.any(Error)
|
||||
);
|
||||
|
||||
// Restore console.error
|
||||
(console.error as jest.MockedFunction<typeof console.error>).mockRestore();
|
||||
});
|
||||
|
||||
it('should update preparation time', async () => {
|
||||
const { result } = renderHook(() => useTimerContext(), {
|
||||
wrapper: TimerProvider
|
||||
});
|
||||
|
||||
// Wait for initial loading to complete
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
// Update preparation time
|
||||
await act(async () => {
|
||||
await result.current.updatePreparationTime(5);
|
||||
});
|
||||
|
||||
// Verify savePreparationTime was called with the correct value
|
||||
expect(timerStore.savePreparationTime).toHaveBeenCalledWith(5);
|
||||
|
||||
// Verify state was updated
|
||||
expect(result.current.timerState.preparationTime).toBe(5);
|
||||
});
|
||||
|
||||
it('should handle errors when updating preparation time', async () => {
|
||||
// Simulate an error
|
||||
(timerStore.savePreparationTime as jest.Mock<Promise<void>>).mockRejectedValueOnce(new Error('Saving error'));
|
||||
|
||||
// Spy on console.error
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { result } = renderHook(() => useTimerContext(), {
|
||||
wrapper: TimerProvider
|
||||
});
|
||||
|
||||
// Wait for initial loading to complete
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
// Attempt to update preparation time
|
||||
await act(async () => {
|
||||
await result.current.updatePreparationTime(5);
|
||||
});
|
||||
|
||||
// Verify error was logged
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'Error updating preparation time:',
|
||||
expect.any(Error)
|
||||
);
|
||||
|
||||
// Restore console.error
|
||||
(console.error as jest.MockedFunction<typeof console.error>).mockRestore();
|
||||
});
|
||||
|
||||
it('should handle errors when updating multiple values at once', async () => {
|
||||
// Simulate an error
|
||||
(timerStore.saveState as jest.Mock<Promise<void>>).mockRejectedValueOnce(new Error('Saving error'));
|
||||
|
||||
// Spy on console.error
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { result } = renderHook(() => useTimerContext(), {
|
||||
wrapper: TimerProvider
|
||||
});
|
||||
|
||||
// Wait for initial loading to complete
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
const newState = {
|
||||
reps: 8,
|
||||
workTime: 60,
|
||||
restTime: 20
|
||||
};
|
||||
|
||||
// Attempt to update complete state
|
||||
await act(async () => {
|
||||
await result.current.updateState(newState);
|
||||
});
|
||||
|
||||
// Verify error was logged
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'Error updating state:',
|
||||
expect.any(Error)
|
||||
);
|
||||
|
||||
// Restore console.error
|
||||
(console.error as jest.MockedFunction<typeof console.error>).mockRestore();
|
||||
});
|
||||
|
||||
it('should update multiple values at once', async () => {
|
||||
const { result } = renderHook(() => useTimerContext(), {
|
||||
wrapper: TimerProvider
|
||||
|
|
|
|||
|
|
@ -11,6 +11,27 @@ jest.mock('@react-native-async-storage/async-storage', () => ({
|
|||
const mockedAsyncStorage = AsyncStorage as jest.Mocked<typeof AsyncStorage>;
|
||||
|
||||
describe('TimerStore', () => {
|
||||
// Tests pour savePreparationTime method
|
||||
describe('savePreparationTime', () => {
|
||||
test('should save preparation time in AsyncStorage', async () => {
|
||||
await timerStore.savePreparationTime(5);
|
||||
expect(mockedAsyncStorage.setItem).toHaveBeenCalledWith('timer_preparation_time', '5');
|
||||
});
|
||||
|
||||
test('should handle errors when saving preparation time', async () => {
|
||||
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
||||
mockedAsyncStorage.setItem.mockRejectedValueOnce(new Error('AsyncStorage Error'));
|
||||
|
||||
await timerStore.savePreparationTime(5);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'Error saving preparation time:',
|
||||
expect.any(Error)
|
||||
);
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
// Clear all mocks after each test
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
|
@ -85,7 +106,8 @@ describe('TimerStore', () => {
|
|||
const state: TimerState = {
|
||||
reps: 3,
|
||||
workTime: 40,
|
||||
restTime: 20
|
||||
restTime: 20,
|
||||
preparationTime: 5
|
||||
};
|
||||
|
||||
await timerStore.saveState(state);
|
||||
|
|
@ -93,6 +115,7 @@ describe('TimerStore', () => {
|
|||
expect(mockedAsyncStorage.setItem).toHaveBeenCalledWith('timer_reps', '3');
|
||||
expect(mockedAsyncStorage.setItem).toHaveBeenCalledWith('timer_work_time', '40');
|
||||
expect(mockedAsyncStorage.setItem).toHaveBeenCalledWith('timer_rest_time', '20');
|
||||
expect(mockedAsyncStorage.setItem).toHaveBeenCalledWith('timer_preparation_time', '5');
|
||||
});
|
||||
|
||||
test('should handle errors when saving state', async () => {
|
||||
|
|
@ -151,6 +174,41 @@ describe('TimerStore', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// Tests for getPreparationTime method
|
||||
describe('getPreparationTime', () => {
|
||||
test('should retrieve preparation time from AsyncStorage', async () => {
|
||||
mockedAsyncStorage.getItem.mockResolvedValueOnce('5');
|
||||
|
||||
const result = await timerStore.getPreparationTime();
|
||||
|
||||
expect(result).toBe(5);
|
||||
expect(mockedAsyncStorage.getItem).toHaveBeenCalledWith('timer_preparation_time');
|
||||
});
|
||||
|
||||
test('should return default value if no data is found', async () => {
|
||||
mockedAsyncStorage.getItem.mockResolvedValueOnce(null);
|
||||
|
||||
const result = await timerStore.getPreparationTime();
|
||||
|
||||
expect(result).toBe(3); // Default preparation time value
|
||||
expect(mockedAsyncStorage.getItem).toHaveBeenCalledWith('timer_preparation_time');
|
||||
});
|
||||
|
||||
test('should handle errors when retrieving preparation time', async () => {
|
||||
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
||||
mockedAsyncStorage.getItem.mockRejectedValueOnce(new Error('AsyncStorage Error'));
|
||||
|
||||
const result = await timerStore.getPreparationTime();
|
||||
|
||||
expect(result).toBe(3); // Default value
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
'Error retrieving preparation time:',
|
||||
expect.any(Error)
|
||||
);
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
// Tests for getWorkTime method
|
||||
describe('getWorkTime', () => {
|
||||
test('should retrieve work time from AsyncStorage', async () => {
|
||||
|
|
@ -227,7 +285,8 @@ describe('TimerStore', () => {
|
|||
mockedAsyncStorage.getItem
|
||||
.mockResolvedValueOnce('3') // reps
|
||||
.mockResolvedValueOnce('40') // workTime
|
||||
.mockResolvedValueOnce('20'); // restTime
|
||||
.mockResolvedValueOnce('20') // restTime
|
||||
.mockResolvedValueOnce('5'); // preparationTime
|
||||
|
||||
const result = await timerStore.getState();
|
||||
|
||||
|
|
@ -235,12 +294,13 @@ describe('TimerStore', () => {
|
|||
reps: 3,
|
||||
workTime: 40,
|
||||
restTime: 20,
|
||||
preparationTime: 3
|
||||
preparationTime: 5
|
||||
});
|
||||
|
||||
expect(mockedAsyncStorage.getItem).toHaveBeenCalledWith('timer_reps');
|
||||
expect(mockedAsyncStorage.getItem).toHaveBeenCalledWith('timer_work_time');
|
||||
expect(mockedAsyncStorage.getItem).toHaveBeenCalledWith('timer_rest_time');
|
||||
expect(mockedAsyncStorage.getItem).toHaveBeenCalledWith('timer_preparation_time');
|
||||
});
|
||||
|
||||
test('should handle errors when retrieving state', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type ButtonColor = 'green' | 'red' | 'grey' | 'white';
|
|||
type LabelColor = ButtonColor | 'black';
|
||||
type IconLocation = 'left' | 'right';
|
||||
|
||||
interface ButtonProps {
|
||||
export interface ButtonProps {
|
||||
label?: string;
|
||||
color?: ButtonColor;
|
||||
labelColor?: LabelColor;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import styled from '@emotion/native';
|
|||
import React, { useCallback } from 'react';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
|
||||
interface CardProps {
|
||||
export interface CardProps {
|
||||
children: React.ReactNode;
|
||||
backgroundColor: CardBackgroundColor;
|
||||
testID?: string;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import styled from '@emotion/native';
|
|||
|
||||
import { HorizontalSpacer } from './Spacers';
|
||||
|
||||
type FinishContentProps = {
|
||||
export interface NumberSelectorProps {
|
||||
reps: number;
|
||||
setReps: (reps: number) => void;
|
||||
};
|
||||
|
|
@ -11,7 +11,7 @@ type FinishContentProps = {
|
|||
export default function NumberSelector({
|
||||
setReps,
|
||||
reps
|
||||
}: FinishContentProps) {
|
||||
}: NumberSelectorProps) {
|
||||
const addReps: () => void = () => {
|
||||
setReps(reps + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
/**
|
||||
* Learn more about Light and Dark modes:
|
||||
* https://docs.expo.io/guides/color-schemes/
|
||||
*/
|
||||
|
||||
import { Text as DefaultText, View as DefaultView } from 'react-native';
|
||||
|
||||
import Colors from '@/constants/Colors';
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
import { fireEvent } from '@testing-library/react-native';
|
||||
|
||||
import { render } from '@/components/testUtils';
|
||||
import Button from '@/components/shared/Button';
|
||||
|
||||
const renderComponent = ({ status, onPress } = {}) => {
|
||||
const base = render(<Button label="Press me" status={status} onPress={onPress} />);
|
||||
|
||||
return base;
|
||||
};
|
||||
|
||||
describe('[Component] Button', () => {
|
||||
describe('Ready state', () => {
|
||||
test('renders correctly', () => {
|
||||
const button = renderComponent();
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('executes an action when pressing it', () => {
|
||||
const action = jest.fn();
|
||||
const button = renderComponent({ onPress: action });
|
||||
|
||||
fireEvent.press(button.getByText('Press me'));
|
||||
expect(action).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Disabled state', () => {
|
||||
test('renders correctly', () => {
|
||||
const button = renderComponent({ status: 'disabled' });
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('does not do anything when pressing it', () => {
|
||||
const action = jest.fn();
|
||||
const button = renderComponent({ status: 'disabled', onPress: action });
|
||||
|
||||
fireEvent.press(button.getByText('Press me'));
|
||||
expect(action).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Loading state', () => {
|
||||
test('renders correctly', () => {
|
||||
const button = renderComponent({ status: 'loading' });
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('does not do anything when pressing it', () => {
|
||||
const action = jest.fn();
|
||||
const button = renderComponent({ status: 'loading', onPress: action });
|
||||
|
||||
fireEvent.press(button.getByText('Press me'));
|
||||
expect(action).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
import React from 'react';
|
||||
|
||||
import { fireEvent } from '@testing-library/react-native';
|
||||
|
||||
import { render } from '@/components/testUtils';
|
||||
import Button, { ButtonProps } from '@/components/shared/Button';
|
||||
|
||||
const renderComponent = ({
|
||||
status,
|
||||
onPress,
|
||||
secondary,
|
||||
icon,
|
||||
iconLocation,
|
||||
label,
|
||||
color,
|
||||
labelColor
|
||||
}: ButtonProps = {}) => {
|
||||
const base = render(
|
||||
<Button
|
||||
label={label || "Press me"}
|
||||
status={status}
|
||||
onPress={onPress}
|
||||
secondary={secondary}
|
||||
icon={icon}
|
||||
iconLocation={iconLocation}
|
||||
color={color}
|
||||
labelColor={labelColor}
|
||||
/>
|
||||
);
|
||||
|
||||
return base;
|
||||
};
|
||||
|
||||
describe('[Component] Button', () => {
|
||||
describe('Ready state', () => {
|
||||
test('renders correctly', () => {
|
||||
const button = renderComponent();
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('executes an action when pressing it', () => {
|
||||
const action = jest.fn();
|
||||
const button = renderComponent({ onPress: action });
|
||||
|
||||
fireEvent.press(button.getByText('Press me'));
|
||||
expect(action).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Disabled state', () => {
|
||||
test('renders correctly', () => {
|
||||
const button = renderComponent({ status: 'disabled' });
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('does not do anything when pressing it', () => {
|
||||
const action = jest.fn();
|
||||
const button = renderComponent({ status: 'disabled', onPress: action });
|
||||
|
||||
fireEvent.press(button.getByText('Press me'));
|
||||
expect(action).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Loading state', () => {
|
||||
test('renders correctly', () => {
|
||||
const button = renderComponent({ status: 'loading' });
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('does not do anything when pressing it', () => {
|
||||
const action = jest.fn();
|
||||
const button = renderComponent({ status: 'loading', onPress: action });
|
||||
|
||||
fireEvent.press(button.getByText('Press me'));
|
||||
expect(action).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Secondary button', () => {
|
||||
test('renders correctly', () => {
|
||||
const button = renderComponent({ secondary: true });
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('with different colors', () => {
|
||||
const button = renderComponent({
|
||||
secondary: true,
|
||||
color: 'green'
|
||||
});
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Icon rendering', () => {
|
||||
const mockIcon = <div data-testid="mock-icon" />;
|
||||
|
||||
test('renders with icon on the right', () => {
|
||||
const button = renderComponent({
|
||||
icon: mockIcon,
|
||||
iconLocation: 'right'
|
||||
});
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders with icon on the left', () => {
|
||||
const button = renderComponent({
|
||||
icon: mockIcon,
|
||||
iconLocation: 'left'
|
||||
});
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders icon only without label', () => {
|
||||
const button = renderComponent({
|
||||
icon: mockIcon,
|
||||
label: undefined
|
||||
});
|
||||
|
||||
expect(button).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Color variations', () => {
|
||||
test('renders with different colors', () => {
|
||||
const greenButton = renderComponent({ color: 'green', labelColor: 'white' });
|
||||
const redButton = renderComponent({ color: 'red', labelColor: 'white' });
|
||||
const greyButton = renderComponent({ color: 'grey' });
|
||||
|
||||
expect(greenButton).toMatchSnapshot();
|
||||
expect(redButton).toMatchSnapshot();
|
||||
expect(greyButton).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -3,14 +3,16 @@ import React from 'react';
|
|||
import { fireEvent } from '@testing-library/react-native';
|
||||
|
||||
import { render } from '@/components/testUtils';
|
||||
import Card from '@/components/shared/Card';
|
||||
import Card, { CardProps } from '@/components/shared/Card';
|
||||
import { Text } from 'react-native';
|
||||
import { theme } from '@/app/shared/theme';
|
||||
|
||||
const renderComponent = ({ backgroundColor, onPress = undefined, content = 'content'} = {}) => {
|
||||
type RenderCardProps = Omit<CardProps, 'children'> & { children?: React.ReactNode };
|
||||
|
||||
const renderComponent = ({ backgroundColor, onPress, children = 'content'}: RenderCardProps) => {
|
||||
const base = render(
|
||||
<Card backgroundColor={backgroundColor} onPress={onPress} testID='card'>
|
||||
<Text>{content}</Text>
|
||||
<Text>{children}</Text>
|
||||
</Card>
|
||||
);
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ describe('[Component] Card', () => {
|
|||
});
|
||||
|
||||
test('renders children correctly', () => {
|
||||
const { getByText } = renderComponent({ backgroundColor: 'red', content: 'Test Content'});
|
||||
const { getByText } = renderComponent({ backgroundColor: 'red', children: 'Test Content'});
|
||||
|
||||
expect(getByText('Test Content')).toBeTruthy();
|
||||
});
|
||||
|
|
@ -40,16 +42,30 @@ describe('[Component] Card', () => {
|
|||
test('does not render as TouchableOpacity when onPress is not provided', () => {
|
||||
const { queryByTestId } = renderComponent({ backgroundColor: 'red' });
|
||||
|
||||
// TouchableOpacity ne doit pas exister
|
||||
// TouchableOpacity should not exist
|
||||
expect(queryByTestId('card').props.onPress).toBeUndefined();
|
||||
});
|
||||
|
||||
test('handles undefined onPress gracefully when pressed', () => {
|
||||
// Ce test vérifie que le comportement est correct quand onPress est undefined
|
||||
const { getByTestId } = renderComponent({
|
||||
backgroundColor: 'red',
|
||||
onPress: undefined,
|
||||
children: 'Press me safely'
|
||||
});
|
||||
|
||||
// Vérifie qu'aucune erreur n'est levée lors de l'appui
|
||||
expect(() => {
|
||||
fireEvent.press(getByTestId('card'));
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
test('calls onPress when pressed', () => {
|
||||
const onPressMock = jest.fn();
|
||||
const { getByTestId } = renderComponent({
|
||||
backgroundColor: 'green',
|
||||
onPress: onPressMock,
|
||||
content: 'Press me'
|
||||
children: 'Press me'
|
||||
});
|
||||
|
||||
fireEvent.press(getByTestId('card'));
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react-native';
|
||||
import { render } from '@/components/testUtils';
|
||||
import NumberSelector from '@/components/shared/NumberSelector';
|
||||
import NumberSelector, { NumberSelectorProps } from '@/components/shared/NumberSelector';
|
||||
|
||||
const renderComponent = ({ reps = 5, setReps = jest.fn() } = {}) => {
|
||||
const renderComponent = ({ reps = 5, setReps = jest.fn() }: NumberSelectorProps) => {
|
||||
const base = render(
|
||||
<NumberSelector reps={reps} setReps={setReps} />
|
||||
);
|
||||
|
|
@ -13,20 +13,20 @@ const renderComponent = ({ reps = 5, setReps = jest.fn() } = {}) => {
|
|||
|
||||
describe('[Component] NumberSelect', () => {
|
||||
test('renders correctly', () => {
|
||||
const component = renderComponent();
|
||||
const component = renderComponent({ reps: 5, setReps: jest.fn() });
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders the correct initial reps value', () => {
|
||||
const { getByText } = renderComponent()
|
||||
const { getByText } = renderComponent({ reps: 5, setReps: jest.fn() });
|
||||
|
||||
expect(getByText('5')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('increments reps when "+" is pressed', () => {
|
||||
const setRepsMock = jest.fn();
|
||||
const { getByText } = renderComponent({ setReps: setRepsMock });
|
||||
const { getByText } = renderComponent({ reps: 5, setReps: setRepsMock });
|
||||
|
||||
fireEvent.press(getByText('+'));
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ describe('[Component] NumberSelect', () => {
|
|||
|
||||
test('decrements reps when "-" is pressed', () => {
|
||||
const setRepsMock = jest.fn();
|
||||
const { getByText } = renderComponent({ setReps: setRepsMock });
|
||||
const { getByText } = renderComponent({ reps: 5, setReps: setRepsMock });
|
||||
|
||||
fireEvent.press(getByText('-'));
|
||||
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`[Component] Button Disabled state renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Loading state renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Ready state renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
|
@ -0,0 +1,823 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`[Component] Button Color variations renders with different colors 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#3AC26E",
|
||||
"borderColor": "#3AC26E",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="white"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Color variations renders with different colors 2`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FF4141",
|
||||
"borderColor": "#FF4141",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="white"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Color variations renders with different colors 3`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#F9F9F9",
|
||||
"borderColor": "#F9F9F9",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Disabled state renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Icon rendering renders icon only without label 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"width": 8,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
widthUnits={2}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": "center",
|
||||
"aspectRatio": 1,
|
||||
"height": 24,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
>
|
||||
<div
|
||||
data-testid="mock-icon"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Icon rendering renders with icon on the left 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": "center",
|
||||
"aspectRatio": 1,
|
||||
"height": 24,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
>
|
||||
<div
|
||||
data-testid="mock-icon"
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"width": 8,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
widthUnits={2}
|
||||
/>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Icon rendering renders with icon on the right 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"width": 8,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
widthUnits={2}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": "center",
|
||||
"aspectRatio": 1,
|
||||
"height": 24,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
>
|
||||
<div
|
||||
data-testid="mock-icon"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Loading state renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Ready state renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Secondary button renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 1,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
bgColor="white"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`[Component] Button Secondary button with different colors 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#3AC26E",
|
||||
"borderColor": "#3AC26E",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 1,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
bgColor="green"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#3AC26E",
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Press me
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { saveUserSettings, loadUserSettings } from '../AsyncStorage';
|
||||
|
||||
// Mock de AsyncStorage
|
||||
jest.mock('@react-native-async-storage/async-storage', () => ({
|
||||
setItem: jest.fn(),
|
||||
getItem: jest.fn(),
|
||||
}));
|
||||
|
||||
const mockedSetItem = AsyncStorage.setItem as jest.MockedFunction<typeof AsyncStorage.setItem>;
|
||||
const mockedGetItem = AsyncStorage.getItem as jest.MockedFunction<typeof AsyncStorage.getItem>;
|
||||
|
||||
describe('UserSettings functions', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
|
@ -23,7 +25,7 @@ describe('UserSettings functions', () => {
|
|||
});
|
||||
|
||||
test('should throw an error if AsyncStorage.setItem fails', async () => {
|
||||
AsyncStorage.setItem.mockRejectedValueOnce(new Error('AsyncStorage error'));
|
||||
mockedSetItem.mockRejectedValueOnce(new Error('AsyncStorage error'));
|
||||
|
||||
await expect(saveUserSettings('theme', 'dark')).rejects.toThrow(
|
||||
'Failed to load the data from AsyncStorage'
|
||||
|
|
@ -36,7 +38,7 @@ describe('UserSettings functions', () => {
|
|||
const key = 'theme';
|
||||
const value = 'dark';
|
||||
|
||||
AsyncStorage.getItem.mockResolvedValueOnce(value);
|
||||
mockedGetItem.mockResolvedValueOnce(value);
|
||||
|
||||
const result = await loadUserSettings(key);
|
||||
|
||||
|
|
@ -46,7 +48,7 @@ describe('UserSettings functions', () => {
|
|||
});
|
||||
|
||||
test('should return null if the value does not exist in AsyncStorage', async () => {
|
||||
AsyncStorage.getItem.mockResolvedValueOnce(null);
|
||||
mockedGetItem.mockResolvedValueOnce(null);
|
||||
|
||||
const result = await loadUserSettings('nonexistent_key');
|
||||
|
||||
|
|
@ -54,7 +56,7 @@ describe('UserSettings functions', () => {
|
|||
});
|
||||
|
||||
test('should throw an error if AsyncStorage.getItem fails', async () => {
|
||||
AsyncStorage.getItem.mockRejectedValueOnce(new Error('AsyncStorage error'));
|
||||
mockedGetItem.mockRejectedValueOnce(new Error('AsyncStorage error'));
|
||||
|
||||
await expect(loadUserSettings('theme')).rejects.toThrow(
|
||||
'Failed to load the data from AsyncStorage'
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
import { renderHook, act } from '@testing-library/react-native';
|
||||
import { Audio } from 'expo-av';
|
||||
import { useAudio } from '../useAudio';
|
||||
|
||||
// Mock expo-av modules
|
||||
jest.mock('expo-av', () => ({
|
||||
Audio: {
|
||||
Sound: {
|
||||
createAsync: jest.fn().mockResolvedValue({ sound: { playAsync: jest.fn(), unloadAsync: jest.fn() } }),
|
||||
},
|
||||
setAudioModeAsync: jest.fn().mockResolvedValue({}),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('useAudio hook', () => {
|
||||
// Reset mocks after each test
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should configure audio when soundEnabled is true', async () => {
|
||||
renderHook(() => useAudio('test-sound.mp3', true));
|
||||
|
||||
// Check that setAudioModeAsync was called with the right parameters
|
||||
expect(Audio.setAudioModeAsync).toHaveBeenCalledWith({
|
||||
allowsRecordingIOS: false,
|
||||
staysActiveInBackground: true,
|
||||
playsInSilentModeIOS: true,
|
||||
shouldDuckAndroid: true,
|
||||
playThroughEarpieceAndroid: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not configure audio when soundEnabled is false', async () => {
|
||||
renderHook(() => useAudio('test-sound.mp3', false));
|
||||
|
||||
// Check that setAudioModeAsync was not called
|
||||
expect(Audio.setAudioModeAsync).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should play sound when playSound is called and soundEnabled is true', async () => {
|
||||
const { result } = renderHook(() => useAudio('test-sound.mp3', true));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.playSound();
|
||||
});
|
||||
|
||||
// Check that createAsync was called with the correct sound file
|
||||
expect(Audio.Sound.createAsync).toHaveBeenCalledWith('test-sound.mp3');
|
||||
});
|
||||
|
||||
it('should not play sound when playSound is called and soundEnabled is false', async () => {
|
||||
const { result } = renderHook(() => useAudio('test-sound.mp3', false));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.playSound();
|
||||
});
|
||||
|
||||
// Check that createAsync was not called
|
||||
expect(Audio.Sound.createAsync).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unload sound when component is unmounted', async () => {
|
||||
const mockUnloadAsync = jest.fn();
|
||||
(Audio.Sound.createAsync as jest.Mock).mockResolvedValueOnce({
|
||||
sound: {
|
||||
playAsync: jest.fn(),
|
||||
unloadAsync: mockUnloadAsync
|
||||
}
|
||||
});
|
||||
|
||||
const { result, unmount } = renderHook(() => useAudio('test-sound.mp3', true));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.playSound();
|
||||
});
|
||||
|
||||
unmount();
|
||||
|
||||
// Check that unloadAsync was called
|
||||
expect(mockUnloadAsync).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
import { renderHook, act } from '@testing-library/react-native';
|
||||
import { PermissionsAndroid, Platform } from 'react-native';
|
||||
import PushNotification from 'react-native-push-notification';
|
||||
import { useNotification } from '../useNotifications';
|
||||
|
||||
// Mock des modules natifs
|
||||
jest.mock('react-native', () => ({
|
||||
Platform: {
|
||||
OS: 'android',
|
||||
Version: 33,
|
||||
},
|
||||
PermissionsAndroid: {
|
||||
request: jest.fn().mockResolvedValue('granted'),
|
||||
PERMISSIONS: {
|
||||
POST_NOTIFICATIONS: 'android.permission.POST_NOTIFICATIONS',
|
||||
},
|
||||
RESULTS: {
|
||||
GRANTED: 'granted',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock de react-native-push-notification
|
||||
jest.mock('react-native-push-notification', () => {
|
||||
return {
|
||||
configure: jest.fn(),
|
||||
createChannel: jest.fn((channel, callback) => callback(true)),
|
||||
localNotification: jest.fn(),
|
||||
cancelLocalNotification: jest.fn(),
|
||||
Importance: {
|
||||
HIGH: 4,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// Typage des mocks pour TypeScript
|
||||
const mockPushNotification = PushNotification as jest.Mocked<typeof PushNotification> & {
|
||||
Importance: { HIGH: number };
|
||||
};
|
||||
|
||||
// Mock de console.log pour éviter de polluer les logs de test
|
||||
console.log = jest.fn();
|
||||
|
||||
describe('useNotification hook', () => {
|
||||
const notificationId = '123';
|
||||
const channelInformations = {
|
||||
channelId: 'testChannel',
|
||||
channelName: 'Test Channel',
|
||||
channelDescription: 'Channel for testing',
|
||||
};
|
||||
|
||||
// Réinitialiser les mocks après chaque test
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('devrait demander les permissions de notification au montage sur Android >= 33', async () => {
|
||||
renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
// Vérifier que la demande de permission a été appelée
|
||||
expect(PermissionsAndroid.request).toHaveBeenCalledWith(
|
||||
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
|
||||
);
|
||||
});
|
||||
|
||||
it('ne devrait pas demander les permissions sur iOS', async () => {
|
||||
Platform.OS = 'ios';
|
||||
|
||||
renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
expect(PermissionsAndroid.request).not.toHaveBeenCalled();
|
||||
|
||||
// Réinitialiser pour les tests suivants
|
||||
Platform.OS = 'android';
|
||||
});
|
||||
|
||||
it('devrait configurer PushNotification au montage', () => {
|
||||
renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
expect(mockPushNotification.configure).toHaveBeenCalled();
|
||||
const configCall = (mockPushNotification.configure as jest.Mock).mock.calls[0][0];
|
||||
|
||||
// Vérifier que les fonctions de callback sont définies
|
||||
expect(typeof configCall.onRegister).toBe('function');
|
||||
expect(typeof configCall.onNotification).toBe('function');
|
||||
|
||||
// Vérifier les permissions
|
||||
expect(configCall.permissions).toEqual({
|
||||
alert: true,
|
||||
badge: true,
|
||||
sound: true,
|
||||
});
|
||||
|
||||
// Vérifier les autres paramètres
|
||||
expect(configCall.popInitialNotification).toBe(true);
|
||||
expect(configCall.requestPermissions).toBe(Platform.OS === 'ios');
|
||||
});
|
||||
|
||||
it('devrait créer un canal de notification sur Android', () => {
|
||||
renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
expect(mockPushNotification.createChannel).toHaveBeenCalledWith(
|
||||
{
|
||||
...channelInformations,
|
||||
vibrate: true,
|
||||
importance: mockPushNotification.Importance.HIGH,
|
||||
},
|
||||
expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('ne devrait pas créer de canal sur iOS', () => {
|
||||
Platform.OS = 'ios';
|
||||
|
||||
renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
expect(mockPushNotification.createChannel).not.toHaveBeenCalled();
|
||||
|
||||
// Réinitialiser pour les tests suivants
|
||||
Platform.OS = 'android';
|
||||
});
|
||||
|
||||
it('devrait retourner les fonctions updateNotification et cancelNotification', () => {
|
||||
const { result } = renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
expect(result.current).toHaveProperty('updateNotification');
|
||||
expect(result.current).toHaveProperty('cancelNotification');
|
||||
expect(typeof result.current.updateNotification).toBe('function');
|
||||
expect(typeof result.current.cancelNotification).toBe('function');
|
||||
});
|
||||
|
||||
it('updateNotification devrait appeler localNotification avec les bons paramètres', () => {
|
||||
const { result } = renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
act(() => {
|
||||
result.current.updateNotification('Test Title', 'Test Message');
|
||||
});
|
||||
|
||||
expect(mockPushNotification.localNotification).toHaveBeenCalledWith({
|
||||
channelId: channelInformations.channelId,
|
||||
id: parseInt(notificationId),
|
||||
title: 'Test Title',
|
||||
message: 'Test Message',
|
||||
playSound: false,
|
||||
vibrate: false,
|
||||
ongoing: true,
|
||||
priority: 'high',
|
||||
importance: 'high',
|
||||
onlyAlertOnce: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('cancelNotification devrait appeler cancelLocalNotification avec le bon ID', () => {
|
||||
const { result } = renderHook(() => useNotification(notificationId, channelInformations));
|
||||
|
||||
act(() => {
|
||||
result.current.cancelNotification();
|
||||
});
|
||||
|
||||
expect(mockPushNotification.cancelLocalNotification).toHaveBeenCalledWith(notificationId);
|
||||
});
|
||||
});
|
||||
|
|
@ -16,7 +16,7 @@ interface TimerContentProps {
|
|||
currentRep: number;
|
||||
isRunning: boolean;
|
||||
handleStop: () => void;
|
||||
handleContine: () => void;
|
||||
handleContinue: () => void;
|
||||
nextRep: () => void;
|
||||
previousRep: () => void;
|
||||
bgColor: TimerBgColor;
|
||||
|
|
@ -33,7 +33,7 @@ export default function TimerContent({
|
|||
currentRep,
|
||||
isRunning,
|
||||
handleStop,
|
||||
handleContine,
|
||||
handleContinue,
|
||||
handleReset,
|
||||
nextRep,
|
||||
previousRep,
|
||||
|
|
@ -86,7 +86,7 @@ export default function TimerContent({
|
|||
{isRunning ? (
|
||||
<Button label={t('stop')} onPress={handleStop} />
|
||||
) : (
|
||||
<Button label={t('start')} onPress={handleContine} />
|
||||
<Button label={t('start')} onPress={handleContinue} />
|
||||
)}
|
||||
|
||||
<ElasticSpacer />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react-native';
|
||||
|
||||
import { render } from '@/components/testUtils';
|
||||
import FinishContent from '../FinishContent';
|
||||
|
||||
// Mock for navigation
|
||||
const mockGoBack = jest.fn();
|
||||
jest.mock('@react-navigation/native', () => ({
|
||||
...jest.requireActual('@react-navigation/native'),
|
||||
useNavigation: () => ({
|
||||
goBack: mockGoBack,
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock for i18n
|
||||
jest.mock('@/app/i18n/i18n', () => ({
|
||||
i18n: {
|
||||
scoped: jest.fn().mockReturnValue((key: string) => {
|
||||
const translations: Record<string, string> = {
|
||||
finish: 'Finished',
|
||||
restart: 'Restart'
|
||||
};
|
||||
return translations[key] || key;
|
||||
}),
|
||||
t: jest.fn((key: string) => {
|
||||
if (key === 'back') return 'Back';
|
||||
return key;
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('[Component] FinishContent', () => {
|
||||
const defaultProps = {
|
||||
handleStart: jest.fn(),
|
||||
handleReset: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('matches snapshot', () => {
|
||||
const tree = render(
|
||||
<FinishContent {...defaultProps} />
|
||||
).toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('displays content correctly', () => {
|
||||
const { getByText } = render(
|
||||
<FinishContent {...defaultProps} />
|
||||
);
|
||||
|
||||
// Check that "Finished" text is displayed (translated from "finish")
|
||||
expect(getByText('Finished')).toBeTruthy();
|
||||
|
||||
// Check that buttons are displayed
|
||||
expect(getByText('Restart')).toBeTruthy();
|
||||
expect(getByText('Back')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('calls handleStart when restart button is clicked', () => {
|
||||
const { getByText } = render(
|
||||
<FinishContent {...defaultProps} />
|
||||
);
|
||||
|
||||
// Click the restart button
|
||||
fireEvent.press(getByText('Restart'));
|
||||
|
||||
// Check that handleStart was called
|
||||
expect(defaultProps.handleStart).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('calls goBack and handleReset when back button is clicked', () => {
|
||||
const { getByText } = render(
|
||||
<FinishContent {...defaultProps} />
|
||||
);
|
||||
|
||||
// Click the back button
|
||||
fireEvent.press(getByText('Back'));
|
||||
|
||||
// Check that navigation.goBack was called
|
||||
expect(mockGoBack).toHaveBeenCalled();
|
||||
|
||||
// Check that handleReset was called
|
||||
expect(defaultProps.handleReset).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react-native';
|
||||
|
||||
import { render } from '@/components/testUtils';
|
||||
import TimerContent from '../TimerContent';
|
||||
import { TimerBgColor } from '@/components/useCases/timer/business/type';
|
||||
|
||||
// Mock for navigation
|
||||
const mockGoBack = jest.fn();
|
||||
jest.mock('@react-navigation/native', () => ({
|
||||
...jest.requireActual('@react-navigation/native'),
|
||||
useNavigation: () => ({
|
||||
goBack: mockGoBack,
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock for i18n
|
||||
jest.mock('@/app/i18n/i18n', () => ({
|
||||
i18n: {
|
||||
scoped: jest.fn().mockReturnValue((key: string) => {
|
||||
const translations: Record<string, string> = {
|
||||
preparation: 'Préparation',
|
||||
fight: 'Combat',
|
||||
rest: 'Repos',
|
||||
prev: 'Précédent',
|
||||
next: 'Suivant',
|
||||
stop: 'Arrêter',
|
||||
start: 'Démarrer',
|
||||
preparationDescription: 'Préparez-vous !'
|
||||
};
|
||||
return translations[key] || key;
|
||||
}),
|
||||
t: jest.fn((key: string) => {
|
||||
if (key === 'back') return 'Retour';
|
||||
return key;
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock for formatTime
|
||||
jest.mock('@/components/shared/business/timeHelpers', () => ({
|
||||
formatTime: jest.fn((time: number) => {
|
||||
if (time === 60000) return '01:00';
|
||||
return '00:00';
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('[Component] TimerContent', () => {
|
||||
const defaultProps = {
|
||||
isWorkPhase: true,
|
||||
timeLeft: 60000,
|
||||
reps: 5,
|
||||
currentRep: 2,
|
||||
isRunning: false,
|
||||
handleStop: jest.fn(),
|
||||
handleContinue: jest.fn(),
|
||||
nextRep: jest.fn(),
|
||||
previousRep: jest.fn(),
|
||||
bgColor: 'green' as TimerBgColor,
|
||||
handleReset: jest.fn()
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('matches snapshot', () => {
|
||||
const tree = render(
|
||||
<TimerContent {...defaultProps} />
|
||||
).toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('displays work phase content correctly', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} />
|
||||
);
|
||||
|
||||
expect(getByText('Combat')).toBeTruthy();
|
||||
expect(getByText('01:00')).toBeTruthy();
|
||||
expect(getByText('2 / 5')).toBeTruthy();
|
||||
expect(getByText('Précédent')).toBeTruthy();
|
||||
expect(getByText('Démarrer')).toBeTruthy();
|
||||
expect(getByText('Suivant')).toBeTruthy();
|
||||
expect(getByText('Retour')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('displays rest phase content correctly', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} isWorkPhase={false} />
|
||||
);
|
||||
|
||||
expect(getByText('Repos')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('displays preparation phase content correctly', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} isWorkPhase={true} isPreparationPhase={true} />
|
||||
);
|
||||
|
||||
expect(getByText('Préparation')).toBeTruthy();
|
||||
expect(getByText('Préparez-vous !')).toBeTruthy();
|
||||
// Previous button should be disabled in preparation phase
|
||||
expect(getByText('Précédent')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('shows Stop button when timer is running', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} isRunning={true} />
|
||||
);
|
||||
|
||||
expect(getByText('Arrêter')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('shows Start button when timer is stopped', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} isRunning={false} />
|
||||
);
|
||||
|
||||
expect(getByText('Démarrer')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('calls handleContinue when Start button is clicked', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} />
|
||||
);
|
||||
|
||||
fireEvent.press(getByText('Démarrer'));
|
||||
|
||||
expect(defaultProps.handleContinue).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('calls handleStop when Stop button is clicked', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} isRunning={true} />
|
||||
);
|
||||
|
||||
fireEvent.press(getByText('Arrêter'));
|
||||
|
||||
expect(defaultProps.handleStop).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('calls previousRep when Previous button is clicked', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} />
|
||||
);
|
||||
|
||||
fireEvent.press(getByText('Précédent'));
|
||||
|
||||
expect(defaultProps.previousRep).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('Previous button is disabled in preparation phase', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} isPreparationPhase={true} />
|
||||
);
|
||||
|
||||
fireEvent.press(getByText('Précédent'));
|
||||
|
||||
expect(defaultProps.previousRep).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('calls nextRep when Next button is clicked', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} />
|
||||
);
|
||||
|
||||
fireEvent.press(getByText('Suivant'));
|
||||
|
||||
expect(defaultProps.nextRep).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('calls goBack and handleReset when Back button is clicked', () => {
|
||||
const { getByText } = render(
|
||||
<TimerContent {...defaultProps} />
|
||||
);
|
||||
|
||||
fireEvent.press(getByText('Retour'));
|
||||
|
||||
expect(mockGoBack).toHaveBeenCalled();
|
||||
expect(defaultProps.handleReset).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`[Component] FinishContent matches snapshot 1`] = `
|
||||
[
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
"fontSize": 70,
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Finished
|
||||
</Text>,
|
||||
<View
|
||||
heightUnits={8}
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"height": 32,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>,
|
||||
<View
|
||||
style={
|
||||
[
|
||||
{
|
||||
"backgroundColor": "#FFFFFF",
|
||||
},
|
||||
[
|
||||
{
|
||||
"backgroundColor": "black",
|
||||
"flexDirection": "row",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Restart
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"width": 12,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
widthUnits={3}
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Back
|
||||
</Text>
|
||||
</View>
|
||||
</View>,
|
||||
]
|
||||
`;
|
||||
|
|
@ -0,0 +1,412 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`[Component] TimerContent matches snapshot 1`] = `
|
||||
[
|
||||
<Text
|
||||
isPreparationPhase={false}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
"fontSize": 50,
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Combat
|
||||
</Text>,
|
||||
<View
|
||||
heightUnits={8}
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"height": 32,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>,
|
||||
<Text
|
||||
isPreparationPhase={false}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
"fontSize": 100,
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
01:00
|
||||
</Text>,
|
||||
<View
|
||||
heightUnits={8}
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"height": 32,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>,
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
"fontSize": 30,
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
2
|
||||
/
|
||||
5
|
||||
</Text>,
|
||||
<View
|
||||
heightUnits={8}
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"height": 32,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>,
|
||||
<View
|
||||
bgColor="green"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"backgroundColor": "#FFFFFF",
|
||||
},
|
||||
[
|
||||
{
|
||||
"backgroundColor": "#3AC26E",
|
||||
"flexDirection": "row",
|
||||
"justifyContent": "space-between",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Précédent
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"flexGrow": 1,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Démarrer
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"flexGrow": 1,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Suivant
|
||||
</Text>
|
||||
</View>
|
||||
</View>,
|
||||
<View
|
||||
heightUnits={4}
|
||||
pointerEvents="none"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"height": 16,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>,
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"alignItems": "center",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"borderColor": "#FFFFFF",
|
||||
"borderRadius": 6,
|
||||
"borderWidth": 0,
|
||||
"flexDirection": "row",
|
||||
"height": 48,
|
||||
"justifyContent": "center",
|
||||
"opacity": 1,
|
||||
"paddingHorizontal": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
color="black"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
},
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "semibold",
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
]
|
||||
}
|
||||
>
|
||||
Retour
|
||||
</Text>
|
||||
</View>,
|
||||
]
|
||||
`;
|
||||
Loading…
Reference in New Issue