import { render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, expect, it, vi } from 'vitest';
import { ActivityCard } from '../../src/product/ActivityCard.tsx';
import { Kbd } from '../../src/product/Kbd.tsx';
import { SearchField } from '../../src/product/SearchField.tsx';
import { SetupChecklist } from '../../src/product/SetupChecklist.tsx';
const STEPS = [
{ state: 'done', title: 'Site address added', detail: 'harborbakery.com' },
{ state: 'done', title: 'Connection verified', detail: 'Secure, read and write' },
{ state: 'next', title: 'Safe copy ready', detail: 'Wursor is creating it' },
{ state: 'todo', title: 'Make your first change', detail: 'Pick a suggestion' },
] as const;
describe('SetupChecklist', () => {
it('lists the steps in order, saying which is done, which is next and which is to do', () => {
render();
const items = within(screen.getByRole('list', { name: 'Setup steps' })).getAllByRole('listitem');
expect(items).toHaveLength(4);
expect(items.map((i) => i.getAttribute('data-state'))).toEqual(['done', 'done', 'next', 'todo']);
expect(within(items[0]!).getByText('Done')).toBeInTheDocument();
expect(within(items[2]!).getByText('Next')).toBeInTheDocument();
expect(within(items[3]!).getByText('To do')).toBeInTheDocument();
});
it('marks the next step as the current one', () => {
render();
expect(screen.getByText('Safe copy ready').closest('li')).toHaveAttribute('aria-current', 'step');
});
it('offers Continue on the next step only', async () => {
const onContinue = vi.fn();
render();
expect(screen.getAllByRole('button', { name: 'Continue' })).toHaveLength(1);
await userEvent.click(screen.getByRole('button', { name: 'Continue' }));
expect(onContinue).toHaveBeenCalledOnce();
});
});
describe('ActivityCard', () => {
const rows = [
{ kind: 'published', text: 'Published the Contact page', time: 'Just now' },
{ kind: 'check', text: 'Checked 9 things, all passed', time: '2 min ago' },
{ kind: 'change', text: 'Changed the Contact page', time: '3 min ago' },
{ kind: 'safe-copy', text: 'Made a safe copy of your site', time: '5 min ago' },
] as const;
it('shows what happened and when, newest first', () => {
render();
const items = within(screen.getByRole('list', { name: 'Activity' })).getAllByRole('listitem');
expect(items.map((i) => i.querySelector('.p-activity-text')?.textContent)).toEqual(rows.map((r) => r.text));
expect(within(items[0]!).getByText('Just now')).toBeInTheDocument();
});
it('gives each kind its own icon', () => {
render();
const kinds = screen.getAllByRole('listitem').map((i) => i.getAttribute('data-kind'));
expect(kinds).toEqual(['published', 'check', 'change', 'safe-copy']);
});
});
describe('Kbd and SearchField', () => {
it('shows a key cap', () => {
render(⌘K);
expect(screen.getByText('⌘K').tagName).toBe('KBD');
});
it('is a labelled search box with a shortcut hint', async () => {
render();
const box = screen.getByRole('searchbox', { name: 'Search the docs' });
expect(box).toHaveAttribute('placeholder', 'Search or ask…');
expect(screen.getByText('⌘K')).toBeInTheDocument();
await userEvent.type(box, 'undo');
expect(box).toHaveValue('undo');
});
it('can be shown but not used until search exists', () => {
render();
expect(screen.getByRole('searchbox', { name: 'Search the docs' })).toBeDisabled();
});
});