@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
293 lines (248 loc) • 9.13 kB
JavaScript
import React from 'react'
import update from 'immutability-helper'
import {expect, find, mount, within} from '@instructure/ui-test-utils'
import * as util from '../util'
import FormulaSection from '../FormulaSection'
import {render, screen} from '@testing-library/react'
describe('FormulaSection', () => {
const defaultProps = {
formulaErrors: [],
generatedSolutionsErrors: [],
handleAnswerCountChange: Function.prototype,
handleAnswerPrecisionChange: Function.prototype,
handleFormulaChange: Function.prototype,
handleGenerateSolutions: Function.prototype,
handleMarginOfErrorChange: Function.prototype,
handleMarginOfErrorTypeChange: Function.prototype,
handleScientificNotationChange: Function.prototype,
locale: 'en',
overrideEditableForRegrading: false,
scoringData: {
value: {
generatedSolutions: [
{
inputs: [{name: 'x', value: 2}],
output: 2,
},
{
inputs: [{name: 'x', value: 3}],
output: 3,
},
],
numeric: {
type: 'marginOfError',
margin: '0',
marginType: 'absolute',
},
variables: [{name: 'x', min: 0, max: 5, precision: 1}],
},
},
status: util.STATUS_STOPPED,
}
it('renders a table and no spinner when solutions are available', async () => {
render(<FormulaSection {...defaultProps} />)
expect(screen.queryByRole('table')).to.not.be.null()
expect(screen.queryByRole('img', {name: /running/i})).to.be.null()
})
// TODO: QUIZ-17438 - This test fails in jsdom due to getAttributeNames not being
// available on some internal element during Inst UI Spinner rendering. The component
// behavior is verified by the surrounding tests. Needs jsdom upgrade or Spinner mock.
it.skip('renders a spinner and no table while waiting for solutions', async () => {
const testProps = {
...defaultProps,
status: util.STATUS_RUNNING,
}
render(<FormulaSection {...testProps} />)
expect(screen.queryByRole('table')).to.be.null()
expect(screen.queryByRole('img', {name: /running/i})).to.not.be.null()
})
it('renders neither a table nor spinner when canceled', async () => {
const testProps = {
...defaultProps,
status: util.STATUS_CANCELED,
}
render(<FormulaSection {...testProps} />)
expect(screen.queryByRole('table')).to.be.null()
expect(screen.queryByRole('img', {name: /running/i})).to.be.null()
})
it('renders neither a table nor spinner when there are no solutions and stopped', async () => {
const testProps = {
...defaultProps,
scoringData: {
value: {
generatedSolutions: [],
variables: [],
numeric: {
type: 'marginOfError',
margin: '0',
marginType: 'absolute',
},
},
},
}
render(<FormulaSection {...testProps} />)
expect(screen.queryByRole('table')).to.be.null()
expect(screen.queryByRole('img', {name: /running/i})).to.be.null()
})
it('renders a message when not enough solutions could be found', async () => {
const testProps = {
...defaultProps,
status: util.STATUS_FAILED,
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
expect(formulaSection.getTextContent()).to.match(/We were only able to find 2 solutions\./)
})
it('renders a message when no solutions could be found', async () => {
const scoringData = update(defaultProps.scoringData, {
value: {
generatedSolutions: {$set: []},
},
})
const testProps = {
...defaultProps,
status: util.STATUS_FAILED,
scoringData,
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
expect(formulaSection.getTextContent()).to.match(/We were not able to find any solutions\./)
})
it('renders error messages with invalid setup', async () => {
const testProps = {
...defaultProps,
status: util.STATUS_FORMULA_SETUP_INVALID,
formulaErrors: ['hello world'],
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
expect(formulaSection.getTextContent()).to.include('hello world')
})
it('does not render error messages with valid setup', async () => {
const testProps = {
...defaultProps,
status: util.STATUS_STOPPED,
formulaErrors: ['hello world'],
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
expect(formulaSection.getTextContent()).to.not.include('hello world')
})
describe('override editable for regrading', () => {
it('renders a disabled formula input', async () => {
const testProps = {
...defaultProps,
overrideEditableForRegrading: true,
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
const formulaTextarea = await formulaSection.find(':label(Formula)')
expect(formulaTextarea.getDOMNode().disabled).to.be.true()
})
it('renders disabled generate button', async () => {
const testProps = {
...defaultProps,
overrideEditableForRegrading: true,
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
const generateButton = await formulaSection.find(':label(Generate)', {exact: false})
expect(generateButton.getDOMNode().disabled).to.be.true()
})
})
describe('formatNumStr', () => {
it('properly formats en numbers', async () => {
const scoringData = update(defaultProps.scoringData, {
value: {
generatedSolutions: {
$set: [{inputs: [{name: 'x', value: 4000.5}], output: 4000.5}],
},
},
})
const testProps = {
...defaultProps,
scoringData,
locale: 'en',
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
const formatted = await formulaSection.find(':textContent(4,000.5)')
expect(formatted).to.be.ok()
})
it('properly formats non-en numbers', async () => {
const scoringData = update(defaultProps.scoringData, {
value: {
generatedSolutions: {
$set: [{inputs: [{name: 'x', value: 4000.5}], output: 4000.5}],
},
},
})
const testProps = {
...defaultProps,
scoringData,
locale: 'fr',
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
const formatted = await formulaSection.find(':textContent(4 000,5)')
expect(formatted).to.be.ok()
})
it('properly formats en for multiple variables', async () => {
const scoringData = update(defaultProps.scoringData, {
value: {
variables: {
$push: [{name: 'x', min: 0, max: 5, precision: 5}],
},
generatedSolutions: {
$set: [{inputs: [{name: 'x', value: 4.56789}], output: 4.56789}],
},
},
})
const testProps = {
...defaultProps,
scoringData,
}
const subject = await mount(<FormulaSection {...testProps} />)
const formulaSection = within(subject.getDOMNode())
const formatted = await formulaSection.find(':textContent(4.56789)')
expect(formatted).to.be.ok()
})
it('does localize numbers in scientific notation', async () => {
const scoringData = {
...defaultProps.scoringData,
value: {
...defaultProps.scoringData.value,
variables: [
{name: 'x', min: '5.0*10^-3', max: '2.5*10^-2', precision: '1'},
{name: 'y', min: '0.01', max: '0.10', precision: '2'},
],
generatedSolutions: [
{
inputs: [
{name: 'x', value: '6.2*10^-3'},
{name: 'y', value: '0.07'},
],
output: '0.076',
},
],
},
}
await mount(<FormulaSection {...defaultProps} locale="es" scoringData={scoringData} />)
expect(await find(':textContent(6,2*10^-3)')).to.be.ok()
expect(await find(':textContent(0,07)')).to.be.ok()
expect(await find(':textContent(0,076)')).to.be.ok()
})
})
it('should meet a11y standards', async () => {
const subject = await mount(<FormulaSection {...defaultProps} />)
const formulaSection = within(subject.getDOMNode())
expect(
await formulaSection.accessible({
ignores: [
'aria-allowed-role', // TODO: remove this when instui fixes Select
'aria-allowed-attr',
] /* QUIZ-8495 */,
}),
).to.be.true()
})
})