fix: resolve AppCard description overlap with tag area (#23585)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
97
web/__tests__/description-validation.test.tsx
Normal file
97
web/__tests__/description-validation.test.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Description Validation Test
|
||||
*
|
||||
* Tests for the 400-character description validation across App and Dataset
|
||||
* creation and editing workflows to ensure consistent validation behavior.
|
||||
*/
|
||||
|
||||
describe('Description Validation Logic', () => {
|
||||
// Simulate backend validation function
|
||||
const validateDescriptionLength = (description?: string | null) => {
|
||||
if (description && description.length > 400)
|
||||
throw new Error('Description cannot exceed 400 characters.')
|
||||
|
||||
return description
|
||||
}
|
||||
|
||||
describe('Backend Validation Function', () => {
|
||||
test('allows description within 400 characters', () => {
|
||||
const validDescription = 'x'.repeat(400)
|
||||
expect(() => validateDescriptionLength(validDescription)).not.toThrow()
|
||||
expect(validateDescriptionLength(validDescription)).toBe(validDescription)
|
||||
})
|
||||
|
||||
test('allows empty description', () => {
|
||||
expect(() => validateDescriptionLength('')).not.toThrow()
|
||||
expect(() => validateDescriptionLength(null)).not.toThrow()
|
||||
expect(() => validateDescriptionLength(undefined)).not.toThrow()
|
||||
})
|
||||
|
||||
test('rejects description exceeding 400 characters', () => {
|
||||
const invalidDescription = 'x'.repeat(401)
|
||||
expect(() => validateDescriptionLength(invalidDescription)).toThrow(
|
||||
'Description cannot exceed 400 characters.',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Backend Validation Consistency', () => {
|
||||
test('App and Dataset have consistent validation limits', () => {
|
||||
const maxLength = 400
|
||||
const validDescription = 'x'.repeat(maxLength)
|
||||
const invalidDescription = 'x'.repeat(maxLength + 1)
|
||||
|
||||
// Both should accept exactly 400 characters
|
||||
expect(validDescription.length).toBe(400)
|
||||
expect(() => validateDescriptionLength(validDescription)).not.toThrow()
|
||||
|
||||
// Both should reject 401 characters
|
||||
expect(invalidDescription.length).toBe(401)
|
||||
expect(() => validateDescriptionLength(invalidDescription)).toThrow()
|
||||
})
|
||||
|
||||
test('validation error messages are consistent', () => {
|
||||
const expectedErrorMessage = 'Description cannot exceed 400 characters.'
|
||||
|
||||
// This would be the error message from both App and Dataset backend validation
|
||||
expect(expectedErrorMessage).toBe('Description cannot exceed 400 characters.')
|
||||
|
||||
const invalidDescription = 'x'.repeat(401)
|
||||
try {
|
||||
validateDescriptionLength(invalidDescription)
|
||||
}
|
||||
catch (error) {
|
||||
expect((error as Error).message).toBe(expectedErrorMessage)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('Character Length Edge Cases', () => {
|
||||
const testCases = [
|
||||
{ length: 0, shouldPass: true, description: 'empty description' },
|
||||
{ length: 1, shouldPass: true, description: '1 character' },
|
||||
{ length: 399, shouldPass: true, description: '399 characters' },
|
||||
{ length: 400, shouldPass: true, description: '400 characters (boundary)' },
|
||||
{ length: 401, shouldPass: false, description: '401 characters (over limit)' },
|
||||
{ length: 500, shouldPass: false, description: '500 characters' },
|
||||
{ length: 1000, shouldPass: false, description: '1000 characters' },
|
||||
]
|
||||
|
||||
testCases.forEach(({ length, shouldPass, description }) => {
|
||||
test(`handles ${description} correctly`, () => {
|
||||
const testDescription = length > 0 ? 'x'.repeat(length) : ''
|
||||
expect(testDescription.length).toBe(length)
|
||||
|
||||
if (shouldPass) {
|
||||
expect(() => validateDescriptionLength(testDescription)).not.toThrow()
|
||||
expect(validateDescriptionLength(testDescription)).toBe(testDescription)
|
||||
}
|
||||
else {
|
||||
expect(() => validateDescriptionLength(testDescription)).toThrow(
|
||||
'Description cannot exceed 400 characters.',
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -82,8 +82,11 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
|
||||
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
||||
getRedirection(isCurrentWorkspaceEditor, app, push)
|
||||
}
|
||||
catch {
|
||||
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
|
||||
catch (e: any) {
|
||||
notify({
|
||||
type: 'error',
|
||||
message: e.message || t('app.newApp.appCreateFailed'),
|
||||
})
|
||||
}
|
||||
isCreatingRef.current = false
|
||||
}, [name, notify, t, appMode, appIcon, description, onSuccess, onClose, push, isCurrentWorkspaceEditor])
|
||||
|
@@ -117,8 +117,11 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
if (onRefresh)
|
||||
onRefresh()
|
||||
}
|
||||
catch {
|
||||
notify({ type: 'error', message: t('app.editFailed') })
|
||||
catch (e: any) {
|
||||
notify({
|
||||
type: 'error',
|
||||
message: e.message || t('app.editFailed'),
|
||||
})
|
||||
}
|
||||
}, [app.id, notify, onRefresh, t])
|
||||
|
||||
@@ -364,7 +367,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
|
||||
</div>
|
||||
<div className='title-wrapper h-[90px] px-[14px] text-xs leading-normal text-text-tertiary'>
|
||||
<div
|
||||
className={cn(tags.length ? 'line-clamp-2' : 'line-clamp-4', 'group-hover:line-clamp-2')}
|
||||
className='line-clamp-2'
|
||||
title={app.description}
|
||||
>
|
||||
{app.description}
|
||||
|
Reference in New Issue
Block a user