diff --git a/web/__tests__/develop/develop-page-flow.test.tsx b/web/__tests__/develop/develop-page-flow.test.tsx index 703f7362f1..5fe78fb3a6 100644 --- a/web/__tests__/develop/develop-page-flow.test.tsx +++ b/web/__tests__/develop/develop-page-flow.test.tsx @@ -6,27 +6,12 @@ * * Uses real DevelopMain, ApiServer, and Doc components with minimal mocks. */ -import { act, render, screen, waitFor } from '@testing-library/react' +import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { beforeEach, describe, expect, it, vi } from 'vitest' import DevelopMain from '@/app/components/develop' import { AppModeEnum, Theme } from '@/types/app' -beforeEach(() => { - vi.useFakeTimers({ shouldAdvanceTime: true }) -}) - -afterEach(() => { - vi.runOnlyPendingTimers() - vi.useRealTimers() -}) - -async function flushUI() { - await act(async () => { - vi.runAllTimers() - }) -} - let storeAppDetail: unknown vi.mock('@/app/components/app/store', () => ({ @@ -85,6 +70,10 @@ vi.mock('@/service/knowledge/use-dataset', () => ({ useInvalidateDatasetApiKeys: () => vi.fn(), })) +vi.mock('@/app/components/develop/secret-key/secret-key-modal', () => ({ + default: ({ isShow }: { isShow: boolean }) => (isShow ?
: null), +})) + // ---------- tests ---------- describe('DevelopMain page flow', () => { @@ -159,7 +148,7 @@ describe('DevelopMain page flow', () => { }) it('should open API key modal from the page', async () => { - const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }) + const user = userEvent.setup() storeAppDetail = { id: 'app-1', @@ -171,14 +160,11 @@ describe('DevelopMain page flow', () => { render() // Click API Key button in the header - await act(async () => { - await user.click(screen.getByText('appApi.apiKey')) - }) - await flushUI() + await user.click(screen.getByText('appApi.apiKey')) // SecretKeyModal should open await waitFor(() => { - expect(screen.getByText('appApi.apiKeyModal.apiSecretKey')).toBeInTheDocument() + expect(screen.getByRole('dialog', { name: 'Secret key modal' })).toBeInTheDocument() }) }) diff --git a/web/__tests__/explore/explore-app-list-flow.test.tsx b/web/__tests__/explore/explore-app-list-flow.test.tsx index 40f2156c06..accdb6014c 100644 --- a/web/__tests__/explore/explore-app-list-flow.test.tsx +++ b/web/__tests__/explore/explore-app-list-flow.test.tsx @@ -62,6 +62,15 @@ vi.mock('@/context/app-context', () => ({ useAppContext: vi.fn(), })) +vi.mock('@/context/global-public-context', () => ({ + useGlobalPublicStore: () => ({ + systemFeatures: { + enable_explore_banner: false, + enable_trial_app: false, + }, + }), +})) + vi.mock('@/service/use-common', () => ({ useMembers: vi.fn(), })) @@ -108,6 +117,10 @@ vi.mock('@/app/components/app/create-from-dsl-modal/dsl-confirm-modal', () => ({ ), })) +vi.mock('@/app/components/explore/try-app', () => ({ + default: () => null, +})) + const createApp = (overrides: Partial = {}): App => ({ app: { id: overrides.app?.id ?? 'app-id', diff --git a/web/vite.config.ts b/web/vite.config.ts index de74154651..12eca33cda 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -84,6 +84,7 @@ export default defineConfig(({ mode }) => { // Vitest config test: { + detectAsyncLeaks: true, environment: 'jsdom', globals: true, setupFiles: ['./vitest.setup.ts'], diff --git a/web/vitest.setup.ts b/web/vitest.setup.ts index e63ea2b54e..46ec7e5b4b 100644 --- a/web/vitest.setup.ts +++ b/web/vitest.setup.ts @@ -98,6 +98,10 @@ afterEach(async () => { await act(async () => { cleanup() }) + + // Give Headless UI transition scheduler tasks one event-loop turn to settle + // so detectAsyncLeaks does not report teardown false positives. + await new Promise(resolve => setTimeout(resolve, 0)) }) // mock foxact/use-clipboard - not available in test environment