Skip to content

Commit 696bb7f

Browse files
feat: tests added to problem editor
1 parent 7ad1f7e commit 696bb7f

3 files changed

Lines changed: 83 additions & 1 deletion

File tree

src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { render, screen, initializeMocks } from '@src/testUtils';
33
import { selectors } from '@src/editors/data/redux';
44
import AnswerOption from './AnswerOption';
55
import * as hooks from './hooks';
6+
import * as reactQueryHooks from '../../../data/apiHooks';
67

78
const { problem } = selectors;
89

@@ -101,4 +102,16 @@ describe('AnswerOption', () => {
101102
expect(screen.getByText(answerRange.title)).toBeInTheDocument();
102103
expect(screen.getByRole('textbox')).toBeInTheDocument();
103104
});
105+
106+
test('shows numeric error feedback when data.isValid is false', () => {
107+
// Mock useValidateInputBlock to simulate invalid state
108+
// @ts-ignore-next-line
109+
jest.spyOn(reactQueryHooks, 'useValidateInputBlock').mockReturnValue({ data: { isValid: false } });
110+
jest.spyOn(problem, 'problemType').mockReturnValue('numericalresponse');
111+
const myProps = { ...props, answer: { ...answerWithOnlyFeedback, isAnswerRange: false } };
112+
render(<AnswerOption {...myProps} />);
113+
expect(
114+
screen.getByText('Error: This input type only supports numeric answers. Did you mean to make a Text input or Math expression input problem?'),
115+
).toBeInTheDocument();
116+
});
104117
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { renderHook, waitFor } from '@testing-library/react';
2+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3+
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
4+
import api from '@src/editors/data/services/cms/api';
5+
import { useValidateInputBlock } from './apiHooks';
6+
7+
// Mock external dependencies
8+
jest.mock('@edx/frontend-platform');
9+
jest.mock('@src/editors/data/services/cms/api', () => ({
10+
validateBlockNumericInput: jest.fn(),
11+
}));
12+
13+
const mockedCamelCaseObject = jest.mocked(camelCaseObject);
14+
const mockedGetConfig = jest.mocked(getConfig);
15+
const mockedValidateBlockNumericInput = jest.mocked(api.validateBlockNumericInput);
16+
17+
// Test wrapper component
18+
const createWrapper = () => {
19+
const queryClient = new QueryClient({
20+
defaultOptions: {
21+
queries: { retry: false },
22+
mutations: { retry: false },
23+
},
24+
});
25+
26+
const wrapper = ({ children }) => (
27+
<QueryClientProvider client={queryClient}>
28+
{children}
29+
</QueryClientProvider>
30+
);
31+
return wrapper;
32+
};
33+
34+
describe('useValidateInputBlock', () => {
35+
beforeEach(() => {
36+
jest.clearAllMocks();
37+
mockedGetConfig.mockReturnValue({
38+
STUDIO_BASE_URL: 'http://studio.local.openedx.io:8001',
39+
});
40+
});
41+
42+
test('should return camelCase data on successful API call', async () => {
43+
const mockResponse = {
44+
data: { is_valid: true, result: 'success' },
45+
} as any;
46+
const mockCamelCaseResult = { isValid: true, result: 'success' };
47+
48+
mockedValidateBlockNumericInput.mockResolvedValue(Promise.resolve(mockResponse));
49+
mockedCamelCaseObject.mockReturnValue(mockCamelCaseResult);
50+
51+
const { result } = renderHook(() => useValidateInputBlock(), {
52+
wrapper: createWrapper(),
53+
});
54+
55+
const testFormula = 'x + 1';
56+
result.current.mutate(testFormula);
57+
58+
await waitFor(() => {
59+
expect(result.current.isSuccess).toBe(true);
60+
});
61+
62+
expect(mockedValidateBlockNumericInput).toHaveBeenCalledWith({
63+
studioEndpointUrl: 'http://studio.local.openedx.io:8001',
64+
data: { formula: testFormula },
65+
});
66+
expect(mockedCamelCaseObject).toHaveBeenCalledWith(mockResponse.data);
67+
expect(result.current.data).toEqual({ isValid: true, result: 'success' });
68+
});
69+
});

src/editors/containers/ProblemEditor/data/apiHooks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import api from '@src/editors/data/services/cms/api';
55
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
66

77
export const useValidateInputBlock = () => useMutation({
8-
mutationFn: async (title) => {
8+
mutationFn: async (title : string) => {
99
try {
1010
const res = await api.validateBlockNumericInput({ studioEndpointUrl: `${getApiBaseUrl()}`, data: { formula: title } });
1111
return camelCaseObject(res.data);

0 commit comments

Comments
 (0)