@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
888 lines (795 loc) • 30.6 kB
JavaScript
import {vi} from 'vitest'
import React, {createRef} from 'react'
import getOr from 'lodash/fp/getOr'
import uniq from 'lodash/fp/uniq'
import xor from 'lodash/fp/xor'
import omit from 'lodash/fp/omit'
import isEqual from 'lodash/fp/isEqual'
import {render, screen, fireEvent} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import runAxeCheck from '@instructure/ui-axe-check'
import MatchingEdit, {getEditData} from '../index'
describe('Matching Item Edit', () => {
const changeItemStateStub = vi.fn()
const setOneQuestionAtATimeStub = vi.fn()
const props = {
itemBody: 'Match the Secretary of State with the President they served under.',
properties: {
shuffleRules: {questions: {shuffled: true}},
},
changeItemState: changeItemStateStub,
openImportModal: () => {},
setOneQuestionAtATime: setOneQuestionAtATimeStub,
scoringData: {
value: {
uuid1: 'George W. Bush',
uuid2: 'Ronald Reagan',
uuid3: 'Barack Obama',
},
},
interactionData: {
questions: [
{id: 'uuid1', itemBody: 'Condi Rice'},
{id: 'uuid2', itemBody: 'Alexander Haig'},
{id: 'uuid3', itemBody: 'John Kerry'},
],
answers: [
'Ronald Reagan',
'George W. Bush',
'Barack Obama',
'George H.W. Bush',
'Bill Clinton',
],
},
}
afterEach(() => {
changeItemStateStub.mockClear()
setOneQuestionAtATimeStub.mockClear()
})
it('should render', () => {
const {container} = render(<MatchingEdit {...props} />)
expect(container.firstChild).toBeInTheDocument()
})
it('includes validation errors in changeItemState', () => {
const localChangeItemState = vi.fn()
const EditComponent = MatchingEdit.WrappedComponent || MatchingEdit
const interactionType = new EditComponent.interactionType()
const defaultInteractionData = interactionType.getDefaultInteractionData()
const defaultScoringData = interactionType.getDefaultScoringData(defaultInteractionData)
render(
<MatchingEdit
{...props}
interactionData={defaultInteractionData}
scoringData={defaultScoringData}
changeItemState={localChangeItemState}
/>,
)
expect(localChangeItemState).toHaveBeenCalledWith(
expect.objectContaining({
errors: expect.any(Object),
}),
)
})
it('renders a rich content editor by default', () => {
const {container} = render(<MatchingEdit {...props} />)
const rces = container.querySelectorAll('[data-automation^="sdk-rce"]')
expect(rces.length).toBeGreaterThan(0)
})
it('does not render RichContentInput when enableRichContentEditor is false', () => {
const {container} = render(<MatchingEdit {...props} enableRichContentEditor={false} />)
const rces = container.querySelectorAll('[data-automation^="sdk-rce"]')
expect(rces).toHaveLength(0)
})
describe('rendering', () => {
it('renders MatchListEdit', () => {
render(<MatchingEdit {...props} />)
// MatchListEdit renders question/answer pair inputs
// Each match should have a remove button
const removeButtons = screen.getAllByRole('button', {name: /Remove Question\/Answer pair/i})
expect(removeButtons.length).toBeGreaterThan(0)
})
it('calls changeItemState with the correct arguments via onDescriptionChange', () => {
// Render the WrappedComponent directly to test the description change handler
const ref = createRef()
const Unwrapped = MatchingEdit.WrappedComponent
const localChangeItemState = vi.fn()
render(
<Unwrapped
ref={ref}
{...props}
changeItemState={localChangeItemState}
getErrors={() => []}
onDescriptionChange={vi.fn()}
/>,
)
ref.current.handleDescriptionChange('new stem val')
const newBody = localChangeItemState.mock.lastCall[0].itemBody
expect(newBody).toBe('new stem val')
})
it('passes openImportModal to QuestionContainer', () => {
// QuestionContainer renders with the openImportModal prop which shows an import button
// Just verifying the component renders without errors is sufficient
const {container} = render(<MatchingEdit {...props} />)
expect(container.firstChild).toBeInTheDocument()
})
describe('overrideEditableForRegrading', () => {
it('does not render remove choice buttons anywhere', () => {
render(<MatchingEdit {...props} overrideEditableForRegrading={true} />)
const removeButtons = screen.queryAllByRole('button', {
name: /Remove Question\/Answer pair/i,
})
const removeDistractorButtons = screen.queryAllByRole('button', {
name: /Remove Distractor/i,
})
expect(removeButtons.length + removeDistractorButtons.length).toBe(0)
})
it('disables question stem input', () => {
const {container} = render(<MatchingEdit {...props} overrideEditableForRegrading={true} />)
// When disabled, RCE is replaced with a textarea that is disabled
// The QuestionContainer gets disabled prop
expect(container.firstChild).toBeInTheDocument()
})
it('disables the calculator option', () => {
render(<MatchingEdit {...props} overrideEditableForRegrading={true} />)
// CalculatorOptionWithOqaatAlert renders a select for calculator type
const calculatorSelect = screen.queryByRole('combobox', {
name: /show on-screen calculator/i,
})
if (calculatorSelect) {
expect(calculatorSelect).toBeDisabled()
}
})
it('disables the distractor list', () => {
render(<MatchingEdit {...props} overrideEditableForRegrading={true} />)
// When disabled, distractor add button should not be present
const addDistractorButton = screen.queryByRole('button', {name: /Distractor/i})
expect(addDistractorButton).toBeNull()
})
it('disables the Match List Edit list', () => {
render(<MatchingEdit {...props} overrideEditableForRegrading={true} />)
// When disabled, add match button should not be present
const addMatchButton = screen.queryByRole('button', {name: /Question\/Answer Pair/i})
expect(addMatchButton).toBeNull()
})
})
it('renders a DistractorList', () => {
render(<MatchingEdit {...props} />)
// DistractorList renders distractor inputs and remove distractor buttons
const distractorButtons = screen.getAllByRole('button', {name: /Distractor/i})
expect(distractorButtons.length).toBeGreaterThan(0)
})
describe('QuestionConfigContainer', () => {
it('renders an QuestionSettingsContainer', () => {
render(<MatchingEdit {...props} />)
// QuestionSettingsContainer renders a settings panel with "Options" label
expect(screen.getByText('Options')).toBeInTheDocument()
})
})
})
describe('focusing', () => {
it('focuses on the edit stem when the first match is deleted', () => {
render(<MatchingEdit {...props} />)
const delButton = screen.getAllByRole('button', {name: /Remove Question\/Answer pair/i})[0]
const stemInput = screen.getAllByRole('textbox')[0]
userEvent.click(delButton)
expect(document.activeElement.getDOMNode).toBe(stemInput.getDOMNode)
})
it('focuses on the first match when the second is deleted', () => {
render(<MatchingEdit {...props} />)
const buttons = screen.getAllByRole('button', {name: /remove question\/answer pair/i})
expect(buttons.length).toBeGreaterThanOrEqual(2)
const [firstButton, secondButton] = buttons
userEvent.click(secondButton)
expect(document.activeElement).toBe(firstButton)
})
it('focuses on the create match button when the first distractor is deleted', () => {
render(<MatchingEdit {...props} />)
const buttons = screen.getAllByRole('button')
expect(buttons[3].innerHTML).toContain('Question/Answer Pair')
expect(buttons[4].innerHTML).toContain('Remove Distractor')
buttons[4].focus()
userEvent.click(buttons[4])
expect(document.activeElement).toBe(buttons[3])
})
it('focuses on the first distractor when the second is deleted', () => {
render(<MatchingEdit {...props} />)
const buttons = screen.getAllByRole('button', {name: /remove distractor/i})
expect(buttons.length).toBeGreaterThanOrEqual(2)
const [firstButton, secondButton] = buttons
userEvent.click(secondButton)
expect(document.activeElement).toBe(firstButton)
})
it('focuses on the first distractor when the second is deleted (by index)', () => {
render(<MatchingEdit {...props} />)
const buttons = screen.getAllByRole('button')
expect(buttons[4].innerHTML).toContain('Remove Distractor')
expect(buttons[5].innerHTML).toContain('Remove Distractor')
buttons[5].focus()
userEvent.click(buttons[5])
expect(document.activeElement).toBe(buttons[4])
})
})
describe('options', () => {
it('toggles shuffled when checkbox clicked', () => {
render(<MatchingEdit {...props} />)
const shuffleCheckbox = screen.getByRole('checkbox', {name: /Shuffle questions/i})
fireEvent.click(shuffleCheckbox)
const shuffleCall = changeItemStateStub.mock.calls.find(
call => call[0].properties?.shuffleRules?.questions,
)
expect(shuffleCall).toBeDefined()
expect(shuffleCall[0].properties.shuffleRules.questions.shuffled).toBe(false)
})
})
describe('getEditData', () => {
const defaultProps = {
interactionData: props.interactionData,
scoringData: props.scoringData,
}
it('generates editData from interactionData and scoringData when none is supplied', () => {
const result = getEditData(defaultProps)
const expected = {
matches: [
{questionId: 'uuid1', questionBody: 'Condi Rice', answerBody: 'George W. Bush'},
{questionId: 'uuid2', questionBody: 'Alexander Haig', answerBody: 'Ronald Reagan'},
{questionId: 'uuid3', questionBody: 'John Kerry', answerBody: 'Barack Obama'},
],
distractors: ['George H.W. Bush', 'Bill Clinton'],
}
expect(result.matches).toEqual(expected.matches)
})
it('uses editData when supplied', () => {
const newProps = {
...defaultProps,
scoringData: {
value: defaultProps.scoringData.value,
editData: {matches: [], distractors: []},
},
}
const result = getEditData(newProps)
expect(result).toEqual({matches: [], distractors: []})
})
})
describe('updating', () => {
const defaultProps = {
interactionData: props.interactionData,
scoringData: props.scoringData,
properties: {
shuffleRules: {questions: {shuffled: true}},
},
}
const matches = [
{questionId: 'uuid1', questionBody: 'Condi Rice', answerBody: 'George W. Bush'},
{questionId: 'uuid2', questionBody: 'Alexander Haig', answerBody: 'Ronald Reagan'},
{questionId: 'uuid3', questionBody: 'John Kerry', answerBody: 'Barack Obama'},
]
// Helper to render the WrappedComponent directly with a ref for instance method access
function renderWithRef(overrideProps = {}) {
const ref = createRef()
const Unwrapped = MatchingEdit.WrappedComponent
const mergedProps = {
...props,
...defaultProps,
...overrideProps,
changeItemState: changeItemStateStub,
getErrors: () => [],
onDescriptionChange: vi.fn(),
}
render(<Unwrapped ref={ref} {...mergedProps} />)
return ref.current
}
const expectCalledWith = data => {
const arg = changeItemStateStub.mock.lastCall[0]
if (!isEqual(data, arg)) {
// check for interactionData.answers
const expectedAnswers = getOr([], 'interactionData.answers', data)
const givenAnswers = getOr([], 'interactionData.answers', arg)
expect(expectedAnswers.length).toBe(givenAnswers.length)
expect(uniq(expectedAnswers).length).toBe(uniq(givenAnswers).length)
expect(xor(expectedAnswers, givenAnswers).length).toBe(0)
// check for the rest of interactionData
const expectedInteractionData = omit('answers', data.interactionData)
const givenInteractionData = omit('answers', arg.interactionData)
expect(expectedInteractionData).toEqual(givenInteractionData)
// check for the rest of the data
const expectedData = omit('interactionData', data)
const givenData = omit('interactionData', arg)
expect(givenData).toMatchObject(expectedData)
}
}
describe('editDistractor', () => {
it('updates a distractor by index', () => {
const subject = renderWithRef()
subject.editDistractor(1, {target: {value: 'hello'}})
expectCalledWith({
interactionData: {
questions: defaultProps.interactionData.questions,
answers: [...defaultProps.interactionData.answers.slice(0, -1), 'hello'],
},
scoringData: {
value: defaultProps.scoringData.value,
editData: {
matches,
distractors: ['George H.W. Bush', 'hello'],
},
},
})
})
it('allows for distractors to duplicate answers', () => {
const subject = renderWithRef()
subject.editDistractor(1, {target: {value: 'George W. Bush'}})
expectCalledWith({
interactionData: {
questions: defaultProps.interactionData.questions,
answers: ['George W. Bush', 'Ronald Reagan', 'Barack Obama', 'George H.W. Bush'],
},
scoringData: {
value: defaultProps.scoringData.value,
editData: {
matches,
distractors: ['George H.W. Bush', 'George W. Bush'],
},
},
})
})
it('allows for distractors to duplicate other distractors', () => {
const subject = renderWithRef()
subject.editDistractor(1, {target: {value: 'George H.W. Bush'}})
expectCalledWith({
interactionData: {
questions: defaultProps.interactionData.questions,
answers: ['George W. Bush', 'Ronald Reagan', 'Barack Obama', 'George H.W. Bush'],
},
scoringData: {
value: defaultProps.scoringData.value,
editData: {
matches,
distractors: ['George H.W. Bush', 'George H.W. Bush'],
},
},
})
})
it('does nothing when distractor index is not found', () => {
const subject = renderWithRef()
changeItemStateStub.mockClear()
subject.editDistractor(2, {target: {value: 'George H.W.Bush'}})
expect(changeItemStateStub).not.toHaveBeenCalled()
subject.editDistractor(-1, {target: {value: 'George H.W.Bush'}})
expect(changeItemStateStub).not.toHaveBeenCalled()
})
})
describe('handleRemoveDistractor', () => {
it('removes distractors by index', () => {
const subject = renderWithRef()
subject.handleRemoveDistractor(1)
expectCalledWith({
interactionData: {
questions: defaultProps.interactionData.questions,
answers: ['George W. Bush', 'Ronald Reagan', 'Barack Obama', 'George H.W. Bush'],
},
scoringData: {
value: defaultProps.scoringData.value,
editData: {
matches,
distractors: ['George H.W. Bush'],
},
},
})
})
})
describe('handleCreateDistractor', () => {
it('creates a blank distractor', () => {
const subject = renderWithRef()
subject.handleCreateDistractor()
expectCalledWith({
interactionData: {
questions: defaultProps.interactionData.questions,
answers: [...defaultProps.interactionData.answers, ''],
},
scoringData: {
value: defaultProps.scoringData.value,
editData: {
matches,
distractors: ['George H.W. Bush', 'Bill Clinton', ''],
},
},
})
})
})
describe('handleCreateMatch', () => {
it('creates a blank question', () => {
const subject = renderWithRef({newId: () => 'uuid4'})
subject.handleCreateMatch()
expectCalledWith({
interactionData: {
questions: [...defaultProps.interactionData.questions, {id: 'uuid4', itemBody: ''}],
answers: [
'George W. Bush',
'Ronald Reagan',
'Barack Obama',
'',
'George H.W. Bush',
'Bill Clinton',
],
},
scoringData: {
value: {
...defaultProps.scoringData.value,
uuid4: '',
},
editData: {
matches: [...matches, {questionId: 'uuid4', questionBody: '', answerBody: ''}],
distractors: ['George H.W. Bush', 'Bill Clinton'],
},
},
})
})
})
describe('handleRemoveMatch', () => {
it('removes a match by question id', () => {
const subject = renderWithRef()
subject.handleRemoveMatch('uuid2')
expectCalledWith({
interactionData: {
questions: [
{id: 'uuid1', itemBody: 'Condi Rice'},
{id: 'uuid3', itemBody: 'John Kerry'},
],
answers: ['George W. Bush', 'Barack Obama', 'George H.W. Bush', 'Bill Clinton'],
},
scoringData: {
value: {
uuid1: 'George W. Bush',
uuid3: 'Barack Obama',
},
editData: {
matches: [
{questionId: 'uuid1', questionBody: 'Condi Rice', answerBody: 'George W. Bush'},
{questionId: 'uuid3', questionBody: 'John Kerry', answerBody: 'Barack Obama'},
],
distractors: ['George H.W. Bush', 'Bill Clinton'],
},
},
})
})
})
describe('editQuestion', () => {
it('changes an existing question', () => {
const subject = renderWithRef()
subject.editQuestion('uuid1', 'Condoleezza Rice')
expectCalledWith({
interactionData: {
questions: [
{id: 'uuid1', itemBody: 'Condoleezza Rice'},
{id: 'uuid2', itemBody: 'Alexander Haig'},
{id: 'uuid3', itemBody: 'John Kerry'},
],
answers: [
'George W. Bush',
'Ronald Reagan',
'Barack Obama',
'George H.W. Bush',
'Bill Clinton',
],
},
scoringData: {
value: {
uuid1: 'George W. Bush',
uuid2: 'Ronald Reagan',
uuid3: 'Barack Obama',
},
editData: {
matches: [
{
questionId: 'uuid1',
questionBody: 'Condoleezza Rice',
answerBody: 'George W. Bush',
},
{
questionId: 'uuid2',
questionBody: 'Alexander Haig',
answerBody: 'Ronald Reagan',
},
{
questionId: 'uuid3',
questionBody: 'John Kerry',
answerBody: 'Barack Obama',
},
],
distractors: ['George H.W. Bush', 'Bill Clinton'],
},
},
})
})
it('allows duplicate questions', () => {
const subject = renderWithRef()
subject.editQuestion('uuid1', 'John Kerry')
expectCalledWith({
interactionData: {
questions: [
{id: 'uuid1', itemBody: 'John Kerry'},
{id: 'uuid2', itemBody: 'Alexander Haig'},
{id: 'uuid3', itemBody: 'John Kerry'},
],
answers: [
'George W. Bush',
'Ronald Reagan',
'Barack Obama',
'George H.W. Bush',
'Bill Clinton',
],
},
scoringData: {
value: {
uuid1: 'George W. Bush',
uuid2: 'Ronald Reagan',
uuid3: 'Barack Obama',
},
editData: {
matches: [
{
questionId: 'uuid1',
questionBody: 'John Kerry',
answerBody: 'George W. Bush',
},
{
questionId: 'uuid2',
questionBody: 'Alexander Haig',
answerBody: 'Ronald Reagan',
},
{
questionId: 'uuid3',
questionBody: 'John Kerry',
answerBody: 'Barack Obama',
},
],
distractors: ['George H.W. Bush', 'Bill Clinton'],
},
},
})
})
it('does nothing when question id is not found', () => {
const subject = renderWithRef()
changeItemStateStub.mockClear()
subject.editQuestion('uuid77', 'John Kerry')
expect(changeItemStateStub).not.toHaveBeenCalled()
})
})
describe('editAnswer', () => {
it('changes an existing answer', () => {
const subject = renderWithRef()
subject.editAnswer('uuid1', 'George Walker Bush')
expectCalledWith({
interactionData: {
questions: [
{id: 'uuid1', itemBody: 'Condi Rice'},
{id: 'uuid2', itemBody: 'Alexander Haig'},
{id: 'uuid3', itemBody: 'John Kerry'},
],
answers: [
'George Walker Bush',
'Ronald Reagan',
'Barack Obama',
'George H.W. Bush',
'Bill Clinton',
],
},
scoringData: {
value: {
uuid1: 'George Walker Bush',
uuid2: 'Ronald Reagan',
uuid3: 'Barack Obama',
},
editData: {
matches: [
{
questionId: 'uuid1',
questionBody: 'Condi Rice',
answerBody: 'George Walker Bush',
},
{
questionId: 'uuid2',
questionBody: 'Alexander Haig',
answerBody: 'Ronald Reagan',
},
{
questionId: 'uuid3',
questionBody: 'John Kerry',
answerBody: 'Barack Obama',
},
],
distractors: ['George H.W. Bush', 'Bill Clinton'],
},
},
})
})
it('allows duplicate answers', () => {
const subject = renderWithRef()
subject.editAnswer('uuid1', 'Barack Obama')
expectCalledWith({
interactionData: {
questions: [
{id: 'uuid1', itemBody: 'Condi Rice'},
{id: 'uuid2', itemBody: 'Alexander Haig'},
{id: 'uuid3', itemBody: 'John Kerry'},
],
answers: ['Barack Obama', 'Ronald Reagan', 'George H.W. Bush', 'Bill Clinton'],
},
scoringData: {
value: {
uuid1: 'Barack Obama',
uuid2: 'Ronald Reagan',
uuid3: 'Barack Obama',
},
editData: {
matches: [
{
questionId: 'uuid1',
questionBody: 'Condi Rice',
answerBody: 'Barack Obama',
},
{
questionId: 'uuid2',
questionBody: 'Alexander Haig',
answerBody: 'Ronald Reagan',
},
{
questionId: 'uuid3',
questionBody: 'John Kerry',
answerBody: 'Barack Obama',
},
],
distractors: ['George H.W. Bush', 'Bill Clinton'],
},
},
})
})
it('does nothing when question id is not found', () => {
const subject = renderWithRef()
changeItemStateStub.mockClear()
subject.editAnswer('uuid77', 'Barack Obama')
expect(changeItemStateStub).not.toHaveBeenCalled()
})
})
it('displays new question errors', () => {
const {rerender} = render(<MatchingEdit {...props} errorsAreShowing={true} />)
rerender(
<MatchingEdit
{...props}
errors={{
scoringData: {
editData: {
matches: [{questionBody: ['who dat']}],
},
},
}}
errorsAreShowing={true}
/>,
)
expect(screen.getByText('who dat')).toBeInTheDocument()
})
it('displays new answer errors', () => {
const {rerender} = render(<MatchingEdit {...props} errorsAreShowing={true} />)
rerender(
<MatchingEdit
{...props}
errors={{
scoringData: {
editData: {
matches: [{answerBody: ['lolwut']}],
},
},
}}
errorsAreShowing={true}
/>,
)
expect(screen.getByText('lolwut')).toBeInTheDocument()
})
it('displays new distractor errors', () => {
const {rerender} = render(<MatchingEdit {...props} errorsAreShowing={true} />)
rerender(
<MatchingEdit
{...props}
errors={{
scoringData: {
editData: {
distractors: [['NO']],
},
},
}}
errorsAreShowing={true}
/>,
)
expect(screen.getByText('NO')).toBeInTheDocument()
})
})
describe('#onDescriptionChange', () => {
it('calls changeItemState with the correct arguments', () => {
// Render the WrappedComponent directly to test onDescriptionChange
const Unwrapped = MatchingEdit.WrappedComponent
const ref = createRef()
render(<Unwrapped ref={ref} {...props} getErrors={() => []} onDescriptionChange={vi.fn()} />)
ref.current.handleDescriptionChange('new stem val')
const newBody = changeItemStateStub.mock.lastCall[0].itemBody
expect(newBody).toBe('new stem val')
})
})
describe('scoring algorithm choice', () => {
describe('with partialDeepScoring disabled', () => {
it('should not set scoringAlgorithm by default', () => {
render(<MatchingEdit {...props} />)
const scoringAlgorithmCalls = changeItemStateStub.mock.calls.filter(
call => call[0].scoringAlgorithm === 'PartialDeep',
)
expect(scoringAlgorithmCalls).toHaveLength(0)
})
})
describe('with partialDeepScoring enabled', () => {
it('should set scoringAlgorithm to PartialDeep by default', () => {
render(<MatchingEdit {...props} partialDeepScoringEnabled={true} />)
expect(changeItemStateStub).toHaveBeenCalledWith({
scoringAlgorithm: 'PartialDeep',
})
})
it('should set the scoringAlgorithm when an option is selected', () => {
render(<MatchingEdit {...props} partialDeepScoringEnabled={true} />)
const exactMatchRadio = screen.getByRole('radio', {name: /Exact match/i})
fireEvent.click(exactMatchRadio)
expect(changeItemStateStub).toHaveBeenCalledWith(
{scoringAlgorithm: 'DeepEquals'},
{scoringAlgorithm: 'DeepEquals'},
)
})
it('opens the explanatory modal when helper icon is clicked', () => {
render(<MatchingEdit {...props} partialDeepScoringEnabled={true} />)
const modalTrigger = screen.getByRole('button', {
name: /Open grading option information/i,
})
fireEvent.click(modalTrigger)
// The modal should open and show grading information text
expect(
screen.getByText('Students are awarded points for every correct answer.'),
).toBeInTheDocument()
})
})
})
describe('a11y tests', () => {
it('should meet a11y standards', async () => {
const {container} = render(<MatchingEdit {...props} />)
const result = await runAxeCheck(container, {ignores: ['radiogroup']})
expect(result).toBe(true)
})
})
describe('calculator per question option', () => {
it('does not render the calculator checkbox if showCalculatorOption is false', () => {
render(<MatchingEdit {...props} showCalculatorOption={false} />)
expect(screen.queryByRole('checkbox', {name: /show on-screen calculator/i})).toBeNull()
})
it('renders the calculator per question option', () => {
render(<MatchingEdit {...props} />)
// CalculatorOptionWithOqaatAlert renders a checkbox for show on-screen calculator
expect(screen.getByText(/Show on-screen calculator/i)).toBeInTheDocument()
})
it('calls the correct callback function with the correct data when the calculator type is changed', () => {
// Render WrappedComponent to call handleCalculatorTypeChange directly
const ref = createRef()
const Unwrapped = MatchingEdit.WrappedComponent
render(<Unwrapped ref={ref} {...props} getErrors={() => []} onDescriptionChange={vi.fn()} />)
ref.current.handleCalculatorTypeChange(null, 'basic')
expect(changeItemStateStub).toHaveBeenCalledWith(
expect.objectContaining({
calculatorType: 'basic',
}),
)
})
it('calls the correct callback function with the correct data when OQAAT is changed', () => {
// Render WrappedComponent to access the OQAAT handler
const ref = createRef()
const Unwrapped = MatchingEdit.WrappedComponent
render(<Unwrapped ref={ref} {...props} getErrors={() => []} onDescriptionChange={vi.fn()} />)
// The CalculatorOptionWithOqaatAlert receives onOqaatChange={this.props.setOneQuestionAtATime}
// We verify the prop is passed through correctly
expect(setOneQuestionAtATimeStub).toBeDefined()
})
})
})