UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

237 lines (198 loc) • 8.15 kB
import {vi} from 'vitest' import React from 'react' import {render, screen} from '@testing-library/react' import userEvent from '@testing-library/user-event' import runAxeCheck from '@instructure/ui-axe-check' import Match from '../Match' describe('Shared Match component', () => { const updateStub = vi.fn() const defaultProps = { disabled: false, handleResponseUpdate: updateStub, itemBody: 'Match the Presidential term with the corresponding President', interactionData: { questions: [ {id: 'quuid1', itemBody: '1st President'}, {id: 'quuid2', itemBody: '16th President'}, {id: 'quuid3', itemBody: '44th President'}, {id: 'quuid4', itemBody: '45th President'}, {id: 'quuid5', itemBody: '46th President'}, ], answers: [ 'George Washington', 'george washington', 'Thomas Jefferson', 'Abraham Lincoln', 'Barack Obama', 'Donald"Trump', "Jo'e Biden", ], }, selectedAnswers: {value: {}}, readOnly: false, } afterEach(() => { updateStub.mockClear() }) it('should render', () => { const {container} = render(<Match {...defaultProps} />) expect(container.firstChild).toBeInTheDocument() }) describe('rendering', () => { it('renders each question', () => { const {container} = render(<Match {...defaultProps} />) const expected = defaultProps.interactionData.questions.map(question => question.itemBody) const result = Array.from(container.querySelectorAll('[data-testid="question"]')).map( elem => elem.innerHTML, ) const contains = result.reduce((prev, curr, i) => curr.includes(expected[i]) && prev, true) expect(contains).toBe(true) }) it('renders an option for each answer', async () => { render(<Match {...defaultProps} />) const select = await screen.findByRole('combobox', {name: /1st president/i}) userEvent.click(select) const options = await screen.findAllByRole('option') const availableOptions = options.map(option => option.textContent) expect(availableOptions).toEqual(defaultProps.interactionData.answers) }) it('renders with answers which are supplied', async () => { render( <Match {...defaultProps} selectedAnswers={{ value: { quuid1: 'Thomas Jefferson', quuid3: 'Barack Obama', }, }} />, ) const firstSelect = await screen.findByRole('combobox', {name: /1st president/i}) userEvent.click(firstSelect) const firstSelection = screen.queryByRole('option', {selected: true}) const secondSelect = await screen.findByRole('combobox', {name: /16th president/i}) userEvent.click(secondSelect) const secondSelection = screen.queryByRole('option', {selected: true}) const thirdSelect = await screen.findByRole('combobox', {name: /44th president/i}) userEvent.click(thirdSelect) const thirdSelection = screen.queryByRole('option', {selected: true}) expect(firstSelection.textContent).toBe('Thomas Jefferson') expect(secondSelection).toBeNull() expect(thirdSelection.textContent).toBe('Barack Obama') }) it('renders questions with quotes properly', async () => { render( <Match {...defaultProps} selectedAnswers={{ value: { quuid4: 'Donald"Trump', quuid5: "Jo'e Biden", }, }} />, ) const firstSelect = await screen.findByRole('combobox', {name: /45th president/i}) userEvent.click(firstSelect) const firstSelection = screen.queryByRole('option', {selected: true}) const secondSelect = await screen.findByRole('combobox', {name: /46th president/i}) userEvent.click(secondSelect) const secondSelection = screen.queryByRole('option', {selected: true}) expect(firstSelection.textContent).toBe('Donald"Trump') expect(secondSelection.textContent).toBe("Jo'e Biden") }) }) describe('updating', () => { const selectOptionInFirstSelect = async targetOption => { const select = await screen.findByRole('combobox', {name: /1st president/i}) userEvent.click(select) const options = await screen.findAllByRole('option') const optionToSelect = options.find(option => option.textContent === targetOption) userEvent.click(optionToSelect) } it('does not change case when answers only differ by case', async () => { render(<Match {...defaultProps} />) await selectOptionInFirstSelect('george washington') const call1 = updateStub.mock.calls[0] expect(call1).toEqual([{quuid1: 'george washington'}]) userEvent.click(document.body) const call2 = updateStub.mock.calls[1] expect(call2).toEqual([{quuid1: 'george washington'}]) }) it('updates with a new answer when no answers are present', async () => { render(<Match {...defaultProps} />) await selectOptionInFirstSelect('Thomas Jefferson') const call = updateStub.mock.calls[0] expect(call).toEqual([{quuid1: 'Thomas Jefferson'}]) }) it('updates with a new answer when an answers is already present', async () => { render(<Match {...defaultProps} selectedAnswers={{value: {quuid2: 'Thomas Jefferson'}}} />) await selectOptionInFirstSelect('Abraham Lincoln') const call = updateStub.mock.calls[0] expect(call).toEqual([{quuid1: 'Abraham Lincoln', quuid2: 'Thomas Jefferson'}]) }) it('updates with a changed answer when an answer is already present', async () => { render(<Match {...defaultProps} selectedAnswers={{value: {quuid1: 'Thomas Jefferson'}}} />) await selectOptionInFirstSelect('George Washington') const call = updateStub.mock.calls[0] expect(call).toEqual([{quuid1: 'George Washington'}]) }) it('updates with a changed answer when an answer is already present', async () => { render( <Match {...defaultProps} selectedAnswers={{value: {quuid1: 'Thomas Jefferson', quuid2: 'Abraham Lincoln'}}} />, ) const select = await screen.findByRole('combobox', {name: /1st president/i}) userEvent.clear(select) userEvent.click(document.body) const call = updateStub.mock.calls[0] expect(call).toEqual([{quuid1: '', quuid2: 'Abraham Lincoln'}]) }) it('updates with no answer after answer was present', async () => { render(<Match {...defaultProps} selectedAnswers={{value: {quuid1: 'Abraham Lincoln'}}} />) const select = await screen.findByRole('combobox', {name: /1st president/i}) userEvent.clear(select) userEvent.click(document.body) const call = updateStub.mock.calls[0] expect(call).toEqual([{quuid1: ''}]) }) }) describe('show component', () => { it('does render readOnly elements', () => { render( <Match {...defaultProps} readOnly selectedAnswers={{value: {quuid1: 'Thomas Jefferson', quuid3: 'Barack Obama'}}} />, ) const selects = screen.getAllByRole('combobox') expect(selects.length > 0).toBe(true) selects.forEach(select => { expect(select.readOnly).toBe(true) }) }) }) describe('interaction tests', () => { // TODO: Cannot migrate to RTL - checkInteractionComponents walks React fiber tree to verify // InstUI component props, which is not feasible with RTL. Jira: QUIZ-XXXXX it.skip('should pass the given readOnly prop as readonly interaction to instui components', () => {}) }) describe('a11y tests', () => { it('should meet a11y standards', async () => { render(<Match {...defaultProps} />) await expect( await runAxeCheck(document.body, { ignores: [ 'aria-allowed-role', // TODO: remove this when instui fixes Select 'label', // FIXME: false positive? 'region', ], }), ).toBe(true) }) }) })