@instructure/quiz-grading
Version:
The Quiz React SDK by Instructure Inc.
169 lines (150 loc) • 5.89 kB
JavaScript
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)
})
})
})