@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
273 lines (231 loc) • 8.02 kB
JavaScript
import React from 'react'
import {vi} from 'vitest'
import {render, screen, fireEvent} from '@testing-library/react'
import runAxeCheck from '@instructure/ui-axe-check'
import FileUploadEdit from '../index'
describe('File Upload Edit', () => {
const changeItemStateStub = vi.fn()
const setOneQuestionAtATimeStub = vi.fn()
const props = {
itemBody: 'STEM',
interactionData: {
restrictCount: true,
filesCount: '2',
},
properties: {
restrictTypes: true,
allowedTypes: 'media/*',
},
changeItemState: changeItemStateStub,
openImportModal: () => {},
setOneQuestionAtATime: setOneQuestionAtATimeStub,
}
afterEach(() => {
changeItemStateStub.mockClear()
setOneQuestionAtATimeStub.mockClear()
})
it('should render', () => {
render(<FileUploadEdit {...props} />)
expect(document.body.textContent).toBeDefined()
})
it('includes validation errors in changeItemState', () => {
render(
<FileUploadEdit {...props} interactionData={{restrictCount: true, filesCount: 'invalid'}} />,
)
expect(changeItemStateStub).toHaveBeenCalledWith(
expect.objectContaining({errors: expect.any(Object)}),
)
})
it('renders RCE by default', () => {
const {container} = render(<FileUploadEdit {...props} />)
expect(container.querySelectorAll('[data-automation^="sdk-rce"]').length).toBeGreaterThan(0)
})
it('does not render RCE when disabled', () => {
const {container} = render(<FileUploadEdit {...props} enableRichContentEditor={false} />)
expect(container.querySelectorAll('[data-automation^="sdk-rce"]')).toHaveLength(0)
})
it('handles changes of restrictCount', () => {
render(<FileUploadEdit {...props} />)
document.body.querySelectorAll('input[type=checkbox]')[1].click()
expect(changeItemStateStub.mock.calls[0][0]).toEqual(
expect.objectContaining({
interactionData: {
restrictCount: false,
filesCount: '2',
},
}),
)
})
it('handles changes of filesCount', () => {
render(<FileUploadEdit {...props} />)
const inputElement = screen.getAllByRole('spinbutton')[0]
fireEvent.change(inputElement, {target: {value: '4'}})
expect(changeItemStateStub.mock.calls[0][0]).toEqual(
expect.objectContaining({
interactionData: {
restrictCount: true,
filesCount: '4',
},
}),
)
})
it('handles changes of restrictTypes', () => {
render(<FileUploadEdit {...props} />)
document.body.querySelectorAll('input[type=checkbox]')[2].click()
expect(changeItemStateStub.mock.calls[0][0]).toEqual(
expect.objectContaining({
properties: {
restrictTypes: false,
allowedTypes: 'media/*',
},
}),
)
})
it('handles changes of allowedTypes', () => {
render(<FileUploadEdit {...props} />)
const inputElement = screen.getAllByRole('textbox')[1]
fireEvent.change(inputElement, {target: {value: '.jpeg'}})
expect(changeItemStateStub.mock.calls[0][0]).toEqual(
expect.objectContaining({
properties: {
restrictTypes: true,
allowedTypes: '.jpeg',
},
}),
)
})
it('should show Errors if errorsAreShowing is true and there are itemBody errors', () => {
const errorMsg = "I'm sorry Dave"
render(
<FileUploadEdit
{...props}
errorsAreShowing={true}
errors={{
itemBody: [errorMsg],
}}
/>,
)
expect(document.body.textContent).toContain(errorMsg)
})
it('should show Errors if errorsAreShowing is true and there are properties errors', () => {
const errorMsg = "I'm afraid"
render(
<FileUploadEdit
{...props}
errorsAreShowing={true}
errors={{
properties: {
allowedTypes: [errorMsg],
},
}}
/>,
)
expect(document.body.textContent).toContain(errorMsg)
})
it('should show Errors if errorsAreShowing is true and there are interactionData errors', () => {
const errorMsg = "I can't do that"
render(
<FileUploadEdit
{...props}
errorsAreShowing={true}
errors={{
interactionData: {
filesCount: [errorMsg],
},
}}
/>,
)
expect(document.body.textContent).toContain(errorMsg)
})
it('should not render allowedTypes TextInput inside an QuestionSettingsContainer when restrictTypes is false', () => {
render(
<FileUploadEdit
{...props}
properties={{
restrictTypes: false,
allowedTypes: 'media/*',
}}
/>,
)
const input = screen.queryByPlaceholderText(/file extensions/i)
expect(input).toBeNull()
})
it('should render allowedTypes TextInput inside an QuestionSettingsContainer when restrictTypes is true', () => {
const allowedTypes = 'comma, separated, values'
render(
<FileUploadEdit
{...props}
properties={{
restrictTypes: true,
allowedTypes,
}}
/>,
)
const input = screen.getByPlaceholderText(/file extensions/i)
expect(input.value).toBe(allowedTypes)
})
describe('overrideEditableForRegrading', () => {
it('disables text input', () => {
render(<FileUploadEdit {...props} overrideEditableForRegrading={true} />)
expect(document.body.querySelector('input[type=checkbox]').disabled).toBe(true)
})
it('disables number input', () => {
render(<FileUploadEdit {...props} overrideEditableForRegrading={true} />)
expect(document.body.querySelector('input[inputMode=decimal]').disabled).toBe(true)
})
it('disables checkbox inputs', () => {
render(<FileUploadEdit {...props} overrideEditableForRegrading={true} />)
document.body
.querySelectorAll('input[type=checkbox]')
.forEach(cb => expect(cb.disabled).toBe(true))
})
it('disables the calculator option', () => {
render(<FileUploadEdit {...props} overrideEditableForRegrading={true} />)
expect(screen.getByRole('checkbox', {name: /show on-screen calculator/i}).disabled).toBe(true)
})
})
describe('a11y tests', () => {
it('should meet a11y standards', async () => {
render(<FileUploadEdit {...props} />)
expect(
await runAxeCheck(document.body, {
ignores: ['label', 'region'],
}),
).toBe(true)
})
})
describe('calculator per question option', () => {
it('does not render the calculator checkbox if showCalculatorOption is false', () => {
render(<FileUploadEdit {...props} showCalculatorOption={false} />)
expect(screen.queryByRole('checkbox', {name: /show on-screen calculator/i})).toBeNull()
})
it('renders the calculator per question option', () => {
render(<FileUploadEdit {...props} />)
expect(screen.queryAllByRole('checkbox', {name: /show on-screen calculator/i})).toHaveLength(
1,
)
})
it('calls the correct callback function with the correct data when the calculator type is changed', () => {
render(<FileUploadEdit {...props} />)
const calculatorCheckbox = screen.getByRole('checkbox', {
name: /show on-screen calculator/i,
})
// Clicking the checkbox toggles from 'none' to 'basic'
fireEvent.click(calculatorCheckbox)
expect(changeItemStateStub).toHaveBeenCalledWith(
expect.objectContaining({
calculatorType: 'basic',
}),
)
})
it('calls the correct callback function with the correct data when OQAAT is changed', () => {
// Need calculatorType != 'none' for OQAAT toggle to appear
render(<FileUploadEdit {...props} calculatorType="basic" />)
const toggle = screen.getByRole('checkbox', {
name: /enable one question at a time/i,
})
fireEvent.click(toggle)
expect(setOneQuestionAtATimeStub).toHaveBeenCalledTimes(1)
})
})
})