import React from "react" import { describe, expect, it, vi, beforeEach, afterEach } from "vitest" import { render, act } from "@testing-library/react" import { MemoryRouter } from "react-router-dom" // Hoisted mock icons factory - must be before all vi.mock calls const hoistedIcons = vi.hoisted(() => { const iconNames = [ "AudioOutlined", "PlayCircleOutlined", "PauseCircleOutlined", "SearchOutlined", "PlusOutlined", "EditOutlined", "DeleteOutlined", "UploadOutlined", "UnorderedListOutlined", "AppstoreOutlined", "CloseOutlined", "SoundOutlined", "UserOutlined", "ManOutlined", "WomanOutlined", "CheckOutlined", "TagsOutlined", "MutedOutlined", "RobotOutlined", "LoadingOutlined", "FolderOutlined", "FolderAddOutlined", "MoreOutlined", "ExperimentOutlined", "ExclamationCircleOutlined", "DownloadOutlined", "InboxOutlined", "VideoCameraOutlined", "PictureOutlined", "SaveOutlined", "UndoOutlined", "RedoOutlined", "SettingOutlined", "HistoryOutlined", "FilterOutlined", "FontColorsOutlined", "BgColorsOutlined", "MusicOutlined", "ScissorOutlined", "ThunderboltOutlined", "BulbOutlined", "FundOutlined", "LayoutOutlined", "ColumnHeightOutlined", "SwapOutlined", "LeftOutlined", "RightOutlined", "UpOutlined", "DownOutlined", "CopyOutlined", ] const icons: Record = {} iconNames.forEach((name) => { icons[name] = () => React.createElement("span", null, name.charAt(0)) }) return icons }) // === React Query mock === vi.mock("@tanstack/react-query", () => ({ useQuery: vi.fn(() => ({ data: undefined, isLoading: false, isError: false, refetch: vi.fn(), })), useMutation: vi.fn(() => ({ mutate: vi.fn(), mutateAsync: vi.fn(), isLoading: false, })), useQueryClient: vi.fn(() => ({ invalidateQueries: vi.fn(), setQueryData: vi.fn(), getQueryData: vi.fn(), })), useInfiniteQuery: vi.fn(() => ({ data: { pages: [] }, isLoading: false, fetchNextPage: vi.fn(), hasNextPage: false, })), })) // === Ant Design Icons mock === vi.mock("@ant-design/icons", () => hoistedIcons) // === Ant Design mock === vi.mock("antd", () => ({ message: { success: vi.fn(), error: vi.fn(), warning: vi.fn(), info: vi.fn() }, Modal: ({ open, children, title }: any) => open ? React.createElement("div", { role: "dialog", "data-title": title }, children) : null, Progress: () => React.createElement("div"), Popover: ({ children }: any) => React.createElement("span", null, children), Popconfirm: ({ children }: any) => React.createElement("span", null, children), Tooltip: ({ children }: any) => React.createElement("span", null, children), Tabs: () => React.createElement("div"), Drawer: ({ open, children }: any) => open ? React.createElement("div", { role: "dialog" }, children) : null, Upload: ({ children }: any) => React.createElement("div", null, children), Slider: () => React.createElement("div"), Switch: () => React.createElement("input", { type: "checkbox" }), Segmented: () => React.createElement("div"), Spin: () => React.createElement("div", null, "Loading"), Empty: () => React.createElement("div", null, "Empty"), Divider: () => React.createElement("hr"), Space: ({ children }: any) => React.createElement("div", null, children), Dropdown: ({ children }: any) => React.createElement("span", null, children), Menu: () => React.createElement("div"), Badge: ({ children }: any) => React.createElement("span", null, children), Radio: ({ children }: any) => React.createElement("span", null, children), RadioGroup: ({ children }: any) => React.createElement("div", null, children), Checkbox: ({ children }: any) => React.createElement("span", null, children), InputNumber: () => React.createElement("input", { type: "number" }), Form: ({ children }: any) => React.createElement("form", null, children), FormItem: ({ children }: any) => React.createElement("div", null, children), Result: ({ status, title }: any) => React.createElement("div", { "data-status": status }, title), List: () => React.createElement("div"), Table: () => React.createElement("div"), Pagination: () => React.createElement("div"), Card: ({ children }: any) => React.createElement("div", null, children), Avatar: ({ children }: any) => React.createElement("span", null, children), Collapse: ({ children }: any) => React.createElement("div", null, children), CollapsePanel: ({ children }: any) => React.createElement("div", null, children), Tag: ({ children }: any) => React.createElement("span", null, children), Button: ({ children, onClick }: any) => React.createElement("button", { onClick }, children), Input: ({ placeholder }: any) => React.createElement("input", { placeholder }), Select: ({ children }: any) => React.createElement("select", null, children), Option: ({ children }: any) => React.createElement("option", null, children), ConfigProvider: ({ children }: any) => React.createElement(React.Fragment, null, children), TextArea: ({ placeholder }: any) => React.createElement("textarea", { placeholder }), })) // === UI Components mock === vi.mock("@/components/ui", () => ({ Button: ({ children, onClick }: any) => React.createElement("button", { onClick }, children), Input: ({ placeholder }: any) => React.createElement("input", { placeholder }), Modal: ({ open, children }: any) => open ? React.createElement("div", { role: "dialog" }, children) : null, Drawer: ({ open, children }: any) => open ? React.createElement("div", { role: "dialog" }, children) : null, Empty: () => React.createElement("div", null, "Empty"), Card: ({ children }: any) => React.createElement("div", null, children), Tag: ({ children }: any) => React.createElement("span", null, children), Tooltip: ({ children }: any) => React.createElement("span", null, children), Select: ({ children }: any) => React.createElement("select", null, children), Progress: () => React.createElement("div"), Upload: ({ children }: any) => React.createElement("div", null, children), Slider: () => React.createElement("div"), Switch: () => React.createElement("input", { type: "checkbox" }), })) // === API mocks === vi.mock("@/api/assets", () => ({ getAssetLibraries: vi.fn().mockResolvedValue([]), createAssetLibrary: vi.fn().mockResolvedValue({}), deleteAssetLibrary: vi.fn().mockResolvedValue({}), getAssetsByKind: vi.fn().mockResolvedValue({ items: [], total: 0 }), getAssets: vi.fn().mockResolvedValue({ items: [], total: 0 }), createAsset: vi.fn().mockResolvedValue({}), updateAsset: vi.fn().mockResolvedValue({}), deleteAsset: vi.fn().mockResolvedValue({}), uploadAssetDirect: vi.fn().mockResolvedValue({}), batchDeleteAssets: vi.fn().mockResolvedValue({}), batchTagAssets: vi.fn().mockResolvedValue({}), AssetType: { VIDEO: "video", IMAGE: "image", AUDIO: "audio", VOICE: "voice" }, })) vi.mock("@/api/tags", () => ({ getTags: vi.fn().mockResolvedValue({ items: [] }), createTag: vi.fn().mockResolvedValue({}), tagAsset: vi.fn().mockResolvedValue({}), untagAsset: vi.fn().mockResolvedValue({}), })) vi.mock("@/api/tts", () => ({ synthesizeSpeech: vi.fn().mockResolvedValue({ job_id: "test-job" }), getTTSJobStatus: vi.fn().mockResolvedValue({ status: "completed", audio_url: "" }), saveTtsToLibrary: vi.fn().mockResolvedValue({}), })) vi.mock("@/api/voices", () => ({ fetchPresetVoices: vi.fn().mockResolvedValue({ items: [] }), })) // === PageHead mock === vi.mock("@/components/layout/PageHead", () => ({ default: ({ title }: { title: string }) => React.createElement("div", { "data-testid": "page-head" }, title), })) import VoiceMaterialLibrary from "@/pages/voice-materials/VoiceMaterialLibrary" describe("VoiceMaterialLibrary", () => { beforeEach(() => { vi.useFakeTimers() }) afterEach(() => { vi.useRealTimers() }) it("renders without crashing", () => { const { container } = render( React.createElement(MemoryRouter, null, React.createElement(VoiceMaterialLibrary)), ) expect(container).toBeTruthy() }) it("advances timers without errors", () => { render(React.createElement(MemoryRouter, null, React.createElement(VoiceMaterialLibrary))) act(() => { vi.advanceTimersByTime(30000) }) expect(true).toBe(true) }) })