/** * Carousel Component Tests * * 測試目標: * 1. 元件能正確渲染 * 2. 元件能正確呼叫廠商 carousel.js * 3. 元件卸載時能正確 cleanup */ import React from 'react'; import { render, waitFor, cleanup as rtlCleanup } from '@testing-library/react'; import { Carousel } from '@/components/aia/carousel'; import * as vendorCarousel from '@vendor-web/js/patterns/carousel.js'; // Mock 廠商 carousel.js jest.mock('@vendor-web/js/patterns/carousel.js', () => ({ carousel: jest.fn(), })); describe('Carousel Component', () => { let mockCleanup: jest.Mock; beforeEach(() => { mockCleanup = jest.fn(); (vendorCarousel.carousel as jest.Mock).mockReturnValue(mockCleanup); }); afterEach(() => { rtlCleanup(); jest.clearAllMocks(); }); it('應該渲染 carousel 結構', () => { const { container } = render(
Item 1
Item 2
); expect(container.querySelector('.carousel')).toBeInTheDocument(); expect(container.querySelector('.carousel-list')).toBeInTheDocument(); expect(container.querySelectorAll('.carousel-control')).toHaveLength(2); }); it('應該呼叫廠商 carousel 初始化函式', async () => { render(
Item 1
); await waitFor(() => { expect(vendorCarousel.carousel).toHaveBeenCalledTimes(1); expect(vendorCarousel.carousel).toHaveBeenCalledWith( expect.any(HTMLElement) ); }); }); it('應該在元件卸載時呼叫 cleanup 函式', async () => { const { unmount } = render(
Item 1
); await waitFor(() => { expect(vendorCarousel.carousel).toHaveBeenCalled(); }); unmount(); expect(mockCleanup).toHaveBeenCalledTimes(1); }); it('應該能處理廠商 JS 未返回 cleanup 的情況', async () => { (vendorCarousel.carousel as jest.Mock).mockReturnValue(undefined); const { unmount } = render(
Item 1
); // 不應該拋出錯誤 expect(() => unmount()).not.toThrow(); }); it('應該能接收並渲染 children', () => { const { getByText } = render(
Test Item 1
Test Item 2
Test Item 3
); expect(getByText('Test Item 1')).toBeInTheDocument(); expect(getByText('Test Item 2')).toBeInTheDocument(); expect(getByText('Test Item 3')).toBeInTheDocument(); }); });