test(ComparisonView): cover parts of the widget with tests

This commit is contained in:
Ilia Mashkov
2026-04-18 01:19:01 +03:00
parent 993812de0a
commit 6c69d7a5b3
4 changed files with 211 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
import {
fireEvent,
render,
screen,
} from '@testing-library/svelte';
import Header from './Header.svelte';
const context = new Map([['responsive', { isMobile: false }]]);
describe('Header', () => {
describe('Rendering', () => {
it('renders a header element', () => {
render(Header, { props: { isSidebarOpen: false, onSidebarToggle: () => {} }, context });
expect(document.querySelector('header')).toBeInTheDocument();
});
it('shows "Open Config" title when sidebar is closed', () => {
render(Header, { props: { isSidebarOpen: false, onSidebarToggle: () => {} }, context });
expect(screen.getByTitle('Open Config')).toBeInTheDocument();
});
it('shows "Close Config" title when sidebar is open', () => {
render(Header, { props: { isSidebarOpen: true, onSidebarToggle: () => {} }, context });
expect(screen.getByTitle('Close Config')).toBeInTheDocument();
});
it('renders a text input for the sample text', () => {
render(Header, { props: { isSidebarOpen: false, onSidebarToggle: () => {} }, context });
expect(screen.getByPlaceholderText('The quick brown fox...')).toBeInTheDocument();
});
it('renders the theme toggle button', () => {
render(Header, { props: { isSidebarOpen: false, onSidebarToggle: () => {} }, context });
expect(screen.getByTitle('Toggle theme')).toBeInTheDocument();
});
});
describe('Interaction', () => {
it('calls onSidebarToggle when toggle button is clicked', async () => {
const onSidebarToggle = vi.fn();
render(Header, { props: { isSidebarOpen: false, onSidebarToggle }, context });
await fireEvent.click(screen.getByTitle('Open Config'));
expect(onSidebarToggle).toHaveBeenCalledOnce();
});
});
});

View File

@@ -0,0 +1,32 @@
import { filterManager } from '$features/GetFonts';
import {
render,
screen,
} from '@testing-library/svelte';
import Search from './Search.svelte';
describe('Search', () => {
beforeEach(() => {
filterManager.queryValue = '';
});
describe('Rendering', () => {
it('renders a text input', () => {
render(Search);
expect(screen.getByRole('textbox')).toBeInTheDocument();
});
it('has "Typeface Search" placeholder', () => {
render(Search);
expect(screen.getByPlaceholderText('Typeface Search')).toBeInTheDocument();
});
});
describe('Value binding', () => {
it('reflects filterManager.queryValue as initial value', () => {
filterManager.queryValue = 'Inter';
render(Search);
expect(screen.getByRole('textbox')).toHaveValue('Inter');
});
});
});

View File

@@ -0,0 +1,91 @@
import {
fireEvent,
render,
screen,
waitFor,
} from '@testing-library/svelte';
import { createRawSnippet } from 'svelte';
import { comparisonStore } from '../../model';
import Sidebar from './Sidebar.svelte';
function textSnippet(text: string) {
return createRawSnippet(() => ({ render: () => `<span>${text}</span>` }));
}
describe('Sidebar', () => {
afterEach(() => {
comparisonStore.side = 'A';
});
describe('Rendering', () => {
it('renders the "Configuration" title', () => {
render(Sidebar);
expect(screen.getByText('Configuration')).toBeInTheDocument();
});
it('renders Left Font and Right Font toggle buttons', () => {
render(Sidebar);
expect(screen.getByText('Left Font')).toBeInTheDocument();
expect(screen.getByText('Right Font')).toBeInTheDocument();
});
it('renders main snippet when provided', () => {
render(Sidebar, { props: { main: textSnippet('main-content') } });
expect(screen.getByText('main-content')).toBeInTheDocument();
});
it('renders controls snippet when provided', () => {
render(Sidebar, { props: { controls: textSnippet('controls-content') } });
expect(screen.getByText('controls-content')).toBeInTheDocument();
});
it('renders nothing in main area when no main snippet', () => {
const { container } = render(Sidebar);
expect(container.querySelector('[data-main]')).toBeNull();
});
});
describe('A/B toggle', () => {
it('Left Font button is active in side A mode', () => {
comparisonStore.side = 'A';
render(Sidebar);
const leftBtn = screen.getByText('Left Font').closest('button');
expect(leftBtn).toHaveClass('shadow-sm');
});
it('Right Font button is not active in side A mode', () => {
comparisonStore.side = 'A';
render(Sidebar);
const rightBtn = screen.getByText('Right Font').closest('button');
expect(rightBtn).not.toHaveClass('shadow-sm');
});
it('Right Font button is active in side B mode', () => {
comparisonStore.side = 'B';
render(Sidebar);
const rightBtn = screen.getByText('Right Font').closest('button');
expect(rightBtn).toHaveClass('shadow-sm');
});
it('clicking Right Font switches to side B', async () => {
render(Sidebar);
expect(comparisonStore.side).toBe('A');
await fireEvent.click(screen.getByText('Right Font'));
expect(comparisonStore.side).toBe('B');
});
it('clicking Left Font switches back to side A from B', async () => {
comparisonStore.side = 'B';
render(Sidebar);
await fireEvent.click(screen.getByText('Left Font'));
expect(comparisonStore.side).toBe('A');
});
it('UI updates reactively after side switch', async () => {
render(Sidebar);
await fireEvent.click(screen.getByText('Right Font'));
const rightBtn = screen.getByText('Right Font').closest('button');
await waitFor(() => expect(rightBtn).toHaveClass('shadow-sm'));
});
});
});

View File

@@ -0,0 +1,42 @@
import { render } from '@testing-library/svelte';
import Thumb from './Thumb.svelte';
describe('Thumb', () => {
describe('Rendering', () => {
it('renders a container element', () => {
const { container } = render(Thumb, { sliderPos: 50, isDragging: false });
expect(container.firstElementChild).toBeInTheDocument();
});
it('applies sliderPos as left CSS style', () => {
const { container } = render(Thumb, { sliderPos: 30, isDragging: false });
const el = container.firstElementChild as HTMLElement;
expect(el.style.left).toBe('30%');
});
it('renders two handle squares', () => {
const { container } = render(Thumb, { sliderPos: 50, isDragging: false });
const handles = container.querySelectorAll('.bg-brand.text-white');
expect(handles).toHaveLength(2);
});
});
describe('Dragging state', () => {
it('applies scale-110 to handles when dragging', () => {
const { container } = render(Thumb, { sliderPos: 50, isDragging: true });
const handles = container.querySelectorAll('.scale-110');
expect(handles.length).toBeGreaterThan(0);
});
it('applies scale-100 to handles when not dragging', () => {
const { container } = render(Thumb, { sliderPos: 50, isDragging: false });
const handles = container.querySelectorAll('.scale-100');
expect(handles.length).toBeGreaterThan(0);
});
it('does not apply scale-110 when not dragging', () => {
const { container } = render(Thumb, { sliderPos: 50, isDragging: false });
expect(container.querySelector('.scale-110')).toBeNull();
});
});
});