Skip to content

Commit

Permalink
Merge pull request #687 from bounswe/MOBILE-682
Browse files Browse the repository at this point in the history
feat(mobile): add unit tests for quiz review page
  • Loading branch information
YavizGuldalf authored Nov 25, 2024
2 parents a655253 + b2ba23f commit 3f1ad04
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 0 deletions.
166 changes: 166 additions & 0 deletions mobile/bulingo/__tests__/quizReview.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React from 'react';
import { render, waitFor, fireEvent, act } from '@testing-library/react-native';
import QuizReviewQuestion from '@/app/(tabs)/quizzes/quizReview';
import TokenManager from '@/app/TokenManager';

jest.useFakeTimers();

jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');

jest.mock('expo-router', () => ({
useLocalSearchParams: jest.fn(() => ({ quizId: '1' })),
router: { back: jest.fn(), push: jest.fn() },
}));

jest.mock('@/app/TokenManager', () => ({
__esModule: true,
default: {
authenticatedFetch: jest.fn(),
},
}));

describe('QuizReviewQuestion Component', () => {
const mockQuizData = {
quiz_progress_id: 1,
quiz_title: 'Sample Quiz',
question_count: 3,
questions: [
{
question_number: 1,
question: 'Mercimek',
choices: ['Lentils', 'Tomato', 'Potato', 'Peas'],
correct_choice: 1,
previous_answer: 3,
},
{
question_number: 2,
question: 'Elma',
choices: ['Apple', 'Orange', 'Banana', 'Grape'],
correct_choice: 1,
previous_answer: 2,
},
{
question_number: 3,
question: 'Kedi',
choices: ['Cat', 'Dog', 'Bird', 'Fish'],
correct_choice: 1,
previous_answer: 4,
},
],
};

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

it('renders quiz questions after data is loaded', async () => {
(TokenManager.authenticatedFetch as jest.Mock).mockResolvedValueOnce({
ok: true,
json: jest.fn().mockResolvedValue(mockQuizData),
});

const { getByText } = render(<QuizReviewQuestion />);

await waitFor(() => {
expect(getByText('Mercimek')).toBeTruthy();
expect(getByText('Lentils')).toBeTruthy();
expect(getByText('Tomato')).toBeTruthy();
expect(getByText('Potato')).toBeTruthy();
expect(getByText('Peas')).toBeTruthy();
});
});

it('handles API error gracefully', async () => {
(TokenManager.authenticatedFetch as jest.Mock).mockResolvedValueOnce({
ok: false,
json: jest.fn().mockResolvedValue({ error: 'Failed to fetch quiz review.' }),
});

const { getByText } = render(<QuizReviewQuestion />);

await waitFor(() => {
expect(getByText('Error: Failed to fetch quiz review.')).toBeTruthy();
});
});

it('navigates to the next question', async () => {
(TokenManager.authenticatedFetch as jest.Mock).mockResolvedValueOnce({
ok: true,
json: jest.fn().mockResolvedValue(mockQuizData),
});

const { getByText } = render(<QuizReviewQuestion />);

await act(async () => {
await waitFor(() => {
expect(getByText('Mercimek')).toBeTruthy();
});

fireEvent.press(getByText('Next'));
jest.advanceTimersByTime(1000);
});

await waitFor(() => {
expect(getByText('Elma')).toBeTruthy();
});
});

it('handles the "Previous" button correctly', async () => {
(TokenManager.authenticatedFetch as jest.Mock).mockResolvedValueOnce({
ok: true,
json: jest.fn().mockResolvedValue(mockQuizData),
});

const { getByText } = render(<QuizReviewQuestion />);

await act(async () => {
await waitFor(() => {
expect(getByText('Mercimek')).toBeTruthy();
});

fireEvent.press(getByText('Next'));
jest.advanceTimersByTime(1000);
});

await waitFor(() => {
expect(getByText('Elma')).toBeTruthy();
});

await act(async () => {
fireEvent.press(getByText('Previous'));
jest.advanceTimersByTime(1000);
});

await waitFor(() => {
expect(getByText('Mercimek')).toBeTruthy();
});
});

it('styles correct and wrong answer buttons correctly', async () => {
(TokenManager.authenticatedFetch as jest.Mock).mockResolvedValueOnce({
ok: true,
json: jest.fn().mockResolvedValue(mockQuizData),
});

const { getAllByTestId } = render(<QuizReviewQuestion />);

await waitFor(() => {
const buttons = getAllByTestId('button');
const correctAnswerButton = buttons.find((button) => {
const textElement = button.findByType('Text');
return textElement.props.children === 'Lentils';
});
expect(correctAnswerButton.props.style).toEqual(
expect.objectContaining({ backgroundColor: 'lightgreen' })
);

const wrongAnswerButton = buttons.find((button) => {
const textElement = button.findByType('Text');
return textElement.props.children === 'Potato';
});
expect(wrongAnswerButton.props.style).toEqual(
expect.objectContaining({ backgroundColor: 'lightcoral' })
);
});
});
});
1 change: 1 addition & 0 deletions mobile/bulingo/app/(tabs)/quizzes/quizReview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ useEffect(() => {
isUserAnswer && !isCorrectAnswer && styles.wrongAnswer,
]}
onPress={() => handleOptionSelect(index)}
testID='button'
>
<Text style={styles.optionText}>{choice}</Text>
</TouchableOpacity>
Expand Down

0 comments on commit 3f1ad04

Please sign in to comment.