@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
206 lines (169 loc) • 6.83 kB
JSX
import {vi} from 'vitest'
import React from 'react'
import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import TrueFalseEdit from '../index'
import {
verifyAtLeastOneRichContentEditorExists,
verifyNoRichContentEditorsExist,
} from '../../../../../tests/util/enableRichContentEditorChecks'
import {verifyItemChangesAreValidated} from '../../../../../tests/util/shouldValidateItemChanges'
import runAxeCheck from '@instructure/ui-axe-check'
function createProps(changeItemStateStub, setOneQuestionAtATimeStub) {
return {
calculatorType: 'basic',
itemBody: 'STEM',
itemId: '12',
interactionData: {
trueChoice: 'True',
falseChoice: 'False',
},
scoringData: {
value: true,
},
openImportModal: Function.prototype,
changeItemState: changeItemStateStub,
setOneQuestionAtATime: setOneQuestionAtATimeStub,
isSurvey: false,
}
}
describe('***** old tests *****', () => {
const changeItemStateStub = vi.fn()
const oldProps = createProps(changeItemStateStub, vi.fn())
afterEach(() => {
changeItemStateStub.mockClear()
})
describe('overrideEditableForRegrading', () => {
it('disables the question stem', () => {
const {container} = render(<TrueFalseEdit {...oldProps} overrideEditableForRegrading />)
// QuestionContainer passes readOnly to the RCE when disabled is true
// Verify the RCE area is not editable
const questionStem = container.querySelector('[data-automation="sdk-question-stem"]')
expect(questionStem).toBeInTheDocument()
// The calculator options should also be disabled
const calculatorCheckbox = screen.getByRole('checkbox', {
name: /show on-screen calculator/i,
})
expect(calculatorCheckbox.disabled).toBe(true)
})
})
})
describe('True False Item Edit', () => {
let changeItemStateStub, setOneQuestionAtATimeStub, props
beforeEach(() => {
changeItemStateStub = vi.fn()
setOneQuestionAtATimeStub = vi.fn()
props = createProps(changeItemStateStub, setOneQuestionAtATimeStub)
})
it('renders a rich content editor by default', async () => {
await verifyAtLeastOneRichContentEditorExists(TrueFalseEdit, props)
})
it('does not render a rich content editor when it is turned off', async () => {
await verifyNoRichContentEditorsExist(TrueFalseEdit, {...props, enableRichContentEditor: false})
})
it('includes validation errors in changeItemState', async () => {
await verifyItemChangesAreValidated(TrueFalseEdit, {...props, itemBody: ''})
})
describe('QuestionConfigContainer', () => {
it('renders an QuestionSettingsContainer', () => {
render(<TrueFalseEdit {...props} />)
const questionSettingsContainers = screen.getAllByTestId('question-settings-container')
expect(questionSettingsContainers).toHaveLength(1)
})
})
describe('#onSelectionUpdate', () => {
it('calls changeItemState with the correct arguments', () => {
render(<TrueFalseEdit {...props} />)
const radioInput = screen.getByRole('radio', {
name: new RegExp(`Answer: ${props.interactionData.falseChoice}`),
})
userEvent.click(radioInput)
expect(changeItemStateStub).toHaveBeenCalledWith(
expect.objectContaining({scoringData: {value: false}}),
)
})
})
describe('#selectedValue', () => {
it('selects the correct input from scoredData', () => {
render(<TrueFalseEdit {...props} />)
const trueInput = screen.getByRole('radio', {
name: new RegExp(`Answer: ${props.interactionData.trueChoice}`),
})
expect(trueInput.checked).toBe(true)
const falseInput = screen.getByRole('radio', {
name: new RegExp(`Answer: ${props.interactionData.falseChoice}`),
})
expect(falseInput.checked).toBe(false)
})
it('selects the correct input from scoredData when false', () => {
const falseProps = Object.assign({}, props, {
scoringData: {
value: false,
},
})
render(<TrueFalseEdit {...falseProps} />)
const trueInput = screen.getByRole('radio', {
name: new RegExp(`Answer: ${props.interactionData.trueChoice}`),
})
expect(trueInput.checked).toBe(false)
const falseInput = screen.getByRole('radio', {
name: new RegExp(`Answer: ${props.interactionData.falseChoice}`),
})
expect(falseInput.checked).toBe(true)
})
})
describe('overrideEditableForRegrading', () => {
it('disables the calculator option', () => {
render(<TrueFalseEdit {...props} overrideEditableForRegrading />)
const calculatorCheckbox = screen.getByRole('checkbox', {name: /show on-screen calculator/i})
const calculatorBasicRadioInput = screen.getByRole('radio', {name: /basic calculator/i})
const calculatorScientificRadioInput = screen.getByRole('radio', {
name: /scientific calculator/i,
})
expect(calculatorCheckbox.disabled).toBe(true)
expect(calculatorBasicRadioInput.disabled).toBe(true)
expect(calculatorScientificRadioInput.disabled).toBe(true)
})
})
describe('a11y tests', () => {
it('should meet a11y standards', async () => {
render(
<main>
<TrueFalseEdit {...props} />
</main>,
)
expect(
await runAxeCheck(document.body, {
ignores: ['scrollable-region-focusable'],
}),
).toBe(true)
})
})
describe('calculator per question option', () => {
it('does not render the options if showCalculatorOption is false', () => {
render(<TrueFalseEdit {...props} showCalculatorOption={false} />)
expect(screen.queryByRole('button', {name: /options/i})).toBeNull()
})
it('renders the calculator per question option', () => {
render(<TrueFalseEdit {...props} />)
const calculatorCheckboxes = screen.queryAllByRole('checkbox', {
name: /show on-screen calculator/i,
})
expect(calculatorCheckboxes).toHaveLength(1)
})
it('calls the correct callback function with the correct data when the calculator type is changed', () => {
render(<TrueFalseEdit {...props} />)
const scientificOption = screen.getByRole('radio', {name: /scientific calculator/i})
userEvent.click(scientificOption)
expect(changeItemStateStub).toHaveBeenCalledWith(
expect.objectContaining({calculatorType: 'scientific'}),
)
})
it('calls the correct callback function when OQAAT is changed', () => {
render(<TrueFalseEdit {...props} />)
const toggle = screen.getByRole('checkbox', {name: /enable one question at a time/i})
userEvent.click(toggle)
expect(setOneQuestionAtATimeStub).toHaveBeenCalledTimes(1)
})
})
})