mirror of https://github.com/langgenius/dify.git
test(web): add global zustand mock for tests (#31149)
This commit is contained in:
parent
fad6fa141d
commit
e3b0918dd9
|
|
@ -0,0 +1,56 @@
|
|||
import type * as ZustandExportedTypes from 'zustand'
|
||||
import { act } from '@testing-library/react'
|
||||
|
||||
export * from 'zustand'
|
||||
|
||||
const { create: actualCreate, createStore: actualCreateStore }
|
||||
// eslint-disable-next-line antfu/no-top-level-await
|
||||
= await vi.importActual<typeof ZustandExportedTypes>('zustand')
|
||||
|
||||
export const storeResetFns = new Set<() => void>()
|
||||
|
||||
const createUncurried = <T>(
|
||||
stateCreator: ZustandExportedTypes.StateCreator<T>,
|
||||
) => {
|
||||
const store = actualCreate(stateCreator)
|
||||
const initialState = store.getInitialState()
|
||||
storeResetFns.add(() => {
|
||||
store.setState(initialState, true)
|
||||
})
|
||||
return store
|
||||
}
|
||||
|
||||
export const create = (<T>(
|
||||
stateCreator: ZustandExportedTypes.StateCreator<T>,
|
||||
) => {
|
||||
return typeof stateCreator === 'function'
|
||||
? createUncurried(stateCreator)
|
||||
: createUncurried
|
||||
}) as typeof ZustandExportedTypes.create
|
||||
|
||||
const createStoreUncurried = <T>(
|
||||
stateCreator: ZustandExportedTypes.StateCreator<T>,
|
||||
) => {
|
||||
const store = actualCreateStore(stateCreator)
|
||||
const initialState = store.getInitialState()
|
||||
storeResetFns.add(() => {
|
||||
store.setState(initialState, true)
|
||||
})
|
||||
return store
|
||||
}
|
||||
|
||||
export const createStore = (<T>(
|
||||
stateCreator: ZustandExportedTypes.StateCreator<T>,
|
||||
) => {
|
||||
return typeof stateCreator === 'function'
|
||||
? createStoreUncurried(stateCreator)
|
||||
: createStoreUncurried
|
||||
}) as typeof ZustandExportedTypes.createStore
|
||||
|
||||
afterEach(() => {
|
||||
act(() => {
|
||||
storeResetFns.forEach((resetFn) => {
|
||||
resetFn()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -3,9 +3,7 @@ import type { App } from '@/types/app'
|
|||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import useAccessControlStore from '@/context/access-control-store'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { AccessMode, SubjectType } from '@/models/access-control'
|
||||
import { defaultSystemFeatures } from '@/types/feature'
|
||||
import Toast from '../../base/toast'
|
||||
import AccessControlDialog from './access-control-dialog'
|
||||
import AccessControlItem from './access-control-item'
|
||||
|
|
@ -105,22 +103,6 @@ const memberSubject: Subject = {
|
|||
accountData: baseMember,
|
||||
} as Subject
|
||||
|
||||
const resetAccessControlStore = () => {
|
||||
useAccessControlStore.setState({
|
||||
appId: '',
|
||||
specificGroups: [],
|
||||
specificMembers: [],
|
||||
currentMenu: AccessMode.SPECIFIC_GROUPS_MEMBERS,
|
||||
selectedGroupsForBreadcrumb: [],
|
||||
})
|
||||
}
|
||||
|
||||
const resetGlobalStore = () => {
|
||||
useGlobalPublicStore.setState({
|
||||
systemFeatures: defaultSystemFeatures,
|
||||
})
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
class MockIntersectionObserver {
|
||||
observe = vi.fn(() => undefined)
|
||||
|
|
@ -132,9 +114,6 @@ beforeAll(() => {
|
|||
})
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
resetAccessControlStore()
|
||||
resetGlobalStore()
|
||||
mockMutateAsync.mockResolvedValue(undefined)
|
||||
mockUseUpdateAccessMode.mockReturnValue({
|
||||
isPending: false,
|
||||
|
|
|
|||
|
|
@ -144,17 +144,6 @@ describe('constant.ts - Type Definitions', () => {
|
|||
|
||||
// ==================== store.ts Tests ====================
|
||||
describe('store.ts - Zustand Store', () => {
|
||||
beforeEach(() => {
|
||||
// Reset store to initial state
|
||||
const { setState } = useStore
|
||||
setState({
|
||||
tagList: [],
|
||||
categoryList: [],
|
||||
showTagManagementModal: false,
|
||||
showCategoryManagementModal: false,
|
||||
})
|
||||
})
|
||||
|
||||
describe('Initial State', () => {
|
||||
it('should have empty tagList initially', () => {
|
||||
const { result } = renderHook(() => useStore(state => state.tagList))
|
||||
|
|
|
|||
|
|
@ -134,13 +134,6 @@ describe('BUILTIN_TOOLS_ARRAY', () => {
|
|||
// Store Tests
|
||||
// ================================
|
||||
describe('useReadmePanelStore', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
// Reset store state before each test
|
||||
const { setCurrentPluginDetail } = useReadmePanelStore.getState()
|
||||
setCurrentPluginDetail()
|
||||
})
|
||||
|
||||
describe('Initial State', () => {
|
||||
it('should have undefined currentPluginDetail initially', () => {
|
||||
const { currentPluginDetail } = useReadmePanelStore.getState()
|
||||
|
|
@ -228,12 +221,6 @@ describe('useReadmePanelStore', () => {
|
|||
// ReadmeEntrance Component Tests
|
||||
// ================================
|
||||
describe('ReadmeEntrance', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
// Reset store state
|
||||
const { setCurrentPluginDetail } = useReadmePanelStore.getState()
|
||||
setCurrentPluginDetail()
|
||||
})
|
||||
|
||||
// ================================
|
||||
// Rendering Tests
|
||||
|
|
@ -417,11 +404,6 @@ describe('ReadmeEntrance', () => {
|
|||
// ================================
|
||||
describe('ReadmePanel', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
// Reset store state
|
||||
const { setCurrentPluginDetail } = useReadmePanelStore.getState()
|
||||
setCurrentPluginDetail()
|
||||
// Reset mock
|
||||
mockUsePluginReadme.mockReturnValue({
|
||||
data: null,
|
||||
isLoading: false,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"target": "es2015",
|
||||
"target": "es2022",
|
||||
"jsx": "preserve",
|
||||
"lib": [
|
||||
"dom",
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@ afterEach(() => {
|
|||
// mock next/image to avoid width/height requirements for data URLs
|
||||
vi.mock('next/image')
|
||||
|
||||
// mock zustand - auto-resets all stores after each test
|
||||
// Based on official Zustand testing guide: https://zustand.docs.pmnd.rs/guides/testing
|
||||
vi.mock('zustand')
|
||||
|
||||
// mock react-i18next
|
||||
vi.mock('react-i18next', async () => {
|
||||
const actual = await vi.importActual<typeof import('react-i18next')>('react-i18next')
|
||||
|
|
|
|||
Loading…
Reference in New Issue