mirror of
https://github.com/langgenius/dify.git
synced 2026-07-21 10:38:32 +08:00
test(web): centralize i18n mocks (#38670)
This commit is contained in:
parent
6f47950fe2
commit
e3a08b40f2
@ -16,16 +16,6 @@ const mockDeleteDataset = vi.fn()
|
||||
const mockDownloadBlob = vi.fn()
|
||||
|
||||
let mockDataset: DataSet
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/next/navigation', () => ({
|
||||
useRouter: () => ({
|
||||
replace: mockReplace,
|
||||
|
||||
@ -32,16 +32,6 @@ const renderWithQueryClient = (ui: React.ReactElement) =>
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/app/store', () => ({
|
||||
useStore: (selector: (state: Record<string, unknown>) => unknown) => selector({
|
||||
appDetail: mockAppDetail,
|
||||
|
||||
@ -35,16 +35,6 @@ const renderWithQueryClient = (ui: React.ReactElement) =>
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/app/store', () => ({
|
||||
useStore: (selector: (state: Record<string, unknown>) => unknown) => selector({
|
||||
appDetail: mockAppDetail,
|
||||
@ -173,12 +163,12 @@ describe('App Publisher Flow', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
|
||||
expect(screen.getByText('common.latestPublished')).toBeInTheDocument()
|
||||
expect(screen.getByText('common.publishUpdate')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)common\.latestPublished(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)common\.publishUpdate(?=$|:)/)).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('common.publishUpdate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publishUpdate(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onPublish).toHaveBeenCalledTimes(1)
|
||||
@ -193,13 +183,13 @@ describe('App Publisher Flow', () => {
|
||||
it('opens embedded modal and resolves the installed explore target', async () => {
|
||||
renderWithQueryClient(<AppPublisher publishedAt={1700000000} />)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText('common.embedIntoSite'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.embedIntoSite(?=$|:)/))
|
||||
|
||||
expect(screen.getByTestId('embedded-modal')).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText('common.openInExplore'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.openInExplore(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockFetchInstalledAppList).toHaveBeenCalledWith('app-1')
|
||||
@ -214,11 +204,11 @@ describe('App Publisher Flow', () => {
|
||||
|
||||
renderWithQueryClient(<AppPublisher publishedAt={1700000000} />)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText('common.openInExplore'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.openInExplore(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockToastError).toHaveBeenCalledWith('notPublishedYet')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)notPublishedYet(?=$|:)/))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -51,10 +51,6 @@ vi.mock('jotai', async (importOriginal) => {
|
||||
return createAppContextStateJotaiMock(importOriginal)
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en-US',
|
||||
}))
|
||||
|
||||
// ─── Service mocks ───────────────────────────────────────────────────────────
|
||||
vi.mock('@/service/billing', () => ({
|
||||
fetchSubscriptionUrls: (...args: unknown[]) => mockFetchSubscriptionUrls(...args),
|
||||
|
||||
@ -73,10 +73,6 @@ vi.mock('@/context/modal-context', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en-US',
|
||||
}))
|
||||
|
||||
// ─── Service mocks ───────────────────────────────────────────────────────────
|
||||
vi.mock('@/service/use-education', () => ({
|
||||
useEducationVerify: () => ({
|
||||
|
||||
@ -46,10 +46,6 @@ vi.mock('jotai', async (importOriginal) => {
|
||||
return createAppContextStateJotaiMock(importOriginal)
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-theme', () => ({
|
||||
default: () => ({ theme: 'light' }),
|
||||
useTheme: () => ({ theme: 'light' }),
|
||||
|
||||
@ -15,16 +15,6 @@ vi.mock('@/config', async (importOriginal) => {
|
||||
IS_CLOUD_EDITION: true,
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/provider-context', () => ({
|
||||
useProviderContext: vi.fn(),
|
||||
}))
|
||||
|
||||
@ -16,15 +16,6 @@ import type { MetadataItemWithValueLength } from '@/app/components/datasets/meta
|
||||
import { renderHook } from '@testing-library/react'
|
||||
import { DataType } from '@/app/components/datasets/metadata/types'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
const { default: useCheckMetadataName } = await import(
|
||||
'@/app/components/datasets/metadata/hooks/use-check-metadata-name',
|
||||
)
|
||||
|
||||
@ -34,11 +34,6 @@ vi.mock('@/app/components/app/store', () => ({
|
||||
return selector({ appDetail: storeAppDetail })
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-theme', () => ({
|
||||
default: () => ({ theme: Theme.light }),
|
||||
}))
|
||||
|
||||
@ -21,7 +21,7 @@ type MockAppContext = {
|
||||
|
||||
const mockUseAppContext = vi.hoisted(() => vi.fn<() => MockAppContext>())
|
||||
|
||||
const allCategoriesEn = 'explore.apps.allCategories:{"lng":"en"}'
|
||||
const allCategoriesEn = 'explore.apps.allCategories:{"lng":"en-US"}'
|
||||
let mockTabValue = allCategoriesEn
|
||||
const mockSetTab = vi.fn()
|
||||
let mockExploreData: { categories: string[], allList: App[] } | undefined
|
||||
@ -235,8 +235,8 @@ const mockMemberRole = (hasEditPermission: boolean) => {
|
||||
} as unknown as ReturnType<typeof useMembers>)
|
||||
}
|
||||
|
||||
const localeInput = { query: { language: 'en' } }
|
||||
const exploreAppListQueryKey = ['console', 'explore', 'apps', 'get', localeInput, 'en']
|
||||
const localeInput = { query: { language: 'en-US' } }
|
||||
const exploreAppListQueryKey = ['console', 'explore', 'apps', 'get', localeInput, 'en-US']
|
||||
const homeContinueWorkAppsInput = {
|
||||
query: {
|
||||
page: 1,
|
||||
|
||||
@ -14,17 +14,6 @@ import { fetchAppList } from '@/service/apps'
|
||||
import { postMarketplace } from '@/service/base'
|
||||
import { fetchDatasets } from '@/service/datasets'
|
||||
|
||||
// Mock react-i18next before importing modules that use it
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
getI18n: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
language: 'en',
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
// Mock API functions
|
||||
vi.mock('@/service/base', () => ({
|
||||
postMarketplace: vi.fn(),
|
||||
|
||||
@ -5,6 +5,10 @@ import { Plan } from '@/app/components/billing/type'
|
||||
import AccountDropdown from '@/app/components/header/account-dropdown'
|
||||
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
const {
|
||||
mockAppContextState,
|
||||
mockPush,
|
||||
@ -92,10 +96,6 @@ vi.mock('@/context/modal-context', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('@/service/use-common', async importOriginal => ({
|
||||
...await importOriginal<typeof import('@/service/use-common')>(),
|
||||
useLogout: () => ({
|
||||
|
||||
@ -10,19 +10,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
let mockTheme = 'light'
|
||||
|
||||
vi.mock('#i18n', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en_US',
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-theme', () => ({
|
||||
default: () => ({ theme: mockTheme }),
|
||||
}))
|
||||
|
||||
@ -9,16 +9,6 @@ const mockFetchManifestFromMarketPlace = vi.fn()
|
||||
const { mockRouterReplace } = vi.hoisted(() => ({
|
||||
mockRouterReplace: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/utils', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/utils')>()
|
||||
return {
|
||||
@ -38,10 +28,6 @@ vi.mock('@/next/navigation', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('@/context/account-state', async (importOriginal) => {
|
||||
const { createAppContextStateAtomMock } = await import('@/__tests__/utils/mock-app-context-state')
|
||||
return createAppContextStateAtomMock(importOriginal, () => ({
|
||||
|
||||
@ -8,15 +8,6 @@ import { act, renderHook } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
// Mutable holder so mock data can reference BlockEnum after imports
|
||||
const mockNodesHolder = vi.hoisted(() => ({ value: [] as Record<string, unknown>[] }))
|
||||
|
||||
|
||||
@ -5,16 +5,6 @@ import TextGeneration from '@/app/components/share/text-generation'
|
||||
const useSearchParamsMock = vi.fn(() => new URLSearchParams())
|
||||
const mockUseTextGenerationAppState = vi.fn()
|
||||
const mockUseTextGenerationBatch = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/next/navigation', () => ({
|
||||
useSearchParams: () => useSearchParamsMock(),
|
||||
}))
|
||||
|
||||
@ -7,16 +7,6 @@ import { CollectionType } from '@/app/components/tools/types'
|
||||
import { createNuqsTestWrapper } from '@/test/nuqs-testing'
|
||||
|
||||
const mockInvalidateInstalledPluginList = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/plugins/hooks', () => ({
|
||||
useTags: () => ({
|
||||
getTagLabel: (name: string) => name,
|
||||
|
||||
@ -21,6 +21,10 @@ import { AppModeEnum } from '@/types/app'
|
||||
import Annotation from '../index'
|
||||
import { AnnotationEnableStatus, JobStatus } from '../type'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('ahooks', () => ({
|
||||
useDebounce: (value: any) => value,
|
||||
}))
|
||||
@ -41,10 +45,6 @@ vi.mock('@/context/provider-context', () => ({
|
||||
useProviderContext: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('../filter', () => ({
|
||||
default: ({ children }: { children: React.ReactNode }) => (
|
||||
<div data-testid="filter">{children}</div>
|
||||
|
||||
@ -7,6 +7,10 @@ import { useLocale } from '@/context/i18n'
|
||||
import { LanguagesSupported } from '@/i18n-config/language'
|
||||
import CSVDownload from '../csv-downloader'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: vi.fn(() => 'en-US'),
|
||||
}))
|
||||
|
||||
const downloaderProps: any[] = []
|
||||
|
||||
vi.mock('react-papaparse', () => ({
|
||||
@ -19,10 +23,6 @@ vi.mock('react-papaparse', () => ({
|
||||
})),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: vi.fn(() => 'en-US'),
|
||||
}))
|
||||
|
||||
const renderWithLocale = (locale: Locale) => {
|
||||
;(useLocale as Mock).mockReturnValue(locale)
|
||||
return render(<CSVDownload />)
|
||||
|
||||
@ -31,16 +31,6 @@ const mockFeatures = {
|
||||
number_limits: 3,
|
||||
},
|
||||
}
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/app/app-publisher', () => ({
|
||||
AppPublisher: (props: Record<string, any>) => {
|
||||
mockAppPublisherProps.current = props
|
||||
@ -120,7 +110,7 @@ describe('FeaturesWrappedAppPublisher', () => {
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('restore-through-wrapper'))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.confirm' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.confirm(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(publishedConfig.modelConfig.resetAppConfig).toHaveBeenCalledTimes(1)
|
||||
@ -151,7 +141,7 @@ describe('FeaturesWrappedAppPublisher', () => {
|
||||
fireEvent.click(screen.getByText('restore-through-wrapper'))
|
||||
const dialog = screen.getByRole('alertdialog')
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: 'operation.cancel' }))
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: /(?:^|\.)operation\.cancel(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole('alertdialog')).not.toBeInTheDocument()
|
||||
|
||||
@ -37,16 +37,6 @@ const hotkeyMocks = vi.hoisted(() => ({
|
||||
let mockAppDetail: Record<string, any> | null = null
|
||||
let mockWorkspacePermissionKeys: string[] = ['tool.manage']
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey, withSelectorKeyProps } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
Trans: withSelectorKeyProps(({ i18nKey }: { i18nKey?: string }) => i18nKey ?? null),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@tanstack/react-hotkeys', () => ({
|
||||
useHotkey: (hotkey: string, handler: (event: { preventDefault: () => void }) => void) => {
|
||||
hotkeyMocks.hotkeys.push(hotkey)
|
||||
@ -272,7 +262,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
|
||||
expect(screen.getByText('publisher-summary-publish'))!.toBeInTheDocument()
|
||||
expect(mockOnToggle).toHaveBeenCalledWith(true)
|
||||
@ -297,7 +287,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-summary-publish'))
|
||||
|
||||
await waitFor(() => {
|
||||
@ -317,7 +307,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-embed'))
|
||||
|
||||
expect(screen.getByTestId('embedded-modal'))!.toBeInTheDocument()
|
||||
@ -338,15 +328,15 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-run-config'))
|
||||
|
||||
expect(screen.getByText('overview.appInfo.workflowLaunchHiddenInputs.title')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.appInfo\.workflowLaunchHiddenInputs\.title(?=$|:)/)).toBeInTheDocument()
|
||||
|
||||
fireEvent.change(screen.getByLabelText('Secret'), {
|
||||
target: { value: 'top-secret' },
|
||||
})
|
||||
fireEvent.click(screen.getByRole('button', { name: 'overview.appInfo.launch' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)overview\.appInfo\.launch(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith(
|
||||
@ -376,13 +366,13 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-batch-run-config'))
|
||||
|
||||
fireEvent.change(screen.getByLabelText('Batch Secret'), {
|
||||
target: { value: 'batch-value' },
|
||||
})
|
||||
fireEvent.click(screen.getByRole('button', { name: 'overview.appInfo.launch' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)overview\.appInfo\.launch(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith(
|
||||
@ -404,7 +394,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-workflow-tool'))
|
||||
|
||||
expect(screen.queryByTestId('popover-content')).not.toBeInTheDocument()
|
||||
@ -424,7 +414,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-workflow-tool'))
|
||||
|
||||
expect(screen.queryByTestId('workflow-tool-drawer')).not.toBeInTheDocument()
|
||||
@ -438,12 +428,12 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-embed'))
|
||||
fireEvent.click(screen.getByText('close-embedded-modal'))
|
||||
expect(screen.queryByTestId('embedded-modal')).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-access-control'))
|
||||
expect(screen.getByTestId('access-control'))!.toBeInTheDocument()
|
||||
fireEvent.click(screen.getByText('close-access-control'))
|
||||
@ -458,7 +448,7 @@ describe('AppPublisher', () => {
|
||||
)
|
||||
const setQueryDataSpy = vi.spyOn(queryClient, 'setQueryData')
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-access-control'))
|
||||
|
||||
expect(screen.getByTestId('access-control'))!.toBeInTheDocument()
|
||||
@ -488,7 +478,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-open-in-explore'))
|
||||
|
||||
await waitFor(() => {
|
||||
@ -508,7 +498,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish').parentElement?.parentElement as HTMLElement)
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/).parentElement?.parentElement as HTMLElement)
|
||||
|
||||
expect(screen.queryByText('publisher-summary-publish')).not.toBeInTheDocument()
|
||||
expect(mockOnToggle).not.toHaveBeenCalled()
|
||||
@ -535,7 +525,7 @@ describe('AppPublisher', () => {
|
||||
expect(mockOnPublish).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-summary-restore'))
|
||||
|
||||
await waitFor(() => {
|
||||
@ -565,7 +555,7 @@ describe('AppPublisher', () => {
|
||||
})
|
||||
expect(mockTrackEvent).not.toHaveBeenCalled()
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-summary-restore'))
|
||||
|
||||
await waitFor(() => {
|
||||
@ -593,11 +583,11 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-open-in-explore'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockToastError).toHaveBeenCalledWith('notPublishedYet')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)notPublishedYet(?=$|:)/))
|
||||
})
|
||||
})
|
||||
|
||||
@ -621,7 +611,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-open-in-explore'))
|
||||
|
||||
await waitFor(() => {
|
||||
@ -641,8 +631,8 @@ describe('AppPublisher', () => {
|
||||
{ systemFeatures: { webapp_auth: { enabled: true }, enable_creators_platform: true } },
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText('common.publishToMarketplace'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publishToMarketplace(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockPublishToCreatorsPlatform).toHaveBeenCalledWith({ appID: 'app-1' })
|
||||
@ -663,11 +653,11 @@ describe('AppPublisher', () => {
|
||||
{ systemFeatures: { webapp_auth: { enabled: true }, enable_creators_platform: true } },
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText('common.publishToMarketplace'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publishToMarketplace(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockToastError).toHaveBeenCalledWith('common.publishToMarketplaceFailed')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)common\.publishToMarketplaceFailed(?=$|:)/))
|
||||
})
|
||||
})
|
||||
|
||||
@ -679,11 +669,11 @@ describe('AppPublisher', () => {
|
||||
{ systemFeatures: { webapp_auth: { enabled: true }, enable_creators_platform: true } },
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
const marketplaceButton = screen.getByText('common.publishToMarketplace').closest('a, button, div[role="button"]') as HTMLElement
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
const marketplaceButton = screen.getByText(/(?:^|\.)common\.publishToMarketplace(?=$|:)/).closest('a, button, div[role="button"]') as HTMLElement
|
||||
expect(marketplaceButton).toBeInTheDocument()
|
||||
// clicking should not call the API because publishedAt is undefined
|
||||
fireEvent.click(screen.getByText('common.publishToMarketplace'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publishToMarketplace(?=$|:)/))
|
||||
expect(mockPublishToCreatorsPlatform).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -695,8 +685,8 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
expect(screen.queryByText('common.publishToMarketplace')).not.toBeInTheDocument()
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
expect(screen.queryByText(/(?:^|\.)common\.publishToMarketplace(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should keep access control open when app detail is unavailable during confirmation', async () => {
|
||||
@ -708,7 +698,7 @@ describe('AppPublisher', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.publish'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.publish(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('publisher-access-control'))
|
||||
fireEvent.click(screen.getByText('confirm-access-control'))
|
||||
|
||||
|
||||
@ -3,16 +3,6 @@ import * as React from 'react'
|
||||
import PublishWithMultipleModel from '../publish-with-multiple-model'
|
||||
|
||||
const mockUseProviderContext = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/provider-context', () => ({
|
||||
useProviderContext: () => mockUseProviderContext(),
|
||||
}))
|
||||
@ -115,8 +105,8 @@ describe('PublishWithMultipleModel', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByRole('button', { name: 'operation.applyConfig' })).toBeDisabled()
|
||||
expect(screen.queryByText('publishAs')).not.toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /(?:^|\.)operation\.applyConfig(?=$|:)/ })).toBeDisabled()
|
||||
expect(screen.queryByText(/(?:^|\.)publishAs(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should open matching model options and call onSelect', () => {
|
||||
@ -135,9 +125,9 @@ describe('PublishWithMultipleModel', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.applyConfig' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.applyConfig(?=$|:)/ }))
|
||||
|
||||
expect(screen.getByText('publishAs')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)publishAs(?=$|:)/)).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('GPT-4o'))
|
||||
|
||||
|
||||
@ -5,15 +5,6 @@ import { AccessMode } from '@/models/access-control'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import { AccessModeDisplay, PublisherAccessSection, PublisherActionsSection, PublisherSummarySection } from '../sections'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('../publish-with-multiple-model', () => ({
|
||||
default: ({ onSelect }: { onSelect: (item: Record<string, unknown>) => void }) => (
|
||||
<button type="button" onClick={() => onSelect({ model: 'gpt-4o' })}>publish-multiple-model</button>
|
||||
@ -81,7 +72,7 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.restore'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.restore(?=$|:)/))
|
||||
expect(handleRestore).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -96,8 +87,8 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('publishApp.notSet')).toBeInTheDocument()
|
||||
expect(screen.getByText('publishApp.notSetDesc')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)publishApp\.notSet(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)publishApp\.notSetDesc(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the publish update action when the draft has not been published yet', () => {
|
||||
@ -119,7 +110,7 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('common.publishUpdate')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)common\.publishUpdate(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render multiple-model publishing', () => {
|
||||
@ -167,7 +158,7 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('publishLimit.startNodeDesc')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)publishLimit\.startNodeDesc(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render loading access state and access mode labels when enabled', () => {
|
||||
@ -193,7 +184,7 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('accessControlDialog.accessItems.anyone')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)accessControlDialog\.accessItems\.anyone(?=$|:)/)).toBeInTheDocument()
|
||||
expect(render(<AccessModeDisplay />).container).toBeEmptyDOMElement()
|
||||
})
|
||||
|
||||
@ -208,8 +199,8 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.queryByText('publishApp.title')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('accessControlDialog.accessItems.anyone')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)publishApp\.title(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)accessControlDialog\.accessItems\.anyone(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render workflow actions, batch run links, and workflow tool configuration', () => {
|
||||
@ -251,12 +242,12 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('common.batchRunApp')).toHaveAttribute('data-link', 'https://example.com/app?mode=batch')
|
||||
fireEvent.click(screen.getAllByRole('button', { name: 'operation.config' })[0]!)
|
||||
expect(screen.getByText(/(?:^|\.)common\.batchRunApp(?=$|:)/)).toHaveAttribute('data-link', 'https://example.com/app?mode=batch')
|
||||
fireEvent.click(screen.getAllByRole('button', { name: /(?:^|\.)operation\.config(?=$|:)/ })[0]!)
|
||||
expect(handleOpenRunConfig).toHaveBeenCalledWith('https://example.com/app')
|
||||
fireEvent.click(screen.getAllByRole('button', { name: 'operation.config' })[1]!)
|
||||
fireEvent.click(screen.getAllByRole('button', { name: /(?:^|\.)operation\.config(?=$|:)/ })[1]!)
|
||||
expect(handleOpenRunConfig).toHaveBeenCalledWith('https://example.com/app?mode=batch')
|
||||
fireEvent.click(screen.getByText('common.openInExplore'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.openInExplore(?=$|:)/))
|
||||
expect(handleOpenInExplore).toHaveBeenCalled()
|
||||
expect(screen.getByText('workflow-tool-configure')).toBeInTheDocument()
|
||||
expect(screen.getByText('workflow-disabled')).toBeInTheDocument()
|
||||
@ -288,9 +279,9 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('common.embedIntoSite'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)common\.embedIntoSite(?=$|:)/))
|
||||
expect(handleEmbed).toHaveBeenCalled()
|
||||
expect(screen.getByText('common.accessAPIReference')).toBeDisabled()
|
||||
expect(screen.getByText(/(?:^|\.)common\.accessAPIReference(?=$|:)/)).toBeDisabled()
|
||||
|
||||
rerender(
|
||||
<PublisherActionsSection
|
||||
@ -314,6 +305,6 @@ describe('app-publisher sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.queryByText('common.runApp')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)common\.runApp(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -3,15 +3,6 @@ import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import VersionInfoModal from '../version-info-modal'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
toast: {
|
||||
error: vi.fn(),
|
||||
@ -54,9 +45,9 @@ describe('VersionInfoModal', () => {
|
||||
|
||||
const [titleInput] = screen.getAllByRole('textbox')
|
||||
fireEvent.change(titleInput!, { target: { value: 'a'.repeat(16) } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.publish' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)common\.publish(?=$|:)/ }))
|
||||
|
||||
expect(toast.error).toHaveBeenCalledWith('versionHistory.editField.titleLengthLimit')
|
||||
expect(toast.error).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)versionHistory\.editField\.titleLengthLimit(?=$|:)/))
|
||||
expect(handlePublish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -80,7 +71,7 @@ describe('VersionInfoModal', () => {
|
||||
const [titleInput, notesInput] = screen.getAllByRole('textbox')
|
||||
fireEvent.change(titleInput!, { target: { value: 'Release 2' } })
|
||||
fireEvent.change(notesInput!, { target: { value: 'Updated notes' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.publish' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)common\.publish(?=$|:)/ }))
|
||||
|
||||
expect(handlePublish).toHaveBeenCalledWith({
|
||||
title: 'Release 2',
|
||||
@ -117,7 +108,7 @@ describe('VersionInfoModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.close' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.close(?=$|:)/ }))
|
||||
|
||||
expect(handleClose).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
@ -142,16 +133,16 @@ describe('VersionInfoModal', () => {
|
||||
const [titleInput, notesInput] = screen.getAllByRole('textbox')
|
||||
|
||||
fireEvent.change(titleInput!, { target: { value: 'a'.repeat(16) } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.publish' }))
|
||||
expect(toast.error).toHaveBeenCalledWith('versionHistory.editField.titleLengthLimit')
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)common\.publish(?=$|:)/ }))
|
||||
expect(toast.error).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)versionHistory\.editField\.titleLengthLimit(?=$|:)/))
|
||||
|
||||
fireEvent.change(titleInput!, { target: { value: 'Release 3' } })
|
||||
fireEvent.change(notesInput!, { target: { value: 'b'.repeat(101) } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.publish' }))
|
||||
expect(toast.error).toHaveBeenCalledWith('versionHistory.editField.releaseNotesLengthLimit')
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)common\.publish(?=$|:)/ }))
|
||||
expect(toast.error).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)versionHistory\.editField\.releaseNotesLengthLimit(?=$|:)/))
|
||||
|
||||
fireEvent.change(notesInput!, { target: { value: 'Stable release notes' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.publish' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)common\.publish(?=$|:)/ }))
|
||||
|
||||
expect(handlePublish).toHaveBeenCalledWith({
|
||||
title: 'Release 3',
|
||||
|
||||
@ -16,16 +16,6 @@ const mockOnDelete = vi.fn()
|
||||
const mockOnHideContextMissingTip = vi.fn()
|
||||
const mockCopy = vi.fn()
|
||||
const mockToastError = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('copy-to-clipboard', () => ({
|
||||
default: (...args: unknown[]) => mockCopy(...args),
|
||||
}))
|
||||
@ -175,7 +165,7 @@ describe('AdvancedPromptInput', () => {
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('blur-advanced'))
|
||||
fireEvent.click(screen.getByText('operation.add'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)operation\.add(?=$|:)/))
|
||||
|
||||
expect(mockSetModelConfig).toHaveBeenCalledWith(expect.objectContaining({
|
||||
configs: expect.objectContaining({
|
||||
@ -213,7 +203,7 @@ describe('AdvancedPromptInput', () => {
|
||||
|
||||
const modalConfig = mockSetShowExternalDataToolModal.mock.calls[0]![0]
|
||||
expect(modalConfig.onValidateBeforeSaveCallback({ variable: 'existing_var' })).toBe(false)
|
||||
expect(mockToastError).toHaveBeenCalledWith('varKeyError.keyAlreadyExists')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)varKeyError\.keyAlreadyExists(?=$|:)/))
|
||||
|
||||
modalConfig.onSaveCallback({
|
||||
label: 'Search',
|
||||
|
||||
@ -14,16 +14,6 @@ const mockSetPrevPromptConfig = vi.fn()
|
||||
const mockSetIntroduction = vi.fn()
|
||||
const mockOnChange = vi.fn()
|
||||
const mockToastError = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/hooks/use-breakpoints', () => ({
|
||||
__esModule: true,
|
||||
default: () => 'desktop',
|
||||
@ -154,9 +144,9 @@ describe('SimplePromptInput', () => {
|
||||
|
||||
fireEvent.click(screen.getByText('blur-prompt'))
|
||||
|
||||
expect(screen.getByText('autoAddVar'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)autoAddVar(?=$|:)/))!.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('operation.add'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)operation\.add(?=$|:)/))
|
||||
|
||||
expect(mockOnChange).toHaveBeenCalledWith('Hello {{new_var}}', [
|
||||
expect.objectContaining({
|
||||
@ -186,7 +176,7 @@ describe('SimplePromptInput', () => {
|
||||
const modalConfig = mockSetShowExternalDataToolModal.mock.calls[0]![0]
|
||||
|
||||
expect(modalConfig.onValidateBeforeSaveCallback({ variable: 'existing_var' })).toBe(false)
|
||||
expect(mockToastError).toHaveBeenCalledWith('varKeyError.keyAlreadyExists')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)varKeyError\.keyAlreadyExists(?=$|:)/))
|
||||
expect(modalConfig.onValidateBeforeSaveCallback({ variable: 'fresh_var' })).toBe(true)
|
||||
|
||||
modalConfig.onSaveCallback(undefined)
|
||||
@ -315,9 +305,9 @@ describe('SimplePromptInput', () => {
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('blur-prompt'))
|
||||
expect(screen.getByText('autoAddVar'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)autoAddVar(?=$|:)/))!.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('operation.cancel'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)operation\.cancel(?=$|:)/))
|
||||
expect(mockOnChange).toHaveBeenCalledWith('Hello {{existing_var}}', [])
|
||||
})
|
||||
})
|
||||
|
||||
@ -12,16 +12,6 @@ import ConfigModal from '../index'
|
||||
|
||||
const toastErrorSpy = vi.spyOn(toast, 'error').mockReturnValue('toast-error')
|
||||
let latestFormProps: Record<string, any> | null = null
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('../form-fields', () => ({
|
||||
default: (props: Record<string, any>) => {
|
||||
latestFormProps = props
|
||||
|
||||
@ -55,10 +55,6 @@ vi.mock('@/app/components/plugins/readme-panel/entrance', () => ({
|
||||
ReadmeEntrance: ({ className }: { className?: string }) => <div className={className}>readme</div>,
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: vi.fn(() => 'en-US'),
|
||||
}))
|
||||
|
||||
const createParameter = (overrides?: Partial<ToolParameter>): ToolParameter => ({
|
||||
name: 'settingParam',
|
||||
label: {
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import AutomaticBtn from '../automatic-btn'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
describe('AutomaticBtn', () => {
|
||||
const mockOnClick = vi.fn()
|
||||
|
||||
@ -21,7 +12,7 @@ describe('AutomaticBtn', () => {
|
||||
it('should render the button with correct text', () => {
|
||||
render(<AutomaticBtn onClick={mockOnClick} />)
|
||||
|
||||
expect(screen.getByText('operation.automatic')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)operation\.automatic(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the sparkling icon', () => {
|
||||
|
||||
@ -14,16 +14,6 @@ let mockDefaultModel: {
|
||||
} | null = null
|
||||
|
||||
let mockInstructionTemplate: { data: string } | undefined
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
toast: {
|
||||
error: (...args: unknown[]) => mockToastError(...args),
|
||||
@ -161,7 +151,7 @@ describe('GetAutomaticRes', () => {
|
||||
expect(screen.getByTestId('basic-editor')).toHaveTextContent('template instruction')
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByText('generate.template.pythonDebugger.name'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.template\.pythonDebugger\.name(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('basic-editor')).toHaveTextContent('generate.template.pythonDebugger.instruction')
|
||||
@ -186,9 +176,9 @@ describe('GetAutomaticRes', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('generate.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.generate(?=$|:)/))
|
||||
|
||||
expect(mockToastError).toHaveBeenCalledWith('errorMsg.fieldRequired')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)errorMsg\.fieldRequired(?=$|:)/))
|
||||
expect(mockGenerateBasicAppFirstTimeRule).not.toHaveBeenCalled()
|
||||
expect(screen.getByText('result-placeholder')).toBeInTheDocument()
|
||||
})
|
||||
@ -212,7 +202,7 @@ describe('GetAutomaticRes', () => {
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('set-basic-instruction'))
|
||||
fireEvent.click(screen.getByText('generate.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.generate(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockGenerateBasicAppFirstTimeRule).toHaveBeenCalledWith(expect.objectContaining({
|
||||
@ -228,10 +218,10 @@ describe('GetAutomaticRes', () => {
|
||||
fireEvent.click(screen.getByText('apply-result'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('generate.overwriteTitle')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)generate\.overwriteTitle(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.confirm' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.confirm(?=$|:)/ }))
|
||||
|
||||
expect(mockOnFinished).toHaveBeenCalledWith(expect.objectContaining({
|
||||
modified: 'generated prompt',
|
||||
@ -259,7 +249,7 @@ describe('GetAutomaticRes', () => {
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('set-basic-instruction'))
|
||||
fireEvent.click(screen.getByText('generate.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.generate(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('result-panel')).toHaveTextContent('generated prompt')
|
||||
@ -268,7 +258,7 @@ describe('GetAutomaticRes', () => {
|
||||
fireEvent.click(screen.getByText('apply-result'))
|
||||
const dialog = await screen.findByRole('alertdialog')
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: 'operation.cancel' }))
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: /(?:^|\.)operation\.cancel(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole('alertdialog')).not.toBeInTheDocument()
|
||||
@ -298,7 +288,7 @@ describe('GetAutomaticRes', () => {
|
||||
|
||||
fireEvent.click(screen.getByText('set-workflow-instruction'))
|
||||
fireEvent.click(screen.getByText('set-idea-output'))
|
||||
fireEvent.click(screen.getByText('generate.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.generate(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockGenerateRule).toHaveBeenCalledWith(expect.objectContaining({
|
||||
|
||||
@ -1,31 +1,22 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import IdeaOutput from '../idea-output'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
describe('IdeaOutput', () => {
|
||||
it('should toggle the fold state and propagate textarea changes when expanded', () => {
|
||||
const onChange = vi.fn()
|
||||
render(<IdeaOutput value="Initial idea" onChange={onChange} />)
|
||||
|
||||
expect(screen.queryByPlaceholderText('generate.idealOutputPlaceholder')).not.toBeInTheDocument()
|
||||
expect(screen.queryByPlaceholderText(/(?:^|\.)generate\.idealOutputPlaceholder(?=$|:)/)).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('generate.idealOutput'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.idealOutput(?=$|:)/))
|
||||
|
||||
const textarea = screen.getByPlaceholderText('generate.idealOutputPlaceholder')
|
||||
const textarea = screen.getByPlaceholderText(/(?:^|\.)generate\.idealOutputPlaceholder(?=$|:)/)
|
||||
fireEvent.change(textarea, { target: { value: 'Updated idea' } })
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith('Updated idea')
|
||||
|
||||
fireEvent.click(screen.getByText('generate.idealOutput'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.idealOutput(?=$|:)/))
|
||||
|
||||
expect(screen.queryByPlaceholderText('generate.idealOutputPlaceholder')).not.toBeInTheDocument()
|
||||
expect(screen.queryByPlaceholderText(/(?:^|\.)generate\.idealOutputPlaceholder(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -4,16 +4,6 @@ import InstructionEditor from '../instruction-editor'
|
||||
import { GeneratorType } from '../types'
|
||||
|
||||
const mockEmit = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/event-emitter', () => ({
|
||||
useEventEmitterContextContext: () => ({
|
||||
eventEmitter: {
|
||||
@ -63,7 +53,7 @@ describe('InstructionEditor', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('generate.instructionPlaceHolderTitle')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)generate\.instructionPlaceHolderTitle(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByTestId('current-block')).toHaveTextContent('true')
|
||||
expect(screen.getByTestId('error-block')).toHaveTextContent('false')
|
||||
|
||||
@ -81,11 +71,11 @@ describe('InstructionEditor', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('generate.codeGenInstructionPlaceHolderLine')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)generate\.codeGenInstructionPlaceHolderLine(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByTestId('error-block')).toHaveTextContent('true')
|
||||
expect(screen.getByTestId('last-run-block')).toHaveTextContent('true')
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'generate.insertContext' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)generate\.insertContext(?=$|:)/ }))
|
||||
|
||||
expect(mockEmit).toHaveBeenCalledWith(expect.objectContaining({
|
||||
instanceId: 'editor-1',
|
||||
|
||||
@ -4,16 +4,6 @@ import PromptResInWorkflow from '../prompt-res-in-workflow'
|
||||
|
||||
const mockUseAvailableVarList = vi.fn()
|
||||
const mockPromptRes = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/hooks/use-available-var-list', () => ({
|
||||
default: (...args: unknown[]) => mockUseAvailableVarList(...args),
|
||||
}))
|
||||
@ -66,7 +56,7 @@ describe('PromptResInWorkflow', () => {
|
||||
type: BlockEnum.KnowledgeRetrieval,
|
||||
}),
|
||||
'sys': expect.objectContaining({
|
||||
title: 'blocks.start',
|
||||
title: 'workflow.blocks.start',
|
||||
type: BlockEnum.Start,
|
||||
}),
|
||||
}),
|
||||
|
||||
@ -8,16 +8,6 @@ const mockPromptRes = vi.fn()
|
||||
const mockPromptResInWorkflow = vi.fn()
|
||||
const mockSetCurrentVersionIndex = vi.fn()
|
||||
const mockOnApply = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('copy-to-clipboard', () => ({
|
||||
default: (...args: unknown[]) => mockCopy(...args),
|
||||
}))
|
||||
@ -89,11 +79,11 @@ describe('Result', () => {
|
||||
|
||||
fireEvent.click(screen.getByTestId('version-selector'))
|
||||
fireEvent.click(screen.getAllByRole('button')[1]!)
|
||||
fireEvent.click(screen.getByText('generate.apply'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.apply(?=$|:)/))
|
||||
|
||||
expect(mockSetCurrentVersionIndex).toHaveBeenCalledWith(1)
|
||||
expect(mockCopy).toHaveBeenCalledWith('generated output')
|
||||
expect(toast.success).toHaveBeenCalledWith('actionMsg.copySuccessfully')
|
||||
expect(toast.success).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)actionMsg\.copySuccessfully(?=$|:)/))
|
||||
expect(mockOnApply).toHaveBeenCalled()
|
||||
expect(mockPromptRes).toHaveBeenCalledWith(expect.objectContaining({
|
||||
workflowVariableBlock: { show: false },
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import VersionSelector from '../version-selector'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
describe('VersionSelector', () => {
|
||||
it('should not open the selector when only one version exists', () => {
|
||||
const onChange = vi.fn()
|
||||
@ -22,9 +13,9 @@ describe('VersionSelector', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('generate.version 1 · generate.latest'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.version 1 · (?:.*\.)?generate\.latest$/))
|
||||
|
||||
expect(screen.queryByText('generate.versions')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)generate\.versions(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(onChange).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -39,16 +30,16 @@ describe('VersionSelector', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('generate.version 3 · generate.latest'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.version 3 · (?:.*\.)?generate\.latest$/))
|
||||
|
||||
expect(screen.getByText('generate.versions')).toBeInTheDocument()
|
||||
expect(screen.getByText('generate.version 1')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)generate\.versions(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)generate\.version 1$/)).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('generate.version 1'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)generate\.version 1$/))
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(0)
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('generate.versions')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)generate\.versions(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -14,16 +14,6 @@ let mockDefaultModel: {
|
||||
} | null = null
|
||||
|
||||
let mockInstructionTemplate: { data: string } | undefined
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
toast: {
|
||||
error: (...args: unknown[]) => mockToastError(...args),
|
||||
@ -168,9 +158,9 @@ describe('GetCodeGeneratorResModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('codegen.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)codegen\.generate(?=$|:)/))
|
||||
|
||||
expect(mockToastError).toHaveBeenCalledWith('errorMsg.fieldRequired')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)errorMsg\.fieldRequired(?=$|:)/))
|
||||
expect(mockGenerateRule).not.toHaveBeenCalled()
|
||||
expect(screen.getByText('code-result-placeholder')).toBeInTheDocument()
|
||||
})
|
||||
@ -195,7 +185,7 @@ describe('GetCodeGeneratorResModal', () => {
|
||||
|
||||
fireEvent.click(screen.getByText('set-code-instruction'))
|
||||
fireEvent.click(screen.getByText('set-code-output'))
|
||||
fireEvent.click(screen.getByText('codegen.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)codegen\.generate(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockGenerateRule).toHaveBeenCalledWith(expect.objectContaining({
|
||||
@ -215,10 +205,10 @@ describe('GetCodeGeneratorResModal', () => {
|
||||
fireEvent.click(screen.getByText('apply-code-result'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('codegen.overwriteConfirmTitle')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)codegen\.overwriteConfirmTitle(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.confirm' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.confirm(?=$|:)/ }))
|
||||
|
||||
expect(mockOnFinished).toHaveBeenCalledWith(expect.objectContaining({
|
||||
modified: 'print("hello")',
|
||||
@ -246,7 +236,7 @@ describe('GetCodeGeneratorResModal', () => {
|
||||
|
||||
fireEvent.click(screen.getByText('set-code-instruction'))
|
||||
fireEvent.click(screen.getByText('set-code-output'))
|
||||
fireEvent.click(screen.getByText('codegen.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)codegen\.generate(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('code-result-panel')).toHaveTextContent('print("hello")')
|
||||
@ -255,7 +245,7 @@ describe('GetCodeGeneratorResModal', () => {
|
||||
fireEvent.click(screen.getByText('apply-code-result'))
|
||||
const dialog = await screen.findByRole('alertdialog')
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: 'operation.cancel' }))
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: /(?:^|\.)operation\.cancel(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole('alertdialog')).not.toBeInTheDocument()
|
||||
@ -283,7 +273,7 @@ describe('GetCodeGeneratorResModal', () => {
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('set-code-instruction'))
|
||||
fireEvent.click(screen.getByText('codegen.generate'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)codegen\.generate(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockToastError).toHaveBeenCalledWith('generation failed')
|
||||
|
||||
@ -5,16 +5,6 @@ import ChatUserInput from '../chat-user-input'
|
||||
|
||||
const mockSetInputs = vi.fn()
|
||||
const mockUseContext = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('use-context-selector', () => ({
|
||||
useContext: () => mockUseContext(),
|
||||
createContext: vi.fn(() => ({})),
|
||||
@ -273,7 +263,7 @@ describe('ChatUserInput', () => {
|
||||
}))
|
||||
|
||||
render(<ChatUserInput inputs={{}} />)
|
||||
expect(screen.getByText('panel.optional')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)panel\.optional(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should not show optional label for required fields', () => {
|
||||
@ -284,7 +274,7 @@ describe('ChatUserInput', () => {
|
||||
}))
|
||||
|
||||
render(<ChatUserInput inputs={{}} />)
|
||||
expect(screen.queryByText('panel.optional')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)panel\.optional(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should use key as label when name is not provided', () => {
|
||||
|
||||
@ -29,16 +29,6 @@ let mockTempStopState: string[] = []
|
||||
let mockCurrentModelFeatures = ['vision']
|
||||
let mockCurrentModelMode = ModelModeType.chat
|
||||
let mockAppPermissionKeys: string[] = [AppACLPermission.Edit, AppACLPermission.ReleaseAndVersion]
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('ahooks', async () => {
|
||||
const actual = await vi.importActual<any>('ahooks')
|
||||
|
||||
|
||||
@ -4,16 +4,6 @@ import ExternalDataToolModal from '../external-data-tool-modal'
|
||||
const mockToastError = vi.fn()
|
||||
|
||||
let mockLocale = 'en-US'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
toast: {
|
||||
error: (...args: unknown[]) => mockToastError(...args),
|
||||
@ -102,15 +92,15 @@ describe('ExternalDataToolModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('feature.tools.modal.name.placeholder'), {
|
||||
fireEvent.change(screen.getByPlaceholderText(/(?:^|\.)feature\.tools\.modal\.name\.placeholder(?=$|:)/), {
|
||||
target: { value: 'Search' },
|
||||
})
|
||||
fireEvent.change(screen.getByPlaceholderText('feature.tools.modal.variableName.placeholder'), {
|
||||
fireEvent.change(screen.getByPlaceholderText(/(?:^|\.)feature\.tools\.modal\.variableName\.placeholder(?=$|:)/), {
|
||||
target: { value: 'search_api' },
|
||||
})
|
||||
fireEvent.click(screen.getByText('operation.save'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)operation\.save(?=$|:)/))
|
||||
|
||||
expect(mockToastError).toHaveBeenCalledWith('errorMessage.valueOfVarRequired')
|
||||
expect(mockToastError).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)errorMessage\.valueOfVarRequired(?=$|:)/))
|
||||
expect(mockOnSave).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -126,10 +116,10 @@ describe('ExternalDataToolModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('feature.tools.modal.name.placeholder'), {
|
||||
fireEvent.change(screen.getByPlaceholderText(/(?:^|\.)feature\.tools\.modal\.name\.placeholder(?=$|:)/), {
|
||||
target: { value: 'Search' },
|
||||
})
|
||||
fireEvent.change(screen.getByPlaceholderText('feature.tools.modal.variableName.placeholder'), {
|
||||
fireEvent.change(screen.getByPlaceholderText(/(?:^|\.)feature\.tools\.modal\.variableName\.placeholder(?=$|:)/), {
|
||||
target: { value: 'search_api' },
|
||||
})
|
||||
fireEvent.click(screen.getByText('pick-extension'))
|
||||
@ -142,7 +132,7 @@ describe('ExternalDataToolModal', () => {
|
||||
fireEvent.click(emojiButton!)
|
||||
fireEvent.click(screen.getByRole('button', { name: '#E4FBCC' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /iconPicker\.ok/ }))
|
||||
fireEvent.click(screen.getByText('operation.save'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)operation\.save(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockOnValidateBeforeSave).toHaveBeenCalledWith(expect.objectContaining({
|
||||
@ -170,7 +160,7 @@ describe('ExternalDataToolModal', () => {
|
||||
variable: 'search_api',
|
||||
}))
|
||||
|
||||
expect(screen.getByRole('link', { name: 'apiBasedExtension.link' })).toHaveAttribute(
|
||||
expect(screen.getByRole('link', { name: /(?:^|\.)apiBasedExtension\.link(?=$|:)/ })).toHaveAttribute(
|
||||
'href',
|
||||
'https://docs.example.com/use-dify/workspace/api-extension/api-extension',
|
||||
)
|
||||
@ -191,14 +181,14 @@ describe('ExternalDataToolModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('feature.tools.modal.name.placeholder'), {
|
||||
fireEvent.change(screen.getByPlaceholderText(/(?:^|\.)feature\.tools\.modal\.name\.placeholder(?=$|:)/), {
|
||||
target: { value: 'Code Search' },
|
||||
})
|
||||
fireEvent.change(screen.getByPlaceholderText('feature.tools.modal.variableName.placeholder'), {
|
||||
fireEvent.change(screen.getByPlaceholderText(/(?:^|\.)feature\.tools\.modal\.variableName\.placeholder(?=$|:)/), {
|
||||
target: { value: 'code_search' },
|
||||
})
|
||||
fireEvent.click(screen.getByText('fill-form'))
|
||||
fireEvent.click(screen.getByText('operation.save'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)operation\.save(?=$|:)/))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockOnSave).toHaveBeenCalledWith(expect.objectContaining({
|
||||
@ -212,7 +202,7 @@ describe('ExternalDataToolModal', () => {
|
||||
}))
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByText('operation.cancel'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)operation\.cancel(?=$|:)/))
|
||||
expect(mockOnCancel).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import DSLConfirmModal from '../dsl-confirm-modal'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
describe('DSLConfirmModal', () => {
|
||||
it('should render the version details', () => {
|
||||
render(
|
||||
@ -23,7 +14,7 @@ describe('DSLConfirmModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('newApp.appCreateDSLErrorTitle')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)newApp\.appCreateDSLErrorTitle(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByText('1.0.0')).toBeInTheDocument()
|
||||
expect(screen.getByText('2.0.0')).toBeInTheDocument()
|
||||
})
|
||||
@ -39,8 +30,8 @@ describe('DSLConfirmModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'newApp.Cancel' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'newApp.Confirm' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)newApp\.Cancel(?=$|:)/ }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)newApp\.Confirm(?=$|:)/ }))
|
||||
|
||||
expect(handleCancel).toHaveBeenCalledTimes(1)
|
||||
expect(handleConfirm).toHaveBeenCalledTimes(1)
|
||||
|
||||
@ -31,16 +31,6 @@ let mockPlanUsage = 0
|
||||
let mockPlanTotal = 10
|
||||
let mockWorkspacePermissionKeys: string[] = ['app.create_and_management']
|
||||
const mockUserProfile = { id: 'user-1' }
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('ahooks', () => ({
|
||||
useDebounceFn: (fn: (...args: any[]) => any) => ({
|
||||
run: fn,
|
||||
@ -202,10 +192,10 @@ describe('CreateFromDSLModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('importApp'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)importApp(?=$|:)/))!.toBeInTheDocument()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('demo.yml'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)demo\.yml(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -217,14 +207,14 @@ describe('CreateFromDSLModal', () => {
|
||||
expect(mockImportDSL).not.toHaveBeenCalled()
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByText('importFromDSLUrl'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)importFromDSLUrl(?=$|:)/))
|
||||
})
|
||||
expect(
|
||||
screen.getByPlaceholderText('importFromDSLUrlPlaceholder'),
|
||||
screen.getByPlaceholderText(/(?:^|\.)importFromDSLUrlPlaceholder(?=$|:)/),
|
||||
)!.toBeInTheDocument()
|
||||
|
||||
const closeTrigger = screen
|
||||
.getByText('importApp')
|
||||
.getByText(/(?:^|\.)importApp(?=$|:)/)
|
||||
.parentElement
|
||||
?.querySelector(
|
||||
'.cursor-pointer.items-center',
|
||||
@ -268,7 +258,7 @@ describe('CreateFromDSLModal', () => {
|
||||
)
|
||||
|
||||
fireEvent.change(
|
||||
screen.getByPlaceholderText('importFromDSLUrlPlaceholder'),
|
||||
screen.getByPlaceholderText(/(?:^|\.)importFromDSLUrlPlaceholder(?=$|:)/),
|
||||
{
|
||||
target: { value: 'https://example.com/app.yml' },
|
||||
},
|
||||
@ -354,7 +344,7 @@ describe('CreateFromDSLModal', () => {
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('demo.yml'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)demo\.yml(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
await act(async () => {
|
||||
@ -377,11 +367,11 @@ describe('CreateFromDSLModal', () => {
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('demo.yml'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)demo\.yml(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
const removeButton = screen
|
||||
.getByText('demo.yml')
|
||||
.getByText(/(?:^|\.)demo\.yml(?=$|:)/)
|
||||
.closest('.group')
|
||||
?.querySelector('button') as HTMLButtonElement
|
||||
await act(async () => {
|
||||
@ -389,7 +379,7 @@ describe('CreateFromDSLModal', () => {
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('demo.yml')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)demo\.yml(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(getCreateButton())!.toBeDisabled()
|
||||
})
|
||||
|
||||
@ -431,12 +421,12 @@ describe('CreateFromDSLModal', () => {
|
||||
})
|
||||
|
||||
expect(
|
||||
screen.getAllByText('newApp.appCreateDSLErrorTitle')[0],
|
||||
screen.getAllByText(/(?:^|\.)newApp\.appCreateDSLErrorTitle(?=$|:)/)[0],
|
||||
)!.toBeInTheDocument()
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
screen.getAllByRole('button', { name: 'newApp.Confirm' })[0]!,
|
||||
screen.getAllByRole('button', { name: /(?:^|\.)newApp\.Confirm(?=$|:)/ })[0]!,
|
||||
)
|
||||
})
|
||||
|
||||
@ -487,7 +477,7 @@ describe('CreateFromDSLModal', () => {
|
||||
})
|
||||
|
||||
expect(
|
||||
screen.getByText('newApp.appCreateDSLErrorTitle'),
|
||||
screen.getByText(/(?:^|\.)newApp\.appCreateDSLErrorTitle(?=$|:)/),
|
||||
)!.toBeInTheDocument()
|
||||
|
||||
vi.useRealTimers()
|
||||
@ -495,7 +485,7 @@ describe('CreateFromDSLModal', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.queryByText('newApp.appCreateDSLErrorTitle'),
|
||||
screen.queryByText(/(?:^|\.)newApp\.appCreateDSLErrorTitle(?=$|:)/),
|
||||
).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
@ -527,17 +517,17 @@ describe('CreateFromDSLModal', () => {
|
||||
})
|
||||
|
||||
expect(
|
||||
screen.getByText('newApp.appCreateDSLErrorTitle'),
|
||||
screen.getByText(/(?:^|\.)newApp\.appCreateDSLErrorTitle(?=$|:)/),
|
||||
)!.toBeInTheDocument()
|
||||
|
||||
vi.useRealTimers()
|
||||
fireEvent.click(
|
||||
screen.getAllByRole('button', { name: 'newApp.Cancel' }).at(-1)!,
|
||||
screen.getAllByRole('button', { name: /(?:^|\.)newApp\.Cancel(?=$|:)/ }).at(-1)!,
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.queryByText('newApp.appCreateDSLErrorTitle'),
|
||||
screen.queryByText(/(?:^|\.)newApp\.appCreateDSLErrorTitle(?=$|:)/),
|
||||
).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
@ -670,7 +660,7 @@ describe('CreateFromDSLModal', () => {
|
||||
fireEvent.click(getCreateButton())
|
||||
})
|
||||
expect(toastMocks.error).toHaveBeenCalledTimes(2)
|
||||
expect(toastMocks.error).toHaveBeenLastCalledWith('newApp.appCreateFailed')
|
||||
expect(toastMocks.error).toHaveBeenLastCalledWith(expect.stringMatching(/(?:^|\.)newApp\.appCreateFailed(?=$|:)/))
|
||||
})
|
||||
|
||||
it('should handle pending import confirmation failures and cancellation', async () => {
|
||||
@ -703,10 +693,10 @@ describe('CreateFromDSLModal', () => {
|
||||
})
|
||||
|
||||
fireEvent.click(
|
||||
screen.getAllByRole('button', { name: 'newApp.Cancel' }).at(-1)!,
|
||||
screen.getAllByRole('button', { name: /(?:^|\.)newApp\.Cancel(?=$|:)/ }).at(-1)!,
|
||||
)
|
||||
expect(
|
||||
screen.queryByText('newApp.appCreateDSLErrorTitle'),
|
||||
screen.queryByText(/(?:^|\.)newApp\.appCreateDSLErrorTitle(?=$|:)/),
|
||||
).not.toBeInTheDocument()
|
||||
|
||||
await act(async () => {
|
||||
@ -715,17 +705,17 @@ describe('CreateFromDSLModal', () => {
|
||||
})
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
screen.getAllByRole('button', { name: 'newApp.Confirm' })[0]!,
|
||||
screen.getAllByRole('button', { name: /(?:^|\.)newApp\.Confirm(?=$|:)/ })[0]!,
|
||||
)
|
||||
})
|
||||
expect(toastMocks.error).toHaveBeenCalledWith('Confirm failed')
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
screen.getAllByRole('button', { name: 'newApp.Confirm' })[0]!,
|
||||
screen.getAllByRole('button', { name: /(?:^|\.)newApp\.Confirm(?=$|:)/ })[0]!,
|
||||
)
|
||||
})
|
||||
expect(toastMocks.error).toHaveBeenCalledTimes(2)
|
||||
expect(toastMocks.error).toHaveBeenLastCalledWith('newApp.appCreateFailed')
|
||||
expect(toastMocks.error).toHaveBeenLastCalledWith(expect.stringMatching(/(?:^|\.)newApp\.appCreateFailed(?=$|:)/))
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,15 +2,6 @@ import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import Uploader from '../uploader'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
toast: {
|
||||
error: vi.fn(),
|
||||
@ -66,7 +57,7 @@ describe('Uploader', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(toast.error).toHaveBeenCalledWith('stepOne.uploader.validation.count')
|
||||
expect(toast.error).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)stepOne\.uploader\.validation\.count(?=$|:)/))
|
||||
expect(updateFile).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -82,7 +73,7 @@ describe('Uploader', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('demo.yml')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)demo\.yml(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByText('DSL')).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByRole('button'))
|
||||
@ -160,7 +151,7 @@ describe('Uploader', () => {
|
||||
const hiddenInput = getHiddenInput()
|
||||
const clickSpy = vi.spyOn(hiddenInput, 'click')
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'dslUploader.browse' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)dslUploader\.browse(?=$|:)/ }))
|
||||
|
||||
expect(clickSpy).toHaveBeenCalled()
|
||||
|
||||
|
||||
@ -3,16 +3,6 @@ import userEvent from '@testing-library/user-event'
|
||||
import DuplicateAppModal from '../index'
|
||||
|
||||
const toastErrorMock = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/provider-context', () => ({
|
||||
useProviderContext: () => ({
|
||||
plan: {
|
||||
@ -94,9 +84,9 @@ describe('DuplicateAppModal', () => {
|
||||
expect(input).toHaveValue('Updated App')
|
||||
|
||||
await user.clear(input)
|
||||
await user.click(screen.getByRole('button', { name: 'duplicate' }))
|
||||
await user.click(screen.getByRole('button', { name: /(?:^|\.)duplicate(?=$|:)/ }))
|
||||
|
||||
expect(toastErrorMock).toHaveBeenCalledWith('appCustomize.nameRequired')
|
||||
expect(toastErrorMock).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)appCustomize\.nameRequired(?=$|:)/))
|
||||
expect(onConfirm).not.toHaveBeenCalled()
|
||||
expect(onHide).not.toHaveBeenCalled()
|
||||
})
|
||||
@ -127,7 +117,7 @@ describe('DuplicateAppModal', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByPlaceholderText('Search emojis...')).not.toBeInTheDocument()
|
||||
})
|
||||
await user.click(screen.getByRole('button', { name: 'duplicate' }))
|
||||
await user.click(screen.getByRole('button', { name: /(?:^|\.)duplicate(?=$|:)/ }))
|
||||
|
||||
expect(onConfirm).toHaveBeenCalledWith({
|
||||
name: 'Demo App',
|
||||
@ -154,7 +144,7 @@ describe('DuplicateAppModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'operation.close' }))
|
||||
await user.click(screen.getByRole('button', { name: /(?:^|\.)operation\.close(?=$|:)/ }))
|
||||
|
||||
expect(onHide).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
@ -195,7 +185,7 @@ describe('DuplicateAppModal', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByPlaceholderText('Search emojis...')).not.toBeInTheDocument()
|
||||
})
|
||||
await user.click(screen.getByRole('button', { name: 'duplicate' }))
|
||||
await user.click(screen.getByRole('button', { name: /(?:^|\.)duplicate(?=$|:)/ }))
|
||||
|
||||
expect(onConfirm).toHaveBeenCalledWith(expect.objectContaining({
|
||||
name: 'Image App',
|
||||
|
||||
@ -5,19 +5,6 @@ import Filter, { TIME_PERIOD_MAPPING } from '../filter'
|
||||
let mockAnnotationsCountLoading = false
|
||||
let mockAnnotationsCountData: { count: number } | null = { count: 10 }
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { count?: number }) => {
|
||||
if (options?.count !== undefined)
|
||||
return `${key} (${options.count})`
|
||||
return key
|
||||
}),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/service/use-log', () => ({
|
||||
useAnnotationsCount: () => ({
|
||||
data: mockAnnotationsCountData,
|
||||
@ -80,7 +67,7 @@ describe('Filter', () => {
|
||||
it('should render filter components', () => {
|
||||
render(<Filter {...defaultProps} />)
|
||||
|
||||
expect(screen.getByPlaceholderText('operation.search'))!.toBeInTheDocument()
|
||||
expect(screen.getByPlaceholderText(/(?:^|\.)operation\.search(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should return null when loading', () => {
|
||||
@ -92,13 +79,13 @@ describe('Filter', () => {
|
||||
it('should render sort component in chat mode', () => {
|
||||
render(<Filter {...defaultProps} isChatMode />)
|
||||
|
||||
expect(screen.getByPlaceholderText('operation.search'))!.toBeInTheDocument()
|
||||
expect(screen.getByPlaceholderText(/(?:^|\.)operation\.search(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should not render sort component when not in chat mode', () => {
|
||||
render(<Filter {...defaultProps} isChatMode={false} />)
|
||||
|
||||
expect(screen.getByPlaceholderText('operation.search'))!.toBeInTheDocument()
|
||||
expect(screen.getByPlaceholderText(/(?:^|\.)operation\.search(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -132,7 +119,7 @@ describe('Filter', () => {
|
||||
it('should update keyword when typing in search input', () => {
|
||||
render(<Filter {...defaultProps} />)
|
||||
|
||||
const searchInput = screen.getByPlaceholderText('operation.search')
|
||||
const searchInput = screen.getByPlaceholderText(/(?:^|\.)operation\.search(?=$|:)/)
|
||||
fireEvent.change(searchInput, { target: { value: 'test search' } })
|
||||
|
||||
expect(mockSetQueryParams).toHaveBeenCalledWith({
|
||||
@ -149,7 +136,7 @@ describe('Filter', () => {
|
||||
|
||||
render(<Filter {...propsWithKeyword} />)
|
||||
|
||||
const clearButton = screen.getByRole('button', { name: 'operation.clear' })
|
||||
const clearButton = screen.getByRole('button', { name: /(?:^|\.)operation\.clear(?=$|:)/ })
|
||||
fireEvent.click(clearButton)
|
||||
|
||||
expect(mockSetQueryParams).toHaveBeenCalledWith({
|
||||
@ -204,7 +191,7 @@ describe('Filter', () => {
|
||||
|
||||
// Period '1' maps to 'today' in TIME_PERIOD_MAPPING
|
||||
// Period '1' maps to 'today' in TIME_PERIOD_MAPPING
|
||||
expect(screen.getByText('filter.period.today'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)filter\.period\.today(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should display "last7days" when period is set to 2', () => {
|
||||
@ -215,7 +202,7 @@ describe('Filter', () => {
|
||||
|
||||
render(<Filter {...propsWithPeriod} />)
|
||||
|
||||
expect(screen.getByText('filter.period.last7days'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)filter\.period\.last7days(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should display "allTime" when period is set to 9', () => {
|
||||
@ -223,7 +210,7 @@ describe('Filter', () => {
|
||||
|
||||
// Default period is '9' which maps to 'allTime'
|
||||
// Default period is '9' which maps to 'allTime'
|
||||
expect(screen.getByText('filter.period.allTime'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)filter\.period\.allTime(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should display annotated status with count when annotation_status is annotated', () => {
|
||||
@ -236,7 +223,7 @@ describe('Filter', () => {
|
||||
|
||||
// The mock returns count: 10, so the text should include the count
|
||||
// The mock returns count: 10, so the text should include the count
|
||||
expect(screen.getByText('filter.annotation.annotated (10)'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/filter\.annotation\.annotated.*10/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should display not_annotated status when annotation_status is not_annotated', () => {
|
||||
@ -247,7 +234,7 @@ describe('Filter', () => {
|
||||
|
||||
render(<Filter {...propsWithNotAnnotated} />)
|
||||
|
||||
expect(screen.getByText('filter.annotation.not_annotated'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)filter\.annotation\.not_annotated(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should display all annotation status when annotation_status is all', () => {
|
||||
@ -255,7 +242,7 @@ describe('Filter', () => {
|
||||
|
||||
// Default annotation_status is 'all'
|
||||
// Default annotation_status is 'all'
|
||||
expect(screen.getByText('filter.annotation.all'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)filter\.annotation\.all(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should return null when annotation count data is unavailable', () => {
|
||||
@ -276,7 +263,7 @@ describe('Filter', () => {
|
||||
|
||||
render(<Filter {...propsWithSort} />)
|
||||
|
||||
expect(screen.getByPlaceholderText('operation.search'))!.toBeInTheDocument()
|
||||
expect(screen.getByPlaceholderText(/(?:^|\.)operation\.search(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle descending sort order', () => {
|
||||
@ -288,7 +275,7 @@ describe('Filter', () => {
|
||||
|
||||
render(<Filter {...propsWithDescSort} />)
|
||||
|
||||
expect(screen.getByPlaceholderText('operation.search'))!.toBeInTheDocument()
|
||||
expect(screen.getByPlaceholderText(/(?:^|\.)operation\.search(?=$|:)/))!.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -4,21 +4,15 @@ import { APP_PAGE_LIMIT } from '@/config'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import Logs from '../index'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
const mockReplace = vi.fn()
|
||||
const mockUseChatConversations = vi.fn()
|
||||
const mockUseCompletionConversations = vi.fn()
|
||||
|
||||
let mockSearchParams = new URLSearchParams()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('ahooks', async () => {
|
||||
return {
|
||||
useDebounce: <T,>(value: T) => value,
|
||||
@ -36,10 +30,6 @@ vi.mock('@/next/navigation', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('@/service/use-log', () => ({
|
||||
useChatConversations: (...args: unknown[]) => mockUseChatConversations(...args),
|
||||
useCompletionConversations: (...args: unknown[]) => mockUseCompletionConversations(...args),
|
||||
@ -109,9 +99,9 @@ describe('Logs', () => {
|
||||
expect(mockUseChatConversations).toHaveBeenCalledWith(expect.objectContaining({
|
||||
appId: 'app-1',
|
||||
}))
|
||||
expect(screen.getByRole('heading', { name: 'title' })).toBeInTheDocument()
|
||||
expect(screen.getByText('description')).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'operation.learnMore' })).toHaveAttribute('href', 'https://docs.example.com/use-dify/monitor/logs')
|
||||
expect(screen.getByRole('heading', { name: /(?:^|\.)title(?=$|:)/ })).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)description(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: /(?:^|\.)operation\.learnMore(?=$|:)/ })).toHaveAttribute('href', 'https://docs.example.com/use-dify/monitor/logs')
|
||||
expect(screen.getByText('loading-logs')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
|
||||
@ -24,16 +24,6 @@ let mockShowPromptLogModal = false
|
||||
let mockShowAgentLogModal = false
|
||||
let mockCurrentLogItem: Record<string, unknown> | undefined
|
||||
let mockCurrentLogModalActiveTab = 'messages'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/hooks/use-timestamp', () => ({
|
||||
default: () => ({
|
||||
formatTime: (timestamp: number) => `formatted-${timestamp}`,
|
||||
@ -311,7 +301,7 @@ describe('ConversationList', () => {
|
||||
searchParams: '?page=2&conversation_id=conversation-1',
|
||||
})
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'operation.close' }))
|
||||
fireEvent.click(await screen.findByRole('button', { name: /(?:^|\.)operation\.close(?=$|:)/ }))
|
||||
|
||||
expect(mockOnRefresh).toHaveBeenCalledTimes(1)
|
||||
expect(mockSetShowPromptLogModal).toHaveBeenCalledWith(false)
|
||||
@ -636,7 +626,7 @@ describe('ConversationList', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('chat-panel')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('chat-panel')).toHaveTextContent('8')
|
||||
expect(screen.getByText('detail.loading...')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)detail\.loading\.\.\.(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByText('chat-add-annotation'))
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import ModelInfo from '../model-info'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', () => ({
|
||||
useTextGenerationCurrentProviderAndModelAndModelList: () => ({
|
||||
currentModel: {
|
||||
@ -153,7 +144,7 @@ describe('ModelInfo', () => {
|
||||
render(<ModelInfo model={defaultModel} />)
|
||||
fireEvent.click(screen.getByRole('button'))
|
||||
|
||||
expect(screen.getByText('detail.modelParams')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)detail\.modelParams(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render temperature parameter', () => {
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
import { act, fireEvent, render, screen } from '@testing-library/react'
|
||||
import VarPanel from '../var-panel'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/base/image-uploader/image-preview', () => ({
|
||||
default: ({ url, title, onCancel }: { url: string, title: string, onCancel: () => void }) => (
|
||||
<div data-testid="image-preview" data-url={url} data-title={title}>
|
||||
@ -31,7 +22,7 @@ describe('VarPanel', () => {
|
||||
it('should render variables section header', () => {
|
||||
render(<VarPanel {...defaultProps} />)
|
||||
|
||||
expect(screen.getByText('detail.variables')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)detail\.variables(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render variable labels with braces', () => {
|
||||
@ -77,7 +68,7 @@ describe('VarPanel', () => {
|
||||
it('should collapse when header is clicked', () => {
|
||||
render(<VarPanel {...defaultProps} />)
|
||||
|
||||
const header = screen.getByText('detail.variables').closest('div')
|
||||
const header = screen.getByText(/(?:^|\.)detail\.variables(?=$|:)/).closest('div')
|
||||
fireEvent.click(header!)
|
||||
|
||||
expect(screen.queryByText('John Doe')).not.toBeInTheDocument()
|
||||
@ -87,7 +78,7 @@ describe('VarPanel', () => {
|
||||
it('should expand when clicked again', () => {
|
||||
render(<VarPanel {...defaultProps} />)
|
||||
|
||||
const header = screen.getByText('detail.variables').closest('div')
|
||||
const header = screen.getByText(/(?:^|\.)detail\.variables(?=$|:)/).closest('div')
|
||||
|
||||
// Collapse
|
||||
fireEvent.click(header!)
|
||||
@ -101,7 +92,7 @@ describe('VarPanel', () => {
|
||||
it('should show arrow icon when collapsed', () => {
|
||||
const { container } = render(<VarPanel {...defaultProps} />)
|
||||
|
||||
const header = screen.getByText('detail.variables').closest('div')
|
||||
const header = screen.getByText(/(?:^|\.)detail\.variables(?=$|:)/).closest('div')
|
||||
fireEvent.click(header!)
|
||||
|
||||
// When collapsed, there should be SVG icons in the component
|
||||
@ -122,7 +113,7 @@ describe('VarPanel', () => {
|
||||
it('should not render images section when message_files is empty', () => {
|
||||
render(<VarPanel {...defaultProps} />)
|
||||
|
||||
expect(screen.queryByText('detail.uploadImages')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)detail\.uploadImages(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render images section when message_files has items', () => {
|
||||
@ -133,7 +124,7 @@ describe('VarPanel', () => {
|
||||
|
||||
render(<VarPanel {...propsWithFiles} />)
|
||||
|
||||
expect(screen.getByText('detail.uploadImages')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)detail\.uploadImages(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render image thumbnails with correct background', () => {
|
||||
@ -196,7 +187,7 @@ describe('VarPanel', () => {
|
||||
|
||||
render(<VarPanel {...emptyProps} />)
|
||||
|
||||
expect(screen.getByText('detail.variables')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)detail\.variables(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -7,16 +7,6 @@ import { withSelectorKey } from '@/test/i18n-mock'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import { AppCardAccessControlSection, AppCardDialogs, AppCardOperations, AppCardUrlSection, createAppCardOperations, WorkflowLaunchDialog } from '../app-card-sections'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey, withSelectorKeyProps } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
Trans: withSelectorKeyProps(({ i18nKey }: { i18nKey: string }) => <span>{i18nKey}</span>),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('../settings', () => ({
|
||||
default: () => <div data-testid="settings-modal" />,
|
||||
}))
|
||||
@ -83,9 +73,9 @@ describe('app-card-sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('publishApp.notSet'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)publishApp\.notSet(?=$|:)/))
|
||||
|
||||
expect(screen.getByText('accessControlDialog.accessItems.specific')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)accessControlDialog\.accessItems\.specific(?=$|:)/)).toBeInTheDocument()
|
||||
expect(onClick).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
@ -121,7 +111,7 @@ describe('app-card-sections', () => {
|
||||
|
||||
expect(onLaunch).toHaveBeenCalledTimes(1)
|
||||
expect(onLaunchConfig).toHaveBeenCalledTimes(1)
|
||||
expect(screen.getByText('overview.appInfo.launch')).not.toHaveAttribute('title')
|
||||
expect(screen.getByText(/(?:^|\.)overview\.appInfo\.launch(?=$|:)/)).not.toHaveAttribute('title')
|
||||
expect(screen.getByRole('button', { name: /overview\.appInfo\.embedded\.entry/i })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -180,7 +170,7 @@ describe('app-card-sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByRole('button', { name: 'overview.appInfo.customize.entry' })).toHaveAttribute('title', 'overview.appInfo.customize.entry')
|
||||
expect(screen.getByRole('button', { name: /(?:^|\.)overview\.appInfo\.customize\.entry(?=$|:)/ })).toHaveAttribute('title', 'overview.appInfo.customize.entry')
|
||||
expect(AppModeEnum.CHAT).toBe('chat')
|
||||
})
|
||||
|
||||
@ -254,7 +244,7 @@ describe('app-card-sections', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('overview.appInfo.workflowLaunchHiddenInputs.title')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.appInfo\.workflowLaunchHiddenInputs\.title(?=$|:)/)).toBeInTheDocument()
|
||||
fireEvent.submit(screen.getByRole('button', { name: /overview\.appInfo\.launch/i }).closest('form')!)
|
||||
expect(onSubmit).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -9,6 +9,10 @@ import { AppACLPermission } from '@/utils/permission'
|
||||
import { basePath } from '@/utils/var'
|
||||
import AppCard from '../app-card'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
const render = (ui: ReactElement) => renderWithSystemFeatures(ui, {
|
||||
systemFeatures: { webapp_auth: { enabled: true } },
|
||||
})
|
||||
@ -23,20 +27,6 @@ let mockWorkflow: { graph?: { nodes?: Array<{ data?: { type?: string, variables?
|
||||
let mockAccessSubjects: { groups?: unknown[], members?: unknown[] } = { groups: [], members: [] }
|
||||
let mockAppDetail: AppDetailResponse | undefined
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey, withSelectorKeyProps } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
Trans: withSelectorKeyProps(({ i18nKey }: { i18nKey?: string }) => i18nKey ?? null),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/app/store', () => ({
|
||||
useStore: (selector: (state: { appDetail: AppDetailResponse, setAppDetail: typeof mockSetAppDetail }) => unknown) => selector({
|
||||
appDetail: mockAppDetail as AppDetailResponse,
|
||||
@ -156,7 +146,7 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.launch'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.launch(?=$|:)/))
|
||||
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith(`https://example.com${basePath}/chat/access-token`, '_blank')
|
||||
})
|
||||
@ -192,13 +182,13 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.launch'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.launch(?=$|:)/))
|
||||
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith(
|
||||
`https://example.com${basePath}/workflow/access-token`,
|
||||
'_blank',
|
||||
)
|
||||
expect(screen.queryByText('overview.appInfo.workflowLaunchHiddenInputs.title')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)overview\.appInfo\.workflowLaunchHiddenInputs\.title(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should collect hidden workflow inputs from the config action before launching the workflow web app', async () => {
|
||||
@ -232,14 +222,14 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.config' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.config(?=$|:)/ }))
|
||||
|
||||
expect(screen.getByText('overview.appInfo.workflowLaunchHiddenInputs.title')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.appInfo\.workflowLaunchHiddenInputs\.title(?=$|:)/)).toBeInTheDocument()
|
||||
|
||||
fireEvent.change(screen.getByLabelText('Secret'), {
|
||||
target: { value: 'top-secret' },
|
||||
})
|
||||
fireEvent.click(screen.getByRole('button', { name: 'overview.appInfo.launch' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)overview\.appInfo\.launch(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith(
|
||||
@ -280,13 +270,13 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.launch'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.launch(?=$|:)/))
|
||||
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith(
|
||||
`https://example.com${basePath}/chat/access-token`,
|
||||
'_blank',
|
||||
)
|
||||
expect(screen.queryByText('overview.appInfo.workflowLaunchHiddenInputs.title')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)overview\.appInfo\.workflowLaunchHiddenInputs\.title(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should collect hidden chatflow inputs from the config action before launching the chat web app', async () => {
|
||||
@ -320,14 +310,14 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.config' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.config(?=$|:)/ }))
|
||||
|
||||
expect(screen.getByText('overview.appInfo.workflowLaunchHiddenInputs.title')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.appInfo\.workflowLaunchHiddenInputs\.title(?=$|:)/)).toBeInTheDocument()
|
||||
|
||||
fireEvent.change(screen.getByLabelText('Chat Secret'), {
|
||||
target: { value: 'chat-secret' },
|
||||
})
|
||||
fireEvent.click(screen.getByRole('button', { name: 'overview.appInfo.launch' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)overview\.appInfo\.launch(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith(
|
||||
@ -345,7 +335,7 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('publishApp.notSet')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)publishApp\.notSet(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should hide the access-control section when release permission is missing', () => {
|
||||
@ -359,8 +349,8 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.queryByText('publishApp.title')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('publishApp.notSet')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)publishApp\.title(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)publishApp\.notSet(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should hide the address and operation sections for unpublished workflows', () => {
|
||||
@ -376,9 +366,9 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.queryByText('overview.appInfo.accessibleAddress')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('overview.appInfo.launch')).not.toBeInTheDocument()
|
||||
expect(screen.getByText('overview.status.disable')).toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)overview\.appInfo\.accessibleAddress(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)overview\.appInfo\.launch(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.status\.disable(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render api operations and navigate to the develop page', () => {
|
||||
@ -395,7 +385,7 @@ describe('AppCard', () => {
|
||||
|
||||
expect(screen.getByTestId('secret-key-button')).toHaveTextContent('app-1')
|
||||
|
||||
fireEvent.click(screen.getByText('overview.apiInfo.doc'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.apiInfo\.doc(?=$|:)/))
|
||||
|
||||
expect(mockPush).toHaveBeenCalledWith('/app/app-1/develop')
|
||||
})
|
||||
@ -408,13 +398,13 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.embedded.entry'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.embedded\.entry(?=$|:)/))
|
||||
expect(screen.getByTestId('embedded-modal')).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.customize.entry'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.customize\.entry(?=$|:)/))
|
||||
expect(screen.getByTestId('customize-modal')).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.settings.entry'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.settings\.entry(?=$|:)/))
|
||||
expect(screen.getByTestId('settings-modal')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -428,7 +418,7 @@ describe('AppCard', () => {
|
||||
)
|
||||
const setQueryDataSpy = vi.spyOn(queryClient, 'setQueryData')
|
||||
|
||||
fireEvent.click(screen.getByText('publishApp.notSet'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)publishApp\.notSet(?=$|:)/))
|
||||
expect(screen.getByTestId('access-control-modal')).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('confirm-access-control'))
|
||||
@ -461,8 +451,8 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'overview.appInfo.enableTooltip.description' }))
|
||||
fireEvent.click(screen.getByText('overview.appInfo.enableTooltip.learnMore'))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)overview\.appInfo\.enableTooltip\.description(?=$|:)/ }))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.enableTooltip\.learnMore(?=$|:)/))
|
||||
|
||||
expect(mockWindowOpen).toHaveBeenCalledWith('https://docs.example.com/use-dify/nodes/user-input', '_blank')
|
||||
})
|
||||
@ -475,19 +465,19 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.embedded.entry'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.embedded\.entry(?=$|:)/))
|
||||
fireEvent.click(screen.getByTestId('embedded-modal'))
|
||||
expect(screen.queryByTestId('embedded-modal')).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.customize.entry'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.customize\.entry(?=$|:)/))
|
||||
fireEvent.click(screen.getByTestId('customize-modal'))
|
||||
expect(screen.queryByTestId('customize-modal')).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('overview.appInfo.settings.entry'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)overview\.appInfo\.settings\.entry(?=$|:)/))
|
||||
fireEvent.click(screen.getByTestId('settings-modal'))
|
||||
expect(screen.queryByTestId('settings-modal')).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('publishApp.notSet'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)publishApp\.notSet(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('close-access-control'))
|
||||
expect(screen.queryByTestId('access-control-modal')).not.toBeInTheDocument()
|
||||
})
|
||||
@ -503,7 +493,7 @@ describe('AppCard', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByText('publishApp.notSet'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)publishApp\.notSet(?=$|:)/))
|
||||
fireEvent.click(screen.getByText('confirm-access-control'))
|
||||
|
||||
await waitFor(() => {
|
||||
@ -523,13 +513,13 @@ describe('AppCard', () => {
|
||||
|
||||
const refreshButton = container.querySelector('[class*="refreshIcon"]')?.parentElement as HTMLElement
|
||||
fireEvent.click(refreshButton)
|
||||
expect(screen.getByText('overview.appInfo.regenerateNotice')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.appInfo\.regenerateNotice(?=$|:)/)).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.confirm' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.confirm(?=$|:)/ }))
|
||||
|
||||
expect(mockOnGenerateCode).not.toHaveBeenCalled()
|
||||
return waitFor(() => {
|
||||
expect(screen.queryByText('overview.appInfo.regenerateNotice')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)overview\.appInfo\.regenerateNotice(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -545,7 +535,7 @@ describe('AppCard', () => {
|
||||
|
||||
const refreshButton = container.querySelector('[class*="refreshIcon"]')?.parentElement as HTMLElement
|
||||
fireEvent.click(refreshButton)
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.confirm' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.confirm(?=$|:)/ }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockOnGenerateCode).toHaveBeenCalledTimes(1)
|
||||
|
||||
@ -2,16 +2,6 @@ import { render, screen } from '@testing-library/react'
|
||||
import Chart, { MessagesChart } from '../app-chart'
|
||||
|
||||
const reactEChartsMock = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('echarts-for-react', () => ({
|
||||
default: (props: { option: unknown, opts?: unknown }) => {
|
||||
reactEChartsMock(props)
|
||||
@ -91,7 +81,7 @@ describe('app-chart', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('analysis.totalMessages.title'))!.toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)analysis\.totalMessages\.title(?=$|:)/))!.toBeInTheDocument()
|
||||
expect(screen.getByText('0'))!.toBeInTheDocument()
|
||||
expect(screen.getByTestId('echarts'))!.toBeInTheDocument()
|
||||
|
||||
|
||||
@ -4,19 +4,6 @@ import { AppModeEnum } from '@/types/app'
|
||||
import { AppACLPermission } from '@/utils/permission'
|
||||
import TriggerCard from '../trigger-card'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { count?: number }) => {
|
||||
if (options?.count !== undefined)
|
||||
return `${key} (${options.count})`
|
||||
return key
|
||||
}),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
@ -128,7 +115,7 @@ describe('TriggerCard', () => {
|
||||
|
||||
render(<TriggerCard appInfo={mockAppInfo} onToggleResult={mockOnToggleResult} />)
|
||||
|
||||
expect(screen.getByText('overview.triggerInfo.noTriggerAdded')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.triggerInfo\.noTriggerAdded(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show trigger status description when no triggers', () => {
|
||||
@ -136,7 +123,7 @@ describe('TriggerCard', () => {
|
||||
|
||||
render(<TriggerCard appInfo={mockAppInfo} onToggleResult={mockOnToggleResult} />)
|
||||
|
||||
expect(screen.getByText('overview.triggerInfo.triggerStatusDescription')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.triggerInfo\.triggerStatusDescription(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show learn more link when no triggers', () => {
|
||||
@ -144,7 +131,7 @@ describe('TriggerCard', () => {
|
||||
|
||||
render(<TriggerCard appInfo={mockAppInfo} onToggleResult={mockOnToggleResult} />)
|
||||
|
||||
const learnMoreLink = screen.getByText('overview.triggerInfo.learnAboutTriggers')
|
||||
const learnMoreLink = screen.getByText(/(?:^|\.)overview\.triggerInfo\.learnAboutTriggers(?=$|:)/)
|
||||
expect(learnMoreLink).toBeInTheDocument()
|
||||
expect(learnMoreLink).toHaveAttribute('href', 'https://docs.example.com/use-dify/nodes/trigger/overview')
|
||||
})
|
||||
@ -173,7 +160,7 @@ describe('TriggerCard', () => {
|
||||
it('should show triggers count message', () => {
|
||||
render(<TriggerCard appInfo={mockAppInfo} onToggleResult={mockOnToggleResult} />)
|
||||
|
||||
expect(screen.getByText('overview.triggerInfo.triggersAdded (2)')).toBeInTheDocument()
|
||||
expect(screen.getByText(/overview\.triggerInfo\.triggersAdded.*2/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render trigger titles', () => {
|
||||
@ -186,13 +173,13 @@ describe('TriggerCard', () => {
|
||||
it('should show running status for enabled triggers', () => {
|
||||
render(<TriggerCard appInfo={mockAppInfo} onToggleResult={mockOnToggleResult} />)
|
||||
|
||||
expect(screen.getByText('overview.status.running')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.status\.running(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show disable status for disabled triggers', () => {
|
||||
render(<TriggerCard appInfo={mockAppInfo} onToggleResult={mockOnToggleResult} />)
|
||||
|
||||
expect(screen.getByText('overview.status.disable')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)overview\.status\.disable(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render block icons for each trigger', () => {
|
||||
|
||||
@ -9,16 +9,6 @@ const mockOnMoreLikeThis = vi.fn()
|
||||
const mockOnOpenLogModal = vi.fn()
|
||||
const mockOnRetry = vi.fn()
|
||||
const mockOnSave = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('copy-to-clipboard', () => ({
|
||||
default: (...args: unknown[]) => mockCopy(...args),
|
||||
}))
|
||||
@ -53,10 +43,10 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.copy' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.copy(?=$|:)/ }))
|
||||
|
||||
expect(mockCopy).toHaveBeenCalledWith('hello world')
|
||||
expect(mockSuccess).toHaveBeenCalledWith('actionMsg.copySuccessfully')
|
||||
expect(mockSuccess).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)actionMsg\.copySuccessfully(?=$|:)/))
|
||||
})
|
||||
|
||||
it('should handle more-like-this and feedback actions', () => {
|
||||
@ -80,9 +70,9 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'feature.moreLikeThis.title' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.agree' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.save' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)feature\.moreLikeThis\.title(?=$|:)/ }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.agree(?=$|:)/ }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.save(?=$|:)/ }))
|
||||
|
||||
expect(mockOnMoreLikeThis).toHaveBeenCalledTimes(1)
|
||||
expect(mockOnFeedback).toHaveBeenCalledWith({ rating: 'like' })
|
||||
@ -106,7 +96,7 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByRole('button', { name: 'feature.moreLikeThis.title' })).toBeDisabled()
|
||||
expect(screen.getByRole('button', { name: /(?:^|\.)feature\.moreLikeThis\.title(?=$|:)/ })).toBeDisabled()
|
||||
})
|
||||
|
||||
it('should stringify non-string content before copying', () => {
|
||||
@ -125,7 +115,7 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.copy' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.copy(?=$|:)/ }))
|
||||
|
||||
expect(mockCopy).toHaveBeenCalledWith(JSON.stringify({ result: 'hello world' }))
|
||||
})
|
||||
@ -148,7 +138,7 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'generation.batchFailed.retry' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)generation\.batchFailed\.retry(?=$|:)/ }))
|
||||
|
||||
expect(mockOnRetry).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
@ -171,7 +161,7 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.disagree' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.disagree(?=$|:)/ }))
|
||||
expect(mockOnFeedback).toHaveBeenCalledWith({ rating: 'dislike' })
|
||||
|
||||
rerender(
|
||||
@ -191,7 +181,7 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.cancelAgree' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.cancelAgree(?=$|:)/ }))
|
||||
expect(mockOnFeedback).toHaveBeenCalledWith({ rating: null })
|
||||
|
||||
rerender(
|
||||
@ -211,7 +201,7 @@ describe('GenerationActionGroups', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.cancelDisagree' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.cancelDisagree(?=$|:)/ }))
|
||||
expect(mockOnFeedback).toHaveBeenCalledWith({ rating: null })
|
||||
})
|
||||
})
|
||||
|
||||
@ -11,16 +11,6 @@ const mockSetShowPromptLogModal = vi.fn()
|
||||
const mockSubmitHumanInputForm = vi.fn()
|
||||
const mockSubmitHumanInputFormWorkflow = vi.fn()
|
||||
const mockToastWarning = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/next/navigation', () => ({
|
||||
useParams: () => ({
|
||||
appId: 'app-1',
|
||||
@ -121,7 +111,7 @@ describe('GenerationItem', () => {
|
||||
expect(screen.getByText('markdown:hello world')).toBeInTheDocument()
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'feature.moreLikeThis.title' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)feature\.moreLikeThis\.title(?=$|:)/ }))
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
@ -130,7 +120,7 @@ describe('GenerationItem', () => {
|
||||
expect(mockFetchMoreLikeThis).toHaveBeenCalledWith('msg-1', AppSourceType.webApp, undefined)
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getAllByRole('button', { name: 'operation.agree' }).at(-1)!)
|
||||
fireEvent.click(screen.getAllByRole('button', { name: /(?:^|\.)operation\.agree(?=$|:)/ }).at(-1)!)
|
||||
})
|
||||
|
||||
expect(mockUpdateFeedback).toHaveBeenCalledWith({
|
||||
@ -158,7 +148,7 @@ describe('GenerationItem', () => {
|
||||
)
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'operation.log' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)operation\.log(?=$|:)/ }))
|
||||
})
|
||||
|
||||
expect(mockFetchTextGenerationMessage).toHaveBeenCalledWith({
|
||||
@ -258,7 +248,7 @@ describe('GenerationItem', () => {
|
||||
)
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'feature.moreLikeThis.title' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)feature\.moreLikeThis\.title(?=$|:)/ }))
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
@ -316,10 +306,10 @@ describe('GenerationItem', () => {
|
||||
)
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'feature.moreLikeThis.title' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)feature\.moreLikeThis\.title(?=$|:)/ }))
|
||||
})
|
||||
|
||||
expect(mockToastWarning).toHaveBeenCalledWith('errorMessage.waitForResponse')
|
||||
expect(mockToastWarning).toHaveBeenCalledWith(expect.stringMatching(/(?:^|\.)errorMessage\.waitForResponse(?=$|:)/))
|
||||
expect(mockFetchMoreLikeThis).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@ -4,16 +4,6 @@ import WorkflowBody from '../workflow-body'
|
||||
|
||||
const mockSubmit = vi.fn()
|
||||
const mockSwitchTab = vi.fn()
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/base/chat/chat/answer/workflow-process', () => ({
|
||||
default: () => <div>workflow-process</div>,
|
||||
}))
|
||||
@ -63,7 +53,7 @@ describe('WorkflowBody', () => {
|
||||
expect(screen.getByText('task-1-1')).toBeInTheDocument()
|
||||
expect(screen.getByText('result-tab:RESULT')).toBeInTheDocument()
|
||||
|
||||
fireEvent.click(screen.getByText('detail'))
|
||||
fireEvent.click(screen.getByText(/(?:^|\.)detail(?=$|:)/))
|
||||
|
||||
expect(mockSwitchTab).toHaveBeenCalledWith('DETAIL')
|
||||
})
|
||||
|
||||
@ -24,7 +24,7 @@ const mockIterationInfo: AgentIteration = {
|
||||
{
|
||||
status: 'success',
|
||||
tool_name: 'test_tool',
|
||||
tool_label: { en: 'Test Tool' },
|
||||
tool_label: { 'en': 'Test Tool', 'en-US': 'Test Tool' },
|
||||
tool_icon: null,
|
||||
},
|
||||
],
|
||||
|
||||
@ -3,20 +3,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import ReasoningPanel from '../reasoning-panel'
|
||||
|
||||
// Mock react-i18next so the reused chat.thinking/chat.thought labels resolve.
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => {
|
||||
const translations: Record<string, string> = {
|
||||
'chat.thinking': 'Thinking...',
|
||||
'chat.thought': 'Thought',
|
||||
}
|
||||
return translations[key] || key
|
||||
}),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
// Mock the heavy Markdown renderer to a simple passthrough.
|
||||
vi.mock('@/app/components/base/markdown', () => ({
|
||||
@ -40,13 +26,13 @@ describe('ReasoningPanel', () => {
|
||||
|
||||
it('shows the thinking state while not done', () => {
|
||||
render(<ReasoningPanel content={{ llm: 'let me think' }} done={false} />)
|
||||
expect(screen.getByText(/Thinking\.\.\./)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thinking/)).toBeInTheDocument()
|
||||
expect(screen.getByText('let me think')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows the thought state once done (answer started / terminal / history)', () => {
|
||||
render(<ReasoningPanel content={{ llm: 'done thinking' }} done />)
|
||||
expect(screen.getByText(/Thought/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thought/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('counts elapsed time up while thinking', () => {
|
||||
@ -70,7 +56,7 @@ describe('ReasoningPanel', () => {
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(1000)
|
||||
})
|
||||
expect(screen.getByText(/Thought\(0\.7s\)/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thought\(0\.7s\)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('concatenates reasoning from multiple LLM nodes', () => {
|
||||
|
||||
@ -14,11 +14,6 @@ vi.mock('@/context/modal-context', () => ({
|
||||
setShowModerationSettingModal: mockSetShowModerationSettingModal,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/service/use-common', () => ({
|
||||
useCodeBasedExtensions: () => ({ data: { data: mockCodeBasedExtensionData } }),
|
||||
}))
|
||||
|
||||
@ -4,20 +4,6 @@ import { ChatContextProvider } from '@/app/components/base/chat/chat/context-pro
|
||||
import ThinkBlock from '../think-block'
|
||||
|
||||
// Mock react-i18next
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => {
|
||||
const translations: Record<string, string> = {
|
||||
'chat.thinking': 'Thinking...',
|
||||
'chat.thought': 'Thought',
|
||||
}
|
||||
return translations[key] || key
|
||||
}),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
// Helper to wrap component with ChatContextProvider
|
||||
const renderWithContext = (
|
||||
@ -73,7 +59,7 @@ describe('ThinkBlock', () => {
|
||||
true,
|
||||
)
|
||||
|
||||
expect(screen.getByText(/Thinking\.\.\./)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thinking/)).toBeInTheDocument()
|
||||
expect(screen.getByText('Thinking content')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -85,7 +71,7 @@ describe('ThinkBlock', () => {
|
||||
true,
|
||||
)
|
||||
|
||||
expect(screen.getByText(/Thought/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thought/)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -133,7 +119,7 @@ describe('ThinkBlock', () => {
|
||||
)
|
||||
|
||||
// Verify initial thinking state
|
||||
expect(screen.getByText(/Thinking\.\.\./)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thinking/)).toBeInTheDocument()
|
||||
|
||||
// Advance timer
|
||||
act(() => {
|
||||
@ -163,7 +149,7 @@ describe('ThinkBlock', () => {
|
||||
)
|
||||
|
||||
// Should now show "Thought" instead of "Thinking..."
|
||||
expect(screen.getByText(/Thought/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thought/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should stop timer when isResponding is undefined (historical conversation outside active response)', () => {
|
||||
@ -175,7 +161,7 @@ describe('ThinkBlock', () => {
|
||||
)
|
||||
|
||||
// Timer should be stopped immediately — isResponding undefined means not in active response
|
||||
expect(screen.getByText(/Thought/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thought/)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -203,7 +189,7 @@ describe('ThinkBlock', () => {
|
||||
)
|
||||
|
||||
// Should show "Thought" since ENDTHINKFLAG is present
|
||||
expect(screen.getByText(/Thought/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thought/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should detect ENDTHINKFLAG in array children', () => {
|
||||
@ -214,7 +200,7 @@ describe('ThinkBlock', () => {
|
||||
true,
|
||||
)
|
||||
|
||||
expect(screen.getByText(/Thought/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thought/)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -225,7 +211,7 @@ describe('ThinkBlock', () => {
|
||||
true,
|
||||
)
|
||||
|
||||
expect(screen.getByText(/Thinking\.\.\./)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thinking/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle null children gracefully', () => {
|
||||
@ -236,7 +222,7 @@ describe('ThinkBlock', () => {
|
||||
true,
|
||||
)
|
||||
|
||||
expect(screen.getByText(/Thinking\.\.\./)).toBeInTheDocument()
|
||||
expect(screen.getByText(/chat\.thinking/)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,11 +2,12 @@ import { cleanup, render, screen } from '@testing-library/react'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import NoLinkedAppsPanel from '../no-linked-apps-panel'
|
||||
|
||||
// Mock useDocLink
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
// Mock useDocLink
|
||||
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
})
|
||||
|
||||
@ -26,11 +26,6 @@ vi.mock('@/service/use-common', () => ({
|
||||
data: { allowed_extensions: ['pdf', 'docx', 'txt'] },
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/i18n-config/language', () => ({
|
||||
LanguagesSupported: ['en-US', 'zh-Hans'],
|
||||
}))
|
||||
|
||||
@ -37,13 +37,6 @@ vi.mock('@/service/use-common', () => ({
|
||||
useFileUploadConfig: () => ({ data: mockFileUploadConfig }),
|
||||
useFileSupportTypes: () => ({ data: mockSupportTypes }),
|
||||
}))
|
||||
|
||||
// Mock i18n
|
||||
// Mock locale
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/i18n-config/language', () => ({
|
||||
LanguagesSupported: ['en-US', 'zh-Hans'],
|
||||
}))
|
||||
|
||||
@ -35,10 +35,6 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/model-selec
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
const ns = 'datasetCreation'
|
||||
|
||||
const createDefaultModel = (overrides?: Partial<DefaultModel>): DefaultModel => ({
|
||||
|
||||
@ -5,9 +5,6 @@ import { DataSourceType } from '@/models/datasets'
|
||||
import DocumentsHeader from '../documents-header'
|
||||
|
||||
// Mock the context hooks
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
// Mock child components that require API calls
|
||||
vi.mock('@/app/components/datasets/common/document-status-with-action/auto-disabled-document', () => ({
|
||||
|
||||
@ -34,13 +34,6 @@ vi.mock('@/utils/format', () => ({
|
||||
return parts[parts.length - 1] || ''
|
||||
},
|
||||
}))
|
||||
|
||||
// Mock react-i18next
|
||||
// Mock locale context
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
// Mock i18n config
|
||||
vi.mock('@/i18n-config/language', () => ({
|
||||
LanguagesSupported: ['en-US', 'zh-Hans'],
|
||||
|
||||
@ -19,10 +19,6 @@ vi.mock('@/context/dataset-detail', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
// Mock EmbeddingProcess component as it has complex dependencies
|
||||
vi.mock('../../processing/embedding-process', () => ({
|
||||
default: ({ datasetId, batchId, documents }: {
|
||||
|
||||
@ -3,11 +3,12 @@ import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import Form from '../Form'
|
||||
|
||||
// Mock context for i18n doc link
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
// Mock context for i18n doc link
|
||||
|
||||
describe('Form', () => {
|
||||
const defaultFormSchemas: FormSchema[] = [
|
||||
{
|
||||
|
||||
@ -3,6 +3,10 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import ExternalAPIPanel from '../index'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
// Mock external contexts (only mock context providers, not base components)
|
||||
const mockSetShowExternalKnowledgeAPIModal = vi.fn()
|
||||
const mockMutateExternalKnowledgeApis = vi.fn()
|
||||
@ -23,10 +27,6 @@ vi.mock('@/context/external-knowledge-api-context', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
// Mock the ExternalKnowledgeAPICard to avoid mocking its internal dependencies
|
||||
vi.mock('../../external-knowledge-api-card', () => ({
|
||||
default: ({ api, canManageExternalKnowledgeApi }: { api: ExternalAPIItem, canManageExternalKnowledgeApi: boolean }) => (
|
||||
|
||||
@ -2,11 +2,12 @@ import { render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import InfoPanel from '../InfoPanel'
|
||||
|
||||
// Mock useDocLink from @/context/i18n
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
// Mock useDocLink from @/context/i18n
|
||||
|
||||
describe('InfoPanel', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import type { RelatedApp, RelatedAppResponse } from '@/models/datasets'
|
||||
import { cleanup, render, screen } from '@testing-library/react'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import Statistics from '../statistics'
|
||||
|
||||
// Mock useDocLink
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
|
||||
@ -54,10 +54,6 @@ vi.mock('@/context/dataset-detail', () => ({
|
||||
useDatasetDetailContextWithSelector: () => 'model-name',
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('../../settings/utils', () => ({
|
||||
checkShowMultiModalTip: () => false,
|
||||
}))
|
||||
|
||||
@ -254,10 +254,6 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('../components/indexing-section', () => ({
|
||||
default: ({
|
||||
currentDataset,
|
||||
|
||||
@ -8,19 +8,6 @@ import { RETRIEVE_METHOD } from '@/types/app'
|
||||
import { IndexingType } from '../../../../create/step-two'
|
||||
import IndexingSection from '../indexing-section'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/divider', () => ({
|
||||
default: ({ className }: { className?: string }) => (
|
||||
<div data-testid="divider" className={className} />
|
||||
@ -276,17 +263,17 @@ describe('IndexingSection', () => {
|
||||
it('should render the chunk structure, index method, and retrieval sections for a standard dataset', () => {
|
||||
renderComponent()
|
||||
|
||||
expect(screen.getByText('form.chunkStructure.title')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)form\.chunkStructure\.title(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByTestId('chunk-structure')).toHaveAttribute('data-mode', ChunkingMode.text)
|
||||
expect(screen.getByText('form.indexMethod')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)form\.indexMethod(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByTestId('index-method')).toBeInTheDocument()
|
||||
expect(screen.getByText('form.retrievalSetting.title')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)form\.retrievalSetting\.title(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the embedding model selector when the index method is high quality', () => {
|
||||
renderComponent()
|
||||
|
||||
expect(screen.getByText('form.embeddingModel')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)form\.embeddingModel(?=$|:)/)).toBeInTheDocument()
|
||||
expect(screen.getByTestId('model-selector')).toHaveAttribute('data-model', 'text-embedding-ada-002')
|
||||
})
|
||||
})
|
||||
@ -300,16 +287,16 @@ describe('IndexingSection', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(screen.queryByText('form.chunkStructure.title')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)form\.chunkStructure\.title(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('chunk-structure')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the chunk structure learn more link and description', () => {
|
||||
renderComponent()
|
||||
|
||||
const learnMoreLink = screen.getByRole('link', { name: 'form.chunkStructure.learnMore' })
|
||||
const learnMoreLink = screen.getByRole('link', { name: /(?:^|\.)form\.chunkStructure\.learnMore(?=$|:)/ })
|
||||
expect(learnMoreLink).toHaveAttribute('href', expect.stringContaining('chunking-and-cleaning-text'))
|
||||
expect(screen.getByText('form.chunkStructure.description')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)form\.chunkStructure\.description(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -322,22 +309,22 @@ describe('IndexingSection', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(screen.queryByText('form.indexMethod')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)form\.indexMethod(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('index-method')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render both index method options', () => {
|
||||
renderComponent()
|
||||
|
||||
expect(screen.getByRole('button', { name: 'stepTwo.qualified' })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'form.indexMethodEconomy' })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /(?:^|\.)stepTwo\.qualified(?=$|:)/ })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /(?:^|\.)form\.indexMethodEconomy(?=$|:)/ })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should call setIndexMethod when the user selects a new index method', () => {
|
||||
const setIndexMethod = vi.fn()
|
||||
renderComponent({ setIndexMethod })
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'form.indexMethodEconomy' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /(?:^|\.)form\.indexMethodEconomy(?=$|:)/ }))
|
||||
|
||||
expect(setIndexMethod).toHaveBeenCalledWith(IndexingType.ECONOMICAL)
|
||||
})
|
||||
@ -350,7 +337,7 @@ describe('IndexingSection', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(screen.getByText('form.upgradeHighQualityTip')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)form\.upgradeHighQualityTip(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should pass disabled state to the index method when embeddings are unavailable', () => {
|
||||
@ -383,7 +370,7 @@ describe('IndexingSection', () => {
|
||||
it('should hide the embedding model selector for economy indexing', () => {
|
||||
renderComponent({ indexMethod: IndexingType.ECONOMICAL })
|
||||
|
||||
expect(screen.queryByText('form.embeddingModel')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)form\.embeddingModel(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('model-selector')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -425,9 +412,9 @@ describe('IndexingSection', () => {
|
||||
it('should render the retrieval learn more link', () => {
|
||||
renderComponent()
|
||||
|
||||
const learnMoreLink = screen.getByRole('link', { name: 'form.retrievalSetting.learnMore' })
|
||||
const learnMoreLink = screen.getByRole('link', { name: /(?:^|\.)form\.retrievalSetting\.learnMore(?=$|:)/ })
|
||||
expect(learnMoreLink).toHaveAttribute('href', expect.stringContaining('setting-indexing-methods'))
|
||||
expect(screen.getByText('form.retrievalSetting.description')).toBeInTheDocument()
|
||||
expect(screen.getByText(/(?:^|\.)form\.retrievalSetting\.description(?=$|:)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the high-quality retrieval config and propagate changes', () => {
|
||||
@ -475,7 +462,7 @@ describe('IndexingSection', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(screen.queryByText('form.retrievalSetting.title')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)form\.retrievalSetting\.title(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('retrieval-method-config')).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('economical-retrieval-method-config')).not.toBeInTheDocument()
|
||||
})
|
||||
@ -497,7 +484,7 @@ describe('IndexingSection', () => {
|
||||
indexMethod: undefined,
|
||||
})
|
||||
|
||||
expect(screen.queryByText('form.indexMethod')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)form\.indexMethod(?=$|:)/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('index-method')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -315,9 +315,9 @@ type RenderOptions = {
|
||||
isCloudEdition?: boolean
|
||||
}
|
||||
|
||||
const localeInput = { query: { language: 'en' } }
|
||||
const exploreAppListQueryKey = ['console', 'explore', 'apps', 'get', localeInput, 'en']
|
||||
const exploreBannersQueryKey = ['console', 'explore', 'banners', 'get', localeInput, 'en']
|
||||
const localeInput = { query: { language: 'en-US' } }
|
||||
const exploreAppListQueryKey = ['console', 'explore', 'apps', 'get', localeInput, 'en-US']
|
||||
const exploreBannersQueryKey = ['console', 'explore', 'banners', 'get', localeInput, 'en-US']
|
||||
|
||||
const renderAppList = (
|
||||
hasEditPermission = false,
|
||||
|
||||
@ -20,11 +20,6 @@ const setMockSelectedIndex = (index: number) => {
|
||||
mockSelectedIndex = index
|
||||
mockCarouselListeners.forEach(listener => listener())
|
||||
}
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/context/account-state', async (importOriginal) => {
|
||||
const { createAppContextStateAtomMock } = await import('@/__tests__/utils/mock-app-context-state')
|
||||
|
||||
@ -65,6 +60,7 @@ vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
i18n: { language: 'en-US' },
|
||||
t: withSelectorKey((key: string, opts?: Record<string, unknown>) => {
|
||||
if (key === 'banner.greeting')
|
||||
return `Welcome back, ${opts?.name} 👋`
|
||||
|
||||
@ -2,12 +2,12 @@ import { render, screen } from '@testing-library/react'
|
||||
import { Theme } from '@/types/app'
|
||||
import NoApps from '../index'
|
||||
|
||||
let mockTheme = Theme.light
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
let mockTheme = Theme.light
|
||||
|
||||
vi.mock('@/hooks/use-theme', () => ({
|
||||
default: () => ({ theme: mockTheme }),
|
||||
}))
|
||||
|
||||
@ -66,11 +66,6 @@ let mockQueryResult = { data: [] as TestSearchResult[], isLoading: false, isErro
|
||||
vi.mock('@tanstack/react-query', () => ({
|
||||
useQuery: () => mockQueryResult,
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en_US',
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/plugins/install-plugin/hooks/use-workspace-plugin-install-permission', () => ({
|
||||
default: () => ({
|
||||
canInstallPlugin: true,
|
||||
|
||||
@ -7,16 +7,6 @@ vi.mock('@remixicon/react', () => ({
|
||||
RiNodeTree: () => null,
|
||||
RiSparkling2Line: () => null,
|
||||
}))
|
||||
|
||||
// search() localises its labels via getI18n(); echo the key back so the
|
||||
// filtering/payload assertions stay deterministic without a real i18n init.
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
getI18n: () => ({ t: withSelectorKey((key: string) => key) }),
|
||||
})
|
||||
})
|
||||
|
||||
// We spy on the store at module scope so the `create.open` handler that
|
||||
// register() pushes into the command bus can be observed by the tests.
|
||||
const mockOpenGenerator = vi.fn()
|
||||
|
||||
@ -2,16 +2,6 @@ import { registerCommands, unregisterCommands } from '../command-bus'
|
||||
import { languageCommand } from '../language'
|
||||
|
||||
vi.mock('../command-bus')
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
getI18n: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/i18n-config/language', () => ({
|
||||
languages: [
|
||||
{ value: 'en-US', name: 'English', supported: true },
|
||||
|
||||
@ -5,16 +5,6 @@ import { refineCommand } from '../refine'
|
||||
vi.mock('@remixicon/react', () => ({
|
||||
RiSparkling2Line: () => null,
|
||||
}))
|
||||
|
||||
// search() localises its title/description via getI18n(); echo the key back
|
||||
// so assertions stay deterministic without a real i18n init.
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
getI18n: () => ({ t: withSelectorKey((key: string) => key) }),
|
||||
})
|
||||
})
|
||||
|
||||
// Spy on the generator store so we can observe what /refine opens it with.
|
||||
const mockOpenGenerator = vi.fn()
|
||||
vi.mock('@/app/components/workflow/workflow-generator/store', () => ({
|
||||
|
||||
@ -3,6 +3,11 @@ import { render } from '@testing-library/react'
|
||||
import { slashAction } from '../slash'
|
||||
import { SlashCommandProvider } from '../slash-provider'
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { createReactI18nextLanguageMock } = await import('@/test/i18n-mock')
|
||||
return createReactI18nextLanguageMock('ja')
|
||||
})
|
||||
|
||||
const {
|
||||
mockSetTheme,
|
||||
mockSetLocale,
|
||||
@ -33,17 +38,6 @@ vi.mock('next-themes', () => ({
|
||||
setTheme: mockSetTheme,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
getI18n: () => ({
|
||||
language: 'ja',
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/i18n-config', () => ({
|
||||
setLocaleOnClient: mockSetLocale,
|
||||
}))
|
||||
|
||||
@ -2,16 +2,6 @@ import { registerCommands, unregisterCommands } from '../command-bus'
|
||||
import { themeCommand } from '../theme'
|
||||
|
||||
vi.mock('../command-bus')
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
getI18n: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
describe('themeCommand', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
@ -22,11 +22,6 @@ vi.mock('@tanstack/react-query', () => ({
|
||||
return mockQueryResult
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en_US',
|
||||
}))
|
||||
|
||||
const mockMatchAction = vi.fn()
|
||||
const mockSearchAnything = vi.fn()
|
||||
const mockGetRecentItems = vi.fn(() => [] as Array<Record<string, unknown>>)
|
||||
|
||||
@ -101,10 +101,6 @@ vi.mock('@/next/navigation', async (importOriginal) => {
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
// Mock config and env
|
||||
const { mockConfig, mockEnv } = vi.hoisted(() => ({
|
||||
mockConfig: {
|
||||
|
||||
@ -73,11 +73,6 @@ vi.mock('@langgenius/dify-ui/tooltip', () => ({
|
||||
TooltipTrigger: ({ render }: { render: ReactNode }) => <>{render}</>,
|
||||
TooltipContent: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-theme', () => ({
|
||||
default: () => ({ theme: 'light' }),
|
||||
}))
|
||||
|
||||
@ -27,9 +27,7 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
|
||||
error: mockToastError,
|
||||
},
|
||||
}))
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('react-multi-email', () => ({
|
||||
ReactMultiEmail: ({ emails, onChange, getLabel }: { emails: string[], onChange: (emails: string[]) => void, getLabel: (email: string, index: number, removeEmail: (index: number) => void) => React.ReactNode }) => (
|
||||
<div>
|
||||
|
||||
@ -37,6 +37,10 @@ import {
|
||||
useUpdateModelProviders,
|
||||
} from '../hooks'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: vi.fn(() => 'en-US'),
|
||||
}))
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('@tanstack/react-query', () => ({
|
||||
useQuery: vi.fn(),
|
||||
@ -58,10 +62,6 @@ vi.mock('@/service/use-common', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: vi.fn(() => 'en-US'),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/provider-context', () => ({
|
||||
useProviderContext: vi.fn(() => ({
|
||||
textGenerationModelList: [],
|
||||
|
||||
@ -90,11 +90,6 @@ vi.mock('@/app/components/plugins/update-plugin/plugin-version-picker', () => ({
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-theme', () => ({
|
||||
default: () => ({ theme: 'light' }),
|
||||
}))
|
||||
|
||||
@ -3,14 +3,11 @@ import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import IntegrationsToolProviderCard from '../tool-provider-card'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en_US',
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
i18n: { language: 'en-US' },
|
||||
t: withSelectorKey((key: string, options?: { count?: number, ns?: string }) => options?.ns ? `${options.ns}.${key}${options.count ? `:${options.count}` : ''}` : key),
|
||||
}),
|
||||
})
|
||||
@ -56,7 +53,7 @@ describe('IntegrationsToolProviderCard', () => {
|
||||
it('does not show a source label for builtin tools', () => {
|
||||
render(<IntegrationsToolProviderCard collection={createCollection()} />)
|
||||
|
||||
expect(screen.queryByText('plugin.from')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/(?:^|\.)plugin\.from(?=$|:)/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('does not show a built-in corner badge for marketplace plugin tools', () => {
|
||||
|
||||
@ -21,16 +21,6 @@ vi.mock('@/app/components/header', () => ({
|
||||
vi.mock('@/app/components/header/header-wrapper', () => ({
|
||||
default: ({ children }: { children: ReactNode }) => <div data-testid="header-wrapper">{children}</div>,
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@tanstack/react-query', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@tanstack/react-query')>()
|
||||
return {
|
||||
@ -130,7 +120,7 @@ describe('MainNavLayout', () => {
|
||||
it('renders skip navigation before the repeated main navigation', () => {
|
||||
const { container } = render(<MainNavLayout><div>content</div></MainNavLayout>)
|
||||
|
||||
const skipLink = screen.getByRole('link', { name: 'navigation.skipToMain' })
|
||||
const skipLink = screen.getByRole('link', { name: /(?:^|\.)navigation\.skipToMain(?=$|:)/ })
|
||||
|
||||
expect(skipLink).toHaveAttribute('href', '#main-content')
|
||||
expect(skipLink).toHaveClass('outline-hidden', 'focus-visible:ring-2', 'focus-visible:ring-state-accent-solid')
|
||||
@ -140,7 +130,7 @@ describe('MainNavLayout', () => {
|
||||
it('moves focus to the main content when skip navigation is activated', () => {
|
||||
render(<MainNavLayout><div>content</div></MainNavLayout>)
|
||||
|
||||
const skipLink = screen.getByRole('link', { name: 'navigation.skipToMain' })
|
||||
const skipLink = screen.getByRole('link', { name: /(?:^|\.)navigation\.skipToMain(?=$|:)/ })
|
||||
const main = screen.getByRole('main')
|
||||
|
||||
fireEvent.click(skipLink)
|
||||
|
||||
@ -5,10 +5,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import ProviderCard from '../provider-card'
|
||||
import { PluginCategoryEnum } from '../types'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/use-i18n', () => ({
|
||||
useRenderI18nObject: () => (value: Record<string, string>) => value['en-US'] || value.en_US,
|
||||
}))
|
||||
|
||||
@ -5,15 +5,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createNuqsTestWrapper } from '@/test/nuqs-testing'
|
||||
import StickySearchAndSwitchWrapper from '../sticky-search-and-switch-wrapper'
|
||||
|
||||
vi.mock('#i18n', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string) => key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
// Mock child components to isolate wrapper logic
|
||||
vi.mock('../plugin-type-switch', () => ({
|
||||
default: () => <div data-testid="plugin-type-switch">PluginTypeSwitch</div>,
|
||||
|
||||
@ -5,6 +5,10 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createNuqsTestWrapper } from '@/test/nuqs-testing'
|
||||
import Description from '../index'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
// ================================
|
||||
// Mock external dependencies
|
||||
// ================================
|
||||
@ -52,10 +56,6 @@ vi.mock('#i18n', async () => {
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
const createWrapper = (searchParams = '') => {
|
||||
const { wrapper: NuqsWrapper } = createNuqsTestWrapper({ searchParams })
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
|
||||
@ -6,16 +6,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { PluginCategoryEnum } from '@/app/components/plugins/types'
|
||||
import CardWrapper from '../card-wrapper'
|
||||
|
||||
vi.mock('#i18n', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
useLocale: () => 'en-US',
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('@/app/components/plugins/hooks', () => ({
|
||||
useTags: () => ({
|
||||
getTagLabel: (name: string) => `tag:${name}`,
|
||||
|
||||
@ -53,11 +53,6 @@ vi.mock('../../state', () => ({
|
||||
vi.mock('../../atoms', () => ({
|
||||
useMarketplaceMoreClick: () => mockMoreClick,
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
const mockTags = [
|
||||
{ name: 'search', label: 'Search' },
|
||||
{ name: 'image', label: 'Image' },
|
||||
|
||||
@ -5,17 +5,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import ListWithCollection from '../list-with-collection'
|
||||
|
||||
const mockMoreClick = vi.fn()
|
||||
|
||||
vi.mock('#i18n', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
useLocale: () => 'en-US',
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('../../atoms', () => ({
|
||||
useMarketplaceMoreClick: () => mockMoreClick,
|
||||
}))
|
||||
|
||||
@ -5,16 +5,6 @@ import SearchBoxWrapper from '../search-box-wrapper'
|
||||
const mockHandleSearchPluginTextChange = vi.fn()
|
||||
const mockHandleFilterPluginTagsChange = vi.fn()
|
||||
const mockSearchBox = vi.fn()
|
||||
|
||||
vi.mock('#i18n', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
vi.mock('../../atoms', () => ({
|
||||
useSearchPluginText: () => ['plugin search', mockHandleSearchPluginTextChange],
|
||||
useFilterPluginTags: () => [['agent', 'rag'], mockHandleFilterPluginTagsChange],
|
||||
|
||||
@ -3,15 +3,6 @@ import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import MarketplaceTrigger from '../marketplace'
|
||||
|
||||
vi.mock('#i18n', async () => {
|
||||
const { withSelectorKey } = await import('@/test/i18n-mock')
|
||||
return ({
|
||||
useTranslation: () => ({
|
||||
t: withSelectorKey((key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key),
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
const tagsMap: Record<string, Tag> = {
|
||||
agent: { name: 'agent', label: 'Agent' },
|
||||
rag: { name: 'rag', label: 'RAG' },
|
||||
|
||||
@ -78,12 +78,6 @@ vi.mock('ahooks', async () => {
|
||||
vi.mock('@/hooks/use-theme', () => ({
|
||||
default: () => ({ theme: 'light' }),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useGetLanguage: () => 'en_US',
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
// Global mock state for enable_marketplace seeded into the QueryClient via the local render helper.
|
||||
|
||||
vi.mock('@/context/modal-context', () => ({
|
||||
|
||||
@ -3,10 +3,6 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import EndpointList from '../endpoint-list'
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
vi.mock('@langgenius/dify-ui/cn', () => ({
|
||||
cn: (...args: (string | undefined | false | null)[]) => args.filter(Boolean).join(' '),
|
||||
}))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user