@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
118 lines (104 loc) • 4.11 kB
JavaScript
import {vi} from 'vitest'
import React from 'react'
import {v4 as uuid} from 'uuid'
import {render, screen, fireEvent} from '@testing-library/react'
import runAxeCheck from '@instructure/ui-axe-check'
import MultipleChoiceTake from '../index'
describe('Multiple Choice Item Take', () => {
const firstChoiceID = uuid()
const secondChoiceID = uuid()
const props = {
allowClearMcSelection: false,
choiceElimination: false,
itemBody: 'STEM',
scoringData: {value: firstChoiceID},
itemId: '1',
interactionData: {
choices: [
{id: firstChoiceID, itemBody: 'hey', position: 1},
{id: secondChoiceID, itemBody: 'ho', position: 2},
],
},
handleResponseUpdate: () => {},
userResponse: {value: firstChoiceID},
}
describe('responding', () => {
it('should call editResponse with correct choiceId on radioInput click', () => {
const handleResponseUpdateStub = vi.fn()
render(<MultipleChoiceTake {...props} handleResponseUpdate={handleResponseUpdateStub} />)
const radioInputs = screen.getAllByRole('radio')
const radioInput = radioInputs.find(n => n.value === secondChoiceID)
fireEvent.click(radioInput)
expect(handleResponseUpdateStub).toHaveBeenCalled()
expect(handleResponseUpdateStub.mock.calls[0][0]).toBe(secondChoiceID)
})
})
describe('when allowClearMcSelection is true', () => {
it('should render a button to clear selection', () => {
render(<MultipleChoiceTake {...props} allowClearMcSelection />)
expect(screen.getByText('Clear my selection')).toBeInTheDocument()
})
it('clearing the selection sets response to null', () => {
const handleResponseUpdateStub = vi.fn()
render(
<MultipleChoiceTake
{...props}
allowClearMcSelection
handleResponseUpdate={handleResponseUpdateStub}
/>,
)
const clearButton = screen.getByRole('button', {name: /clear my selection/i})
expect(clearButton.textContent).toBe('Clear my selection')
fireEvent.click(clearButton)
expect(handleResponseUpdateStub).toHaveBeenCalledWith(null)
})
})
describe('when choiceElimination is true', () => {
it('should render buttons to eliminate choices', () => {
render(<MultipleChoiceTake {...props} choiceElimination />)
expect(screen.getAllByText(/Eliminate answer/).length).toBeGreaterThan(0)
})
it('eliminating a choice updates user response data', () => {
const handleResponseUpdateStub = vi.fn()
render(
<MultipleChoiceTake
{...props}
choiceElimination
handleResponseUpdate={handleResponseUpdateStub}
/>,
)
const eliminateButton = screen.getByRole('button', {name: /Eliminate answer hey/})
fireEvent.click(eliminateButton)
expect(handleResponseUpdateStub).toHaveBeenCalledWith(firstChoiceID, {
eliminated: [firstChoiceID],
})
})
it('uneliminating a choice removes it from user response data', () => {
const handleResponseUpdateStub = vi.fn()
render(
<MultipleChoiceTake
{...props}
choiceElimination
userResponse={{value: firstChoiceID, properties: {eliminated: [firstChoiceID]}}}
handleResponseUpdate={handleResponseUpdateStub}
/>,
)
const eliminateButton = screen.getByRole('button', {name: /Undo elimination of answer hey/})
fireEvent.click(eliminateButton)
expect(handleResponseUpdateStub).toHaveBeenCalledWith(firstChoiceID, {eliminated: []})
})
})
it('should meet a11y standards', async () => {
// Note: In this component's context, we don't render any landmarks, so we wrap it in a <main>
// tag to satisfy the Axe check
const {container} = render(
<main>
<MultipleChoiceTake {...props} />
</main>,
)
const result = await runAxeCheck(container, {
ignores: ['scrollable-region-focusable'], // we conditionally make rceRenderer focusable when we detect content overflow
})
expect(result).toBe(true)
})
})