284 lines
8.7 KiB
JavaScript
284 lines
8.7 KiB
JavaScript
|
|
const assert = require('assert')
|
|
const util = require('util')
|
|
const Automerge = require('..')
|
|
const { MAP, LIST, TEXT } = Automerge
|
|
|
|
// str to uint8array
|
|
function en(str) {
|
|
return new TextEncoder('utf8').encode(str)
|
|
}
|
|
// uint8array to str
|
|
function de(bytes) {
|
|
return new TextDecoder('utf8').decode(bytes);
|
|
}
|
|
|
|
describe('Automerge', () => {
|
|
describe('basics', () => {
|
|
it('should init clone and free', () => {
|
|
let doc1 = Automerge.init()
|
|
let doc2 = doc1.clone()
|
|
doc1.free()
|
|
doc2.free()
|
|
})
|
|
|
|
it('should be able to start and commit', () => {
|
|
let doc = Automerge.init()
|
|
doc.commit()
|
|
})
|
|
|
|
it('getting a nonexistant prop does not throw an error', () => {
|
|
let doc = Automerge.init()
|
|
let root = "_root"
|
|
let result = doc.value(root,"hello")
|
|
assert.deepEqual(result,[])
|
|
})
|
|
|
|
it('should be able to set and get a simple value', () => {
|
|
let doc = Automerge.init()
|
|
let root = "_root"
|
|
let result
|
|
|
|
doc.set(root, "hello", "world")
|
|
doc.set(root, "number1", 5, "uint")
|
|
doc.set(root, "number2", 5)
|
|
doc.set(root, "number3", 5.5)
|
|
doc.set(root, "number4", 5.5, "f64")
|
|
doc.set(root, "number5", 5.5, "int")
|
|
doc.set(root, "bool", true)
|
|
|
|
result = doc.value(root,"hello")
|
|
assert.deepEqual(result,["str","world"])
|
|
|
|
result = doc.value(root,"number1")
|
|
assert.deepEqual(result,["uint",5])
|
|
|
|
result = doc.value(root,"number2")
|
|
assert.deepEqual(result,["int",5])
|
|
|
|
result = doc.value(root,"number3")
|
|
assert.deepEqual(result,["f64",5.5])
|
|
|
|
result = doc.value(root,"number4")
|
|
assert.deepEqual(result,["f64",5.5])
|
|
|
|
result = doc.value(root,"number5")
|
|
assert.deepEqual(result,["int",5])
|
|
|
|
result = doc.value(root,"bool")
|
|
assert.deepEqual(result,["boolean",true])
|
|
|
|
doc.set(root, "bool", false, "boolean")
|
|
|
|
result = doc.value(root,"bool")
|
|
assert.deepEqual(result,["boolean",false])
|
|
})
|
|
|
|
it('should be able to use bytes', () => {
|
|
let doc = Automerge.init()
|
|
doc.set("_root","data1", new Uint8Array([10,11,12]));
|
|
doc.set("_root","data2", new Uint8Array([13,14,15]), "bytes");
|
|
let value1 = doc.value("_root", "data1")
|
|
assert.deepEqual(value1, ["bytes", new Uint8Array([10,11,12])]);
|
|
let value2 = doc.value("_root", "data2")
|
|
assert.deepEqual(value2, ["bytes", new Uint8Array([13,14,15])]);
|
|
})
|
|
|
|
it('should be able to make sub objects', () => {
|
|
let doc = Automerge.init()
|
|
let root = "_root"
|
|
let result
|
|
|
|
let submap = doc.set(root, "submap", MAP)
|
|
doc.set(submap, "number", 6, "uint")
|
|
assert.strictEqual(doc.pending_ops(),2)
|
|
|
|
result = doc.value(root,"submap")
|
|
assert.deepEqual(result,["map",submap])
|
|
|
|
result = doc.value(submap,"number")
|
|
assert.deepEqual(result,["uint",6])
|
|
})
|
|
|
|
it('should be able to make lists', () => {
|
|
let doc = Automerge.init()
|
|
let root = "_root"
|
|
|
|
let submap = doc.set(root, "numbers", LIST)
|
|
doc.insert(submap, 0, "a");
|
|
doc.insert(submap, 1, "b");
|
|
doc.insert(submap, 2, "c");
|
|
doc.insert(submap, 0, "z");
|
|
|
|
assert.deepEqual(doc.value(submap, 0),["str","z"])
|
|
assert.deepEqual(doc.value(submap, 1),["str","a"])
|
|
assert.deepEqual(doc.value(submap, 2),["str","b"])
|
|
assert.deepEqual(doc.value(submap, 3),["str","c"])
|
|
assert.deepEqual(doc.length(submap),4)
|
|
|
|
doc.set(submap, 2, "b v2");
|
|
|
|
assert.deepEqual(doc.value(submap, 2),["str","b v2"])
|
|
assert.deepEqual(doc.length(submap),4)
|
|
})
|
|
|
|
it('should be able delete non-existant props', () => {
|
|
let doc = Automerge.init()
|
|
|
|
doc.set("_root", "foo","bar")
|
|
doc.set("_root", "bip","bap")
|
|
let heads1 = doc.commit()
|
|
|
|
assert.deepEqual(doc.keys("_root"),["bip","foo"])
|
|
|
|
doc.del("_root", "foo")
|
|
doc.del("_root", "baz")
|
|
let heads2 = doc.commit()
|
|
|
|
assert.deepEqual(doc.keys("_root"),["bip"])
|
|
assert.deepEqual(doc.keys("_root", heads1),["bip", "foo"])
|
|
assert.deepEqual(doc.keys("_root", heads2),["bip"])
|
|
})
|
|
|
|
it('should be able to del', () => {
|
|
let doc = Automerge.init()
|
|
let root = "_root"
|
|
|
|
doc.set(root, "xxx", "xxx");
|
|
assert.deepEqual(doc.value(root, "xxx"),["str","xxx"])
|
|
doc.del(root, "xxx");
|
|
assert.deepEqual(doc.value(root, "xxx"),[])
|
|
})
|
|
|
|
it('should be able to use counters', () => {
|
|
let doc = Automerge.init()
|
|
let root = "_root"
|
|
|
|
doc.set(root, "counter", 10, "counter");
|
|
assert.deepEqual(doc.value(root, "counter"),["counter",10])
|
|
doc.inc(root, "counter", 10);
|
|
assert.deepEqual(doc.value(root, "counter"),["counter",20])
|
|
doc.inc(root, "counter", -5);
|
|
assert.deepEqual(doc.value(root, "counter"),["counter",15])
|
|
})
|
|
|
|
it('should be able to splice text', () => {
|
|
let doc = Automerge.init()
|
|
let root = "_root";
|
|
|
|
let text = doc.set(root, "text", Automerge.TEXT);
|
|
doc.splice(text, 0, 0, "hello ")
|
|
doc.splice(text, 6, 0, ["w","o","r","l","d"])
|
|
doc.splice(text, 11, 0, [["str","!"],["str","?"]])
|
|
assert.deepEqual(doc.value(text, 0),["str","h"])
|
|
assert.deepEqual(doc.value(text, 1),["str","e"])
|
|
assert.deepEqual(doc.value(text, 9),["str","l"])
|
|
assert.deepEqual(doc.value(text, 10),["str","d"])
|
|
assert.deepEqual(doc.value(text, 11),["str","!"])
|
|
assert.deepEqual(doc.value(text, 12),["str","?"])
|
|
})
|
|
|
|
it('should be able save all or incrementally', () => {
|
|
let doc = Automerge.init()
|
|
|
|
doc.set("_root", "foo", 1)
|
|
|
|
let save1 = doc.save()
|
|
|
|
doc.set("_root", "bar", 2)
|
|
|
|
let saveMidway = doc.clone().save();
|
|
|
|
let save2 = doc.saveIncremental();
|
|
|
|
doc.set("_root", "baz", 3);
|
|
|
|
let save3 = doc.saveIncremental();
|
|
|
|
let saveA = doc.save();
|
|
let saveB = new Uint8Array([... save1, ...save2, ...save3]);
|
|
|
|
assert.notDeepEqual(saveA, saveB);
|
|
|
|
let docA = Automerge.load(saveA);
|
|
let docB = Automerge.load(saveB);
|
|
let docC = Automerge.load(saveMidway)
|
|
docC.loadIncremental(save3)
|
|
|
|
assert.deepEqual(docA.keys("_root"), docB.keys("_root"));
|
|
assert.deepEqual(docA.save(), docB.save());
|
|
assert.deepEqual(docA.save(), docC.save());
|
|
})
|
|
|
|
it('should be able to splice text', () => {
|
|
let doc = Automerge.init()
|
|
let text = doc.set("_root", "text", TEXT);
|
|
doc.splice(text, 0, 0, "hello world");
|
|
let heads1 = doc.commit();
|
|
doc.splice(text, 6, 0, "big bad ");
|
|
let heads2 = doc.commit();
|
|
assert.strictEqual(doc.text(text), "hello big bad world")
|
|
assert.strictEqual(doc.length(text), 19)
|
|
assert.strictEqual(doc.text(text, heads1), "hello world")
|
|
assert.strictEqual(doc.length(text, heads1), 11)
|
|
assert.strictEqual(doc.text(text, heads2), "hello big bad world")
|
|
assert.strictEqual(doc.length(text, heads2), 19)
|
|
})
|
|
|
|
it('local inc increments all visible counters in a map', () => {
|
|
let doc1 = Automerge.init("aaaa")
|
|
doc1.set("_root", "hello", "world")
|
|
let doc2 = Automerge.load(doc1.save(), "bbbb");
|
|
let doc3 = Automerge.load(doc1.save(), "cccc");
|
|
doc1.set("_root", "cnt", 20)
|
|
doc2.set("_root", "cnt", 0, "counter")
|
|
doc3.set("_root", "cnt", 10, "counter")
|
|
doc1.applyChanges(doc2.getChanges(doc1.getHeads()))
|
|
doc1.applyChanges(doc3.getChanges(doc1.getHeads()))
|
|
let result = doc1.values("_root", "cnt")
|
|
assert.deepEqual(result,[
|
|
['counter',10,'2@cccc'],
|
|
['counter',0,'2@bbbb'],
|
|
['int',20,'2@aaaa']
|
|
])
|
|
doc1.inc("_root", "cnt", 5)
|
|
result = doc1.values("_root", "cnt")
|
|
assert.deepEqual(result, [
|
|
[ 'counter', 15, '2@cccc' ], [ 'counter', 5, '2@bbbb' ]
|
|
])
|
|
|
|
let save1 = doc1.save()
|
|
let doc4 = Automerge.load(save1)
|
|
assert.deepEqual(doc4.save(), save1);
|
|
})
|
|
|
|
it('local inc increments all visible counters in a sequence', () => {
|
|
let doc1 = Automerge.init("aaaa")
|
|
let seq = doc1.set("_root", "seq", LIST)
|
|
doc1.insert(seq, 0, "hello")
|
|
let doc2 = Automerge.load(doc1.save(), "bbbb");
|
|
let doc3 = Automerge.load(doc1.save(), "cccc");
|
|
doc1.set(seq, 0, 20)
|
|
doc2.set(seq, 0, 0, "counter")
|
|
doc3.set(seq, 0, 10, "counter")
|
|
doc1.applyChanges(doc2.getChanges(doc1.getHeads()))
|
|
doc1.applyChanges(doc3.getChanges(doc1.getHeads()))
|
|
let result = doc1.values(seq, 0)
|
|
assert.deepEqual(result,[
|
|
['counter',10,'3@cccc'],
|
|
['counter',0,'3@bbbb'],
|
|
['int',20,'3@aaaa']
|
|
])
|
|
doc1.inc(seq, 0, 5)
|
|
result = doc1.values(seq, 0)
|
|
assert.deepEqual(result, [
|
|
[ 'counter', 15, '3@cccc' ], [ 'counter', 5, '3@bbbb' ]
|
|
])
|
|
|
|
let save = doc1.save()
|
|
let doc4 = Automerge.load(save)
|
|
assert.deepEqual(doc4.save(), save);
|
|
})
|
|
|
|
})
|
|
})
|