test(Button): cover Button with tests
This commit is contained in:
89
src/shared/ui/Button/Button.svelte.test.ts
Normal file
89
src/shared/ui/Button/Button.svelte.test.ts
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import {
|
||||||
|
fireEvent,
|
||||||
|
render,
|
||||||
|
screen,
|
||||||
|
} from '@testing-library/svelte';
|
||||||
|
import { createRawSnippet } from 'svelte';
|
||||||
|
import Button from './Button.svelte';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a plain text snippet for passing as children/icon prop
|
||||||
|
*/
|
||||||
|
function textSnippet(text: string) {
|
||||||
|
return createRawSnippet(() => ({
|
||||||
|
render: () => `<span>${text}</span>`,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Button', () => {
|
||||||
|
describe('Rendering', () => {
|
||||||
|
it('renders with text label', () => {
|
||||||
|
render(Button, { children: textSnippet('Click me') });
|
||||||
|
expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has type="button" by default', () => {
|
||||||
|
render(Button, { children: textSnippet('Submit') });
|
||||||
|
expect(screen.getByRole('button')).toHaveAttribute('type', 'button');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders with custom type', () => {
|
||||||
|
render(Button, { children: textSnippet('Submit'), type: 'submit' });
|
||||||
|
expect(screen.getByRole('button')).toHaveAttribute('type', 'submit');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders icon-only when icon snippet is provided without children', () => {
|
||||||
|
render(Button, { icon: textSnippet('×') });
|
||||||
|
const btn = screen.getByRole('button');
|
||||||
|
expect(btn).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Disabled state', () => {
|
||||||
|
it('is not disabled by default', () => {
|
||||||
|
render(Button, { children: textSnippet('Click') });
|
||||||
|
expect(screen.getByRole('button')).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is disabled when disabled prop is true', () => {
|
||||||
|
render(Button, { children: textSnippet('Click'), disabled: true });
|
||||||
|
expect(screen.getByRole('button')).toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Click interaction', () => {
|
||||||
|
it('calls onclick when clicked', async () => {
|
||||||
|
const handler = vi.fn();
|
||||||
|
render(Button, { children: textSnippet('Click'), onclick: handler });
|
||||||
|
await fireEvent.click(screen.getByRole('button'));
|
||||||
|
expect(handler).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls onclick multiple times on repeated clicks', async () => {
|
||||||
|
const handler = vi.fn();
|
||||||
|
render(Button, { children: textSnippet('Click'), onclick: handler });
|
||||||
|
const btn = screen.getByRole('button');
|
||||||
|
await fireEvent.click(btn);
|
||||||
|
await fireEvent.click(btn);
|
||||||
|
await fireEvent.click(btn);
|
||||||
|
expect(handler).toHaveBeenCalledTimes(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Variants', () => {
|
||||||
|
it.each(['primary', 'secondary', 'outline', 'ghost', 'icon', 'tertiary'] as const)(
|
||||||
|
'renders %s variant without error',
|
||||||
|
variant => {
|
||||||
|
render(Button, { children: textSnippet('Click'), variant });
|
||||||
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sizes', () => {
|
||||||
|
it.each(['xs', 'sm', 'md', 'lg', 'xl'] as const)('renders %s size without error', size => {
|
||||||
|
render(Button, { children: textSnippet('Click'), size });
|
||||||
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user