mirror of
https://github.com/langgenius/dify.git
synced 2026-07-24 04:58:32 +08:00
206 lines
5.9 KiB
TypeScript
206 lines
5.9 KiB
TypeScript
import type { QueryClient } from '@tanstack/react-query'
|
|
import { skipToken } from '@tanstack/react-query'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { createQueryAtomTestStore } from '@/test/query-atom'
|
|
|
|
type QueryOptions = {
|
|
enabled?: boolean
|
|
input?: unknown
|
|
}
|
|
|
|
type InfiniteQueryOptions = QueryOptions & {
|
|
input?: (pageParam: number) => unknown
|
|
}
|
|
|
|
const mockSourceAppsInfiniteOptions = vi.hoisted(() => vi.fn())
|
|
const mockPrecheckReleaseQueryOptions = vi.hoisted(() => vi.fn())
|
|
const mockCreateRelease = vi.hoisted(() => vi.fn())
|
|
|
|
vi.mock('../../../shared/domain/feature-flags', () => ({
|
|
isDeploymentDslImportEnabled: true,
|
|
}))
|
|
|
|
vi.mock('@/service/client', () => ({
|
|
consoleQuery: {
|
|
apps: {
|
|
get: {
|
|
infiniteOptions: (options: InfiniteQueryOptions) => {
|
|
mockSourceAppsInfiniteOptions(options)
|
|
|
|
return {
|
|
...options,
|
|
queryKey: ['sourceApps', options.input],
|
|
queryFn: async () => ({
|
|
data: [],
|
|
has_more: false,
|
|
limit: 20,
|
|
page: 1,
|
|
total: 0,
|
|
}),
|
|
}
|
|
},
|
|
},
|
|
},
|
|
enterprise: {
|
|
releaseService: {
|
|
listReleaseSummaries: {
|
|
key: ({ input }: { input?: unknown } = {}) =>
|
|
input === undefined ? ['listReleaseSummaries'] : ['listReleaseSummaries', input],
|
|
},
|
|
listReleases: {
|
|
key: ({ input }: { input?: unknown } = {}) =>
|
|
input === undefined ? ['listReleases'] : ['listReleases', input],
|
|
},
|
|
precheckRelease: {
|
|
queryOptions: (options: QueryOptions) => {
|
|
mockPrecheckReleaseQueryOptions(options)
|
|
|
|
return {
|
|
...options,
|
|
queryKey: ['precheckRelease', options.input],
|
|
}
|
|
},
|
|
},
|
|
createRelease: {
|
|
mutationOptions: () => ({
|
|
mutationKey: ['createRelease'],
|
|
mutationFn: mockCreateRelease,
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}))
|
|
|
|
async function loadState() {
|
|
return await import('../index')
|
|
}
|
|
|
|
async function mountedStore() {
|
|
const state = await loadState()
|
|
const { queryClient, store } = createQueryAtomTestStore()
|
|
const unsubscribe = store.sub(state.createReleaseFormIsSubmittingAtom, () => undefined)
|
|
|
|
return {
|
|
queryClient,
|
|
state,
|
|
store,
|
|
unsubscribe,
|
|
}
|
|
}
|
|
|
|
function workflowDsl() {
|
|
return ['app:', ' mode: workflow', ' name: Release source'].join('\n')
|
|
}
|
|
|
|
function setDslFileContentResult(queryClient: QueryClient, file: File, fileReadVersion: number) {
|
|
queryClient.setQueryData(
|
|
['createReleaseDslFileContent', fileReadVersion, file, file.name, file.size, file.lastModified],
|
|
workflowDsl(),
|
|
)
|
|
}
|
|
|
|
function setPrecheckReleaseResult(
|
|
queryClient: QueryClient,
|
|
input: {
|
|
body: {
|
|
appInstanceId: string
|
|
dsl: string
|
|
}
|
|
},
|
|
) {
|
|
queryClient.setQueryData(['precheckRelease', input], {
|
|
gateCommitId: 'gate-commit-1',
|
|
canCreate: true,
|
|
unsupportedNodes: [],
|
|
})
|
|
}
|
|
|
|
describe('create release state with DSL import enabled', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
mockCreateRelease.mockReset()
|
|
})
|
|
|
|
it('should enable source app search with the current search text while creating from an app', async () => {
|
|
const { state, store, unsubscribe } = await mountedStore()
|
|
store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
|
|
store.set(state.openCreateReleaseDialogAtom)
|
|
store.set(state.createReleaseSourceAppSearchTextAtom, 'customer')
|
|
|
|
store.get(state.createReleaseSourceAppsQueryAtom)
|
|
const sourceAppsQuery = mockSourceAppsInfiniteOptions.mock.lastCall?.[0] as InfiniteQueryOptions
|
|
|
|
expect(sourceAppsQuery.enabled).toBe(true)
|
|
expect(sourceAppsQuery.input?.(2)).toEqual({
|
|
query: {
|
|
page: 2,
|
|
limit: 20,
|
|
name: 'customer',
|
|
mode: 'workflow',
|
|
},
|
|
})
|
|
|
|
unsubscribe()
|
|
})
|
|
|
|
it('should skip DSL release precheck input until DSL content is ready', async () => {
|
|
const { state, store, unsubscribe } = await mountedStore()
|
|
|
|
store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
|
|
store.set(state.openCreateReleaseDialogAtom)
|
|
store.set(state.selectCreateReleaseSourceModeAtom, 'dsl')
|
|
store.get(state.isCheckingCreateReleaseContentAtom)
|
|
|
|
expect(mockPrecheckReleaseQueryOptions).toHaveBeenLastCalledWith(
|
|
expect.objectContaining({
|
|
enabled: false,
|
|
input: skipToken,
|
|
}),
|
|
)
|
|
|
|
unsubscribe()
|
|
})
|
|
|
|
it('should submit a DSL release with encoded workflow content', async () => {
|
|
const { queryClient, state, store, unsubscribe } = await mountedStore()
|
|
const response = {
|
|
release: {
|
|
displayName: 'Release from DSL',
|
|
},
|
|
}
|
|
const file = new File([workflowDsl()], 'workflow.yml', { type: 'text/yaml' })
|
|
mockCreateRelease.mockResolvedValue(response)
|
|
store.set(state.createReleaseAppInstanceIdAtom, 'app-instance-1')
|
|
store.set(state.openCreateReleaseDialogAtom)
|
|
store.set(state.selectCreateReleaseSourceModeAtom, 'dsl')
|
|
store.set(state.updateCreateReleaseDslFileAtom, file)
|
|
setDslFileContentResult(queryClient, file, 2)
|
|
const encodedDslContent = store.get(state.createReleaseEncodedDslContentAtom)
|
|
setPrecheckReleaseResult(queryClient, {
|
|
body: {
|
|
appInstanceId: 'app-instance-1',
|
|
dsl: encodedDslContent,
|
|
},
|
|
})
|
|
store.set(state.createReleaseNameFieldAtom, ' Release from DSL ')
|
|
store.set(state.createReleaseDescriptionFieldAtom, ' Imported workflow ')
|
|
|
|
const result = await store.set(state.submitCreateReleaseFormAtom)
|
|
|
|
expect(result).toBe(response)
|
|
expect(encodedDslContent).not.toBe('')
|
|
expect(mockCreateRelease.mock.calls[0]?.[0]).toEqual({
|
|
body: {
|
|
appInstanceId: 'app-instance-1',
|
|
displayName: 'Release from DSL',
|
|
description: 'Imported workflow',
|
|
createAppInstance: false,
|
|
dsl: encodedDslContent,
|
|
},
|
|
})
|
|
|
|
unsubscribe()
|
|
})
|
|
})
|