UNPKG

@vertisanpro/flowbite-react

Version:

Non-Official React components built for Flowbite and Tailwind CSS

113 lines (112 loc) 6.67 kB
import { act, fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { Carousel } from './Carousel'; beforeEach(() => { vi.useFakeTimers(); vi.spyOn(global, 'setTimeout'); }); afterEach(() => { vi.clearAllMocks(); vi.runOnlyPendingTimers(); vi.useRealTimers(); }); describe('Components / Carousel', () => { it('should render and show first item', () => { render(React.createElement(TestCarousel, null)); expect(carouselItems()[0]).toHaveAttribute('data-active', 'true'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'false'); expect(carouselIndicators()).toHaveLength(5); expect(carouselIndicators()[0]).toHaveClass(activeIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(nonActiveIndicatorClasses); expect(carouselLeftControl()).toBeInTheDocument(); expect(carouselRightControl()).toBeInTheDocument(); }); it('should render without indicators', () => { render(React.createElement(TestCarousel, { indicators: false })); expect(screen.queryAllByTestId('carousel-indicator')).toHaveLength(0); }); it('should change slide via click on indicator', () => { render(React.createElement(TestCarousel, null)); expect(carouselIndicators()[0]).toHaveClass(activeIndicatorClasses); expect(carouselItems()[0]).toHaveAttribute('data-active', 'true'); act(() => { fireEvent.click(carouselIndicators()[3]); }); expect(carouselItems()[0]).toHaveAttribute('data-active', 'false'); expect(carouselItems()[3]).toHaveAttribute('data-active', 'true'); expect(carouselIndicators()[0]).not.toHaveClass(activeIndicatorClasses); expect(carouselIndicators()[3]).toHaveClass(activeIndicatorClasses); }); it('should render custom controls', () => { render(React.createElement(TestCarousel, { leftControl: "<", rightControl: ">" })); expect(screen.getByText(/</)).toBeInTheDocument(); expect(screen.getByText(/>/)).toBeInTheDocument(); }); it('should change slide via click on control', () => { render(React.createElement(TestCarousel, null)); expect(carouselIndicators()[0]).toHaveClass(activeIndicatorClasses); expect(carouselItems()[0]).toHaveAttribute('data-active', 'true'); act(() => { fireEvent.click(carouselRightControl()); }); expect(carouselItems()[0]).toHaveAttribute('data-active', 'false'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'true'); expect(carouselIndicators()[0]).not.toHaveClass(activeIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(activeIndicatorClasses); }); it('should transition to the next item after about 3 s by default', () => { render(React.createElement(TestCarousel, null)); expect(carouselItems()[0]).toHaveAttribute('data-active', 'true'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'false'); expect(carouselIndicators()[0]).toHaveClass(activeIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(nonActiveIndicatorClasses); act(() => { vi.advanceTimersByTime(3000); }); expect(carouselItems()[0]).toHaveAttribute('data-active', 'false'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'true'); expect(carouselIndicators()[0]).toHaveClass(nonActiveIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(activeIndicatorClasses); }); it('should transition to the next item after `slideInterval` when it is provided', () => { render(React.createElement(TestCarousel, { slideInterval: 9000 })); expect(carouselItems()[0]).toHaveAttribute('data-active', 'true'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'false'); expect(carouselIndicators()[0]).toHaveClass(activeIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(nonActiveIndicatorClasses); act(() => { vi.advanceTimersByTime(9000); }); expect(carouselItems()[0]).toHaveAttribute('data-active', 'false'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'true'); expect(carouselIndicators()[0]).toHaveClass(nonActiveIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(activeIndicatorClasses); }); it('should not automatically transition to the next item when `slide={false}`', () => { render(React.createElement(TestCarousel, { slide: false })); expect(carouselItems()[0]).toHaveAttribute('data-active', 'true'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'false'); expect(carouselIndicators()[0]).toHaveClass(activeIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(nonActiveIndicatorClasses); act(() => { vi.advanceTimersByTime(3000); }); expect(carouselItems()[0]).toHaveAttribute('data-active', 'true'); expect(carouselItems()[1]).toHaveAttribute('data-active', 'false'); expect(carouselIndicators()[0]).toHaveClass(activeIndicatorClasses); expect(carouselIndicators()[1]).toHaveClass(nonActiveIndicatorClasses); }); }); const activeIndicatorClasses = 'bg-white dark:bg-gray-800'; const nonActiveIndicatorClasses = 'bg-white/50 hover:bg-white dark:bg-gray-800/50 dark:hover:bg-gray-800'; const TestCarousel = (props) => (React.createElement(Carousel, { ...props }, React.createElement("img", { alt: "", src: "https://flowbite.com/docs/images/carousel/carousel-1.svg", height: "100", width: "100" }), React.createElement("img", { alt: "", src: "https://flowbite.com/docs/images/carousel/carousel-2.svg", height: "100", width: "100" }), React.createElement("img", { alt: "", src: "https://flowbite.com/docs/images/carousel/carousel-3.svg", height: "100", width: "100" }), React.createElement("img", { alt: "", src: "https://flowbite.com/docs/images/carousel/carousel-4.svg", height: "100", width: "100" }), React.createElement("img", { alt: "", src: "https://flowbite.com/docs/images/carousel/carousel-5.svg", height: "100", width: "100" }))); const carouselItems = () => screen.getAllByTestId('carousel-item'); const carouselIndicators = () => screen.getAllByTestId('carousel-indicator'); const carouselLeftControl = () => screen.getByTestId('carousel-left-control'); const carouselRightControl = () => screen.getByTestId('carousel-right-control');