import { describe, it, expect, vi } from 'vitest'; import { render, screen } from '@testing-library/svelte'; import { userEvent } from '@testing-library/user-event'; import RecipeCard from './RecipeCard.svelte'; const mockRecipe = { id: 'recipe-1', name: 'Spaghetti Bolognese', cookTimeMin: 30, effort: 'Easy', heroImageUrl: undefined }; describe('RecipeCard', () => { it('renders the recipe name', () => { render(RecipeCard, { props: { recipe: mockRecipe } }); expect(screen.getByText('Spaghetti Bolognese')).toBeInTheDocument(); }); it('renders cook time when present', () => { render(RecipeCard, { props: { recipe: mockRecipe } }); expect(screen.getByText(/30/)).toBeInTheDocument(); }); it('renders effort when present', () => { render(RecipeCard, { props: { recipe: mockRecipe } }); expect(screen.getByText(/easy/i)).toBeInTheDocument(); }); it('shows placeholder when no heroImageUrl', () => { render(RecipeCard, { props: { recipe: { ...mockRecipe, heroImageUrl: undefined } } }); expect(screen.queryByRole('img')).not.toBeInTheDocument(); expect(document.querySelector('[data-testid="image-placeholder"]')).toBeInTheDocument(); }); it('shows image when heroImageUrl is provided', () => { render(RecipeCard, { props: { recipe: { ...mockRecipe, heroImageUrl: '/uploads/test.jpg' } } }); const img = screen.getByRole('img'); expect(img).toHaveAttribute('src', '/uploads/test.jpg'); expect(img).toHaveAttribute('alt', 'Spaghetti Bolognese'); }); it('has a link to the recipe detail page', () => { render(RecipeCard, { props: { recipe: mockRecipe } }); const link = screen.getByRole('link', { name: /Spaghetti Bolognese/i }); expect(link).toHaveAttribute('href', '/recipes/recipe-1'); }); it('shows Jetzt kochen link when onplan provided', () => { render(RecipeCard, { props: { recipe: mockRecipe, onplan: vi.fn() } }); const cookLink = screen.getByRole('link', { name: /Jetzt kochen/i }); expect(cookLink).toHaveAttribute('href', '/cook/recipe-1'); }); it('does not show Jetzt kochen when onplan not provided', () => { render(RecipeCard, { props: { recipe: mockRecipe } }); expect(screen.queryByRole('link', { name: /Jetzt kochen/i })).toBeNull(); }); it('shows Zur Woche + button when onplan provided', () => { render(RecipeCard, { props: { recipe: mockRecipe, onplan: vi.fn() } }); expect(screen.getByRole('button', { name: /Zur Woche/i })).toBeTruthy(); }); it('calls onplan with recipeId and name when Zur Woche + clicked', async () => { const onplan = vi.fn(); const user = userEvent.setup(); render(RecipeCard, { props: { recipe: mockRecipe, onplan } }); await user.click(screen.getByRole('button', { name: /Zur Woche/i })); expect(onplan).toHaveBeenCalledWith('recipe-1', 'Spaghetti Bolognese'); }); it('applies compact image height when compact prop is true', () => { render(RecipeCard, { props: { recipe: mockRecipe, compact: true } }); const imageArea = document.querySelector('[data-testid="image-area"]'); expect(imageArea?.className).toContain('h-[64px]'); }); it('applies full image height when compact prop is false', () => { render(RecipeCard, { props: { recipe: mockRecipe, compact: false } }); const imageArea = document.querySelector('[data-testid="image-area"]'); expect(imageArea?.className).toContain('h-[100px]'); }); });