import { fireEvent, render, screen } from '@testing-library/svelte'; import { afterEach, describe, expect, it, vi } from 'vitest'; import TestimonialsSection from './TestimonialsSection.svelte'; import { homepageContent } from '$lib/content/homepage'; import type { TestimonialContent } from '$lib/types'; const expectedMappedSlides = [ { reviewer: 'Kate' }, { reviewer: 'Estelle' }, { reviewer: 'Ross' }, { reviewer: 'Nina' } ]; function getActiveSlide(container: HTMLElement) { return container.querySelector('.testimonial-slide-active') as HTMLElement; } function getActiveReviewer(container: HTMLElement) { return getActiveSlide(container).querySelector('.testimonial-author-name')?.textContent; } function getActiveImage(container: HTMLElement) { return getActiveSlide(container).querySelector('img') as HTMLImageElement; } function getNextButton(container: HTMLElement) { return container.querySelector('.testimonial-arrow-right') as HTMLButtonElement; } function getPreviousButton(container: HTMLElement) { return container.querySelector('.testimonial-arrow-left') as HTMLButtonElement; } describe('TestimonialsSection', () => { afterEach(() => { vi.useRealTimers(); }); it('maps all known testimonial images to the local PNG assets', async () => { const { container } = render(TestimonialsSection, { testimonials: homepageContent.testimonials }); const nextButton = getNextButton(container); for (const [index, slide] of expectedMappedSlides.entries()) { expect(getActiveReviewer(container)).toBe(slide.reviewer); expect(getActiveImage(container)).toBeTruthy(); if (index < expectedMappedSlides.length - 1) { await fireEvent.click(nextButton); } } }); it('moves to the next testimonial on arrow click and auto-rotation', async () => { vi.useFakeTimers(); const { container } = render(TestimonialsSection, { testimonials: homepageContent.testimonials }); const nextButton = getNextButton(container); expect(getActiveReviewer(container)).toBe('Kate'); await fireEvent.click(nextButton); expect(getActiveReviewer(container)).toBe('Estelle'); await vi.advanceTimersByTimeAsync(9000); expect(getActiveReviewer(container)).toBe('Ross'); }); it('wraps to the last testimonial when navigating backwards from the first slide', async () => { const { container } = render(TestimonialsSection, { testimonials: homepageContent.testimonials }); const previousButton = getPreviousButton(container); expect(getActiveReviewer(container)).toBe('Kate'); await fireEvent.click(previousButton); expect(getActiveReviewer(container)).toBe('Nina'); expect(getActiveImage(container)).toBeTruthy(); }); it('keeps custom testimonial images and filters out testimonials with no image', async () => { const customTestimonials: TestimonialContent[] = [ ...homepageContent.testimonials, { reviewer: 'Casey', detail: "Poppy's mum", type: 'Client', quote: 'Thoughtful updates and a very happy dog after every walk.', imageUrl: '/images/custom-casey-review.webp', showInSlider: true }, { reviewer: 'Jordan', detail: "Scout's dad", type: 'Client', quote: 'Should be hidden because there is no image.', showInSlider: true } ]; const { container } = render(TestimonialsSection, { testimonials: customTestimonials }); const nextButton = getNextButton(container); expect(container.querySelectorAll('.testimonial-slide')).toHaveLength(5); for (let step = 0; step < 4; step += 1) { await fireEvent.click(nextButton); } expect(getActiveReviewer(container)).toBe('Casey'); expect(getActiveImage(container)).toBeTruthy(); expect(screen.queryByText('Jordan')).not.toBeInTheDocument(); }); it('can start on a different testimonial for a different page seed', () => { const { container } = render(TestimonialsSection, { testimonials: homepageContent.testimonials, seedKey: '/dog-walking' }); expect(getActiveReviewer(container)).not.toBe('Kate'); }); });