/** * Тесты для Track компонента */ import { render, screen } from "@testing-library/react" import { describe, expect, it, vi } from "vitest" // Import mocks before components import "@/test/mocks/dnd-kit" import "../../__mocks__/hooks" import { Track } from "../../components/track/track" // Мокаем данные трека const mockTrack = { id: "track-1", name: "Test Track", type: "video" as const, clips: [], isLocked: false, isMuted: false, isHidden: false, isSolo: false, volume: 1, pan: 0, height: 120, order: 0, trackEffects: [], trackFilters: [], } describe("Track Component", () => { describe("Component Initialization", () => { it("should be defined and exportable", () => { expect(Track).toBeDefined() expect(typeof Track).toBe("function") }) it("should render without errors", () => { expect(() => { render() }).not.toThrow() }) it("should render with track test id", () => { render() const trackElement = screen.getByTestId("timeline-track") expect(trackElement).toBeInTheDocument() }) }) describe("Track Properties", () => { it("should display track name", () => { render() expect(screen.getByText("Test Track")).toBeInTheDocument() }) it("should handle different track types", () => { const videoTrack = { ...mockTrack, type: "video" as const } const audioTrack = { ...mockTrack, type: "audio" as const, name: "Audio Track" } const { rerender } = render() expect(screen.getByTestId("timeline-track")).toBeInTheDocument() rerender() expect(screen.getByText("Audio Track")).toBeInTheDocument() }) it("should reflect track state in UI", () => { const mutedTrack = { ...mockTrack, isMuted: true, name: "Muted Track" } const lockedTrack = { ...mockTrack, isLocked: true, name: "Locked Track" } const { rerender } = render() expect(screen.getByText("Muted Track")).toBeInTheDocument() rerender() expect(screen.getByText("Locked Track")).toBeInTheDocument() }) }) describe("Track Interactions", () => { it("should handle track selection", () => { const onSelect = vi.fn() render() const trackElement = screen.getByTestId("timeline-track") expect(trackElement).toBeInTheDocument() // Клик по треку должен вызвать onSelect trackElement.click() expect(onSelect).toHaveBeenCalledWith(mockTrack.id) }) it("should handle track lock toggle", () => { const onUpdate = vi.fn() render() // Ищем кнопку lock const lockButton = screen.getByTestId("track-lock-button") expect(lockButton).toBeInTheDocument() lockButton.click() expect(onUpdate).toHaveBeenCalledWith({ ...mockTrack, isLocked: !mockTrack.isLocked }) }) it("should handle track mute toggle for audio tracks", () => { const audioTrack = { ...mockTrack, type: "audio" as const } const onUpdate = vi.fn() render() // Ищем кнопку mute (только для аудио треков) const muteButton = screen.getByTestId("track-mute-button") expect(muteButton).toBeInTheDocument() muteButton.click() expect(onUpdate).toHaveBeenCalledWith({ ...audioTrack, isMuted: !audioTrack.isMuted }) }) it("should not show mute button for video tracks", () => { render() // Для видео треков кнопка mute не должна отображаться const muteButton = screen.queryByTestId("track-mute-button") expect(muteButton).not.toBeInTheDocument() }) }) describe("Track Styling", () => { it("should accept className and style props without errors", () => { const customStyle = { backgroundColor: "blue", height: "150px" } expect(() => { render() }).not.toThrow() const trackElement = screen.getByTestId("timeline-track") expect(trackElement).toBeInTheDocument() }) }) describe("Track State Variations", () => { it("should render hidden track", () => { const hiddenTrack = { ...mockTrack, isHidden: true, name: "Hidden Track" } expect(() => { render() }).not.toThrow() }) it("should render solo track", () => { const soloTrack = { ...mockTrack, isSolo: true, name: "Solo Track" } render() expect(screen.getByText("Solo Track")).toBeInTheDocument() }) it("should handle track with clips", () => { const trackWithClips = { ...mockTrack, clips: [ { id: "clip-1", name: "Test Clip", mediaId: "media-1", trackId: "track-1", startTime: 0, duration: 10, mediaStartTime: 0, mediaEndTime: 10, volume: 1, speed: 1, isReversed: false, opacity: 1, effects: [], filters: [], transitions: [], isSelected: false, isLocked: false, createdAt: new Date(), updatedAt: new Date(), }, ], } expect(() => { render() }).not.toThrow() }) }) describe("Track Error Handling", () => { it("should handle missing track prop gracefully", () => { expect(() => { render() }).not.toThrow() // Проверяем, что отображается fallback expect(screen.getByText("Invalid track")).toBeInTheDocument() }) it("should render track with null gracefully", () => { render() const trackElement = screen.getByTestId("timeline-track") expect(trackElement).toBeInTheDocument() expect(screen.getByText("Invalid track")).toBeInTheDocument() }) }) describe("Track Accessibility", () => { it("should have proper ARIA attributes", () => { render() const trackElement = screen.getByTestId("timeline-track") expect(trackElement).toBeInTheDocument() // Семантический button элемент имеет встроенную доступность expect(trackElement.tagName).toBe("BUTTON") }) it("should be keyboard accessible", () => { render() const trackElement = screen.getByTestId("timeline-track") // Button элементы по умолчанию доступны с клавиатуры expect(trackElement.tagName).toBe("BUTTON") // Button элементы имеют tabIndex 0 по умолчанию expect(trackElement).toBeInTheDocument() }) }) })