Skip to content

Commit 3bdb178

Browse files
feat: fix tests
1 parent 18a5074 commit 3bdb178

9 files changed

Lines changed: 119 additions & 101 deletions

File tree

app.d.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,3 @@ declare module '*.svg' {
88
const content: string;
99
export default content;
1010
}
11-
12-
declare module '*.scss' {
13-
const content: Record<string, string>;
14-
export default content;
15-
}

jest.config.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,5 @@ module.exports = createConfig('test', {
1414
'^@src/(.*)$': '<rootDir>/src/$1',
1515
'\\.svg$': '<rootDir>/src/__mocks__/svg.js',
1616
'\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/__mocks__/file.js',
17-
'^codemirror$': '<rootDir>/src/__mocks__/codemirror.js',
18-
'^@codemirror/state$': '<rootDir>/src/__mocks__/codemirror.js',
1917
},
2018
});

src/__mocks__/codemirror.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/certificates/components/DisableCertificatesModal.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ describe('DisableCertificatesModal', () => {
6464

6565
const buttons = screen.getAllByRole('button');
6666
const closeButton = buttons.find(btn => btn.textContent === messages.close.defaultMessage);
67+
if (!closeButton) throw new Error('Close button not found');
6768
await user.click(closeButton);
6869

6970
expect(mockOnClose).toHaveBeenCalledTimes(1);

src/components/CodeEditor.test.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/components/CodeEditor.tsx

Lines changed: 0 additions & 40 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { screen } from '@testing-library/react';
2+
import userEvent from '@testing-library/user-event';
3+
import { useCourseInfo } from '@src/data/apiHook';
4+
import GradingActionRow from '@src/grading/components/GradingActionRow';
5+
import { useGradingConfiguration } from '@src/grading/data/apiHook';
6+
import messages from '@src/grading/messages';
7+
import { renderWithIntl } from '@src/testUtils';
8+
9+
jest.mock('react-router-dom', () => ({
10+
...jest.requireActual('react-router-dom'),
11+
useParams: () => ({
12+
courseId: 'course-v1:edX+DemoX+Demo_Course',
13+
}),
14+
}));
15+
16+
jest.mock('@src/data/apiHook', () => ({
17+
useCourseInfo: jest.fn(),
18+
}));
19+
20+
jest.mock('@src/grading/data/apiHook', () => ({
21+
useGradingConfiguration: jest.fn(),
22+
}));
23+
24+
describe('GradingActionRow', () => {
25+
beforeEach(() => {
26+
jest.clearAllMocks();
27+
(useCourseInfo as jest.Mock).mockReturnValue({ data: { gradebookUrl: 'https://example.com/gradebook', studioGradingUrl: 'https://example.com/studio' } });
28+
// TODO: Update this mock to use similar structure when API is ready, currently just returning random text to ensure component renders without error
29+
(useGradingConfiguration as jest.Mock).mockReturnValue({ data: 'Some random text' });
30+
});
31+
32+
it('renders ActionRow with gradebook and configuration buttons', () => {
33+
renderWithIntl(<GradingActionRow />);
34+
expect(screen.getByRole('link', { name: messages.viewGradebook.defaultMessage })).toBeInTheDocument();
35+
expect(screen.getByRole('button', { name: messages.configurationAlt.defaultMessage })).toBeInTheDocument();
36+
});
37+
38+
it('opens configuration menu when configuration button is clicked', async () => {
39+
renderWithIntl(<GradingActionRow />);
40+
const user = userEvent.setup();
41+
await user.click(screen.getByRole('button', { name: messages.configurationAlt.defaultMessage }));
42+
expect(screen.getByText('View Grading Configuration')).toBeInTheDocument();
43+
expect(screen.getByText('View Course Grading Settings')).toBeInTheDocument();
44+
});
45+
46+
it('opens and closes GradingConfigurationModal when menu item is clicked', async () => {
47+
renderWithIntl(<GradingActionRow />);
48+
const user = userEvent.setup();
49+
await user.click(screen.getByRole('button', { name: messages.configurationAlt.defaultMessage }));
50+
const gradingConfigButton = screen.getByText('View Grading Configuration');
51+
await user.click(gradingConfigButton);
52+
expect(screen.getByRole('dialog', { name: messages.gradingConfiguration.defaultMessage })).toBeInTheDocument();
53+
54+
// Close modal
55+
await user.click(screen.getAllByRole('button', { name: messages.close.defaultMessage })[0]);
56+
expect(screen.queryByRole('dialog', { name: messages.gradingConfiguration.defaultMessage })).not.toBeInTheDocument();
57+
});
58+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { screen } from '@testing-library/react';
2+
import { renderWithIntl } from '@src/testUtils';
3+
import { useGradingConfiguration } from '@src/grading/data/apiHook';
4+
import GradingConfigurationModal from '@src/grading/components/GradingConfigurationModal';
5+
import messages from '@src/grading/messages';
6+
7+
jest.mock('react-router-dom', () => ({
8+
...jest.requireActual('react-router-dom'),
9+
useParams: () => ({
10+
courseId: 'course-v1:edX+DemoX+Demo_Course',
11+
}),
12+
}));
13+
14+
jest.mock('../data/apiHook', () => ({
15+
useGradingConfiguration: jest.fn(),
16+
}));
17+
18+
describe('GradingConfigurationModal', () => {
19+
const mockOnClose = jest.fn();
20+
21+
beforeEach(() => {
22+
(useGradingConfiguration as jest.Mock).mockReturnValue({ data: null });
23+
});
24+
25+
afterEach(() => {
26+
jest.clearAllMocks();
27+
});
28+
29+
it('renders modal when isOpen is true', () => {
30+
renderWithIntl(<GradingConfigurationModal isOpen={true} onClose={mockOnClose} />);
31+
expect(screen.getByRole('dialog')).toBeInTheDocument();
32+
});
33+
34+
it('does not render modal when isOpen is false', () => {
35+
renderWithIntl(<GradingConfigurationModal isOpen={false} onClose={mockOnClose} />);
36+
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
37+
});
38+
39+
it('displays grading configuration data when available', () => {
40+
(useGradingConfiguration as jest.Mock).mockReturnValue({ data: 'Test grading configuration' });
41+
renderWithIntl(<GradingConfigurationModal isOpen={true} onClose={mockOnClose} />);
42+
expect(screen.getByText('Test grading configuration')).toBeInTheDocument();
43+
});
44+
45+
it('displays no grading configuration message when data is null', () => {
46+
(useGradingConfiguration as jest.Mock).mockReturnValue({ data: null });
47+
renderWithIntl(<GradingConfigurationModal isOpen={true} onClose={mockOnClose} />);
48+
expect(screen.getByText(messages.noGradingConfiguration.defaultMessage)).toBeInTheDocument();
49+
});
50+
51+
it('calls useGradingConfiguration with courseId from params', () => {
52+
renderWithIntl(<GradingConfigurationModal isOpen={true} onClose={mockOnClose} />);
53+
expect(useGradingConfiguration).toHaveBeenCalledWith('course-v1:edX+DemoX+Demo_Course');
54+
});
55+
});

src/grading/components/GradingConfigurationModal.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Button, ModalDialog } from '@openedx/paragon';
33
import { useIntl } from '@openedx/frontend-base';
44
import messages from '@src/grading/messages';
55
import { useGradingConfiguration } from '@src/grading/data/apiHook';
6-
import CodeEditor from '@src/components/CodeEditor';
76

87
interface GradingConfigurationModalProps {
98
isOpen: boolean,
@@ -16,16 +15,14 @@ const GradingConfigurationModal = ({ isOpen, onClose }: GradingConfigurationModa
1615
const { data = null } = useGradingConfiguration(courseId);
1716

1817
return (
19-
<ModalDialog size="lg" title={intl.formatMessage(messages.gradingConfiguration)} isOpen={isOpen} onClose={onClose} isOverflowVisible={false}>
20-
<ModalDialog.Header className="p-3 pl-4 border-bottom">
21-
<ModalDialog.Title as="h3" className="m-0">
22-
{intl.formatMessage(messages.gradingConfiguration)}
23-
</ModalDialog.Title>
18+
<ModalDialog title={intl.formatMessage(messages.gradingConfiguration)} isOpen={isOpen} onClose={onClose} isOverflowVisible={false}>
19+
<ModalDialog.Header>
20+
<h3>{intl.formatMessage(messages.gradingConfiguration)}</h3>
2421
</ModalDialog.Header>
2522
<ModalDialog.Body>
26-
{data ? <CodeEditor data={data} /> : <p>{intl.formatMessage(messages.noGradingConfiguration)}</p>}
23+
<p>{data ?? intl.formatMessage(messages.noGradingConfiguration)}</p>
2724
</ModalDialog.Body>
28-
<ModalDialog.Footer className="p-4 border-top">
25+
<ModalDialog.Footer>
2926
<Button onClick={onClose}>{intl.formatMessage(messages.close)}</Button>
3027
</ModalDialog.Footer>
3128
</ModalDialog>

0 commit comments

Comments
 (0)