refactor(web): move component tests into sibling __tests__ directories (#33623)

Co-authored-by: CodingOnStar <hanxujiang@dify.com>
This commit is contained in:
Coding On Star 2026-03-18 10:49:30 +08:00 committed by GitHub
parent 485da15a4d
commit 6100acb780
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 132 additions and 126 deletions

View File

@ -63,7 +63,8 @@ pnpm analyze-component <path> --review
### File Naming
- Test files: `ComponentName.spec.tsx` (same directory as component)
- Test files: `ComponentName.spec.tsx` inside a same-level `__tests__/` directory
- Placement rule: Component, hook, and utility tests must live in a sibling `__tests__/` folder at the same level as the source under test. For example, `foo/index.tsx` maps to `foo/__tests__/index.spec.tsx`, and `foo/bar.ts` maps to `foo/__tests__/bar.spec.ts`.
- Integration tests: `web/__tests__/` directory
## Test Structure Template

View File

@ -2,7 +2,7 @@ import * as amplitude from '@amplitude/analytics-browser'
import { sessionReplayPlugin } from '@amplitude/plugin-session-replay-browser'
import { render } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import AmplitudeProvider, { isAmplitudeEnabled } from './AmplitudeProvider'
import AmplitudeProvider, { isAmplitudeEnabled } from '../AmplitudeProvider'
const mockConfig = vi.hoisted(() => ({
AMPLITUDE_API_KEY: 'test-api-key',

View File

@ -1,18 +1,18 @@
import { describe, expect, it } from 'vitest'
import AmplitudeProvider, { isAmplitudeEnabled } from './AmplitudeProvider'
import AmplitudeProvider, { isAmplitudeEnabled } from '../AmplitudeProvider'
import indexDefault, {
isAmplitudeEnabled as indexIsAmplitudeEnabled,
resetUser,
setUserId,
setUserProperties,
trackEvent,
} from './index'
} from '../index'
import {
resetUser as utilsResetUser,
setUserId as utilsSetUserId,
setUserProperties as utilsSetUserProperties,
trackEvent as utilsTrackEvent,
} from './utils'
} from '../utils'
describe('Amplitude index exports', () => {
it('exports AmplitudeProvider as default', () => {

View File

@ -1,4 +1,4 @@
import { resetUser, setUserId, setUserProperties, trackEvent } from './utils'
import { resetUser, setUserId, setUserProperties, trackEvent } from '../utils'
const mockState = vi.hoisted(() => ({
enabled: true,
@ -20,7 +20,7 @@ const MockIdentify = vi.hoisted(() =>
},
)
vi.mock('./AmplitudeProvider', () => ({
vi.mock('../AmplitudeProvider', () => ({
isAmplitudeEnabled: () => mockState.enabled,
}))

View File

@ -1,5 +1,5 @@
import { fireEvent, render, screen } from '@testing-library/react'
import DynamicPdfPreview from './dynamic-pdf-preview'
import DynamicPdfPreview from '../dynamic-pdf-preview'
type DynamicPdfPreviewProps = {
url: string
@ -44,7 +44,7 @@ vi.mock('next/dynamic', () => ({
default: mockDynamic,
}))
vi.mock('./pdf-preview', () => ({
vi.mock('../pdf-preview', () => ({
default: mockPdfPreview,
}))
@ -78,7 +78,7 @@ describe('dynamic-pdf-preview', () => {
expect(loaded).toBeInstanceOf(Promise)
const loadedModule = (await loaded) as { default: unknown }
const pdfPreviewModule = await import('./pdf-preview')
const pdfPreviewModule = await import('../pdf-preview')
expect(loadedModule.default).toBe(pdfPreviewModule.default)
})

View File

@ -1,9 +1,9 @@
import { render, screen } from '@testing-library/react'
import DOMPurify from 'dompurify'
import { validateDirectiveProps } from './components/markdown-with-directive-schema'
import WithIconCardItem from './components/with-icon-card-item'
import WithIconCardList from './components/with-icon-card-list'
import { MarkdownWithDirective } from './index'
import { validateDirectiveProps } from '../components/markdown-with-directive-schema'
import WithIconCardItem from '../components/with-icon-card-item'
import WithIconCardList from '../components/with-icon-card-list'
import { MarkdownWithDirective } from '../index'
const FOUR_COLON_RE = /:{4}/

View File

@ -1,4 +1,4 @@
import { validateDirectiveProps } from './markdown-with-directive-schema'
import { validateDirectiveProps } from '../markdown-with-directive-schema'
describe('markdown-with-directive-schema', () => {
beforeEach(() => {

View File

@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react'
import WithIconCardItem from './with-icon-card-item'
import WithIconCardItem from '../with-icon-card-item'
describe('WithIconCardItem', () => {
beforeEach(() => {

View File

@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react'
import WithIconCardList from './with-icon-card-list'
import WithIconCardList from '../with-icon-card-list'
describe('WithIconCardList', () => {
beforeEach(() => {

View File

@ -1,7 +1,7 @@
import type { WorkflowNodesMap } from '@/app/components/base/prompt-editor/types'
import { renderHook } from '@testing-library/react'
import { BlockEnum } from '@/app/components/workflow/types'
import { useLlmModelPluginInstalled } from './use-llm-model-plugin-installed'
import { useLlmModelPluginInstalled } from '../use-llm-model-plugin-installed'
let mockModelProviders: Array<{ provider: string }> = []

View File

@ -1,6 +1,6 @@
import type { ReactNode } from 'react'
import { render } from '@testing-library/react'
import MenuDialog from './menu-dialog'
import MenuDialog from '../menu-dialog'
type DialogProps = {
children: ReactNode

View File

@ -2,7 +2,7 @@ import type { ReactNode } from 'react'
import { render } from '@testing-library/react'
import { ToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import EditWorkspaceModal from './index'
import EditWorkspaceModal from '../index'
type DialogProps = {
children: ReactNode

View File

@ -7,7 +7,7 @@ import {
useModelProviderListExpanded,
useResetModelProviderListExpanded,
useSetModelProviderListExpanded,
} from './atoms'
} from '../atoms'
const createWrapper = () => {
return ({ children }: { children: ReactNode }) => (

View File

@ -1,11 +1,11 @@
import type { Model, ModelItem, ModelProvider } from './declarations'
import type { CredentialPanelState } from './provider-added-card/use-credential-panel-state'
import type { Model, ModelItem, ModelProvider } from '../declarations'
import type { CredentialPanelState } from '../provider-added-card/use-credential-panel-state'
import {
ConfigurationMethodEnum,
ModelStatusEnum,
ModelTypeEnum,
} from './declarations'
import { deriveModelStatus } from './derive-model-status'
} from '../declarations'
import { deriveModelStatus } from '../derive-model-status'
const createCredentialState = (overrides: Partial<CredentialPanelState> = {}): CredentialPanelState => ({
variant: 'credits-active',

View File

@ -3,8 +3,8 @@ import {
CurrentSystemQuotaTypeEnum,
CustomConfigurationStatusEnum,
QuotaUnitEnum,
} from './declarations'
import ModelProviderPage from './index'
} from '../declarations'
import ModelProviderPage from '../index'
const mockQuotaConfig = {
quota_type: CurrentSystemQuotaTypeEnum.free,
@ -42,23 +42,23 @@ vi.mock('@/context/provider-context', () => ({
}),
}))
vi.mock('./hooks', () => ({
vi.mock('../hooks', () => ({
useDefaultModel: () => ({ data: null, isLoading: false }),
}))
vi.mock('./provider-added-card', () => ({
vi.mock('../provider-added-card', () => ({
default: () => <div data-testid="provider-card" />,
}))
vi.mock('./provider-added-card/quota-panel', () => ({
vi.mock('../provider-added-card/quota-panel', () => ({
default: () => <div data-testid="quota-panel" />,
}))
vi.mock('./system-model-selector', () => ({
vi.mock('../system-model-selector', () => ({
default: () => <div data-testid="system-model-selector" />,
}))
vi.mock('./install-from-marketplace', () => ({
vi.mock('../install-from-marketplace', () => ({
default: () => <div data-testid="install-from-marketplace" />,
}))

View File

@ -1,6 +1,6 @@
import type { ModelProvider } from './declarations'
import { CurrentSystemQuotaTypeEnum } from './declarations'
import { providerSupportsCredits } from './supports-credits'
import type { ModelProvider } from '../declarations'
import { CurrentSystemQuotaTypeEnum } from '../declarations'
import { providerSupportsCredits } from '../supports-credits'
vi.mock('@/config', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/config')>()

View File

@ -1,8 +1,8 @@
import type { ReactNode } from 'react'
import type { Credential, ModelProvider } from '../declarations'
import type { Credential, ModelProvider } from '../../declarations'
import { act, render, screen } from '@testing-library/react'
import { ConfigurationMethodEnum, ModelModalModeEnum } from '../declarations'
import ModelModal from './index'
import { ConfigurationMethodEnum, ModelModalModeEnum } from '../../declarations'
import ModelModal from '../index'
type DialogProps = {
children: ReactNode
@ -27,7 +27,7 @@ vi.mock('@/app/components/base/form/form-scenarios/auth', () => ({
default: () => <div data-testid="auth-form" />,
}))
vi.mock('../model-auth', () => ({
vi.mock('../../model-auth', () => ({
CredentialSelector: ({ credentials }: { credentials: Credential[] }) => <div>{`credentials:${credentials.length}`}</div>,
}))
@ -52,7 +52,7 @@ vi.mock('@/app/components/base/ui/alert-dialog', () => ({
AlertDialogTitle: ({ children }: { children: ReactNode }) => <div>{children}</div>,
}))
vi.mock('../model-auth/hooks', () => ({
vi.mock('../../model-auth/hooks', () => ({
useCredentialData: () => ({
isLoading: false,
credentialData: {
@ -87,7 +87,7 @@ vi.mock('@/hooks/use-i18n', () => ({
useRenderI18nObject: () => (value: Record<string, string>) => value[mockLanguage] || value.en_US,
}))
vi.mock('../hooks', () => ({
vi.mock('../../hooks', () => ({
useLanguage: () => mockLanguage,
}))

View File

@ -1,7 +1,7 @@
import type { ModelItem, ModelProvider } from '../declarations'
import type { CredentialPanelState } from '../provider-added-card/use-credential-panel-state'
import { ModelStatusEnum } from '../declarations'
import { deriveTriggerStatus } from './derive-trigger-status'
import type { ModelItem, ModelProvider } from '../../declarations'
import type { CredentialPanelState } from '../../provider-added-card/use-credential-panel-state'
import { ModelStatusEnum } from '../../declarations'
import { deriveTriggerStatus } from '../derive-trigger-status'
const baseCredentialState: CredentialPanelState = {
variant: 'api-active',

View File

@ -1,8 +1,8 @@
import type { ReactNode } from 'react'
import { fireEvent, render, screen } from '@testing-library/react'
import ParameterItem from './parameter-item'
import ParameterItem from '../parameter-item'
vi.mock('../hooks', () => ({
vi.mock('../../hooks', () => ({
useLanguage: () => 'en_US',
}))

View File

@ -1,4 +1,4 @@
import type { Model, ModelItem } from '../declarations'
import type { Model, ModelItem } from '../../declarations'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {
@ -6,15 +6,15 @@ import {
ModelFeatureEnum,
ModelStatusEnum,
ModelTypeEnum,
} from '../declarations'
import ModelSelectorTrigger from './model-selector-trigger'
} from '../../declarations'
import ModelSelectorTrigger from '../model-selector-trigger'
const mockUseProviderContext = vi.hoisted(() => vi.fn())
const mockUseCredentialPanelState = vi.hoisted(() => vi.fn())
vi.mock('@/context/provider-context', () => ({
useProviderContext: mockUseProviderContext,
}))
vi.mock('../provider-added-card/use-credential-panel-state', () => ({
vi.mock('../../provider-added-card/use-credential-panel-state', () => ({
useCredentialPanelState: mockUseCredentialPanelState,
}))

View File

@ -1,6 +1,6 @@
import type { ReactNode } from 'react'
import { act, fireEvent, render, screen } from '@testing-library/react'
import ModelSelector from './index'
import ModelSelector from '../index'
type PopoverProps = {
children: ReactNode
@ -9,7 +9,7 @@ type PopoverProps = {
let latestOnOpenChange: PopoverProps['onOpenChange']
vi.mock('../hooks', () => ({
vi.mock('../../hooks', () => ({
useCurrentProviderAndModel: () => ({
currentProvider: undefined,
currentModel: undefined,
@ -25,7 +25,7 @@ vi.mock('@/app/components/base/ui/popover', () => ({
PopoverContent: ({ children }: { children: ReactNode }) => <div>{children}</div>,
}))
vi.mock('./model-selector-trigger', () => ({
vi.mock('../model-selector-trigger', () => ({
default: ({ open, readonly }: { open: boolean, readonly?: boolean }) => (
<span>
{open ? 'open' : 'closed'}
@ -35,7 +35,7 @@ vi.mock('./model-selector-trigger', () => ({
),
}))
vi.mock('./popup', () => ({
vi.mock('../popup', () => ({
default: ({ onHide }: { onHide: () => void }) => (
<div data-testid="popup">
<button type="button" onClick={onHide}>hide-popup</button>

View File

@ -2,7 +2,7 @@ import type { ReactNode } from 'react'
import type { PluginDetail } from '@/app/components/plugins/types'
import { fireEvent, render, screen } from '@testing-library/react'
import { PluginSource } from '@/app/components/plugins/types'
import ProviderCardActions from './provider-card-actions'
import ProviderCardActions from '../provider-card-actions'
const mockHandleUpdate = vi.fn()
const mockHandleUpdatedFromMarketplace = vi.fn()

View File

@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react'
import SystemQuotaCard from './system-quota-card'
import SystemQuotaCard from '../system-quota-card'
describe('SystemQuotaCard', () => {
// Renders container with children

View File

@ -1,10 +1,10 @@
import type { ReactNode } from 'react'
import type { ModelProvider } from '../declarations'
import type { ModelProvider } from '../../declarations'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { act, renderHook, waitFor } from '@testing-library/react'
import * as React from 'react'
import { ConfigurationMethodEnum, ModelTypeEnum, PreferredProviderTypeEnum } from '../declarations'
import { useChangeProviderPriority } from './use-change-provider-priority'
import { ConfigurationMethodEnum, ModelTypeEnum, PreferredProviderTypeEnum } from '../../declarations'
import { useChangeProviderPriority } from '../use-change-provider-priority'
const mockUpdateModelList = vi.fn()
const mockUpdateModelProviders = vi.fn()
@ -35,7 +35,7 @@ vi.mock('@/service/client', () => ({
},
}))
vi.mock('../hooks', () => ({
vi.mock('../../hooks', () => ({
useUpdateModelList: () => mockUpdateModelList,
useUpdateModelProviders: () => mockUpdateModelProviders,
}))

View File

@ -1,17 +1,17 @@
import type { ModelProvider } from '../declarations'
import type { ModelProvider } from '../../declarations'
import { renderHook } from '@testing-library/react'
import {
ConfigurationMethodEnum,
CurrentSystemQuotaTypeEnum,
CustomConfigurationStatusEnum,
PreferredProviderTypeEnum,
} from '../declarations'
import { isDestructiveVariant, useCredentialPanelState } from './use-credential-panel-state'
} from '../../declarations'
import { isDestructiveVariant, useCredentialPanelState } from '../use-credential-panel-state'
const mockTrialCredits = { credits: 100, totalCredits: 10_000, isExhausted: false, isLoading: false, nextCreditResetDate: undefined }
const mockTrialModels = ['langgenius/openai/openai', 'langgenius/anthropic/anthropic']
vi.mock('./use-trial-credits', () => ({
vi.mock('../use-trial-credits', () => ({
useTrialCredits: () => mockTrialCredits,
}))

View File

@ -1,5 +1,5 @@
import { renderHook } from '@testing-library/react'
import { useTrialCredits } from './use-trial-credits'
import { useTrialCredits } from '../use-trial-credits'
const mockUseCurrentWorkspace = vi.fn()

View File

@ -1,7 +1,7 @@
import type { Credential, ModelProvider } from '../../declarations'
import type { Credential, ModelProvider } from '../../../declarations'
import { fireEvent, render, screen } from '@testing-library/react'
import { CustomConfigurationStatusEnum, PreferredProviderTypeEnum } from '../../declarations'
import ApiKeySection from './api-key-section'
import { CustomConfigurationStatusEnum, PreferredProviderTypeEnum } from '../../../declarations'
import ApiKeySection from '../api-key-section'
const createCredential = (overrides: Partial<Credential> = {}): Credential => ({
credential_id: 'cred-1',

View File

@ -1,6 +1,6 @@
import type { ReactNode } from 'react'
import { fireEvent, render, screen } from '@testing-library/react'
import CreditsExhaustedAlert from './credits-exhausted-alert'
import CreditsExhaustedAlert from '../credits-exhausted-alert'
const mockTrialCredits = { credits: 0, totalCredits: 10_000, isExhausted: true, isLoading: false, nextCreditResetDate: undefined }
const mockSetShowPricingModal = vi.fn()
@ -24,7 +24,7 @@ vi.mock('react-i18next', async (importOriginal) => {
}
})
vi.mock('../use-trial-credits', () => ({
vi.mock('../../use-trial-credits', () => ({
useTrialCredits: () => mockTrialCredits,
}))

View File

@ -1,8 +1,8 @@
import type { ReactNode } from 'react'
import type { ModelProvider } from '../../declarations'
import type { CredentialPanelState } from '../use-credential-panel-state'
import type { ModelProvider } from '../../../declarations'
import type { CredentialPanelState } from '../../use-credential-panel-state'
import { act, fireEvent, render, screen } from '@testing-library/react'
import DropdownContent from './dropdown-content'
import DropdownContent from '../dropdown-content'
type AlertDialogProps = {
children: ReactNode
@ -15,7 +15,7 @@ const mockCloseConfirmDelete = vi.fn()
const mockHandleConfirmDelete = vi.fn()
const mockHandleOpenModal = vi.fn()
vi.mock('../../model-auth/hooks', () => ({
vi.mock('../../../model-auth/hooks', () => ({
useAuth: () => ({
openConfirmDelete: mockOpenConfirmDelete,
closeConfirmDelete: mockCloseConfirmDelete,
@ -26,7 +26,7 @@ vi.mock('../../model-auth/hooks', () => ({
}),
}))
vi.mock('./use-activate-credential', () => ({
vi.mock('../use-activate-credential', () => ({
useActivateCredential: () => ({
selectedCredentialId: 'cred-1',
isActivating: false,
@ -47,7 +47,7 @@ vi.mock('@/app/components/base/ui/alert-dialog', () => ({
AlertDialogTitle: ({ children }: { children: ReactNode }) => <div>{children}</div>,
}))
vi.mock('./api-key-section', () => ({
vi.mock('../api-key-section', () => ({
default: ({ credentials, onDelete }: { credentials: unknown[], onDelete: (credential?: unknown) => void }) => (
<div>
<span>{`credentials:${credentials.length}`}</span>
@ -56,15 +56,15 @@ vi.mock('./api-key-section', () => ({
),
}))
vi.mock('./credits-exhausted-alert', () => ({
vi.mock('../credits-exhausted-alert', () => ({
default: () => <div>credits alert</div>,
}))
vi.mock('./credits-fallback-alert', () => ({
vi.mock('../credits-fallback-alert', () => ({
default: () => <div>fallback alert</div>,
}))
vi.mock('./usage-priority-section', () => ({
vi.mock('../usage-priority-section', () => ({
default: () => <div>priority section</div>,
}))

View File

@ -1,8 +1,8 @@
import type { ModelProvider } from '../../declarations'
import type { CredentialPanelState } from '../use-credential-panel-state'
import type { ModelProvider } from '../../../declarations'
import type { CredentialPanelState } from '../../use-credential-panel-state'
import { fireEvent, render, screen } from '@testing-library/react'
import { CustomConfigurationStatusEnum, PreferredProviderTypeEnum } from '../../declarations'
import DropdownContent from './dropdown-content'
import { CustomConfigurationStatusEnum, PreferredProviderTypeEnum } from '../../../declarations'
import DropdownContent from '../dropdown-content'
const mockHandleOpenModal = vi.fn()
const mockActivate = vi.fn()
@ -11,11 +11,11 @@ const mockCloseConfirmDelete = vi.fn()
const mockHandleConfirmDelete = vi.fn()
let mockDeleteCredentialId: string | null = null
vi.mock('../use-trial-credits', () => ({
vi.mock('../../use-trial-credits', () => ({
useTrialCredits: () => ({ credits: 0, totalCredits: 10_000, isExhausted: true, isLoading: false }),
}))
vi.mock('./use-activate-credential', () => ({
vi.mock('../use-activate-credential', () => ({
useActivateCredential: () => ({
selectedCredentialId: 'cred-1',
isActivating: false,
@ -23,7 +23,7 @@ vi.mock('./use-activate-credential', () => ({
}),
}))
vi.mock('../../model-auth/hooks', () => ({
vi.mock('../../../model-auth/hooks', () => ({
useAuth: () => ({
openConfirmDelete: mockOpenConfirmDelete,
closeConfirmDelete: mockCloseConfirmDelete,
@ -34,7 +34,7 @@ vi.mock('../../model-auth/hooks', () => ({
}),
}))
vi.mock('../../model-auth/authorized/credential-item', () => ({
vi.mock('../../../model-auth/authorized/credential-item', () => ({
default: ({ credential, onItemClick, onEdit, onDelete }: {
credential: { credential_id: string, credential_name: string }
onItemClick?: (c: unknown) => void

View File

@ -1,10 +1,10 @@
import type { ModelProvider } from '../../declarations'
import type { CredentialPanelState } from '../use-credential-panel-state'
import type { ModelProvider } from '../../../declarations'
import type { CredentialPanelState } from '../../use-credential-panel-state'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { CustomConfigurationStatusEnum, PreferredProviderTypeEnum } from '../../declarations'
import ModelAuthDropdown from './index'
import { CustomConfigurationStatusEnum, PreferredProviderTypeEnum } from '../../../declarations'
import ModelAuthDropdown from '../index'
vi.mock('../../model-auth/hooks', () => ({
vi.mock('../../../model-auth/hooks', () => ({
useAuth: () => ({
openConfirmDelete: vi.fn(),
closeConfirmDelete: vi.fn(),
@ -15,7 +15,7 @@ vi.mock('../../model-auth/hooks', () => ({
}),
}))
vi.mock('./use-activate-credential', () => ({
vi.mock('../use-activate-credential', () => ({
useActivateCredential: () => ({
selectedCredentialId: undefined,
isActivating: false,
@ -23,7 +23,7 @@ vi.mock('./use-activate-credential', () => ({
}),
}))
vi.mock('../use-trial-credits', () => ({
vi.mock('../../use-trial-credits', () => ({
useTrialCredits: () => ({ credits: 0, totalCredits: 10_000, isExhausted: true, isLoading: false }),
}))

View File

@ -1,6 +1,6 @@
import { fireEvent, render, screen } from '@testing-library/react'
import { PreferredProviderTypeEnum } from '../../declarations'
import UsagePrioritySection from './usage-priority-section'
import { PreferredProviderTypeEnum } from '../../../declarations'
import UsagePrioritySection from '../usage-priority-section'
describe('UsagePrioritySection', () => {
const onSelect = vi.fn()

View File

@ -1,7 +1,7 @@
import type { Credential, ModelProvider } from '../../declarations'
import type { Credential, ModelProvider } from '../../../declarations'
import { act, renderHook } from '@testing-library/react'
import Toast from '@/app/components/base/toast'
import { useActivateCredential } from './use-activate-credential'
import { useActivateCredential } from '../use-activate-credential'
const mockMutate = vi.fn()
const mockUpdateModelProviders = vi.fn()
@ -15,7 +15,7 @@ vi.mock('@/service/use-models', () => ({
}),
}))
vi.mock('../../hooks', () => ({
vi.mock('../../../hooks', () => ({
useUpdateModelProviders: () => mockUpdateModelProviders,
useUpdateModelList: () => mockUpdateModelList,
}))

View File

@ -1,9 +1,9 @@
import type { PluginDetail } from './types'
import type { PluginDetail } from '../types'
import { useQuery } from '@tanstack/react-query'
import { renderHook } from '@testing-library/react'
import { consoleQuery } from '@/service/client'
import { usePluginsWithLatestVersion } from './hooks'
import { PluginSource } from './types'
import { usePluginsWithLatestVersion } from '../hooks'
import { PluginSource } from '../types'
vi.mock('@tanstack/react-query', () => ({
useQuery: vi.fn(),

View File

@ -9,12 +9,6 @@ import PublishToast from '../publish-toast'
import RagPipelineChildren from '../rag-pipeline-children'
import PipelineScreenShot from '../screenshot'
afterEach(async () => {
await act(async () => {
await new Promise(resolve => setTimeout(resolve, 0))
})
})
const mockPush = vi.fn()
vi.mock('next/navigation', () => ({
useParams: () => ({ datasetId: 'test-dataset-id' }),
@ -874,9 +868,11 @@ describe('RagPipelineChildren', () => {
]
if (mockEventSubscriptionCallback) {
mockEventSubscriptionCallback({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
await act(async () => {
mockEventSubscriptionCallback?.({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
})
})
}
@ -889,8 +885,10 @@ describe('RagPipelineChildren', () => {
render(<RagPipelineChildren />)
if (mockEventSubscriptionCallback) {
mockEventSubscriptionCallback({
type: 'OTHER_EVENT',
act(() => {
mockEventSubscriptionCallback?.({
type: 'OTHER_EVENT',
})
})
}
@ -936,9 +934,11 @@ describe('RagPipelineChildren', () => {
]
if (mockEventSubscriptionCallback) {
mockEventSubscriptionCallback({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
await act(async () => {
mockEventSubscriptionCallback?.({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
})
})
}
@ -955,9 +955,11 @@ describe('RagPipelineChildren', () => {
]
if (mockEventSubscriptionCallback) {
mockEventSubscriptionCallback({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
await act(async () => {
mockEventSubscriptionCallback?.({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
})
})
}
@ -980,9 +982,11 @@ describe('RagPipelineChildren', () => {
]
if (mockEventSubscriptionCallback) {
mockEventSubscriptionCallback({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
await act(async () => {
mockEventSubscriptionCallback?.({
type: 'DSL_EXPORT_CHECK',
payload: { data: mockEnvVariables },
})
})
}

View File

@ -1,6 +1,6 @@
import type { WorkflowToolProviderOutputParameter, WorkflowToolProviderOutputSchema } from '../types'
import type { WorkflowToolProviderOutputParameter, WorkflowToolProviderOutputSchema } from '../../types'
import { VarType } from '@/app/components/workflow/types'
import { buildWorkflowOutputParameters } from './utils'
import { buildWorkflowOutputParameters } from '../utils'
describe('buildWorkflowOutputParameters', () => {
it('returns provided output parameters when array input exists', () => {

View File

@ -9,7 +9,8 @@ When I ask you to write/refactor/fix tests, follow these rules by default.
- **Framework**: Next.js 15 + React 19 + TypeScript
- **Testing Tools**: Vitest 4.0.16 + React Testing Library 16.0
- **Test Environment**: jsdom
- **File Naming**: `ComponentName.spec.tsx` (same directory as component)
- **File Naming**: `ComponentName.spec.tsx` inside a same-level `__tests__/` directory
- **Placement Rule**: Component, hook, and utility tests must live in a sibling `__tests__/` folder at the same level as the source under test. For example, `foo/index.tsx` maps to `foo/__tests__/index.spec.tsx`, and `foo/bar.ts` maps to `foo/__tests__/bar.spec.ts`.
## Running Tests