@instructure/quiz-taking
Version:
224 lines (199 loc) • 7.13 kB
JavaScript
import React from 'react'
import {AttemptHistory} from '../presenter'
import {describe, expect, it, vi} from 'vitest'
import userEvent from '@testing-library/user-event'
import {render, screen} from '../../../../tests/utils/rtlRenderOverride'
describe('AttemptHistory Presenter', () => {
const attempt = {
authoritative: false,
displayName: null,
percentage: 0.8,
pointsPossible: 10,
score: 8,
quizSessionId: '1',
}
const attemptHistory = [attempt]
const props = {
attemptHistory,
getQuizSessions: () => {},
quizId: '42',
scoreToKeep: 'highest',
selectedSessionId: '1',
isSurvey: false,
}
it('renders AttemptHistoryPresenter', () => {
render(<AttemptHistory {...props} />)
expect(screen.getByRole('cell', {name: /8 of 10/i})).toBeInTheDocument()
})
it('renders scores as letter grades when restrictQuantitativeData', () => {
render(
<AttemptHistory
{...props}
restrictQuantitativeData
gradingScheme={[
{name: 'A-', value: 0.9},
{name: 'F', value: 0.0},
]}
/>,
)
expect(screen.getByRole('columnheader', {name: /grade/i})).toBeInTheDocument()
})
describe('includes information about score to keep', () => {
describe('scoreToKeep is average', () => {
it('displays the correct scoreToKeep name', () => {
render(<AttemptHistory {...props} scoreToKeep="average" />)
expect(screen.getByText(/average score/i)).toBeInTheDocument()
})
})
describe('scoreToKeep is first', () => {
it('displays the correct scoreToKeep name', () => {
render(<AttemptHistory {...props} scoreToKeep="first" />)
expect(screen.getByText(/first score is kept/i)).toBeInTheDocument()
})
})
})
it('displays display name if present', () => {
const displayName = 'Average'
const attemptWithDisplayName = {
...attempt,
displayName,
}
render(<AttemptHistory {...props} attemptHistory={[attemptWithDisplayName]} />)
expect(screen.getByText(/average/i)).toBeInTheDocument()
})
it('renders empty when no results are present', () => {
render(<AttemptHistory {...props} attemptHistory={[]} />)
expect(screen.getByText(/no attempt information/i)).toBeInTheDocument()
})
it('renders when missing points possible', () => {
const attempt = {
authoritative: true,
score: 1000000,
quizSessionId: '1',
}
render(<AttemptHistory {...props} attemptHistory={[attempt]} />)
expect(screen.getByText(/1,000,000/i)).toBeInTheDocument()
expect(screen.queryByText(/undefined/i)).not.toBeInTheDocument()
expect(screen.queryByText(/NaN/i)).not.toBeInTheDocument()
})
it('calls getQuizSessions when attempt history is given', () => {
const getQuizSessionsStub = vi.fn()
render(<AttemptHistory {...props} getQuizSessions={getQuizSessionsStub} />)
expect(getQuizSessionsStub).toHaveBeenCalledExactlyOnceWith('42', {ids: ['1']})
})
it('does not call getQuizSessions when no attempt history is given', () => {
const getQuizSessionsStub = vi.fn()
render(
<AttemptHistory {...props} attemptHistory={null} getQuizSessions={getQuizSessionsStub} />,
)
expect(getQuizSessionsStub).not.toHaveBeenCalled()
})
it('does not render anything when no attempt history is given', () => {
render(<AttemptHistory {...props} attemptHistory={null} />)
expect(screen.queryByRole('table', {name: /attempt history/i})).not.toBeInTheDocument()
})
it('does not call getQuizSessions when attempt history does not include quiz session ids', () => {
const attempt = {
authoritative: true,
percentage: 0.8,
pointsPossible: 10,
score: 8,
}
const getQuizSessionsStub = vi.fn()
render(
<AttemptHistory
{...props}
attemptHistory={[attempt]}
getQuizSessions={getQuizSessionsStub}
/>,
)
expect(getQuizSessionsStub).not.toHaveBeenCalled()
})
it('calls getQuizSessions on update if there were none previously', () => {
const getQuizSessionsStub = vi.fn()
const {rerender} = render(
<AttemptHistory {...props} attemptHistory={null} getQuizSessions={getQuizSessionsStub} />,
)
rerender(
<AttemptHistory
{...props}
getQuizSessions={getQuizSessionsStub}
attemptHistory={attemptHistory}
/>,
)
expect(getQuizSessionsStub).toHaveBeenCalledExactlyOnceWith('42', {ids: ['1']})
})
it('calls getQuizSessions on update if the new ones have different quiz session ids', () => {
const getQuizSessionsStub = vi.fn()
const {rerender} = render(<AttemptHistory {...props} getQuizSessions={getQuizSessionsStub} />)
rerender(
<AttemptHistory
{...props}
getQuizSessions={getQuizSessionsStub}
attemptHistory={[{...attempt, quizSessionId: '2'}]}
/>,
)
expect(getQuizSessionsStub).toHaveBeenCalledTimes(2)
expect(getQuizSessionsStub).toHaveBeenCalledWith('42', {ids: ['1']})
expect(getQuizSessionsStub).toHaveBeenCalledWith('42', {ids: ['2']})
})
it('does not call getQuizSessions on update if attempts do not change', () => {
const getQuizSessionsStub = vi.fn()
const {rerender} = render(<AttemptHistory {...props} getQuizSessions={getQuizSessionsStub} />)
rerender(
<AttemptHistory
{...props}
getQuizSessions={getQuizSessionsStub}
attemptHistory={[{...attempt}]}
/>,
)
expect(getQuizSessionsStub).toHaveBeenCalledTimes(1)
})
it('renders average score, if given', () => {
render(<AttemptHistory {...props} averageScore={0.8} />)
expect(screen.getByRole('row', {name: /average score.*80%/i})).toBeInTheDocument()
})
it('renders average score as a letter grade when restrictedQuantitativeData', () => {
render(
<AttemptHistory
{...props}
averageScore={0.91}
restrictQuantitativeData
gradingScheme={[
{name: 'A-', value: 0.9},
{name: 'F', value: 0.0},
]}
/>,
)
expect(screen.getByRole('row', {name: /average score.*a-/i})).toBeInTheDocument()
})
it('falls back to letter grade when percentage is not available', () => {
const attempt = {
authoritative: true,
percentage: null,
pointsPossible: 10,
score: 8,
}
render(
<AttemptHistory
{...props}
attemptHistory={[attempt]}
restrictQuantitativeData
gradingScheme={[
{name: 'A-', value: 0.8},
{name: 'F', value: 0.0},
]}
/>,
)
expect(screen.getByRole('row', {name: /attempt 1.*a-/i})).toBeInTheDocument()
})
describe('when callback is provided', () => {
it('sends quizSessionId to callback', () => {
const onAttemptClick = vi.fn()
render(<AttemptHistory {...props} onAttemptClick={onAttemptClick} />)
const button = screen.getByRole('button', {name: /attempt 1/i})
userEvent.click(button)
expect(onAttemptClick).toHaveBeenCalledWith(attempt.quizSessionId)
})
})
})