Barazo default frontend
barazo.forum
1/**
2 * Tests for SaveButton component.
3 * Renders button with state-driven text/icon for idle, saving, and saved states.
4 */
5
6import { describe, it, expect, vi } from 'vitest'
7import { render, screen } from '@testing-library/react'
8import userEvent from '@testing-library/user-event'
9import { axe } from 'vitest-axe'
10import { SaveButton } from './save-button'
11
12describe('SaveButton', () => {
13 it('renders default label in idle state', () => {
14 render(<SaveButton status="idle" onClick={vi.fn()} />)
15 expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument()
16 expect(screen.getByRole('button')).toBeEnabled()
17 })
18
19 it('renders custom label in idle state', () => {
20 render(<SaveButton status="idle" onClick={vi.fn()} label="Save Settings" />)
21 expect(screen.getByRole('button', { name: /save settings/i })).toBeInTheDocument()
22 })
23
24 it('renders saving label and is disabled in saving state', () => {
25 render(<SaveButton status="saving" onClick={vi.fn()} />)
26 const button = screen.getByRole('button', { name: /saving/i })
27 expect(button).toBeDisabled()
28 })
29
30 it('renders custom saving label', () => {
31 render(<SaveButton status="saving" onClick={vi.fn()} savingLabel="Recomputing..." />)
32 expect(screen.getByRole('button', { name: /recomputing/i })).toBeDisabled()
33 })
34
35 it('renders saved label with check icon in saved state', () => {
36 render(<SaveButton status="saved" onClick={vi.fn()} />)
37 const button = screen.getByRole('button', { name: /saved/i })
38 expect(button).toBeEnabled()
39 })
40
41 it('renders custom saved label', () => {
42 render(<SaveButton status="saved" onClick={vi.fn()} savedLabel="Started" />)
43 expect(screen.getByRole('button', { name: /started/i })).toBeInTheDocument()
44 })
45
46 it('calls onClick when clicked in idle state', async () => {
47 const user = userEvent.setup()
48 const onClick = vi.fn()
49 render(<SaveButton status="idle" onClick={onClick} />)
50 await user.click(screen.getByRole('button'))
51 expect(onClick).toHaveBeenCalledOnce()
52 })
53
54 it('does not call onClick when disabled in saving state', async () => {
55 const user = userEvent.setup()
56 const onClick = vi.fn()
57 render(<SaveButton status="saving" onClick={onClick} />)
58 await user.click(screen.getByRole('button'))
59 expect(onClick).not.toHaveBeenCalled()
60 })
61
62 it('has aria-live status region for screen readers', () => {
63 const { rerender } = render(<SaveButton status="idle" onClick={vi.fn()} />)
64 const liveRegion = screen.getByRole('status')
65 expect(liveRegion).toBeInTheDocument()
66 expect(liveRegion).toHaveTextContent('')
67
68 rerender(<SaveButton status="saved" onClick={vi.fn()} />)
69 expect(liveRegion).toHaveTextContent('Saved.')
70 })
71
72 it('announces custom saved label to screen readers', () => {
73 render(<SaveButton status="saved" onClick={vi.fn()} savedLabel="Started" />)
74 expect(screen.getByRole('status')).toHaveTextContent('Started.')
75 })
76
77 it('applies custom className', () => {
78 render(<SaveButton status="idle" onClick={vi.fn()} className="mt-4" />)
79 const button = screen.getByRole('button')
80 expect(button.className).toContain('mt-4')
81 })
82
83 it('passes axe accessibility check in idle state', async () => {
84 const { container } = render(<SaveButton status="idle" onClick={vi.fn()} />)
85 const results = await axe(container)
86 expect(results).toHaveNoViolations()
87 })
88
89 it('passes axe accessibility check in saved state', async () => {
90 const { container } = render(<SaveButton status="saved" onClick={vi.fn()} />)
91 const results = await axe(container)
92 expect(results).toHaveNoViolations()
93 })
94})