UNPKG

@instructure/quiz-grading

Version:

The Quiz React SDK by Instructure Inc.

169 lines (150 loc) • 5.89 kB
import React from 'react' import {render, screen, waitFor} from '../../../../tests/utils/rtlRenderOverride' import {describe, it, expect, vi} from 'vitest' import {RegradingModal} from '../presenter' import userEvent from '@testing-library/user-event' describe('RegradingModal', () => { const quizId = '1' const scoreReconciliation = 'new_score' const defaultProps = { addSuccess: vi.fn(), addAction: vi.fn(), closeModal: vi.fn(), createQuizEntryRegrade: vi.fn().mockResolvedValue({}), modalOpen: true, quizId, regradingPayload: { quizEntryId: '3', pointsPossible: 1.0, scoringAlgorithm: 'Equivalence', scoringData: {value: true}, }, scoreReconciliation, setScoreReconciliation: vi.fn(), toggleRegradingEditMode: vi.fn(), handleValidationErrorsFromApi: vi.fn(), fromSpeedgrader: true, } describe('for speedgrader based views', () => { describe('cancelAction', () => { it('accepts callback for closing the modal', async () => { const closeModalStub = vi.fn() render(<RegradingModal {...defaultProps} selectExpanded closeModal={closeModalStub} />) const cancelButton = screen.getByRole('button', {name: /cancel/i}) userEvent.click(cancelButton) expect(closeModalStub).toHaveBeenCalledOnce() }) }) describe('onSpeedgraderOptionChange', () => { it('calls `setScoreReconciliation` with provided value', () => { const setScoreReconciliationStub = vi.fn() render( <RegradingModal {...defaultProps} selectExpanded setScoreReconciliation={setScoreReconciliationStub} />, ) const scoreReconciliation = 'old_score' expect(setScoreReconciliationStub).not.toHaveBeenCalled() const oldScoreRadioInput = screen.getByRole('radio', { name: /award points for both current and previous answers/i, }) userEvent.click(oldScoreRadioInput) expect(setScoreReconciliationStub).toHaveBeenCalledExactlyOnceWith(scoreReconciliation) }) }) describe('onSubmit', () => { it('calls `createQuizEntryRegrade`', () => { const createQuizEntryRegradeStub = vi.fn().mockResolvedValue({}) render( <RegradingModal {...defaultProps} selectExpanded createQuizEntryRegrade={createQuizEntryRegradeStub} />, ) const regradeButton = screen.getByRole('button', {name: /regrade/i}) expect(createQuizEntryRegradeStub).not.toHaveBeenCalled() userEvent.click(regradeButton) const expectedPayload = {...defaultProps.regradingPayload, scoreReconciliation} expect(createQuizEntryRegradeStub).toHaveBeenCalledExactlyOnceWith(quizId, expectedPayload) }) it('calls `handleValidationErrorsFromApi` if an input validation error is thrown', async () => { const handleValidationErrorsFromApiStub = vi.fn() const mockValidationErrors = {someValue: 'someOtherValue'} const createQuizEntryRegradeStub = vi .fn() .mockRejectedValue({validationErrorsFromApi: mockValidationErrors}) render( <RegradingModal {...defaultProps} selectExpanded createQuizEntryRegrade={createQuizEntryRegradeStub} handleValidationErrorsFromApi={handleValidationErrorsFromApiStub} />, ) const regradeButton = screen.getByRole('button', {name: /regrade/i}) expect(handleValidationErrorsFromApiStub).not.toHaveBeenCalled() userEvent.click(regradeButton) await waitFor(() => expect(handleValidationErrorsFromApiStub).toHaveBeenCalledExactlyOnceWith( mockValidationErrors, ), ) }) it('does not call `handleValidationErrorsFromApi` if an non-input-validation error is thrown', async () => { const mockGenericError = new Error('Custom generic error') const createQuizEntryRegradeStub = vi.fn().mockRejectedValue(mockGenericError) const handleValidationErrorsFromApiStub = vi.fn() render( <RegradingModal {...defaultProps} selectExpanded createQuizEntryRegrade={createQuizEntryRegradeStub} handleValidationErrorsFromApi={handleValidationErrorsFromApiStub} />, ) const regradeButton = screen.getByRole('button', {name: /regrade/i}) userEvent.click(regradeButton) expect(handleValidationErrorsFromApiStub).not.toHaveBeenCalled() expect( await screen.findByText( 'Regrade did not run due to server error. Please try again later!', ), ).toBeInTheDocument() }) }) }) describe('rendered output', () => { const quizId = '1' const scoreReconciliation = 'new_score' const props = { addSuccess: vi.fn(), addAction: vi.fn(), closeModal: vi.fn(), createQuizEntryRegrade: vi.fn().mockReturnValue({then: vi.fn()}), modalOpen: true, quizId, regradingPayload: { quizEntryId: '3', pointsPossible: 1.0, scoringAlgorithm: 'Equivalence', scoringData: {value: true}, }, scoreReconciliation, setScoreReconciliation: vi.fn(), toggleRegradingEditMode: vi.fn(), fromSpeedgrader: true, } it('sets hint text based on `scoreReconciliation`', () => { render(<RegradingModal {...props} selectExpanded scoreReconciliation="old_score" />) expect(screen.getByText(/Result: /i)).toBeInTheDocument() }) it('renders radio options', () => { render(<RegradingModal {...props} selectExpanded />) const radioInputs = screen.getAllByRole('radio') expect(radioInputs).toHaveLength(4) }) }) })