63 lines
2.8 KiB
TypeScript
63 lines
2.8 KiB
TypeScript
import type { AssertableState } from "../utils/assertable-state";
|
|
import type { TestDefinition } from "../test-definition";
|
|
|
|
export const catchupCreateAndUpdateNotSkippedTest: TestDefinition = {
|
|
description:
|
|
"Client 1 disconnects (sync disabled). Client 0 creates a doc and " +
|
|
"then updates it. When Client 1 reconnects, the server's catch-up " +
|
|
"stream sends only the doc's *latest* version (the update), not " +
|
|
"the full history. Client 1 must still pick up the doc — any handler " +
|
|
"that gates the create-on-untracked path on a server-supplied " +
|
|
"'is this the first version' flag would drop it (the latest version " +
|
|
"is not the create), silently leaking the doc. The client treats " +
|
|
"every untracked-doc RemoteChange as a fresh create.",
|
|
clients: 2,
|
|
steps: [
|
|
{ type: "enable-sync", client: 0 },
|
|
{ type: "enable-sync", client: 1 },
|
|
// Establish a baseline so Client 1's last_seen is non-zero before
|
|
// we take it offline. This makes the bug genuinely about catch-up
|
|
// missing the create rather than just an empty-vault first sync.
|
|
{ type: "create", client: 0, path: "warmup.md", content: "w\n" },
|
|
{ type: "barrier" },
|
|
|
|
// Client 1 goes offline.
|
|
{ type: "disable-sync", client: 1 },
|
|
|
|
// Client 0 creates the doc (vault_update_id v_C, after Client 1's
|
|
// watermark). Client 1 doesn't see this because it's offline.
|
|
{ type: "create", client: 0, path: "doc.md", content: "v1\n" },
|
|
// Wait for the create's HTTP to land before the update; otherwise
|
|
// both writes are coalesced into a single POST and the server
|
|
// never sees the doc as "create followed by update".
|
|
{ type: "sync", client: 0 },
|
|
|
|
// Client 0 updates the doc (vault_update_id v_X > v_C). The
|
|
// server's `latest_document_versions` view now returns the
|
|
// *update* row — the create row is no longer the latest.
|
|
{
|
|
type: "update",
|
|
client: 0,
|
|
path: "doc.md",
|
|
content: "v1\nupdate\n"
|
|
},
|
|
{ type: "sync", client: 0 },
|
|
|
|
// Client 1 reconnects. Server's catch-up replays docs with
|
|
// `vault_update_id > last_seen`. For doc.md it sends v_X; Client
|
|
// 1 has no record of the doc, so it treats the RemoteChange as a
|
|
// fresh create and downloads the latest content.
|
|
{ type: "enable-sync", client: 1 },
|
|
{ type: "barrier" },
|
|
|
|
{
|
|
type: "assert-consistent",
|
|
verify: (state: AssertableState): void => {
|
|
state.assertFileCount(2);
|
|
state.assertFileExists("doc.md");
|
|
state.assertContent("doc.md", "v1\nupdate\n");
|
|
state.assertContent("warmup.md", "w\n");
|
|
}
|
|
}
|
|
]
|
|
};
|