1. 排行榜悬浮窗关闭后小按钮消失问题 - 修复面板居中模式关闭时按钮位置错误 - 保存并恢复按钮的居中状态 2. 首页tag按钮按素材数量排序 - 添加按素材数量降序排序逻辑 3. 上传弹窗输入框浅色模式文字不可见 - 添加 text-slate-900 确保浅色模式下文字可见 - 添加 placeholder 样式确保占位符正确显示
366 lines
11 KiB
TypeScript
366 lines
11 KiB
TypeScript
/**
|
|
* 字段数据存储工具测试
|
|
*/
|
|
|
|
import {
|
|
isStandardField,
|
|
separateFieldValues,
|
|
buildMetadata,
|
|
parseMetadata,
|
|
readAllFieldValues,
|
|
prepareMaterialData,
|
|
checkMetadataSize,
|
|
compressMetadata,
|
|
getFieldStorageLocation,
|
|
getFieldsStorageLocations,
|
|
STANDARD_MATERIAL_FIELDS,
|
|
} from '../field-data-storage'
|
|
|
|
describe('field-data-storage', () => {
|
|
describe('isStandardField', () => {
|
|
it('should return true for standard fields', () => {
|
|
expect(isStandardField('productModel')).toBe(true)
|
|
expect(isStandardField('categoryName')).toBe(true)
|
|
expect(isStandardField('sceneName')).toBe(true)
|
|
expect(isStandardField('renderer')).toBe(true)
|
|
expect(isStandardField('authorName')).toBe(true)
|
|
})
|
|
|
|
it('should return false for custom fields', () => {
|
|
expect(isStandardField('customField')).toBe(false)
|
|
expect(isStandardField('myField')).toBe(false)
|
|
expect(isStandardField('unknownField')).toBe(false)
|
|
})
|
|
|
|
it('should be case sensitive', () => {
|
|
expect(isStandardField('ProductModel')).toBe(false)
|
|
expect(isStandardField('PRODUCTMODEL')).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('separateFieldValues', () => {
|
|
it('should separate standard and custom fields', () => {
|
|
const fields = {
|
|
productModel: 'ABC123',
|
|
categoryName: '店铺A',
|
|
customField: '自定义值',
|
|
anotherCustom: 123,
|
|
}
|
|
|
|
const { standardFields, customFields } = separateFieldValues(fields)
|
|
|
|
expect(standardFields).toEqual({
|
|
productModel: 'ABC123',
|
|
categoryName: '店铺A',
|
|
})
|
|
expect(customFields).toEqual({
|
|
customField: '自定义值',
|
|
anotherCustom: 123,
|
|
})
|
|
})
|
|
|
|
it('should convert standard field values to strings', () => {
|
|
const fields = {
|
|
productModel: 123,
|
|
categoryName: true,
|
|
}
|
|
|
|
const { standardFields } = separateFieldValues(fields)
|
|
|
|
expect(standardFields.productModel).toBe('123')
|
|
expect(standardFields.categoryName).toBe('true')
|
|
})
|
|
|
|
it('should handle null/undefined values', () => {
|
|
const fields = {
|
|
productModel: null,
|
|
categoryName: undefined,
|
|
customField: null,
|
|
}
|
|
|
|
const { standardFields, customFields } = separateFieldValues(fields)
|
|
|
|
expect(standardFields.productModel).toBe('')
|
|
expect(standardFields.categoryName).toBe('')
|
|
expect(customFields.customField).toBeNull()
|
|
})
|
|
|
|
it('should handle empty input', () => {
|
|
const { standardFields, customFields } = separateFieldValues({})
|
|
|
|
expect(Object.keys(standardFields)).toHaveLength(0)
|
|
expect(Object.keys(customFields)).toHaveLength(0)
|
|
})
|
|
})
|
|
|
|
describe('buildMetadata', () => {
|
|
it('should build metadata with custom fields', () => {
|
|
const customFields = { myField: 'value', count: 5 }
|
|
const result = buildMetadata(customFields)
|
|
|
|
expect(result).not.toBeNull()
|
|
const parsed = JSON.parse(result!)
|
|
expect(parsed.templateFields).toEqual(customFields)
|
|
})
|
|
|
|
it('should include templateId', () => {
|
|
const result = buildMetadata({}, 'template-123')
|
|
|
|
expect(result).not.toBeNull()
|
|
const parsed = JSON.parse(result!)
|
|
expect(parsed.templateId).toBe('template-123')
|
|
})
|
|
|
|
it('should include previewUrls', () => {
|
|
const previewUrls = ['url1', 'url2']
|
|
const result = buildMetadata({}, null, previewUrls)
|
|
|
|
expect(result).not.toBeNull()
|
|
const parsed = JSON.parse(result!)
|
|
expect(parsed.previewUrls).toEqual(previewUrls)
|
|
})
|
|
|
|
it('should merge with existing metadata', () => {
|
|
const existingMetadata = JSON.stringify({
|
|
templateId: 'old-template',
|
|
templateFields: { oldField: 'oldValue' },
|
|
})
|
|
const result = buildMetadata({ newField: 'newValue' }, 'new-template', undefined, existingMetadata)
|
|
|
|
const parsed = JSON.parse(result!)
|
|
expect(parsed.templateId).toBe('new-template')
|
|
expect(parsed.templateFields.oldField).toBe('oldValue')
|
|
expect(parsed.templateFields.newField).toBe('newValue')
|
|
})
|
|
|
|
it('should return null for empty data', () => {
|
|
const result = buildMetadata({})
|
|
expect(result).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('parseMetadata', () => {
|
|
it('should parse valid metadata', () => {
|
|
const metadata = JSON.stringify({
|
|
templateId: 'template-123',
|
|
templateFields: { field1: 'value1' },
|
|
previewUrls: ['url1'],
|
|
})
|
|
|
|
const result = parseMetadata(metadata)
|
|
|
|
expect(result.templateId).toBe('template-123')
|
|
expect(result.templateFields).toEqual({ field1: 'value1' })
|
|
expect(result.previewUrls).toEqual(['url1'])
|
|
})
|
|
|
|
it('should return empty templateFields for null', () => {
|
|
const result = parseMetadata(null)
|
|
expect(result.templateFields).toEqual({})
|
|
})
|
|
|
|
it('should return empty templateFields for invalid JSON', () => {
|
|
const result = parseMetadata('invalid json')
|
|
expect(result.templateFields).toEqual({})
|
|
})
|
|
|
|
it('should handle missing templateFields', () => {
|
|
const metadata = JSON.stringify({ templateId: 'test' })
|
|
const result = parseMetadata(metadata)
|
|
expect(result.templateFields).toEqual({})
|
|
})
|
|
})
|
|
|
|
describe('readAllFieldValues', () => {
|
|
it('should read standard fields from material', () => {
|
|
const material = {
|
|
productModel: 'ABC123',
|
|
categoryName: '店铺A',
|
|
sceneName: '场景B',
|
|
metadata: null,
|
|
}
|
|
|
|
const result = readAllFieldValues(material)
|
|
|
|
expect(result.productModel).toBe('ABC123')
|
|
expect(result.categoryName).toBe('店铺A')
|
|
expect(result.sceneName).toBe('场景B')
|
|
})
|
|
|
|
it('should read custom fields from metadata', () => {
|
|
const material = {
|
|
productModel: 'ABC123',
|
|
metadata: JSON.stringify({
|
|
templateFields: { customField: 'customValue' },
|
|
}),
|
|
}
|
|
|
|
const result = readAllFieldValues(material)
|
|
|
|
expect(result.productModel).toBe('ABC123')
|
|
expect(result.customField).toBe('customValue')
|
|
})
|
|
|
|
it('should not override standard fields with metadata', () => {
|
|
const material = {
|
|
productModel: 'StandardValue',
|
|
metadata: JSON.stringify({
|
|
templateFields: { productModel: 'MetadataValue' },
|
|
}),
|
|
}
|
|
|
|
const result = readAllFieldValues(material)
|
|
|
|
// 标准字段应该使用数据库列的值
|
|
expect(result.productModel).toBe('StandardValue')
|
|
})
|
|
|
|
it('should skip empty standard fields', () => {
|
|
const material = {
|
|
productModel: '',
|
|
categoryName: null,
|
|
sceneName: undefined,
|
|
metadata: null,
|
|
}
|
|
|
|
const result = readAllFieldValues(material)
|
|
|
|
expect(result.productModel).toBeUndefined()
|
|
expect(result.categoryName).toBeUndefined()
|
|
expect(result.sceneName).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe('prepareMaterialData', () => {
|
|
it('should prepare data for material creation', () => {
|
|
const templateFields = {
|
|
productModel: 'ABC123',
|
|
categoryName: '店铺A',
|
|
customField: '自定义值',
|
|
}
|
|
|
|
const { standardData, metadata } = prepareMaterialData(templateFields, 'template-123')
|
|
|
|
expect(standardData.productModel).toBe('ABC123')
|
|
expect(standardData.categoryName).toBe('店铺A')
|
|
expect(metadata).not.toBeNull()
|
|
|
|
const parsedMetadata = JSON.parse(metadata!)
|
|
expect(parsedMetadata.templateId).toBe('template-123')
|
|
expect(parsedMetadata.templateFields.customField).toBe('自定义值')
|
|
})
|
|
|
|
it('should include previewUrls', () => {
|
|
const { metadata } = prepareMaterialData({}, null, ['url1', 'url2'])
|
|
|
|
const parsed = JSON.parse(metadata!)
|
|
expect(parsed.previewUrls).toEqual(['url1', 'url2'])
|
|
})
|
|
})
|
|
|
|
describe('checkMetadataSize', () => {
|
|
it('should return ok for small metadata', () => {
|
|
const metadata = JSON.stringify({ field: 'value' })
|
|
const result = checkMetadataSize(metadata)
|
|
|
|
expect(result.ok).toBe(true)
|
|
expect(result.size).toBeLessThan(result.maxSize)
|
|
})
|
|
|
|
it('should return not ok for large metadata', () => {
|
|
const largeData = 'x'.repeat(100000)
|
|
const metadata = JSON.stringify({ field: largeData })
|
|
const result = checkMetadataSize(metadata, 1000)
|
|
|
|
expect(result.ok).toBe(false)
|
|
expect(result.size).toBeGreaterThan(result.maxSize)
|
|
})
|
|
|
|
it('should handle null metadata', () => {
|
|
const result = checkMetadataSize(null)
|
|
|
|
expect(result.ok).toBe(true)
|
|
expect(result.size).toBe(0)
|
|
})
|
|
})
|
|
|
|
describe('compressMetadata', () => {
|
|
it('should remove empty templateFields', () => {
|
|
const metadata = JSON.stringify({
|
|
templateId: 'test',
|
|
templateFields: { field1: '', field2: null, field3: 'value' },
|
|
})
|
|
|
|
const result = compressMetadata(metadata)
|
|
const parsed = JSON.parse(result!)
|
|
|
|
expect(parsed.templateFields).toEqual({ field3: 'value' })
|
|
})
|
|
|
|
it('should remove empty previewUrls array', () => {
|
|
const metadata = JSON.stringify({
|
|
templateId: 'test',
|
|
previewUrls: [],
|
|
})
|
|
|
|
const result = compressMetadata(metadata)
|
|
const parsed = JSON.parse(result!)
|
|
|
|
expect(parsed.previewUrls).toBeUndefined()
|
|
})
|
|
|
|
it('should return null for empty result', () => {
|
|
const metadata = JSON.stringify({
|
|
templateFields: { field1: '', field2: null },
|
|
})
|
|
|
|
const result = compressMetadata(metadata)
|
|
expect(result).toBeNull()
|
|
})
|
|
|
|
it('should handle invalid JSON', () => {
|
|
const result = compressMetadata('invalid json')
|
|
expect(result).toBe('invalid json')
|
|
})
|
|
|
|
it('should handle null input', () => {
|
|
const result = compressMetadata(null)
|
|
expect(result).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('getFieldStorageLocation', () => {
|
|
it('should return standard for standard fields', () => {
|
|
expect(getFieldStorageLocation('productModel')).toBe('standard')
|
|
expect(getFieldStorageLocation('categoryName')).toBe('standard')
|
|
})
|
|
|
|
it('should return metadata for custom fields', () => {
|
|
expect(getFieldStorageLocation('customField')).toBe('metadata')
|
|
expect(getFieldStorageLocation('myField')).toBe('metadata')
|
|
})
|
|
})
|
|
|
|
describe('getFieldsStorageLocations', () => {
|
|
it('should return map of storage locations', () => {
|
|
const fields = ['productModel', 'customField', 'categoryName']
|
|
const result = getFieldsStorageLocations(fields)
|
|
|
|
expect(result.get('productModel')).toBe('standard')
|
|
expect(result.get('customField')).toBe('metadata')
|
|
expect(result.get('categoryName')).toBe('standard')
|
|
})
|
|
})
|
|
|
|
describe('STANDARD_MATERIAL_FIELDS', () => {
|
|
it('should contain expected fields', () => {
|
|
expect(STANDARD_MATERIAL_FIELDS).toContain('productModel')
|
|
expect(STANDARD_MATERIAL_FIELDS).toContain('categoryName')
|
|
expect(STANDARD_MATERIAL_FIELDS).toContain('sceneName')
|
|
expect(STANDARD_MATERIAL_FIELDS).toContain('renderer')
|
|
expect(STANDARD_MATERIAL_FIELDS).toContain('authorName')
|
|
expect(STANDARD_MATERIAL_FIELDS).toContain('platformName')
|
|
})
|
|
})
|
|
})
|