75 lines
3.7 KiB
TypeScript
75 lines
3.7 KiB
TypeScript
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
import App from './App'
|
|
import { demoSeries } from './api/demo'
|
|
import { activeHeroBanMap } from './series-utils'
|
|
|
|
describe('Mixmaker frontend', () => {
|
|
afterEach(() => {
|
|
cleanup()
|
|
window.history.replaceState({}, '', '/')
|
|
})
|
|
|
|
it('renders the event dashboard', async () => {
|
|
window.history.replaceState({}, '', '/events')
|
|
render(<App />)
|
|
expect(await screen.findByRole('heading', { name: 'Your events' })).toBeInTheDocument()
|
|
expect(screen.getByText('Saturday Night Scrim')).toBeInTheDocument()
|
|
expect(screen.getByRole('link', { name: 'Open Summer Clash #4' })).toHaveClass('status-live')
|
|
expect(screen.getByRole('link', { name: 'Open Cancelled Community Mix' })).toHaveClass('status-cancelled')
|
|
expect(screen.getByText('Ember Wolves')).toBeInTheDocument()
|
|
expect(screen.getByText('Neon Foxes')).toBeInTheDocument()
|
|
})
|
|
|
|
it('renders the Discord login screen', async () => {
|
|
window.history.replaceState({}, '', '/login')
|
|
render(<App />)
|
|
expect(await screen.findByRole('link', { name: /continue with discord/i })).toHaveAttribute('href', '/api/auth/discord')
|
|
})
|
|
|
|
it('locks RSVP and exposes live navigation after the scrim starts', async () => {
|
|
window.history.replaceState({}, '', '/events/event-3')
|
|
render(<App />)
|
|
expect(await screen.findByRole('link', { name: /^open live$/i })).toHaveAttribute('href', '/events/event-3/live')
|
|
expect(screen.getByRole('heading', { name: 'Balanced teams' })).toBeInTheDocument()
|
|
expect(screen.getByRole('heading', { name: 'Ember Wolves' })).toBeInTheDocument()
|
|
expect(screen.getByRole('heading', { name: 'Azure Phantoms' })).toBeInTheDocument()
|
|
expect(screen.getByRole('button', { name: 'Going' })).toBeDisabled()
|
|
expect(screen.getByText('Registration has been closed by the organizer.')).toBeInTheDocument()
|
|
})
|
|
|
|
it('keeps the full scrollable match and Bo3 ban history visible', async () => {
|
|
window.history.replaceState({}, '', '/watch/series-1')
|
|
render(<App />)
|
|
expect(await screen.findByRole('heading', { name: 'Bo3 hero ban history' })).toBeInTheDocument()
|
|
expect(screen.getByText('Ember Wolves won the toss')).toBeInTheDocument()
|
|
expect(screen.getByText('Winston')).toBeInTheDocument()
|
|
})
|
|
|
|
it('opens a roster participant in series mode', async () => {
|
|
window.history.replaceState({}, '', '/events/event-3/live')
|
|
render(<App />)
|
|
expect(await screen.findByRole('heading', { name: 'Series control' })).toBeInTheDocument()
|
|
expect(screen.getByRole('link', { name: /spectator view/i })).toHaveAttribute('href', '/watch/series-1')
|
|
fireEvent.click(screen.getByRole('tab', { name: /DPS/i }))
|
|
fireEvent.change(screen.getByRole('searchbox', { name: /search hero/i }), { target: { value: 'tRaC' } })
|
|
expect(screen.getByRole('radio', { name: /Tracer/i })).toBeInTheDocument()
|
|
expect(screen.queryByRole('radio', { name: /Ana/i })).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('does not reuse completed-map hero bans during map pick', () => {
|
|
expect(activeHeroBanMap({
|
|
...demoSeries,
|
|
currentStep: { ...demoSeries.currentStep, kind: 'map_pick' },
|
|
})).toBeUndefined()
|
|
})
|
|
|
|
it('explains map selection and captain rules in the FAQ', async () => {
|
|
window.history.replaceState({}, '', '/faq')
|
|
render(<App />)
|
|
expect(await screen.findByRole('heading', { name: 'Frequently asked questions' })).toBeInTheDocument()
|
|
expect(screen.getByRole('heading', { name: 'Who picks later maps?' })).toBeInTheDocument()
|
|
expect(screen.getByText(/team that lost that map immediately chooses/i)).toBeInTheDocument()
|
|
})
|
|
})
|