47 lines
2.4 KiB
TypeScript
47 lines
2.4 KiB
TypeScript
|
|
// canonicalJson 共享导出测试(Plan 3 Task 1,前置事实 6):从 register.service.ts 提取到
|
|||
|
|
// apps/api/src/common/canonical.ts——register 侧改 import 零行为变更(既有 media_bundle 清单
|
|||
|
|
// 哈希测试继续绿的回归责任在 tests/integration/source-register.test.ts,此处钉导出本身的
|
|||
|
|
// 序列化定义:对象键递归排序、无空白、数组保序)。
|
|||
|
|
// 独立重算对照:期望串手写钉死,不 import 实现——定义漂移即爆红。
|
|||
|
|
import { describe, expect, it } from 'vitest'
|
|||
|
|
import { canonicalJson } from '../../apps/api/src/common/canonical.js'
|
|||
|
|
|
|||
|
|
describe('canonicalJson(共享导出,前置事实 6)', () => {
|
|||
|
|
it('对象键递归排序:任意嵌套层级都按键名字典序', () => {
|
|||
|
|
expect(canonicalJson({ b: 1, a: 2 })).toBe('{"a":2,"b":1}')
|
|||
|
|
expect(canonicalJson({ b: 1, a: { d: 2, c: 3 } })).toBe('{"a":{"c":3,"d":2},"b":1}')
|
|||
|
|
expect(canonicalJson({ z: { y: { x: { w: 1, v: 2 } } } })).toBe('{"z":{"y":{"x":{"v":2,"w":1}}}}')
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
it('无空白:键与值、数组元素间均无空格/换行', () => {
|
|||
|
|
expect(canonicalJson({ a: [1, 2, 3], b: { c: 'x' } })).toBe('{"a":[1,2,3],"b":{"c":"x"}}')
|
|||
|
|
expect(canonicalJson({ a: 1, b: 2 })).not.toContain(' ')
|
|||
|
|
expect(canonicalJson({ a: { b: { c: [1, { d: 2 }] } } })).not.toMatch(/\s/)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
it('数组保序:元素顺序是语义的一部分,不排序', () => {
|
|||
|
|
expect(canonicalJson([3, 1, 2])).toBe('[3,1,2]')
|
|||
|
|
expect(canonicalJson([{ z: 1, a: 2 }, { y: 3, b: 4 }])).toBe('[{"a":2,"z":1},{"b":4,"y":3}]')
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
it('原始值走 JSON.stringify 语义:字符串/数字/布尔/null', () => {
|
|||
|
|
expect(canonicalJson('x')).toBe('"x"')
|
|||
|
|
expect(canonicalJson('a"b')).toBe('"a\\"b"')
|
|||
|
|
expect(canonicalJson(3)).toBe('3')
|
|||
|
|
expect(canonicalJson(true)).toBe('true')
|
|||
|
|
expect(canonicalJson(null)).toBe('null')
|
|||
|
|
expect(canonicalJson({ a: null, b: true, c: 0, d: '' })).toBe('{"a":null,"b":true,"c":0,"d":""}')
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
it('键排序按 UTF-16 码元(与 Array.prototype.sort 默认一致)——大写在前、非 ASCII 原样', () => {
|
|||
|
|
expect(canonicalJson({ b: 1, A: 2, a: 3 })).toBe('{"A":2,"a":3,"b":1}')
|
|||
|
|
expect(canonicalJson({ 图: 1, 中: 2 })).toBe(JSON.stringify({ 中: 2, 图: 1 }))
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
it('空对象/空数组序列化', () => {
|
|||
|
|
expect(canonicalJson({})).toBe('{}')
|
|||
|
|
expect(canonicalJson([])).toBe('[]')
|
|||
|
|
expect(canonicalJson({ a: {}, b: [] })).toBe('{"a":{},"b":[]}')
|
|||
|
|
})
|
|||
|
|
})
|