import { RenderOptions as RTLRenderOptions, render as rtlRender } from "@testing-library/react" import React from "react" // Provider imports import { ThemeProvider } from "@/features/media-studio/components/top-bar/theme/theme-context" import { I18nProvider } from "@/i18n/services/i18n-provider" // Type-safe provider configuration interface ProviderConfig { timeline?: { initialProject?: any initialState?: any } media?: { initialFiles?: any[] initialState?: any } player?: { initialState?: any } appSettings?: { initialSettings?: any } userSettings?: { initialSettings?: any } projectSettings?: { initialSettings?: any } resources?: { initialResources?: any[] } theme?: { defaultTheme?: "light" | "dark" | "system" storageKey?: string } i18n?: { language?: string fallbackLanguage?: string } } interface RenderOptions extends Omit { providers?: Array providerConfig?: ProviderConfig } // Dynamic provider imports to avoid circular dependencies const getProviders = async () => { const providers = { TimelineProvider: null as any, BrowserStateProvider: null as any, PlayerProvider: null as any, AppSettingsProvider: null as any, UserSettingsProvider: null as any, ProjectSettingsProvider: null as any, ResourcesProvider: null as any, } try { const { TimelineProvider } = await import("@/features/timeline/services/timeline-provider") providers.TimelineProvider = TimelineProvider } catch (_e) { // Provider not available } try { const { BrowserStateProvider } = await import("@/features/browser/services/browser-state-provider") providers.BrowserStateProvider = BrowserStateProvider } catch (_e) { // Provider not available } try { const { PlayerProvider } = await import("@/features/video-player/services/player-provider") providers.PlayerProvider = PlayerProvider } catch (_e) { // Provider not available } try { const { AppProvider } = await import("@/features/app-state/services/app-provider") providers.AppSettingsProvider = AppProvider } catch (_e) { // Provider not available } try { const { UserSettingsProvider } = await import("@/features/user-settings/services/user-settings-provider") providers.UserSettingsProvider = UserSettingsProvider } catch (_e) { // Provider not available } try { const { ProjectSettingsProvider } = await import("@/features/project-settings/services/project-settings-provider") providers.ProjectSettingsProvider = ProjectSettingsProvider } catch (_e) { // Provider not available } try { const { ResourcesProvider } = await import("@/features/resources/services/resources-provider") providers.ResourcesProvider = ResourcesProvider } catch (_e) { // Provider not available } return providers } export function createWrapper(options: RenderOptions = {}) { const { providers = ["theme", "i18n"] } = options return ({ children }: { children: React.ReactNode }) => { let wrapped = children // Always wrap with basic providers first if (providers.includes("i18n")) { wrapped = {wrapped} } if (providers.includes("theme")) { wrapped = {wrapped} } // Wrap with feature providers (these require dynamic imports) // For now, return the basic wrapper - feature providers will be added dynamically return wrapped } } // Synchronous render function for simple cases export function render(ui: React.ReactElement, options: RenderOptions = {}) { const { providers, providerConfig, ...renderOptions } = options const Wrapper = createWrapper({ providers, providerConfig }) return rtlRender(ui, { wrapper: Wrapper, ...renderOptions, }) } // Async render function for complex cases with dynamic providers export async function renderAsync(ui: React.ReactElement, options: RenderOptions = {}) { const { providers = ["theme", "i18n"], providerConfig = {}, ...renderOptions } = options // Get all available providers const availableProviders = await getProviders() const AsyncWrapper = ({ children }: { children: React.ReactNode }) => { let wrapped = children // Apply providers in correct order (outermost first) if (providers.includes("resources") && availableProviders.ResourcesProvider) { const config = providerConfig.resources || {} wrapped = ( {wrapped} ) } if (providers.includes("projectSettings") && availableProviders.ProjectSettingsProvider) { const config = providerConfig.projectSettings || {} wrapped = ( {wrapped} ) } if (providers.includes("userSettings") && availableProviders.UserSettingsProvider) { const config = providerConfig.userSettings || {} wrapped = ( {wrapped} ) } if (providers.includes("appSettings") && availableProviders.AppSettingsProvider) { const config = providerConfig.appSettings || {} wrapped = ( {wrapped} ) } if (providers.includes("player") && availableProviders.PlayerProvider) { const config = providerConfig.player || {} wrapped = ( {wrapped} ) } if (providers.includes("media") && availableProviders.BrowserStateProvider) { const config = providerConfig.media || {} wrapped = ( {wrapped} ) } if (providers.includes("timeline") && availableProviders.TimelineProvider) { const config = providerConfig.timeline || {} wrapped = ( {wrapped} ) } if (providers.includes("theme")) { wrapped = {wrapped} } if (providers.includes("i18n")) { wrapped = {wrapped} } return wrapped } return rtlRender(ui, { wrapper: AsyncWrapper, ...renderOptions, }) } // Utility render functions for common scenarios export const renderWithTheme = (ui: React.ReactElement, theme: "light" | "dark" = "light") => render(ui, { providers: ["theme"], providerConfig: { theme: { defaultTheme: theme } }, }) export const renderWithProviders = ( ui: React.ReactElement, providers: Array = ["theme", "i18n"], ) => render(ui, { providers }) export const renderWithTimeline = (ui: React.ReactElement, initialProject?: any) => renderAsync(ui, { providers: ["theme", "i18n", "timeline"], providerConfig: { timeline: { initialProject } }, }) export const renderWithMedia = (ui: React.ReactElement, initialFiles?: any[]) => renderAsync(ui, { providers: ["theme", "i18n", "media"], providerConfig: { media: { initialFiles } }, }) // Re-export everything from testing library except render export { act, buildQueries, cleanup, findAllByAltText, findAllByDisplayValue, findAllByLabelText, findAllByPlaceholderText, findAllByRole, findAllByTestId, findAllByText, findAllByTitle, findByAltText, findByDisplayValue, findByLabelText, findByPlaceholderText, findByRole, findByTestId, findByText, findByTitle, fireEvent, getAllByAltText, getAllByDisplayValue, getAllByLabelText, getAllByPlaceholderText, getAllByRole, getAllByTestId, getAllByText, getAllByTitle, getByAltText, getByDisplayValue, getByLabelText, getByPlaceholderText, getByRole, getByTestId, getByText, getByTitle, getNodeText, getQueriesForElement, isInaccessible, logRoles, prettyDOM, prettyFormat, queries, queryAllByAltText, queryAllByDisplayValue, queryAllByLabelText, queryAllByPlaceholderText, queryAllByRole, queryAllByTestId, queryAllByText, queryAllByTitle, queryByAltText, queryByDisplayValue, queryByLabelText, queryByPlaceholderText, queryByRole, queryByTestId, queryByText, queryByTitle, screen, waitFor, waitForElementToBeRemoved, within, } from "@testing-library/react"