From d35bd79d6d7ad0db7910a27781d0fa9c7db4dfb5 Mon Sep 17 00:00:00 2001 From: hjlarry Date: Thu, 9 Apr 2026 17:15:31 +0800 Subject: [PATCH] fix: unittests --- .../app/app-access-control-flow.test.tsx | 36 ++++++++++++++++- web/__tests__/app/app-publisher-flow.test.tsx | 40 +++++++++++++++++-- .../account-setting/__tests__/index.spec.tsx | 36 +++++++++++++++++ ...llaboration-manager.merge-behavior.test.ts | 4 +- .../__tests__/collaboration-manager.test.ts | 4 +- .../core/__tests__/crdt-provider.test.ts | 2 +- 6 files changed, 113 insertions(+), 9 deletions(-) diff --git a/web/__tests__/app/app-access-control-flow.test.tsx b/web/__tests__/app/app-access-control-flow.test.tsx index 49443eb4ec..792d6e3463 100644 --- a/web/__tests__/app/app-access-control-flow.test.tsx +++ b/web/__tests__/app/app-access-control-flow.test.tsx @@ -1,4 +1,5 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { beforeEach, describe, expect, it, vi } from 'vitest' import AppPublisher from '@/app/components/app/app-publisher' import { AccessMode } from '@/models/access-control' @@ -23,6 +24,27 @@ let mockAppDetail: { } } | null = null +const createTestQueryClient = () => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + mutations: { + retry: false, + }, + }, + }) + +const renderWithQueryClient = (ui: React.ReactElement) => { + const queryClient = createTestQueryClient() + return render( + + {ui} + , + ) +} + vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key, @@ -76,6 +98,18 @@ vi.mock('@/app/components/app/overview/embedded', () => ({ default: () => null, })) +vi.mock('@/app/components/workflow/collaboration/core/websocket-manager', () => ({ + webSocketClient: { + getSocket: vi.fn(() => null), + }, +})) + +vi.mock('@/app/components/workflow/collaboration/core/collaboration-manager', () => ({ + collaborationManager: { + onAppPublishUpdate: vi.fn(() => vi.fn()), + }, +})) + vi.mock('@/app/components/app/app-access-control', () => ({ default: ({ onConfirm, @@ -115,7 +149,7 @@ describe('App Access Control Flow', () => { }) it('refreshes app detail after confirming access control updates', async () => { - render() + renderWithQueryClient() fireEvent.click(screen.getByRole('button', { name: 'workflow.common.publish' })) fireEvent.click(screen.getByText('app.accessControlDialog.accessItems.specific')) diff --git a/web/__tests__/app/app-publisher-flow.test.tsx b/web/__tests__/app/app-publisher-flow.test.tsx index 5c330cf71e..801bdca4dd 100644 --- a/web/__tests__/app/app-publisher-flow.test.tsx +++ b/web/__tests__/app/app-publisher-flow.test.tsx @@ -1,4 +1,5 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { beforeEach, describe, expect, it, vi } from 'vitest' import AppPublisher from '@/app/components/app/app-publisher' import { AccessMode } from '@/models/access-control' @@ -27,6 +28,27 @@ let mockAppDetail: { } } | null = null +const createTestQueryClient = () => + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + mutations: { + retry: false, + }, + }, + }) + +const renderWithQueryClient = (ui: React.ReactElement) => { + const queryClient = createTestQueryClient() + return render( + + {ui} + , + ) +} + vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key, @@ -106,6 +128,18 @@ vi.mock('@/app/components/app/overview/embedded', () => ({ ), })) +vi.mock('@/app/components/workflow/collaboration/core/websocket-manager', () => ({ + webSocketClient: { + getSocket: vi.fn(() => null), + }, +})) + +vi.mock('@/app/components/workflow/collaboration/core/collaboration-manager', () => ({ + collaborationManager: { + onAppPublishUpdate: vi.fn(() => vi.fn()), + }, +})) + vi.mock('@/app/components/app/app-access-control', () => ({ default: () =>
, })) @@ -183,7 +217,7 @@ describe('App Publisher Flow', () => { it('publishes from the summary panel and tracks the publish event', async () => { const onPublish = vi.fn().mockResolvedValue(undefined) - render( + renderWithQueryClient( { }) it('opens embedded modal and resolves the installed explore target', async () => { - render() + renderWithQueryClient() fireEvent.click(screen.getByText('common.publish')) fireEvent.click(screen.getByText('common.embedIntoSite')) @@ -231,7 +265,7 @@ describe('App Publisher Flow', () => { installed_apps: [], }) - render() + renderWithQueryClient() fireEvent.click(screen.getByText('common.publish')) fireEvent.click(screen.getByText('common.openInExplore')) diff --git a/web/app/components/header/account-setting/__tests__/index.spec.tsx b/web/app/components/header/account-setting/__tests__/index.spec.tsx index 279af0b114..d4e093bd30 100644 --- a/web/app/components/header/account-setting/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/__tests__/index.spec.tsx @@ -47,6 +47,36 @@ vi.mock('@/hooks/use-breakpoints', () => ({ default: vi.fn(), })) +vi.mock('@/context/global-public-context', async (importOriginal) => { + const actual = await importOriginal() + const systemFeatures = { + ...actual.useGlobalPublicStore.getState().systemFeatures, + webapp_auth: { + ...actual.useGlobalPublicStore.getState().systemFeatures.webapp_auth, + enabled: true, + }, + branding: { + ...actual.useGlobalPublicStore.getState().systemFeatures.branding, + enabled: false, + }, + enable_marketplace: true, + enable_collaboration_mode: false, + } + + return { + ...actual, + useGlobalPublicStore: (selector: (state: Record) => unknown) => selector({ + systemFeatures, + }), + useSystemFeaturesQuery: () => ({ + data: systemFeatures, + isPending: false, + isLoading: false, + isFetching: false, + }), + } +}) + vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', () => ({ useDefaultModel: vi.fn(() => ({ data: null, isLoading: false })), useUpdateDefaultModel: vi.fn(() => ({ trigger: vi.fn() })), @@ -54,6 +84,7 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', () useInvalidateDefaultModel: vi.fn(() => vi.fn()), useModelList: vi.fn(() => ({ data: [], isLoading: false })), useSystemDefaultModelAndModelList: vi.fn(() => [null, vi.fn()]), + useMarketplaceAllPlugins: vi.fn(() => ({ plugins: [], isLoading: false })), })) vi.mock('@/app/components/header/account-setting/model-provider-page/atoms', () => ({ @@ -70,6 +101,11 @@ vi.mock('@/service/use-common', () => ({ useProviderContext: vi.fn(), })) +vi.mock('@/app/components/billing/billing-page', () => ({ + __esModule: true, + default: () =>
, +})) + const baseAppContextValue: AppContextValue = { userProfile: { id: '1', diff --git a/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.merge-behavior.test.ts b/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.merge-behavior.test.ts index 93d1c6b746..1368851783 100644 --- a/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.merge-behavior.test.ts +++ b/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.merge-behavior.test.ts @@ -1,6 +1,6 @@ -import type { LoroMap } from 'loro-crdt' +import type { LoroMap } from 'loro-crdt/base64' import type { Node } from '@/app/components/workflow/types' -import { LoroDoc } from 'loro-crdt' +import { LoroDoc } from 'loro-crdt/base64' import { BlockEnum } from '@/app/components/workflow/types' import { CollaborationManager } from '../collaboration-manager' diff --git a/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.test.ts b/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.test.ts index 1728bcad55..957ef76e86 100644 --- a/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.test.ts +++ b/web/app/components/workflow/collaboration/core/__tests__/collaboration-manager.test.ts @@ -1,10 +1,10 @@ -import type { LoroMap } from 'loro-crdt' +import type { LoroMap } from 'loro-crdt/base64' import type { NodePanelPresenceMap, NodePanelPresenceUser, } from '@/app/components/workflow/collaboration/types/collaboration' import type { CommonNodeType, Edge, Node } from '@/app/components/workflow/types' -import { LoroDoc } from 'loro-crdt' +import { LoroDoc } from 'loro-crdt/base64' import { Position } from 'reactflow' import { CollaborationManager } from '@/app/components/workflow/collaboration/core/collaboration-manager' import { BlockEnum } from '@/app/components/workflow/types' diff --git a/web/app/components/workflow/collaboration/core/__tests__/crdt-provider.test.ts b/web/app/components/workflow/collaboration/core/__tests__/crdt-provider.test.ts index 6c4fe91d2a..613c2d1b75 100644 --- a/web/app/components/workflow/collaboration/core/__tests__/crdt-provider.test.ts +++ b/web/app/components/workflow/collaboration/core/__tests__/crdt-provider.test.ts @@ -1,4 +1,4 @@ -import type { LoroDoc } from 'loro-crdt' +import type { LoroDoc } from 'loro-crdt/base64' import type { Socket } from 'socket.io-client' import { CRDTProvider } from '../crdt-provider'