loro/loro-js/tests/misc.test.ts

278 lines
7.1 KiB
TypeScript
Raw Normal View History

import { describe, expect, it } from "vitest";
import { Loro, LoroList, LoroMap, LoroText, VersionVector } from "../src";
import { expectTypeOf } from "vitest";
function assertEquals(a: any, b: any) {
expect(a).toStrictEqual(b);
}
describe("transaction", () => {
it("transaction", async () => {
const loro = new Loro();
const text = loro.getText("text");
let count = 0;
const sub = loro.subscribe(() => {
count += 1;
loro.unsubscribe(sub);
});
expect(count).toBe(0);
text.insert(0, "hello world");
expect(count).toBe(0);
text.insert(0, "hello world");
assertEquals(count, 0);
loro.commit();
await one_ms();
assertEquals(count, 1);
});
it("transaction origin", async () => {
const loro = new Loro();
const text = loro.getText("text");
let count = 0;
const sub = loro.subscribe((event: { origin: string }) => {
count += 1;
loro.unsubscribe(sub);
assertEquals(event.origin, "origin");
});
assertEquals(count, 0);
text.insert(0, "hello world");
assertEquals(count, 0);
text.insert(0, "hello world");
assertEquals(count, 0);
loro.commit("origin");
await one_ms();
assertEquals(count, 1);
});
});
describe("subscribe", () => {
it("subscribe_lock", async () => {
const loro = new Loro();
const text = loro.getText("text");
const list = loro.getList("list");
let count = 0;
let i = 1;
const sub = loro.subscribe(() => {
if (i > 0) {
list.insert(0, i);
loro.commit();
i--;
}
count += 1;
});
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 2);
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 3);
loro.unsubscribe(sub);
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 3);
});
it("subscribe_lock2", async () => {
const loro = new Loro();
const text = loro.getText("text");
let count = 0;
const sub = loro.subscribe(() => {
count += 1;
loro.unsubscribe(sub);
});
assertEquals(count, 0);
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 1);
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 1);
});
it("subscribe", async () => {
const loro = new Loro();
const text = loro.getText("text");
let count = 0;
const sub = loro.subscribe(() => {
count += 1;
});
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 1);
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 2);
loro.unsubscribe(sub);
text.insert(0, "hello world");
loro.commit();
await one_ms();
assertEquals(count, 2);
});
});
describe("sync", () => {
it("two insert at beginning", async () => {
const a = new Loro();
const b = new Loro();
let a_version: undefined | VersionVector = undefined;
let b_version: undefined | VersionVector = undefined;
a.subscribe((e: { local: boolean }) => {
if (e.local) {
const exported = a.exportFrom(a_version);
b.import(exported);
a_version = a.version();
}
});
b.subscribe((e: { local: boolean }) => {
if (e.local) {
const exported = b.exportFrom(b_version);
a.import(exported);
b_version = b.version();
}
});
const aText = a.getText("text");
const bText = b.getText("text");
aText.insert(0, "abc");
a.commit();
await one_ms();
assertEquals(aText.toString(), bText.toString());
});
it("sync", () => {
const loro = new Loro();
const text = loro.getText("text");
text.insert(0, "hello world");
const loro_bk = new Loro();
loro_bk.import(loro.exportFrom(undefined));
assertEquals(loro_bk.toJson(), loro.toJson());
const text_bk = loro_bk.getText("text");
assertEquals(text_bk.toString(), "hello world");
text_bk.insert(0, "a ");
loro.import(loro_bk.exportFrom(undefined));
assertEquals(text.toString(), "a hello world");
const map = loro.getMap("map");
map.set("key", "value");
});
});
describe("wasm", () => {
const loro = new Loro();
const a = loro.getText("ha");
a.insert(0, "hello world");
a.delete(6, 5);
a.insert(6, "everyone");
loro.commit();
const b = loro.getMap("ha");
b.set("ab", 123);
loro.commit();
const bText = b.setContainer("hh", new LoroText());
loro.commit();
it("map get", () => {
assertEquals(b.get("ab"), 123);
});
it("getValueDeep", () => {
bText.insert(0, "hello world Text");
assertEquals(b.toJson(), { ab: 123, hh: "hello world Text" });
});
it("get container by id", () => {
const id = b.id;
const b2 = loro.getContainerById(id) as LoroMap;
assertEquals(b2.toJson(), b.toJson());
assertEquals(b2.id, id);
b2.set("0", 12);
assertEquals(b2.toJson(), b.toJson());
});
});
describe("type", () => {
it("test map type", () => {
const loro = new Loro<{ map: LoroMap<{ name: "he" }> }>();
const map = loro.getTypedMap("map");
const v = map.getTyped(loro, "name");
expectTypeOf(v).toEqualTypeOf<"he">();
});
it("test recursive map type", () => {
const loro = new Loro<{ map: LoroMap<{ map: LoroMap<{ name: "he" }> }> }>();
const map = loro.getTypedMap("map");
map.setContainer("map", new LoroMap());
const subMap = map.getTyped(loro, "map");
const name = subMap.getTyped(loro, "name");
expectTypeOf(name).toEqualTypeOf<"he">();
});
it("works for list type", () => {
const loro = new Loro<{ list: LoroList<[string, number]> }>();
const list = loro.getTypedList("list");
list.insertTyped(0, "123");
list.insertTyped(1, 123);
const v0 = list.getTyped(loro, 0);
expectTypeOf(v0).toEqualTypeOf<string>();
const v1 = list.getTyped(loro, 1);
expectTypeOf(v1).toEqualTypeOf<number>();
});
2023-09-12 07:57:06 +00:00
it("test binary type", () => {
// const loro = new Loro<{ list: LoroList<[string, number]> }>();
// const list = loro.getTypedList("list");
// console.dir((list as any).__proto__);
// list.insertTyped(0, new Uint8Array(10));
// const v0 = list.getTyped(loro, 0);
// expectTypeOf(v0).toEqualTypeOf<Uint8Array>();
2023-09-12 07:57:06 +00:00
});
});
feat: movable tree support (#120) * feat: tree state * feat: tree value * feat: tree handler * fix: tree diff * test: fuzz tree * feat: tree snapshot * fix: tree default value * fix: test new node * fix: tree diff * fix: tree unresolved value * fix: tree fuzz * fix: tree fuzz move * fix: sort by tree id * fix: tree diff sorted by lamport * fix: sort roots before tree converted to string * fix: rebase main * fix: tree fuzz * fix: delete undo * fix: tree to json children sorted * fix: diff calculate * fix: diff cycle move * fix: tree old parent cache * feat: cache * fix: local op add tree cache * fix: don't add same tree move to cache * fix: need update cache * feat: new cache * bench: add checkout bench * chore: clean * fix: apply node uncheck * perf: lamport bound * fix: calc old parent * feat: tree wasm * fix: change tree diff * fix: tree diff retreat * fix: tree diff should not apply when add node * feat: new tree loro value * chore: typo * fix: tree deep value * fix: snapshot tree index -1 * fix: decode tree snapshot use state * fix: release state lock when emit event * fix: tree node meta container * fix: need set map container when covert to local tree op * fix: tree value add deleted * fix: more then one op in a change * fix: tree fuzz deleted equal * fix: tree calc min lamport * feat: tree encoding v2 * doc: movable tree * fix: test tree meta * test: remove import bytes check * refactor: diff of text and map * refactor: del span * perf: tree state use deleted cache * fix: some details * fix: loro js tree create * feat: add un exist tree node * bench: tree depth * fix: check out should emit event * refactor: event * fix: fuzz err * fix: pass all tests * fix: fuzz err * fix: list child cache err * chore: rm debug code * fix: encode enhanced err * fix: encode enchanced * fix: fix several richtext issue * fix: richtext anchor err * chore: rm debug code * fix: richtext fuzz err * feat: speedup text snapshot decode * perf: optimize snapshot encoding * perf: speed up decode & insert * fix: fugue span merge err * perf: speedup delete & id cursor map * fix: fugue merge err * chore: update utils * fix: fix merge * fix: return err apply op * fix: fix merge * fix: get map container as tree meta
2023-10-30 03:13:52 +00:00
describe("tree", () => {
const loro = new Loro();
const tree = loro.getTree("root");
it("create", () => {
const root = tree.createNode();
const child = root.createNode();
assertEquals(child.parent()!.id, root.id);
});
feat: movable tree support (#120) * feat: tree state * feat: tree value * feat: tree handler * fix: tree diff * test: fuzz tree * feat: tree snapshot * fix: tree default value * fix: test new node * fix: tree diff * fix: tree unresolved value * fix: tree fuzz * fix: tree fuzz move * fix: sort by tree id * fix: tree diff sorted by lamport * fix: sort roots before tree converted to string * fix: rebase main * fix: tree fuzz * fix: delete undo * fix: tree to json children sorted * fix: diff calculate * fix: diff cycle move * fix: tree old parent cache * feat: cache * fix: local op add tree cache * fix: don't add same tree move to cache * fix: need update cache * feat: new cache * bench: add checkout bench * chore: clean * fix: apply node uncheck * perf: lamport bound * fix: calc old parent * feat: tree wasm * fix: change tree diff * fix: tree diff retreat * fix: tree diff should not apply when add node * feat: new tree loro value * chore: typo * fix: tree deep value * fix: snapshot tree index -1 * fix: decode tree snapshot use state * fix: release state lock when emit event * fix: tree node meta container * fix: need set map container when covert to local tree op * fix: tree value add deleted * fix: more then one op in a change * fix: tree fuzz deleted equal * fix: tree calc min lamport * feat: tree encoding v2 * doc: movable tree * fix: test tree meta * test: remove import bytes check * refactor: diff of text and map * refactor: del span * perf: tree state use deleted cache * fix: some details * fix: loro js tree create * feat: add un exist tree node * bench: tree depth * fix: check out should emit event * refactor: event * fix: fuzz err * fix: pass all tests * fix: fuzz err * fix: list child cache err * chore: rm debug code * fix: encode enhanced err * fix: encode enchanced * fix: fix several richtext issue * fix: richtext anchor err * chore: rm debug code * fix: richtext fuzz err * feat: speedup text snapshot decode * perf: optimize snapshot encoding * perf: speed up decode & insert * fix: fugue span merge err * perf: speedup delete & id cursor map * fix: fugue merge err * chore: update utils * fix: fix merge * fix: return err apply op * fix: fix merge * fix: get map container as tree meta
2023-10-30 03:13:52 +00:00
it("move", () => {
const root = tree.createNode();
const child = root.createNode();
const child2 = root.createNode();
assertEquals(child2.parent()!.id, root.id);
child2.moveTo(child);
assertEquals(child2.parent()!.id, child.id);
assertEquals(child.children()[0].id, child2.id);
});
it("meta", () => {
const root = tree.createNode();
root.data.set("a", 123);
assertEquals(root.data.get("a"), 123);
});
});
feat: movable tree support (#120) * feat: tree state * feat: tree value * feat: tree handler * fix: tree diff * test: fuzz tree * feat: tree snapshot * fix: tree default value * fix: test new node * fix: tree diff * fix: tree unresolved value * fix: tree fuzz * fix: tree fuzz move * fix: sort by tree id * fix: tree diff sorted by lamport * fix: sort roots before tree converted to string * fix: rebase main * fix: tree fuzz * fix: delete undo * fix: tree to json children sorted * fix: diff calculate * fix: diff cycle move * fix: tree old parent cache * feat: cache * fix: local op add tree cache * fix: don't add same tree move to cache * fix: need update cache * feat: new cache * bench: add checkout bench * chore: clean * fix: apply node uncheck * perf: lamport bound * fix: calc old parent * feat: tree wasm * fix: change tree diff * fix: tree diff retreat * fix: tree diff should not apply when add node * feat: new tree loro value * chore: typo * fix: tree deep value * fix: snapshot tree index -1 * fix: decode tree snapshot use state * fix: release state lock when emit event * fix: tree node meta container * fix: need set map container when covert to local tree op * fix: tree value add deleted * fix: more then one op in a change * fix: tree fuzz deleted equal * fix: tree calc min lamport * feat: tree encoding v2 * doc: movable tree * fix: test tree meta * test: remove import bytes check * refactor: diff of text and map * refactor: del span * perf: tree state use deleted cache * fix: some details * fix: loro js tree create * feat: add un exist tree node * bench: tree depth * fix: check out should emit event * refactor: event * fix: fuzz err * fix: pass all tests * fix: fuzz err * fix: list child cache err * chore: rm debug code * fix: encode enhanced err * fix: encode enchanced * fix: fix several richtext issue * fix: richtext anchor err * chore: rm debug code * fix: richtext fuzz err * feat: speedup text snapshot decode * perf: optimize snapshot encoding * perf: speed up decode & insert * fix: fugue span merge err * perf: speedup delete & id cursor map * fix: fugue merge err * chore: update utils * fix: fix merge * fix: return err apply op * fix: fix merge * fix: get map container as tree meta
2023-10-30 03:13:52 +00:00
function one_ms(): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, 1));
}