11 lines
1.9 KiB
TypeScript
11 lines
1.9 KiB
TypeScript
import {test} from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {parseDocumentXml,documentInput} from '../src/lib/guidance-input';
|
|
import {guidanceXml} from '../src/content/guides/catalog';
|
|
const doc={id:'user-test',revision:1,kind:'guide' as const,title:'A & B',summary:'摘要',applies:'适用',body:'<正文>',steps:['一步'],checks:[],links:[],tags:[]};
|
|
test('XML canonical round trip and strict rejection',()=>{const xml=guidanceXml(doc);assert.deepEqual(parseDocumentXml(xml),doc);for(const bad of [xml.replace('<title>','<title extra="1">'),xml.replace('</body>','</body><title>duplicate</title>'),xml.replace('urn:linked-guidance:0.1','urn:linked-guidance:0.2'),xml.replace('&','&unknown;'),xml.replace('<guidance','<!DOCTYPE guidance><guidance'),xml.replace('revision="1"','revision="1" revision="2"'),xml.replace('<body>','<body><script>')])assert.throws(()=>parseDocumentXml(bad));assert.throws(()=>documentInput.parse({...doc,admin:true}));assert.throws(()=>documentInput.parse({...doc,id:'review-changes'}));});
|
|
|
|
test('XML rejects forbidden Unicode, CDATA terminator and non-XML whitespace',()=>{const xml=guidanceXml(doc);for(const bad of [xml.replace('摘要','bad]]>value'),xml.replace('摘要','bad\u0000value'),xml.replace('摘要','bad\ud800value'),xml+'\u00a0',xml.replace(' id=', '\u00a0id=')])assert.throws(()=>parseDocumentXml(bad));assert.throws(()=>documentInput.parse({...doc,body:'\u000b正文'}));assert.equal(parseDocumentXml(xml.replace('摘要','😀摘要')).summary,'😀摘要');});
|
|
|
|
test('tags round trip and quoted attribute greater-than remains text',()=>{const value={...doc,tags:['标签'],links:[{target:'source-trust',revision:1,relation:'context' as const,when:'a > b',label:'来源'}]};const xml=guidanceXml(value);assert.deepEqual(parseDocumentXml(xml),value);assert.deepEqual(parseDocumentXml(xml.replace('a > b','a > b')),value);assert.throws(()=>parseDocumentXml(xml.replace('when="a > b"','when="a < b"')));});
|