2026-10-20 18:15:47 +08:00
|
|
|
|
import { describe, it, expect } from 'vitest'
|
|
|
|
|
|
import { UNIVERSAL_ROW_VERSION, isUniversalRow, type UniversalRow } from '../src/index.js'
|
|
|
|
|
|
|
|
|
|
|
|
const valid: UniversalRow = {
|
|
|
|
|
|
sourceType: 'wp:post', sourceId: '101', status: 'publish', locale: 'en',
|
|
|
|
|
|
sourceUrl: 'https://fixture.example/news/fixture-news-a.html',
|
|
|
|
|
|
slug: 'fixture-news-a', title: 'Fixture News A', excerpt: 'Fixture excerpt A',
|
|
|
|
|
|
bodyHtml: '<p>Body</p>', publishedAt: '2026-10-05T09:00:00Z', modifiedAt: '2026-10-06T10:00:00Z',
|
|
|
|
|
|
taxonomyRefs: [{ taxonomy: 'category', sourceTermId: '31' }],
|
|
|
|
|
|
attachmentRefs: [{ role: 'featured', sourceId: '201' }],
|
|
|
|
|
|
seo: { title: 'Fixture SEO Title A' },
|
|
|
|
|
|
knownFields: {}, extras: { custom_meta: 'x' },
|
|
|
|
|
|
rawLocation: 'wxr://item/3',
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
describe('UniversalRow 契约', () => {
|
|
|
|
|
|
it('版本号为 1(冻结,变更须升版并保留转换测试)', () => {
|
|
|
|
|
|
expect(UNIVERSAL_ROW_VERSION).toBe(1)
|
|
|
|
|
|
})
|
|
|
|
|
|
it('合法对象通过守卫', () => {
|
|
|
|
|
|
expect(isUniversalRow(valid)).toBe(true)
|
|
|
|
|
|
})
|
|
|
|
|
|
it('缺必填字段拒绝', () => {
|
|
|
|
|
|
const { sourceId: _omit, ...bad } = valid
|
|
|
|
|
|
expect(isUniversalRow(bad)).toBe(false)
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
2026-10-20 18:26:42 +08:00
|
|
|
|
|
|
|
|
|
|
const REQUIRED_KEYS = [
|
|
|
|
|
|
'sourceType', 'sourceId', 'status', 'locale',
|
|
|
|
|
|
'taxonomyRefs', 'attachmentRefs', 'seo', 'knownFields', 'extras', 'rawLocation',
|
|
|
|
|
|
] as const
|
|
|
|
|
|
|
|
|
|
|
|
describe('UniversalRow 守卫拒绝路径', () => {
|
|
|
|
|
|
it.each(REQUIRED_KEYS)('缺必填字段 %s 拒绝', (key) => {
|
|
|
|
|
|
const clone: Record<string, unknown> = { ...valid }
|
|
|
|
|
|
delete clone[key]
|
|
|
|
|
|
expect(isUniversalRow(clone)).toBe(false)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
it('非对象输入拒绝(null / number)', () => {
|
|
|
|
|
|
expect(isUniversalRow(null)).toBe(false)
|
|
|
|
|
|
expect(isUniversalRow(42)).toBe(false)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
it('taxonomyRefs 非数组拒绝', () => {
|
|
|
|
|
|
expect(isUniversalRow({ ...valid, taxonomyRefs: 'oops' })).toBe(false)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
it('必填字符串字段非字符串拒绝(sourceId 数字)', () => {
|
|
|
|
|
|
expect(isUniversalRow({ ...valid, sourceId: 101 })).toBe(false)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
it('seo 为数组拒绝(数组伪装对象)', () => {
|
|
|
|
|
|
expect(isUniversalRow({ ...valid, seo: [] })).toBe(false)
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|