* fix(workbench): 模型目录与助手形象 - 修正 Live2D 首帧闪现和模型默认分组
进入画布时形象配置与 Live2D 首帧未就绪不再显示默认球,改为加载提示,失败才回退。
新导入模型一级目录默认未分类、二级渠道展示名默认跟随上游 ID;历史非空分组(含与模型 ID 同名)保留。
拉取模型弹窗默认只勾选已存在模型并移除逐项已存在字样;一级分组下拉点击即展开全部选项。
* style(web): 画布与模型导入 - 按 Prettier 规范格式化改动文件
修复 PR 中 Web checks 的格式化检查失败:Live2D 启动器 JSX、模型导入选择工具函数与 Live2D 加载测试按项目 Prettier 配置重新排版,不改变行为。
* test(web): Live2D 生命周期 - 修复 bun 1.3.9 下 text 导入与模块导入冲突
agent-live2d-lifecycle 曾用 with { type: text } 导入 live2d-avatar.tsx,bun 1.3.9 会按路径复用该缓存,导致新增的模块导入拿不到 Live2DAvatar 具名导出并报 SyntaxError。改为 readFileSync 读取源码文本,本地以 bun 1.3.9 复现并验证通过。
31 lines
1.6 KiB
TypeScript
31 lines
1.6 KiB
TypeScript
import { expect, test } from "bun:test";
|
||
import { readFileSync } from "node:fs";
|
||
|
||
import panelSource from "../src/components/canvas/canvas-cloud-agent-panel.tsx" with { type: "text" };
|
||
import partsSource from "../src/components/canvas/canvas-cloud-agent-panel-parts.tsx" with { type: "text" };
|
||
|
||
// 同一路径一旦被 text 加载器注册,bun 1.3.9 的模块缓存会让其它测试的具名导入失效,这里直接读源码文本。
|
||
const avatarSource = readFileSync(new URL("../src/components/canvas/live2d-avatar.tsx", import.meta.url), "utf8");
|
||
|
||
test("Live2D launcher remains mounted while the Agent panel is open", () => {
|
||
expect(panelSource).toContain("<AgentLauncher");
|
||
expect(panelSource).toContain("hidden={open}");
|
||
expect(panelSource).not.toContain("{!open ? <AgentLauncher");
|
||
expect(partsSource).toContain("hidden = false");
|
||
expect(partsSource).toContain('display: "none"');
|
||
});
|
||
|
||
test("launcher waits for appearance configuration before displaying the default orb", () => {
|
||
expect(partsSource).toContain("const appearanceResolved = useAppearanceStore((state) => state.resolved)");
|
||
expect(partsSource).toContain(") : appearanceResolved ? (");
|
||
expect(partsSource).toContain("正在加载助手形象");
|
||
});
|
||
|
||
test("Live2D fallback is reserved for load or render failures, not initial loading", () => {
|
||
expect(avatarSource).toContain("{failed ? (");
|
||
expect(avatarSource).toContain(") : !ready ? (");
|
||
expect(avatarSource).not.toContain("{failed || !ready ? <span");
|
||
expect(avatarSource).toContain("setFailed(true)");
|
||
expect(avatarSource).toContain("callbacks.current.onError?.");
|
||
});
|