Files
opendance-web/web-server
zijunchiang d1c0dd6e7a test(scenes): 加带真实数据库的端到端用例(sql.js 内存库),把生产根因钉死
新增 test/scenes-e2e.spec.ts(4 项,全部真实 SQL,不是 mock):

1. Scene 在 DataSource 里有 metadata、getRepository 不抛错;
2. **反向验证生产根因**:当 ENTITIES 漏掉 Scene 时,`getRepository(Scene)` **不会抛**
   (TypeORM 0.3 是惰性的——这正是"启动完全正常"的原因),而**第一次查询**会 reject
   并抛出与生产完全一致的 `No metadata for "Scene" was found.`;
3. **上传→归档→落库→发布→目录导出 全链路**(真实 StorageService + 真实仓储):
   - 用 multer diskStorage 的文件形状(只有 path、没有 buffer)上传 .glb;
   - 断言 GLB 已归档进 storage、临时目录不再残留该文件(验证 diskStorage 修复);
   - 落 pending;`published()` 为空;发布后能取到完整物理参数(重力/风/地面/相机);
   - `CatalogService.exportBundle()` 的 `scenes[]` 含该场景且参数完整;
   - `catalog/version` 指纹为 64 位十六进制;`scenes.diagnostics()` 报告可用;
   - 删除后 `published()` 不再返回(软删除生效);
4. 越界/非法参数在**真实落库往返**(jsonText transformer)后仍是收敛值
   (重力 -200、摩擦 1、colliders auto、相机 follow)。

实现细节:库内用 `sql.js`(WASM,无原生依赖,devDependency)跑 TypeORM 的 sqljs 驱动;
SQLite 本身对列类型名宽松,但 TypeORM 的 sqlite 驱动会校验 normalizeType 的结果,
因此测试里加了一处**有注释的兼容垫片**:`char→varchar`、`mediumtext/longtext/tinytext→text`、
`enum→varchar`,以及 `bigint` 自增主键→`integer`(SQLite 的 AUTOINCREMENT 只允许
INTEGER PRIMARY KEY)。只影响本测试进程,不改动任何实体定义。

验证:npm run verify 通过(24 文件 / 289 项测试 + 契约/路由/版本一致 + 启动冒烟)。
2026-09-17 03:52:33 +08:00
..