// @vitest-environment jsdom /** * The two manners the page claims (Katerina, 2026-09-09): `page` draws an * icon over the line, `section` draws the line alone. Where each is * aligned is a class the page names and Chrome shows; jsdom pins the * structure. */ import { afterEach, describe, expect, it } from 'vitest' import { cleanup, fireEvent, render, screen } from '@testing-library/react' import { EmptyState } from './EmptyState' afterEach(cleanup) describe('EmptyState', () => { it('draws an icon over the line for a page, centred', () => { const { container } = render() expect(container.querySelector('svg')).not.toBeNull() expect(screen.getByText('Nothing here yet.').className).toContain('text-center') // In the middle of its box both ways: it takes a flex column's room and centres in it. expect(container.firstElementChild!.className).toContain('items-center') expect(container.firstElementChild!.className).toContain('justify-center') expect(container.firstElementChild!.className).toContain('flex-1') }) it('draws the line alone for a section, and nothing else', () => { const { container } = render() expect(container.querySelector('svg')).toBeNull() const line = screen.getByText('Nothing here yet.') expect(container.firstElementChild).toBe(line) expect(line.tagName).toBe('P') expect(line.className).not.toContain('text-center') }) it('a section is the quiet line: caption size, muted colour (Katerina, 2026-09-15)', () => { render() const classes = screen.getByText('Nothing here yet.').className.split(' ') expect(classes).toContain('text-caption') expect(classes).toContain('text-text-muted') expect(classes).not.toContain('text-body-2') expect(classes).not.toContain('text-text-secondary') }) it('a caller’s placement class does not take the quiet look away', () => { render() const classes = screen.getByText('Nothing here yet.').className.split(' ') expect(classes).toEqual(expect.arrayContaining(['text-caption', 'text-text-muted', 'py-8'])) }) it('a section carries no space of its own, so the box it sits in decides where it starts', () => { // Katerina, 2026-09-14: the box is written once and holds the rows or the empty // state; the empty state is never padded. So it may carry no padding or margin. render() const classes = screen.getByText('Nothing here yet.').className.split(' ') expect(classes.filter((c) => /^-?[pm][xytrbl]?-/.test(c))).toEqual([]) }) it('keeps the caller icon for a page', () => { const { container } = render(} message="Nothing here yet." />) expect(container.querySelector('[data-testid="own"]')).not.toBeNull() expect(container.querySelector('svg')).toBeNull() }) it('draws its action under the line as the package Button, outlined (Katerina, 2026-09-18)', () => { let clicked = 0 render( (clicked += 1) }} />) const button = screen.getByRole('button', { name: 'New topic' }) expect(button.className).toContain('border-border-default') expect(button.className).toContain('mt-2') // Under the line, in the same column. expect(screen.getByText('No topics yet.').nextElementSibling).toBe(button) fireEvent.click(button) expect(clicked).toBe(1) }) it('a section takes no action', () => { render( {} }} />) expect(screen.queryByRole('button')).toBeNull() }) })