46 lines
1.7 KiB
TypeScript
46 lines
1.7 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import * as fc from 'fast-check'
|
|
import { searchMolds } from './moldSearch'
|
|
import type { MoldInfo } from '../types/mold'
|
|
|
|
const moldInfoArb: fc.Arbitrary<MoldInfo> = fc.record({
|
|
id: fc.integer({ min: 1, max: 100000 }),
|
|
name: fc.string({ minLength: 1, maxLength: 20 }),
|
|
styleNo: fc.option(fc.string({ minLength: 1, maxLength: 10 }), { nil: undefined }),
|
|
barcodeNo: fc.option(fc.string({ minLength: 1, maxLength: 15 }), { nil: undefined }),
|
|
style: fc.option(fc.string({ minLength: 1, maxLength: 10 }), { nil: undefined }),
|
|
images: fc.array(fc.string(), { minLength: 0, maxLength: 3 }),
|
|
createdAt: fc.constant('2025-01-01'),
|
|
updatedAt: fc.constant('2025-01-01'),
|
|
})
|
|
|
|
// Feature: jewelry-mall, Property 5: 版房搜索结果匹配
|
|
// **Validates: Requirements 5.3**
|
|
describe('Property 5: 版房搜索结果匹配', () => {
|
|
it('搜索结果中每条记录至少有一个字段包含关键词', () => {
|
|
fc.assert(
|
|
fc.property(
|
|
fc.array(moldInfoArb, { minLength: 0, maxLength: 20 }),
|
|
fc.string({ minLength: 1, maxLength: 10 }),
|
|
(molds, keyword) => {
|
|
const results = searchMolds(molds, keyword)
|
|
const kw = keyword.trim().toLowerCase()
|
|
if (!kw) return true // 空关键词返回全部,不需要验证匹配
|
|
|
|
for (const mold of results) {
|
|
const fields = [
|
|
mold.name,
|
|
mold.styleNo ?? '',
|
|
mold.barcodeNo ?? '',
|
|
mold.style ?? '',
|
|
]
|
|
const matched = fields.some((f) => f.toLowerCase().includes(kw))
|
|
expect(matched).toBe(true)
|
|
}
|
|
},
|
|
),
|
|
{ numRuns: 100 },
|
|
)
|
|
})
|
|
})
|