- 上下文清单、任务列表与详情、恢复控制、运行观察、创作对话与消息流、正式变更决策面板、正文写作与候选审阅、资料研究等页面同步本轮后端能力。 - 事件标签表补齐后端事件类型;查询键与生成客户端随 HTTP 契约重新生成。 - 依赖调整后 lockfile 同步;交互用例与浏览器旅程 spec 一并更新。 - 证据:make 前端检查(lint + typecheck + Pi 工具桥 tsc)exit 0;make 前端测试 37 文件 / 120 用例通过。
105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
import { afterEach, expect, it } from "vitest";
|
||
import { 浏览器缓冲 } from "../../src/功能/正文写作/编辑缓冲";
|
||
import { 创建编辑会话 } from "../../src/功能/正文写作/编辑会话";
|
||
import type { 正文草稿, 正文记录 } from "../../src/功能/正文写作/数据";
|
||
|
||
afterEach(() => localStorage.clear());
|
||
|
||
// @muse-case {"case_id":"NC-editor-buffer-late-owner","environment":"离线组件/实际编辑器;HTTP响应替身不计真实链路","given":"旧会话保存尚在途,章节已重新打开","when":"新会话编辑后交付旧回执","then":["新会话私人缓冲保留,旧会话不能清除"],"contract":"docs/系统架构/新版设计/接口契约/正文结构与中文选区.md"}
|
||
it("NC-editor-buffer-late-owner:旧会话迟到成功不清除重开后的新稿", async () => {
|
||
const scope = {
|
||
author_id: "author",
|
||
work_id: "work",
|
||
chapter_id: "a",
|
||
branch_id: "main",
|
||
};
|
||
const draft = (text: string): 正文草稿 => ({
|
||
format_version: 1,
|
||
paragraphs: [
|
||
{ paragraph_id: "p1", content: [{ type: "text", text, marks: [] }] },
|
||
],
|
||
});
|
||
const record: 正文记录 = {
|
||
...scope,
|
||
document_id: "doc",
|
||
revision: 1,
|
||
state: "saved",
|
||
document: draft("原稿"),
|
||
visible_text: "原稿",
|
||
document_hash: "h1",
|
||
visible_text_hash: "t1",
|
||
};
|
||
let finish!: (v: {
|
||
revision: number;
|
||
document_hash: string;
|
||
receipt_id: string;
|
||
}) => void;
|
||
const old = 创建编辑会话(
|
||
scope,
|
||
record,
|
||
() =>
|
||
new Promise((r) => {
|
||
finish = r;
|
||
}),
|
||
浏览器缓冲(scope),
|
||
);
|
||
old.change(draft("旧会话提交"));
|
||
const request = old.save();
|
||
old.dispose();
|
||
const next = 创建编辑会话(
|
||
scope,
|
||
record,
|
||
async () => ({ revision: 2, document_hash: "h2", receipt_id: "r2" }),
|
||
浏览器缓冲(scope),
|
||
浏览器缓冲(scope).read(),
|
||
);
|
||
next.change(draft("重开后新增文字"));
|
||
finish({ revision: 2, document_hash: "h2", receipt_id: "r2" });
|
||
await request;
|
||
expect(浏览器缓冲(scope).read()?.draft).toEqual(draft("重开后新增文字"));
|
||
});
|
||
// @muse-case {"case_id":"NC-editor-buffer-scope","environment":"离线组件/实际编辑器;HTTP响应替身不计真实链路","given":"多个章的私人未提交缓冲","when":"刷新读取与推进其中一个基线","then":["按作者作品章分支和版本区分,清理不影响另一章"],"contract":"docs/系统架构/新版设计/接口契约/正文结构与中文选区.md"}
|
||
it("NC-editor-buffer-scope:刷新读取私人缓冲且切章不混用基线", () => {
|
||
const a = {
|
||
author_id: "author",
|
||
work_id: "work",
|
||
chapter_id: "a",
|
||
branch_id: "main",
|
||
};
|
||
const b = { ...a, chapter_id: "b" };
|
||
const bufferA = 浏览器缓冲(a);
|
||
const draft = {
|
||
format_version: 1,
|
||
paragraphs: [{ paragraph_id: "p", content: [] }],
|
||
};
|
||
bufferA.write({
|
||
scope: a,
|
||
base_revision: 3,
|
||
base_hash: "h3",
|
||
draft,
|
||
updated_at: 1,
|
||
});
|
||
浏览器缓冲(b).write({
|
||
scope: b,
|
||
base_revision: 8,
|
||
base_hash: "h8",
|
||
draft,
|
||
updated_at: 2,
|
||
});
|
||
expect(浏览器缓冲(a).read()?.base_revision).toBe(3);
|
||
expect(浏览器缓冲({ ...a, author_id: "another" }).read()).toBeUndefined();
|
||
bufferA.write({
|
||
scope: a,
|
||
base_revision: 4,
|
||
base_hash: "h4",
|
||
draft,
|
||
updated_at: 3,
|
||
});
|
||
expect(浏览器缓冲(a).read()?.base_revision).toBe(4);
|
||
expect(localStorage.length).toBe(2);
|
||
bufferA.clear();
|
||
bufferA.write({scope:a,base_revision:5,base_hash:"h5",draft,updated_at:4});
|
||
expect(bufferA.read()?.base_revision).toBe(5);
|
||
expect(浏览器缓冲(b).read()?.base_revision).toBe(8);
|
||
});
|