Added new test for Topics on FE
Browse files
frontend/src/tests/App.test.tsx
CHANGED
|
@@ -8,11 +8,11 @@ describe('App', () => {
|
|
| 8 |
render(<App />);
|
| 9 |
|
| 10 |
// Check for title
|
| 11 |
-
expect(screen.getByText('
|
| 12 |
|
| 13 |
// Check for input fields
|
| 14 |
expect(screen.getByLabelText('Source Documentation')).toBeInTheDocument();
|
| 15 |
-
expect(screen.getByLabelText('Quiz
|
| 16 |
|
| 17 |
// Check for buttons
|
| 18 |
expect(screen.getByText('Pull Source Docs')).toBeInTheDocument();
|
|
|
|
| 8 |
render(<App />);
|
| 9 |
|
| 10 |
// Check for title
|
| 11 |
+
expect(screen.getByText('Simplifi')).toBeInTheDocument();
|
| 12 |
|
| 13 |
// Check for input fields
|
| 14 |
expect(screen.getByLabelText('Source Documentation')).toBeInTheDocument();
|
| 15 |
+
expect(screen.getByLabelText('Quiz focus?')).toBeInTheDocument();
|
| 16 |
|
| 17 |
// Check for buttons
|
| 18 |
expect(screen.getByText('Pull Source Docs')).toBeInTheDocument();
|
frontend/src/tests/components/QuizGenerator.test.tsx
CHANGED
|
@@ -19,7 +19,7 @@ describe('QuizGenerator', () => {
|
|
| 19 |
test('generates problems when button is clicked', async () => {
|
| 20 |
render(<QuizGenerator onProblemsGenerated={mockOnProblemsGenerated} />);
|
| 21 |
|
| 22 |
-
const input = screen.getByLabelText('Quiz
|
| 23 |
const button = screen.getByText('Generate');
|
| 24 |
|
| 25 |
await act(async () => {
|
|
|
|
| 19 |
test('generates problems when button is clicked', async () => {
|
| 20 |
render(<QuizGenerator onProblemsGenerated={mockOnProblemsGenerated} />);
|
| 21 |
|
| 22 |
+
const input = screen.getByLabelText('Quiz focus?');
|
| 23 |
const button = screen.getByText('Generate');
|
| 24 |
|
| 25 |
await act(async () => {
|
frontend/src/tests/components/Topics.test.tsx
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
|
| 2 |
+
import Topics from '../../components/Topics';
|
| 3 |
+
import { vi } from 'vitest';
|
| 4 |
+
|
| 5 |
+
describe('Topics Component', () => {
|
| 6 |
+
const mockOnTopicChange = vi.fn();
|
| 7 |
+
|
| 8 |
+
beforeEach(() => {
|
| 9 |
+
vi.clearAllMocks();
|
| 10 |
+
// Clear fetch mock before each test
|
| 11 |
+
vi.spyOn(global, 'fetch').mockClear();
|
| 12 |
+
});
|
| 13 |
+
|
| 14 |
+
it('shows loading state initially', () => {
|
| 15 |
+
render(<Topics onTopicChange={mockOnTopicChange} />);
|
| 16 |
+
|
| 17 |
+
expect(screen.getByLabelText('Topic')).toBeDisabled();
|
| 18 |
+
expect(screen.getByText('Loading topics...')).toBeInTheDocument();
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
it('displays topics after successful fetch', async () => {
|
| 22 |
+
const mockTopics = { sources: ['Topic 1', 'Topic 2', 'Topic 3'] };
|
| 23 |
+
vi.spyOn(global, 'fetch').mockImplementationOnce(() =>
|
| 24 |
+
Promise.resolve({
|
| 25 |
+
ok: true,
|
| 26 |
+
json: () => Promise.resolve(mockTopics),
|
| 27 |
+
} as Response)
|
| 28 |
+
);
|
| 29 |
+
|
| 30 |
+
render(<Topics onTopicChange={mockOnTopicChange} />);
|
| 31 |
+
|
| 32 |
+
// Wait for loading to finish
|
| 33 |
+
await waitFor(() => {
|
| 34 |
+
expect(screen.queryByText('Loading topics...')).not.toBeInTheDocument();
|
| 35 |
+
});
|
| 36 |
+
|
| 37 |
+
// Open the dropdown
|
| 38 |
+
fireEvent.mouseDown(screen.getByLabelText('Topic'));
|
| 39 |
+
|
| 40 |
+
// Check if all topics are rendered
|
| 41 |
+
mockTopics.sources.forEach(topic => {
|
| 42 |
+
expect(screen.getByText(topic)).toBeInTheDocument();
|
| 43 |
+
});
|
| 44 |
+
});
|
| 45 |
+
|
| 46 |
+
it('handles API error correctly', async () => {
|
| 47 |
+
vi.spyOn(global, 'fetch').mockImplementationOnce(() =>
|
| 48 |
+
Promise.resolve({
|
| 49 |
+
ok: false,
|
| 50 |
+
status: 500,
|
| 51 |
+
} as Response)
|
| 52 |
+
);
|
| 53 |
+
|
| 54 |
+
render(<Topics onTopicChange={mockOnTopicChange} />);
|
| 55 |
+
|
| 56 |
+
await waitFor(() => {
|
| 57 |
+
expect(screen.queryByText('Loading topics...')).not.toBeInTheDocument();
|
| 58 |
+
});
|
| 59 |
+
|
| 60 |
+
const select = screen.getByLabelText('Topic');
|
| 61 |
+
expect(select).toHaveAttribute('aria-invalid', 'true');
|
| 62 |
+
});
|
| 63 |
+
|
| 64 |
+
it('calls onTopicChange when topic is selected', async () => {
|
| 65 |
+
const mockTopics = { sources: ['Topic 1', 'Topic 2'] };
|
| 66 |
+
vi.spyOn(global, 'fetch').mockImplementationOnce(() =>
|
| 67 |
+
Promise.resolve({
|
| 68 |
+
ok: true,
|
| 69 |
+
json: () => Promise.resolve(mockTopics),
|
| 70 |
+
} as Response)
|
| 71 |
+
);
|
| 72 |
+
|
| 73 |
+
render(<Topics onTopicChange={mockOnTopicChange} />);
|
| 74 |
+
|
| 75 |
+
// Wait for loading to finish
|
| 76 |
+
await waitFor(() => {
|
| 77 |
+
expect(screen.queryByText('Loading topics...')).not.toBeInTheDocument();
|
| 78 |
+
});
|
| 79 |
+
|
| 80 |
+
// Open the dropdown
|
| 81 |
+
fireEvent.mouseDown(screen.getByLabelText('Topic'));
|
| 82 |
+
|
| 83 |
+
// Select a topic
|
| 84 |
+
fireEvent.click(screen.getByText('Topic 1'));
|
| 85 |
+
|
| 86 |
+
expect(mockOnTopicChange).toHaveBeenCalledWith('Topic 1');
|
| 87 |
+
});
|
| 88 |
+
|
| 89 |
+
it('handles malformed API response correctly', async () => {
|
| 90 |
+
const malformedResponse = { wrongKey: [] };
|
| 91 |
+
vi.spyOn(global, 'fetch').mockImplementationOnce(() =>
|
| 92 |
+
Promise.resolve({
|
| 93 |
+
ok: true,
|
| 94 |
+
json: () => Promise.resolve(malformedResponse),
|
| 95 |
+
} as Response)
|
| 96 |
+
);
|
| 97 |
+
|
| 98 |
+
render(<Topics onTopicChange={mockOnTopicChange} />);
|
| 99 |
+
|
| 100 |
+
await waitFor(() => {
|
| 101 |
+
expect(screen.queryByText('Loading topics...')).not.toBeInTheDocument();
|
| 102 |
+
});
|
| 103 |
+
|
| 104 |
+
const select = screen.getByLabelText('Topic');
|
| 105 |
+
expect(select).toHaveAttribute('aria-invalid', 'true');
|
| 106 |
+
});
|
| 107 |
+
|
| 108 |
+
it('handles network errors correctly', async () => {
|
| 109 |
+
vi.spyOn(global, 'fetch').mockImplementationOnce(() =>
|
| 110 |
+
Promise.reject(new Error('Network error'))
|
| 111 |
+
);
|
| 112 |
+
|
| 113 |
+
render(<Topics onTopicChange={mockOnTopicChange} />);
|
| 114 |
+
|
| 115 |
+
await waitFor(() => {
|
| 116 |
+
expect(screen.queryByText('Loading topics...')).not.toBeInTheDocument();
|
| 117 |
+
});
|
| 118 |
+
|
| 119 |
+
const select = screen.getByLabelText('Topic');
|
| 120 |
+
expect(select).toHaveAttribute('aria-invalid', 'true');
|
| 121 |
+
});
|
| 122 |
+
});
|