diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 180a51f723..ec78d88f11 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -2413,11 +2413,6 @@ "count": 2 } }, - "web/app/components/explore/create-app-modal/index.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "web/app/components/explore/try-app/tab.tsx": { "erasable-syntax-only/enums": { "count": 1 diff --git a/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx b/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx index 48b801b5b3..cb31c432de 100644 --- a/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx +++ b/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx @@ -1,6 +1,6 @@ import type { CreateAppModalProps } from '../index' import type { UsagePlanInfo } from '@/app/components/billing/type' -import { act, fireEvent, render, screen } from '@testing-library/react' +import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react' import * as React from 'react' import { createMockPlan, createMockPlanTotal, createMockPlanUsage } from '@/__mocks__/provider-context' import { Plan } from '@/app/components/billing/type' @@ -107,13 +107,19 @@ const setup = async (overrides: Partial = {}) => { const getAppIconTrigger = (): HTMLElement => { const nameInput = screen.getByPlaceholderText('app.newApp.appNamePlaceholder') - const iconRow = nameInput.parentElement?.parentElement + const iconRow = nameInput.parentElement const iconTrigger = iconRow?.firstElementChild if (!(iconTrigger instanceof HTMLElement)) throw new Error('Failed to locate app icon trigger') return iconTrigger } +const openAppIconPicker = () => { + fireEvent.click(getAppIconTrigger()) + + return screen.getByRole('dialog', { name: 'app.iconPicker.emoji' }) +} + describe('CreateAppModal', () => { beforeEach(() => { vi.clearAllMocks() @@ -322,13 +328,15 @@ describe('CreateAppModal', () => { appIconUrl: 'https://example.com/icon.png', }) - fireEvent.click(getAppIconTrigger()) + const pickerDialog = openAppIconPicker() - expect(screen.getByRole('button', { name: 'app.iconPicker.cancel' }))!.toBeInTheDocument() + expect(within(pickerDialog).getByRole('button', { name: 'app.iconPicker.cancel' }))!.toBeInTheDocument() - fireEvent.click(screen.getByRole('button', { name: 'app.iconPicker.cancel' })) + fireEvent.click(within(pickerDialog).getByRole('button', { name: 'app.iconPicker.cancel' })) - expect(screen.queryByRole('button', { name: 'app.iconPicker.cancel' })).not.toBeInTheDocument() + await waitFor(() => { + expect(screen.queryByRole('button', { name: 'app.iconPicker.cancel' })).not.toBeInTheDocument() + }) }) it('should update icon payload when selecting emoji and confirming', async () => { @@ -340,16 +348,11 @@ describe('CreateAppModal', () => { appIconUrl: 'https://example.com/icon.png', }) - fireEvent.click(getAppIconTrigger()) + const pickerDialog = openAppIconPicker() - const categoryLabel = screen.getByText('people') - const emojiGrid = categoryLabel.nextElementSibling - const clickableEmojiWrapper = emojiGrid?.firstElementChild - if (!(clickableEmojiWrapper instanceof HTMLElement)) - throw new Error('Failed to locate emoji wrapper') - fireEvent.click(clickableEmojiWrapper) + fireEvent.click(within(pickerDialog).getByRole('button', { name: '😀' })) - fireEvent.click(screen.getByRole('button', { name: 'app.iconPicker.ok' })) + fireEvent.click(within(pickerDialog).getByRole('button', { name: 'app.iconPicker.ok' })) fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ })) await act(async () => { @@ -378,15 +381,10 @@ describe('CreateAppModal', () => { appIconBackground: '#FFEAD5', }) - fireEvent.click(getAppIconTrigger()) + const pickerDialog = openAppIconPicker() - const colorOption = Array.from(document.querySelectorAll('[style^="background:"]')) - .find(element => element.getAttribute('style')?.includes('#E4FBCC')) - if (!(colorOption instanceof HTMLElement) || !(colorOption.parentElement instanceof HTMLElement)) - throw new Error('Failed to locate background color option') - - fireEvent.click(colorOption.parentElement) - fireEvent.click(screen.getByRole('button', { name: 'app.iconPicker.ok' })) + fireEvent.click(within(pickerDialog).getByRole('button', { name: '#E4FBCC' })) + fireEvent.click(within(pickerDialog).getByRole('button', { name: 'app.iconPicker.ok' })) fireEvent.click(screen.getByRole('button', { name: /common\.operation\.create/ })) await act(async () => { diff --git a/web/app/components/explore/create-app-modal/index.tsx b/web/app/components/explore/create-app-modal/index.tsx index 3664ab865c..4fa1212f38 100644 --- a/web/app/components/explore/create-app-modal/index.tsx +++ b/web/app/components/explore/create-app-modal/index.tsx @@ -2,6 +2,7 @@ import type { AppIconType } from '@/types/app' import { Button } from '@langgenius/dify-ui/button' import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog' +import { Input } from '@langgenius/dify-ui/input' import { Kbd, KbdGroup } from '@langgenius/dify-ui/kbd' import { Switch } from '@langgenius/dify-ui/switch' import { Textarea } from '@langgenius/dify-ui/textarea' @@ -12,7 +13,6 @@ import * as React from 'react' import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import AppIcon from '@/app/components/base/app-icon' -import Input from '@/app/components/base/input' import AppsFull from '@/app/components/billing/apps-full-in-dialog' import { useProviderContext } from '@/context/provider-context' import { AppModeEnum } from '@/types/app' @@ -114,7 +114,7 @@ const CreateAppModal = ({ return ( <> !open && onHide()} disablePointerDismissal> - + {isEditModal && ( {t('editAppTitle', { ns: 'app' })}