mirror of
https://github.com/langgenius/dify.git
synced 2026-01-31 04:34:36 +00:00
Compare commits
3 Commits
deploy/age
...
1-30-fix-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d1d76055a | ||
|
|
a34d3ffc28 | ||
|
|
1d2ed8da2a |
@@ -124,7 +124,7 @@ describe('CreateAppModal', () => {
|
||||
|
||||
const nameInput = screen.getByPlaceholderText('app.newApp.appNamePlaceholder')
|
||||
fireEvent.change(nameInput, { target: { value: 'My App' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'app.newApp.Create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /app\.newApp\.Create/ }))
|
||||
|
||||
await waitFor(() => expect(mockCreateApp).toHaveBeenCalledWith({
|
||||
name: 'My App',
|
||||
@@ -152,7 +152,7 @@ describe('CreateAppModal', () => {
|
||||
|
||||
const nameInput = screen.getByPlaceholderText('app.newApp.appNamePlaceholder')
|
||||
fireEvent.change(nameInput, { target: { value: 'My App' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'app.newApp.Create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /app\.newApp\.Create/ }))
|
||||
|
||||
await waitFor(() => expect(mockCreateApp).toHaveBeenCalled())
|
||||
expect(mockNotify).toHaveBeenCalledWith({ type: 'error', message: 'boom' })
|
||||
|
||||
@@ -138,7 +138,7 @@ describe('CreateAppModal', () => {
|
||||
setup({ appName: 'My App', isEditModal: false })
|
||||
|
||||
expect(screen.getByText('explore.appCustomize.title:{"name":"My App"}')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'common.operation.create' })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'common.operation.cancel' })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@@ -146,7 +146,7 @@ describe('CreateAppModal', () => {
|
||||
setup({ isEditModal: true, appMode: AppModeEnum.CHAT, max_active_requests: 5 })
|
||||
|
||||
expect(screen.getByText('app.editAppTitle')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'common.operation.save' })).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: /common\.operation\.save/ })).toBeInTheDocument()
|
||||
expect(screen.getByRole('switch')).toBeInTheDocument()
|
||||
expect((screen.getByRole('spinbutton') as HTMLInputElement).value).toBe('5')
|
||||
})
|
||||
@@ -166,7 +166,7 @@ describe('CreateAppModal', () => {
|
||||
it('should not render modal content when hidden', () => {
|
||||
setup({ show: false })
|
||||
|
||||
expect(screen.queryByRole('button', { name: 'common.operation.create' })).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: /common\.operation\.create/ })).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -175,13 +175,13 @@ describe('CreateAppModal', () => {
|
||||
it('should disable confirm action when confirmDisabled is true', () => {
|
||||
setup({ confirmDisabled: true })
|
||||
|
||||
expect(screen.getByRole('button', { name: 'common.operation.create' })).toBeDisabled()
|
||||
expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeDisabled()
|
||||
})
|
||||
|
||||
it('should disable confirm action when appName is empty', () => {
|
||||
setup({ appName: ' ' })
|
||||
|
||||
expect(screen.getByRole('button', { name: 'common.operation.create' })).toBeDisabled()
|
||||
expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeDisabled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -245,7 +245,7 @@ describe('CreateAppModal', () => {
|
||||
setup({ isEditModal: false })
|
||||
|
||||
expect(screen.getByText('billing.apps.fullTip2')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'common.operation.create' })).toBeDisabled()
|
||||
expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeDisabled()
|
||||
})
|
||||
|
||||
it('should allow saving when apps quota is reached in edit mode', () => {
|
||||
@@ -257,7 +257,7 @@ describe('CreateAppModal', () => {
|
||||
setup({ isEditModal: true })
|
||||
|
||||
expect(screen.queryByText('billing.apps.fullTip2')).not.toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'common.operation.save' })).toBeEnabled()
|
||||
expect(screen.getByRole('button', { name: /common\.operation\.save/ })).toBeEnabled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -384,7 +384,7 @@ describe('CreateAppModal', () => {
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'app.iconPicker.ok' }))
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -433,7 +433,7 @@ describe('CreateAppModal', () => {
|
||||
expect(screen.queryByRole('button', { name: 'app.iconPicker.cancel' })).not.toBeInTheDocument()
|
||||
|
||||
// Submit and verify the payload uses the original icon (cancel reverts to props)
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -471,7 +471,7 @@ describe('CreateAppModal', () => {
|
||||
appIconBackground: '#000000',
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -495,7 +495,7 @@ describe('CreateAppModal', () => {
|
||||
const { onConfirm } = setup({ appDescription: 'Old description' })
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('app.newApp.appDescriptionPlaceholder'), { target: { value: 'Updated description' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -512,7 +512,7 @@ describe('CreateAppModal', () => {
|
||||
appIconBackground: null,
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -536,7 +536,7 @@ describe('CreateAppModal', () => {
|
||||
fireEvent.click(screen.getByRole('switch'))
|
||||
fireEvent.change(screen.getByRole('spinbutton'), { target: { value: '12' } })
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.save/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -551,7 +551,7 @@ describe('CreateAppModal', () => {
|
||||
it('should omit max_active_requests when input is empty', () => {
|
||||
const { onConfirm } = setup({ isEditModal: true, max_active_requests: null })
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.save/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -564,7 +564,7 @@ describe('CreateAppModal', () => {
|
||||
const { onConfirm } = setup({ isEditModal: true, max_active_requests: null })
|
||||
|
||||
fireEvent.change(screen.getByRole('spinbutton'), { target: { value: 'abc' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.save/ }))
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(300)
|
||||
})
|
||||
@@ -576,7 +576,7 @@ describe('CreateAppModal', () => {
|
||||
it('should show toast error and not submit when name becomes empty before debounced submit runs', () => {
|
||||
const { onConfirm, onHide } = setup({ appName: 'My App' })
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.create' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ }))
|
||||
fireEvent.change(screen.getByPlaceholderText('app.newApp.appNamePlaceholder'), { target: { value: ' ' } })
|
||||
|
||||
act(() => {
|
||||
|
||||
@@ -86,6 +86,7 @@ vi.mock('./actions/commands/registry', () => ({
|
||||
|
||||
vi.mock('@/app/components/workflow/utils/common', () => ({
|
||||
getKeyboardKeyCodeBySystem: () => 'ctrl',
|
||||
getKeyboardKeyNameBySystem: (key: string) => key,
|
||||
isEventTargetInputArea: () => false,
|
||||
isMac: () => false,
|
||||
}))
|
||||
|
||||
@@ -134,19 +134,20 @@ vi.mock('@/app/components/workflow/constants', () => ({
|
||||
WORKFLOW_DATA_UPDATE: 'WORKFLOW_DATA_UPDATE',
|
||||
}))
|
||||
|
||||
// Mock FileReader
|
||||
// Mock FileReader - synchronous to avoid timing issues in tests
|
||||
class MockFileReader {
|
||||
result: string | null = null
|
||||
onload: ((e: { target: { result: string | null } }) => void) | null = null
|
||||
|
||||
readAsText(_file: File) {
|
||||
// Simulate async file reading
|
||||
setTimeout(() => {
|
||||
this.result = 'test file content'
|
||||
if (this.onload) {
|
||||
// Call onload synchronously to avoid race conditions in tests
|
||||
this.result = 'test file content'
|
||||
// Use queueMicrotask instead of setTimeout to ensure it runs before other timers
|
||||
// but still allows React state updates to complete
|
||||
queueMicrotask(() => {
|
||||
if (this.onload)
|
||||
this.onload({ target: { result: this.result } })
|
||||
}
|
||||
}, 0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@ vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
|
||||
}))
|
||||
|
||||
// Mock workflow utils for ShortcutsName component
|
||||
vi.mock('@/app/components/workflow/utils', () => ({
|
||||
getKeyboardKeyNameBySystem: (key: string) => key,
|
||||
}))
|
||||
|
||||
// Mock StartNodeSelectionPanel (using real component would be better for integration,
|
||||
// but for this test we'll mock to control behavior)
|
||||
vi.mock('./start-node-selection-panel', () => ({
|
||||
@@ -551,8 +556,10 @@ describe('WorkflowOnboardingModal', () => {
|
||||
|
||||
// Assert
|
||||
const escKey = screen.getByText('workflow.onboarding.escTip.key')
|
||||
expect(escKey.closest('kbd')).toBeInTheDocument()
|
||||
expect(escKey.closest('kbd')).toHaveClass('system-kbd')
|
||||
// ShortcutsName renders a div with system-kbd class, not a kbd element
|
||||
const kbdContainer = escKey.closest('.system-kbd')
|
||||
expect(kbdContainer).toBeInTheDocument()
|
||||
expect(kbdContainer).toHaveClass('system-kbd')
|
||||
})
|
||||
|
||||
it('should have descriptive text for ESC functionality', () => {
|
||||
|
||||
Reference in New Issue
Block a user