UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

205 lines (166 loc) • 6.32 kB
import {vi} from 'vitest' import React from 'react' import {render} from '@testing-library/react' import withEditTools from '../withEditTools' describe('withEditTools test', () => { let changeItemState let getInteractionErrors beforeEach(() => { changeItemState = vi.fn() getInteractionErrors = vi.fn().mockReturnValue({}) }) class ExampleComponent extends React.Component { static interactionType = {getErrors: (...args) => getInteractionErrors(...args)} render() { return <div /> } } const DecoratedComponent = withEditTools(ExampleComponent) function getBaseProps(overrides = {}) { return { changeItemState, itemBody: 'STEM', interactionData: {}, scoringData: {}, userResponse: {}, errorsAreShowing: true, ...overrides, } } it('should render', () => { const {container} = render(<DecoratedComponent {...getBaseProps()} />) expect(container.firstChild).toBeDefined() }) it('has onDescriptionChange and getErrors functions', () => { let capturedProps class ProbeComponent extends React.Component { static interactionType = {getErrors: (...args) => getInteractionErrors(...args)} render() { capturedProps = this.props return <div /> } } const Decorated = withEditTools(ProbeComponent) render(<Decorated {...getBaseProps()} />) expect(typeof capturedProps.onDescriptionChange).toBe('function') expect(typeof capturedProps.getErrors).toBe('function') }) it('has "getErrors" that gets errors', () => { let capturedProps class ProbeComponent extends React.Component { static interactionType = {getErrors: (...args) => getInteractionErrors(...args)} render() { capturedProps = this.props return <div /> } } const Decorated = withEditTools(ProbeComponent) const errors = { scoringData: { data: { errors: ['scoringData error message'], }, }, } render(<Decorated {...getBaseProps({errors})} />) const scoringDataErrors = capturedProps.getErrors('scoringData.data.errors') const interactionDataErrors = capturedProps.getErrors('interactionData.data.errors') const expectedErrors = errors.scoringData.data.errors.map(error => ({ text: error, type: 'error', })) expect(scoringDataErrors).toEqual(expectedErrors) expect(interactionDataErrors).toHaveLength(0) }) it('has "getErrors" that returns [] when errors are not showing', () => { let capturedProps class ProbeComponent extends React.Component { static interactionType = {getErrors: (...args) => getInteractionErrors(...args)} render() { capturedProps = this.props return <div /> } } const Decorated = withEditTools(ProbeComponent) render( <Decorated {...getBaseProps({ errors: { scoringData: { data: { errors: ['scoringData error message'], }, }, }, errorsAreShowing: false, })} />, ) const scoringDataErrors = capturedProps.getErrors('scoringData.data.errors') const interactionDataErrors = capturedProps.getErrors('interactionData.data.errors') expect(scoringDataErrors).toHaveLength(0) expect(interactionDataErrors).toHaveLength(0) }) it('has "onDescriptionChange" that calls changeItemState', () => { let capturedProps const localChangeItemState = vi.fn() class ProbeComponent extends React.Component { static interactionType = {getErrors: () => ({})} render() { capturedProps = this.props return <div /> } } const Decorated = withEditTools(ProbeComponent) render(<Decorated {...getBaseProps({changeItemState: localChangeItemState})} />) const newDescription = 'This is a new description' capturedProps.onDescriptionChange(newDescription) expect(localChangeItemState).toHaveBeenCalledWith( expect.objectContaining({ itemBody: newDescription, }), ) }) describe('changeItemState', () => { it('calls changeItemState on mount if there are errors', () => { const localChangeItemState = vi.fn() const errors = {interactionData: ['nope']} getInteractionErrors.mockReturnValue(errors) render(<DecoratedComponent {...getBaseProps({changeItemState: localChangeItemState})} />) expect(localChangeItemState).toHaveBeenCalledWith(expect.objectContaining({errors})) }) it('does not call changeItemState on mount if there are no errors', () => { const localChangeItemState = vi.fn() getInteractionErrors.mockReturnValue({}) render(<DecoratedComponent {...getBaseProps({changeItemState: localChangeItemState})} />) expect(localChangeItemState).not.toHaveBeenCalled() }) it('calls changeItemState on update if there are new errors', () => { const localChangeItemState = vi.fn() getInteractionErrors.mockReturnValue({}) const {rerender} = render( <DecoratedComponent {...getBaseProps({changeItemState: localChangeItemState})} />, ) const errors = {interactionData: ['nope']} getInteractionErrors.mockReturnValue(errors) rerender(<DecoratedComponent {...getBaseProps({changeItemState: localChangeItemState})} />) expect(localChangeItemState).toHaveBeenCalledWith(expect.objectContaining({errors})) }) it('does not call changeItemState on update if there are no new errors', () => { const localChangeItemState = vi.fn() const errors = {interactionData: ['nope']} getInteractionErrors.mockReturnValue(errors) const {rerender} = render( <DecoratedComponent {...getBaseProps({changeItemState: localChangeItemState, errors})} />, ) // changeItemState was called once on mount due to errors expect(localChangeItemState).toHaveBeenCalledTimes(1) localChangeItemState.mockClear() // Re-render with same errors - componentDidUpdate should not call again rerender( <DecoratedComponent {...getBaseProps({changeItemState: localChangeItemState, errors})} />, ) expect(localChangeItemState).not.toHaveBeenCalled() }) }) })