84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import { render, screen, waitFor, within } from '@testing-library/react'
|
|
import { MemoryRouter } from 'react-router-dom'
|
|
import StatsPage from '../src/pages/StatsPage.js'
|
|
import type { Stats } from '../src/types.js'
|
|
|
|
vi.mock('../src/api.js', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('../src/api.js')>()
|
|
return { ...actual, api: { ...actual.api, getStats: vi.fn() } }
|
|
})
|
|
import { api } from '../src/api.js'
|
|
|
|
const stats: Stats = {
|
|
totals: { items: 4, ripped: 1, notRipped: 3, onLoan: 1 },
|
|
ripRatio: 0.25,
|
|
formats: [
|
|
{ name: 'CD', count: 3 },
|
|
{ name: 'Vinyl', count: 1 },
|
|
],
|
|
decades: [{ name: '1990s', count: 4 }],
|
|
topGenres: [
|
|
{ name: 'Electronic', count: 3 },
|
|
{ name: 'Downtempo', count: 2 },
|
|
],
|
|
topArtists: [{ name: 'Massive Attack', count: 2 }],
|
|
addedByMonth: [
|
|
{ month: '2025-10', count: 0 },
|
|
{ month: '2025-11', count: 0 },
|
|
{ month: '2025-12', count: 0 },
|
|
{ month: '2026-01', count: 0 },
|
|
{ month: '2026-02', count: 0 },
|
|
{ month: '2026-03', count: 0 },
|
|
{ month: '2026-04', count: 0 },
|
|
{ month: '2026-05', count: 0 },
|
|
{ month: '2026-06', count: 0 },
|
|
{ month: '2026-07', count: 0 },
|
|
{ month: '2026-08', count: 4 },
|
|
{ month: '2026-09', count: 0 },
|
|
],
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.mocked(api.getStats).mockReset()
|
|
vi.mocked(api.getStats).mockResolvedValue(stats as never)
|
|
})
|
|
|
|
describe('StatsPage', () => {
|
|
it('renders totals and rip ratio', async () => {
|
|
render(
|
|
<MemoryRouter>
|
|
<StatsPage />
|
|
</MemoryRouter>
|
|
)
|
|
expect((await screen.findAllByText('4')).length).toBeGreaterThanOrEqual(1)
|
|
expect(screen.getByText(/25% ripped/i)).toBeTruthy()
|
|
const onLoanLabel = screen.getByText('on loan')
|
|
expect(within(onLoanLabel.parentElement as HTMLElement).getByText('1')).toBeTruthy()
|
|
})
|
|
|
|
it('renders format, genre, artist and month bars', async () => {
|
|
render(
|
|
<MemoryRouter>
|
|
<StatsPage />
|
|
</MemoryRouter>
|
|
)
|
|
expect(await screen.findByText('CD')).toBeTruthy()
|
|
expect(screen.getByText('Electronic')).toBeTruthy()
|
|
expect(screen.getByText('Massive Attack')).toBeTruthy()
|
|
expect(screen.getByText('1990s')).toBeTruthy()
|
|
// month bars: 12 bars rendered
|
|
expect(document.querySelectorAll('[data-bar]').length).toBeGreaterThanOrEqual(12)
|
|
})
|
|
|
|
it('error state on failure', async () => {
|
|
vi.mocked(api.getStats).mockRejectedValue(new TypeError('fetch failed'))
|
|
render(
|
|
<MemoryRouter>
|
|
<StatsPage />
|
|
</MemoryRouter>
|
|
)
|
|
expect(await screen.findByText(/could not load stats/i)).toBeTruthy()
|
|
})
|
|
})
|