UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

318 lines (285 loc) • 9.41 kB
import React from 'react' import {render} from '@testing-library/react' import runAxeCheck from '@instructure/ui-axe-check' import update from 'immutability-helper' import omit from 'lodash/omit' import words from 'lodash/words' import difference from 'lodash/difference' import RichFillBlankResult from '../index' const defaultScoredData = { value: { fitb_uuid1: { resultScore: 1, userResponse: 'Christopfer', correctAnswer: 'Christopher', }, fitb_uuid2: { resultScore: 1, userResponse: '1492', }, fitb_uuid3: { value: { Spain: { resultScore: 1, userResponded: false, }, Espana: { resultScore: 1, userResponded: false, }, 'Kingdom of Spain': { resultScore: 1, userResponded: false, }, Portugal: { resultScore: 0, userResponded: true, }, }, }, fitb_uuid4: { resultScore: 1, userResponse: 'Asia', correctAnswer: 'Europe', }, fitb_uuid5: { resultScore: 1, correctAnswer: 'Atlantic', userResponse: 'Atlantic Ocean', }, fitb_uuid6: { value: { choice_uuid13_america: { resultScore: 1, userResponded: true, }, }, }, fitb_uuid7: { value: { choice_uuid13_confused: { resultScore: 1, userResponded: false, }, choice_uuid11_peaceful: { resultScore: 0, userResponded: true, }, }, }, }, } const props = { itemBody: `<p><span id="blank_fitb_uuid1"></span> Columbus sailed in <span id="blank_fitb_uuid2"></span> from the country of <span id="blank_fitb_uuid3"></span> on the continent of <span id="blank_fitb_uuid4"></span> across the <span id="blank_fitb_uuid5"></span> and found... <span id="blank_fitb_uuid6"></span>!!! Where the people were " <span id="blank_fitb_uuid7"></span>"</p>`, interactionData: { blanks: [ { id: 'fitb_uuid1', answerType: 'openEntry', }, { id: 'fitb_uuid2', answerType: 'openEntry', }, { id: 'fitb_uuid3', answerType: 'openEntry', }, { id: 'fitb_uuid4', answerType: 'openEntry', }, { id: 'fitb_uuid5', answerType: 'openEntry', }, { id: 'fitb_uuid6', choices: [ {id: 'choice_uuid11_brazil', position: 1, itemBody: 'Brazil'}, {id: 'choice_uuid12_austria', position: 2, itemBody: 'Austria'}, {id: 'choice_uuid13_america', position: 3, itemBody: 'America'}, ], answerType: 'wordbank', }, { id: 'fitb_uuid7', choices: [ {id: 'choice_uuid11_peaceful', position: 1, itemBody: 'peaceful'}, {id: 'choice_uuid12_war-torn', position: 2, itemBody: 'war-torn'}, {id: 'choice_uuid13_confused', position: 3, itemBody: 'confused'}, ], answerType: 'dropdown', }, ], }, scoredData: defaultScoredData, } // A dumb helper for stripping some keys from the complex scoredData above const cloneWithoutKey = (obj, key) => { let objCopy = obj.constructor() let prop for (prop in obj) { if (obj.hasOwnProperty(prop) && prop !== key) { if (typeof obj[prop] === 'object') { objCopy[prop] = cloneWithoutKey(obj[prop], key) } else { objCopy[prop] = obj[prop] } } } return objCopy } describe('Rich Fill in the Blank Result', () => { it('should render', () => { const {container} = render(<RichFillBlankResult {...props} />) expect(container.firstChild).toBeInTheDocument() }) describe('blanks', () => { it('renders text content for each blank item', () => { const {container} = render(<RichFillBlankResult {...props} />) const showingText = container.textContent expect(showingText).toContain('Columbus sailed in') expect(showingText).toContain('and found') }) describe('blanks', () => { it('renders a Feedback wrapper for each blank item', () => { const {container} = render(<RichFillBlankResult {...props} />) // FeedbackWrapper renders elements with data-automation attributes for status // Each blank renders a user response text within the component // With 7 blanks, we should see 7 user response areas const blankElements = container.querySelectorAll('[id^="blank_"]') expect(blankElements).toHaveLength(7) }) it('renders the correct user response and correct answer for the first blank', () => { const {container} = render(<RichFillBlankResult {...props} />) // The first blank should show user response 'Christopfer' expect(container.textContent).toContain('Christopfer') // The correct answer label should be present expect(container.textContent).toContain('Correct answer:') }) }) }) describe('scoredData variants', () => { it("renders if wordbank choice id is not in blank's choice list", () => { const newVal = { choice_uuid13_confused: { resultScore: 1, userResponded: false, }, // changed to match other blank's choice choice_uuid11_brazil: { resultScore: 0, userResponded: true, }, } const scoredDataWithWordbankChoice = update(defaultScoredData, { value: {fitb_uuid7: {value: {$set: newVal}}}, }) const {container} = render( <RichFillBlankResult {...props} scoredData={scoredDataWithWordbankChoice} />, ) expect(container.firstChild).toBeInTheDocument() }) it('renders if wordbank choice id does not match option', () => { const newVal = { choice_uuid13_confused: { resultScore: 1, userResponded: false, }, some_key_that_does_not_exist: { resultScore: 0, userResponded: true, }, } const scoredDataWithUnmatchedWordbankChoice = update(defaultScoredData, { value: {fitb_uuid7: {value: {$set: newVal}}}, }) const {container} = render( <RichFillBlankResult {...props} scoredData={scoredDataWithUnmatchedWordbankChoice} />, ) expect(container.firstChild).toBeInTheDocument() }) it('renders if wordbank was unanswered', () => { const newVal = { choice_uuid13_confused: { resultScore: 1, userResponded: false, }, } const scoredDataWithNoWordbankChoice = update(defaultScoredData, { value: {fitb_uuid7: {value: {$set: newVal}}}, }) const {container} = render( <RichFillBlankResult {...props} scoredData={scoredDataWithNoWordbankChoice} />, ) expect(container.firstChild).toBeInTheDocument() }) it('renders if value is completely missing', () => { const scoredDataWithNonResponse = update(defaultScoredData, { value: {$apply: val => omit(val, ['fitb_uuid3'])}, }) const {container} = render( <RichFillBlankResult {...props} scoredData={scoredDataWithNonResponse} />, ) expect(container.firstChild).toBeInTheDocument() }) it('renders with missing scores', () => { const scoredDataMissingScores = cloneWithoutKey(defaultScoredData, 'resultScore') const {container} = render( <RichFillBlankResult {...props} scoredData={scoredDataMissingScores} />, ) expect(container.firstChild).toBeInTheDocument() }) it('renders with no user responses', () => { const scoredDataMissingScores = cloneWithoutKey(defaultScoredData, 'userResponse') const {container} = render( <RichFillBlankResult {...props} scoredData={scoredDataMissingScores} />, ) expect(container.firstChild).toBeInTheDocument() }) }) describe('results display', () => { it('renders the correctAnswer if given and incorrect', () => { const withAtlanticWrong = update(defaultScoredData, { value: {fitb_uuid5: {resultScore: {$set: 0}}}, }) const {container} = render(<RichFillBlankResult {...props} scoredData={withAtlanticWrong} />) const innerTextWords = words(container.textContent) const expectedWords = words('Correct Answer:Atlantic') expect(difference(expectedWords, innerTextWords).length).toBe(0) }) it('renders correctAnswer if multiple choice blank was unanswered', () => { const newVal = { choice_uuid13_confused: { resultScore: 1, userResponded: false, }, } const scoredDataWithNoWordbankChoice = update(defaultScoredData, { value: {fitb_uuid7: {value: {$set: newVal}}}, }) const {container} = render( <RichFillBlankResult {...props} scoredData={scoredDataWithNoWordbankChoice} />, ) // The unanswered dropdown blank should show 'confused' as the correct answer expect(container.textContent).toContain('confused') }) }) describe('a11y tests', () => { it('should meet a11y standards', async () => { render( <main> <RichFillBlankResult {...props} /> </main>, ) expect(await runAxeCheck(document.body)).toBe(true) }) }) })