|
- """Validate real UI exports; run from ute2e. No authentication data is read."""
- from pathlib import Path
- import struct
- import json
- import zipfile
- import xml.etree.ElementTree as ET
- from pypdf import PdfReader
-
- root = Path('reports/guide-closure-20260910')
- checks = []
- def check(name, passed, detail=''):
- checks.append(dict(name=name, status='PASS' if passed else 'FAIL', detail=detail))
-
- pdf = PdfReader(root / 'export-pdf.pdf')
- check('PDF 四页可解析且每页含文本', len(pdf.pages) == 4 and all(p.extract_text().strip() for p in pdf.pages), f'{len(pdf.pages)} pages')
- with zipfile.ZipFile(root / 'export-ofd.ofd') as z:
- xmls = [n for n in z.namelist() if n.lower().endswith('.xml')]
- for name in xmls:
- ET.fromstring(z.read(name))
- check('OFD ZIP 完整、入口和 XML 可解析', z.testzip() is None and 'OFD.xml' in z.namelist() and len(xmls) > 4, f'{len(xmls)} XML files; 未使用第三方 OFD 阅读器认证')
- with zipfile.ZipFile(root / 'export-offline.zip') as z:
- names = z.namelist()
- check('离线 ZIP 完整', z.testzip() is None, f'{len(names)} files')
- scripts = [z.read(n) for n in names if n.endswith(('.js', '.html'))]
- check('离线脚本没有 Vite 开发缓存引用', not any(b'/.vite-cache/' in s or b'/node_modules/.pnpm/' in s for s in scripts))
- glbs = [z.read(n) for n in names if n.lower().endswith('.glb')]
- originals = [Path('../../文档/素材') / n for n in ['09-Fox.glb', '08-CesiumMilkTruck.glb']]
- def structure(b):
- assert b[:4] == b'glTF' and struct.unpack_from('<I', b, 8)[0] == len(b)
- doc = json.loads(b[20:20 + struct.unpack_from('<I', b, 12)[0]])
- return {k: len(doc.get(k, [])) for k in ['nodes', 'meshes', 'animations', 'materials', 'skins']}
- expected = [structure(p.read_bytes()) for p in originals]
- actual = [structure(b) for b in glbs]
- check('离线狐狸和卡车 GLB 结构及动画保留', expected == actual, '导出按现有逻辑轻量化,卡车从 369980 缩至 318276 字节;非原文件逐字节复制。实际渲染和动画另由浏览器验证。')
- check('离线包含本地 Three.js 和解码器', any('three.module' in n for n in names) and any(n.endswith('.wasm') for n in names))
- (root / 'artifact-validation.json').write_text(json.dumps(dict(checks=checks), ensure_ascii=False, indent=2), encoding='utf-8')
- for item in checks:
- print(item['status'], item['name'])
- raise SystemExit(any(c['status'] != 'PASS' for c in checks))
|