ElectronicBabylonianLiterature/ebl-frontend

View on GitHub
src/fragmentarium/ui/info/ScriptSelection.test.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
import React from 'react'
import { render, screen, waitFor } from '@testing-library/react'
import { Fragment } from 'fragmentarium/domain/fragment'
import Promise from 'bluebird'
import SessionContext from 'auth/SessionContext'
import { fragmentFactory } from 'test-support/fragment-fixtures'
import { waitForSpinnerToBeRemoved } from '../../../test-support/waitForSpinnerToBeRemoved'
import ScriptSelection from './ScriptSelection'
import FragmentService from 'fragmentarium/application/FragmentService'
import { PeriodModifiers, Periods } from 'common/period'
import userEvent from '@testing-library/user-event'
import selectEvent from 'react-select-event'
import Session from 'auth/Session'
import MemorySession from 'auth/Session'

jest.mock('fragmentarium/application/FragmentService')
jest.mock('auth/Session')

const updateScript = jest.fn()
let fragment: Fragment
let session: jest.Mocked<Session>

const MockFragmentService = FragmentService as jest.Mock<
  jest.Mocked<FragmentService>
>
const fragmentService = new MockFragmentService()
const script = {
  period: Periods['Old Elamite'],
  periodModifier: PeriodModifiers.Early,
  uncertain: false,
}

async function renderScriptSelection() {
  render(
    <SessionContext.Provider value={session}>
      <ScriptSelection
        fragment={fragment}
        updateScript={updateScript}
        fragmentService={fragmentService}
      />
    </SessionContext.Provider>
  )
  await waitForSpinnerToBeRemoved(screen)
}

beforeEach(async () => {
  fragment = fragmentFactory.build(
    {},
    {
      associations: {
        script: script,
      },
    }
  )
  fragmentService.fetchPeriods.mockReturnValue(
    Promise.resolve([...Object.keys(Periods)])
  )
  session = new (MemorySession as jest.Mock<jest.Mocked<MemorySession>>)()
  session.isAllowedToTransliterateFragments.mockReturnValue(true)

  await renderScriptSelection()

  userEvent.click(screen.getByRole('button'))
})
describe('User Input', () => {
  test.each([
    script.period.name,
    script.periodModifier.name,
    'Uncertain',
    'Save',
  ])('%s is visible', (element) => {
    expect(screen.getByText(element)).toBeInTheDocument()
  })
  test('Save button is disabled', async () => {
    expect(screen.getByText('Save')).toBeDisabled()
  })
  test('Save button is enabled after changes', async () => {
    await selectEvent.select(
      screen.getByText(script.period.name),
      Periods.Hellenistic.name
    )
    expect(screen.getByText('Save')).toBeEnabled()
  })
  test('Save button is disabled after changing back to previous value', async () => {
    await selectEvent.select(
      screen.getByText(script.period.name),
      Periods.Hellenistic.name
    )
    await selectEvent.select(
      screen.getByText(Periods.Hellenistic.name),
      script.period.name
    )
    expect(screen.getByText('Save')).toBeDisabled()
  })
  test('Clicking Save triggers update', async () => {
    updateScript.mockReturnValue(Promise.resolve(fragment))
    await selectEvent.select(
      screen.getByText(script.periodModifier.name),
      PeriodModifiers.Late.name
    )
    userEvent.click(screen.getByText('Save'))

    await waitFor(() => expect(updateScript).toHaveBeenCalled())
  })
})