mirror of
https://github.com/langgenius/dify.git
synced 2026-11-10 21:35:45 +08:00
fix(web): sync workflow node catalog after availability changes (#44769)
This commit is contained in:
1 parent
a5cf299d1b
commit
e758d8c30c
2 files changed
+87
-4
No files matched your search
@@ -1,13 +1,43 @@
|
||||
import type { AvailableNodesMetaData } from '../store'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { BlockClassification } from '../../block-selector/types'
|
||||
import { BlockEnum } from '../../types'
|
||||
import { HooksStoreContextProvider } from '../provider'
|
||||
import { useHooksStore } from '../store'
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
useStore: (selector: (state: { d3Selection: null; d3Zoom: null }) => unknown) =>
|
||||
selector({ d3Selection: null, d3Zoom: null }),
|
||||
const canvas = vi.hoisted(() => ({
|
||||
d3Selection: null as object | null,
|
||||
d3Zoom: null as object | null,
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', () => ({
|
||||
useStore: (selector: (state: typeof canvas) => unknown) => selector(canvas),
|
||||
}))
|
||||
|
||||
const createCatalog = (...types: BlockEnum[]): AvailableNodesMetaData => ({
|
||||
nodes: types.map((type) => ({
|
||||
metaData: {
|
||||
classification: BlockClassification.Default,
|
||||
sort: 0,
|
||||
type,
|
||||
title: type,
|
||||
author: 'Dify',
|
||||
},
|
||||
defaultValue: {},
|
||||
checkValid: () => ({ isValid: true }),
|
||||
})),
|
||||
})
|
||||
|
||||
const AvailableNodes = () => {
|
||||
const catalog = useHooksStore((state) => state.availableNodesMetaData)
|
||||
return (
|
||||
<output aria-label="Available nodes">
|
||||
{catalog?.nodes.map((node) => node.metaData.type).join(', ')}
|
||||
</output>
|
||||
)
|
||||
}
|
||||
|
||||
const ExportButton = () => {
|
||||
const isExporting = useHooksStore((state) => state.isExporting)
|
||||
const handleExportDSL = useHooksStore((state) => state.handleExportDSL)
|
||||
@@ -19,6 +49,49 @@ const ExportButton = () => {
|
||||
}
|
||||
|
||||
describe('hooks-store provider', () => {
|
||||
beforeEach(() => {
|
||||
canvas.d3Selection = null
|
||||
canvas.d3Zoom = null
|
||||
})
|
||||
|
||||
it.each(['before', 'after'] as const)(
|
||||
'propagates node catalog changes %s canvas initialization',
|
||||
(timing) => {
|
||||
if (timing === 'after') {
|
||||
canvas.d3Selection = {}
|
||||
canvas.d3Zoom = {}
|
||||
}
|
||||
const initialCatalog = createCatalog(BlockEnum.KnowledgeRetrieval)
|
||||
const enabledCatalog = createCatalog(
|
||||
BlockEnum.KnowledgeRetrieval,
|
||||
BlockEnum.KnowledgeRetrievalV2,
|
||||
)
|
||||
const { rerender } = render(
|
||||
<HooksStoreContextProvider availableNodesMetaData={initialCatalog}>
|
||||
<AvailableNodes />
|
||||
</HooksStoreContextProvider>,
|
||||
)
|
||||
const availableNodes = screen.getByRole('status', { name: 'Available nodes' })
|
||||
expect(availableNodes).toHaveTextContent(BlockEnum.KnowledgeRetrieval)
|
||||
expect(availableNodes).not.toHaveTextContent(BlockEnum.KnowledgeRetrievalV2)
|
||||
|
||||
rerender(
|
||||
<HooksStoreContextProvider availableNodesMetaData={enabledCatalog}>
|
||||
<AvailableNodes />
|
||||
</HooksStoreContextProvider>,
|
||||
)
|
||||
expect(availableNodes).toHaveTextContent(BlockEnum.KnowledgeRetrievalV2)
|
||||
|
||||
rerender(
|
||||
<HooksStoreContextProvider availableNodesMetaData={initialCatalog}>
|
||||
<AvailableNodes />
|
||||
</HooksStoreContextProvider>,
|
||||
)
|
||||
expect(availableNodes).toHaveTextContent(BlockEnum.KnowledgeRetrieval)
|
||||
expect(availableNodes).not.toHaveTextContent(BlockEnum.KnowledgeRetrievalV2)
|
||||
},
|
||||
)
|
||||
|
||||
it('propagates export pending state and the latest handler independently of canvas initialization', async () => {
|
||||
const user = userEvent.setup()
|
||||
const firstExport = vi.fn().mockResolvedValue(true)
|
||||
|
||||
@@ -16,6 +16,7 @@ export const HooksStoreContextProvider = ({
|
||||
const d3Selection = useStore((s) => s.d3Selection)
|
||||
const d3Zoom = useStore((s) => s.d3Zoom)
|
||||
const {
|
||||
availableNodesMetaData,
|
||||
fileSettings,
|
||||
accessControl,
|
||||
exportCheck,
|
||||
@@ -29,13 +30,22 @@ export const HooksStoreContextProvider = ({
|
||||
|
||||
useEffect(() => {
|
||||
store.getState().refreshAll({
|
||||
...(availableNodesMetaData && { availableNodesMetaData }),
|
||||
...(accessControl && { accessControl }),
|
||||
...(exportCheck && { exportCheck }),
|
||||
...(handleExportDSL && { handleExportDSL }),
|
||||
isExporting,
|
||||
fileSettings,
|
||||
})
|
||||
}, [fileSettings, accessControl, exportCheck, handleExportDSL, isExporting, store])
|
||||
}, [
|
||||
availableNodesMetaData,
|
||||
fileSettings,
|
||||
accessControl,
|
||||
exportCheck,
|
||||
handleExportDSL,
|
||||
isExporting,
|
||||
store,
|
||||
])
|
||||
|
||||
return <HooksStoreContext.Provider value={store}>{children}</HooksStoreContext.Provider>
|
||||
}
|
||||
Reference in new issue
Block a user