import { render, screen } from "@testing-library/react"
import { beforeEach, describe, expect, it, vi } from "vitest"
import { TimelineMarkersLayer } from "../../../components/markers/timeline-markers-layer"
import { ExtendedTimelineMarker } from "../../../types/markers"
// Mock компонента TimelineMarker
vi.mock("../../../components/markers/timeline-marker", () => ({
TimelineMarker: ({ marker, onClick }: any) => (
onClick?.(marker.id)}>
{marker.name}
),
}))
// Mock хука маркеров
const mockUseTimelineMarkers = {
markers: [] as ExtendedTimelineMarker[],
updateMarker: vi.fn(),
removeMarker: vi.fn(),
goToMarker: vi.fn(),
}
vi.mock("../../../hooks/use-timeline-markers", () => ({
useTimelineMarkers: () => mockUseTimelineMarkers,
}))
describe("TimelineMarkersLayer", () => {
const defaultProps = {
timeScale: 100,
scrollOffset: 0,
containerWidth: 1000,
currentTime: 5.5,
duration: 60,
}
const mockMarkers: ExtendedTimelineMarker[] = [
{
id: "marker-1",
time: 10,
name: "Chapter 1",
type: "chapter",
color: "#3b82f6",
isLocked: false,
},
{
id: "marker-2",
time: 25,
name: "Important Note",
type: "note",
color: "#f59e0b",
isLocked: false,
},
{
id: "marker-3",
time: 45,
name: "Export Point",
type: "export",
color: "#ef4444",
isLocked: true,
},
]
beforeEach(() => {
vi.clearAllMocks()
mockUseTimelineMarkers.markers = []
})
it("рендерит слой с правильными размерами и позицией", () => {
render()
const layer = screen.getByTestId("timeline-markers-layer")
expect(layer).toHaveStyle({
transform: "translateX(-0px)",
width: "6000px", // 60 секунд * 100 пикселей/сек
})
})
it("применяет смещение прокрутки", () => {
render()
const layer = screen.getByTestId("timeline-markers-layer")
expect(layer).toHaveStyle({
transform: "translateX(-200px)",
})
})
it("отображает линию текущего времени в правильной позиции", () => {
render()
const playhead = screen.getByTestId("timeline-markers-layer").querySelector(".bg-red-500")
expect(playhead).toHaveStyle({
left: "550px", // 5.5 секунд * 100 пикселей/сек
})
})
it("рендерит все маркеры", () => {
mockUseTimelineMarkers.markers = mockMarkers
render()
expect(screen.getByTestId("marker-marker-1")).toBeInTheDocument()
expect(screen.getByTestId("marker-marker-2")).toBeInTheDocument()
expect(screen.getByTestId("marker-marker-3")).toBeInTheDocument()
expect(screen.getByText("Chapter 1")).toBeInTheDocument()
expect(screen.getByText("Important Note")).toBeInTheDocument()
expect(screen.getByText("Export Point")).toBeInTheDocument()
})
it("передает правильные пропсы в компоненты маркеров", () => {
mockUseTimelineMarkers.markers = [mockMarkers[0]]
render()
// Проверяем, что маркер рендерится с правильными пропсами
const marker = screen.getByTestId("marker-marker-1")
expect(marker).toBeInTheDocument()
})
it("обрабатывает перетаскивание маркера с ограничением по времени", () => {
mockUseTimelineMarkers.markers = [mockMarkers[0]]
const { rerender } = render()
// Симулируем вызов handleMarkerDrag через callback
// В реальном компоненте это происходит через пропс onDrag
const updateMarker = mockUseTimelineMarkers.updateMarker
// Проверяем, что функция updateMarker готова к вызову
expect(updateMarker).toBeDefined()
})
it("ограничивает время маркера в пределах duration", () => {
mockUseTimelineMarkers.markers = [mockMarkers[0]]
render()
// В реальном сценарии handleMarkerDrag должен ограничить время до 30 секунд
// Здесь мы просто проверяем, что компонент рендерится с корректным duration
const layer = screen.getByTestId("timeline-markers-layer")
expect(layer).toHaveStyle({
width: "3000px", // 30 секунд * 100 пикселей/сек
})
})
it("обрабатывает клик по маркеру", () => {
mockUseTimelineMarkers.markers = [mockMarkers[0]]
render()
const marker = screen.getByTestId("marker-marker-1")
marker.click()
// В реальной реализации handleMarkerClick вызовет goToMarker
expect(mockUseTimelineMarkers.goToMarker).toHaveBeenCalledWith("marker-1")
})
it("применяет дополнительные CSS классы", () => {
render()
const layer = screen.getByTestId("timeline-markers-layer")
expect(layer).toHaveClass("custom-layer")
})
it("не рендерит маркеры если список пуст", () => {
mockUseTimelineMarkers.markers = []
render()
// Должна быть только линия текущего времени, без маркеров
const markers = screen.queryAllByTestId(/marker-/)
expect(markers).toHaveLength(0)
})
it("обновляет позицию при изменении timeScale", () => {
const { rerender } = render()
// Меняем масштаб времени
rerender()
const layer = screen.getByTestId("timeline-markers-layer")
expect(layer).toHaveStyle({
width: "12000px", // 60 секунд * 200 пикселей/сек
})
const playhead = layer.querySelector(".bg-red-500")
expect(playhead).toHaveStyle({
left: "1100px", // 5.5 секунд * 200 пикселей/сек
})
})
})