/**
* Integration test for new architecture
*
* Тестирует базовую функциональность новой архитектуры state management
*/
import { render, screen, waitFor } from "@testing-library/react"
import { act } from "react"
import { beforeEach, describe, expect, it, vi } from "vitest"
import { useTimeline } from "../../../timeline/hooks/use-timeline"
import { TimelineProvider } from "../../../timeline/services/timeline-provider"
import { PlayerProvider, usePlayer } from "../../../video-player/services/player-provider"
import { AppProvider, useApp } from "../../services/app-provider"
// Mock backend sync module completely
vi.mock("../../services/backend-sync", () => {
const mockBackendSyncInstance = {
connect: vi.fn().mockResolvedValue(undefined),
disconnect: vi.fn(),
executeCommand: vi.fn().mockResolvedValue({ success: true, data: {} }),
onStateChange: vi.fn().mockReturnValue(() => {}),
onEvent: vi.fn().mockReturnValue(() => {}),
}
return {
getBackendSync: () => mockBackendSyncInstance,
BackendSync: vi.fn(() => mockBackendSyncInstance),
}
})
// Mock user settings
vi.mock("../../../user-settings", () => ({
useUserSettings: () => ({
playerVolume: 50,
handlePlayerVolumeChange: vi.fn(),
}),
}))
// Test component that uses new architecture
function TestComponent() {
const app = useApp()
const timeline = useTimeline()
const player = usePlayer()
const handleCreateProject = async () => {
try {
await timeline.createProject("Test Project")
} catch (error) {
console.error("Create project failed:", error)
}
}
const handlePlay = async () => {
try {
await player.play()
} catch (error) {
console.error("Play failed:", error)
}
}
return (
{app.isConnected ? "Connected" : "Disconnected"}
{timeline.project?.name || "No Project"}
{player.isPlaying ? "Playing" : "Paused"}
{player.currentTime}
{timeline.timeScale}
)
}
function TestWrapper({ children }: { children: React.ReactNode }) {
return (
{children}
)
}
describe("New Architecture Integration", () => {
beforeEach(() => {
vi.clearAllMocks()
})
it("should render all providers without errors", async () => {
render(
,
)
// Проверяем что компонент отрендерился
expect(screen.getByTestId("connection-status")).toBeInTheDocument()
expect(screen.getByTestId("project-name")).toBeInTheDocument()
expect(screen.getByTestId("playback-status")).toBeInTheDocument()
})
it("should show initial state correctly", async () => {
render(
,
)
// Проверяем начальное состояние
expect(screen.getByTestId("project-name")).toHaveTextContent("No Project")
expect(screen.getByTestId("playback-status")).toHaveTextContent("Paused")
expect(screen.getByTestId("current-time")).toHaveTextContent("0")
expect(screen.getByTestId("timeline-scale")).toHaveTextContent("1")
})
it("should handle UI commands locally (timeline scale)", async () => {
render(
,
)
const setScaleButton = screen.getByTestId("set-scale")
// Кликаем на кнопку изменения масштаба
await act(async () => {
setScaleButton.click()
})
// Проверяем что масштаб изменился локально (без backend)
expect(screen.getByTestId("timeline-scale")).toHaveTextContent("2")
})
it("should handle backend commands (create project)", async () => {
const { getBackendSync } = await import("../../services/backend-sync")
const mockBackendSync = getBackendSync()
render(
,
)
const createProjectButton = screen.getByTestId("create-project")
// Кликаем на создание проекта
await act(async () => {
createProjectButton.click()
})
// Проверяем что вызвана backend команда
await waitFor(() => {
expect(mockBackendSync.executeCommand).toHaveBeenCalledWith({
type: "CreateProject",
params: { name: "Test Project", settings: {} },
})
})
})
it("should handle player commands (play)", async () => {
const { getBackendSync } = await import("../../services/backend-sync")
const mockBackendSync = getBackendSync()
render(
,
)
const playButton = screen.getByTestId("play-button")
// Кликаем на воспроизведение
await act(async () => {
playButton.click()
})
// Проверяем что вызвана backend команда
await waitFor(() => {
expect(mockBackendSync.executeCommand).toHaveBeenCalledWith({
type: "Play",
params: {},
})
})
})
it("should maintain separation between UI and backend state", async () => {
render(
,
)
// UI команды должны выполняться мгновенно
const setScaleButton = screen.getByTestId("set-scale")
await act(async () => {
setScaleButton.click()
})
expect(screen.getByTestId("timeline-scale")).toHaveTextContent("2")
// Backend команды требуют асинхронного выполнения
const createProjectButton = screen.getByTestId("create-project")
await act(async () => {
createProjectButton.click()
})
// Проект должен быть создан через backend (mock не изменяет состояние)
expect(screen.getByTestId("project-name")).toHaveTextContent("No Project")
})
})