first commit

This commit is contained in:
2026-06-24 09:48:54 +02:00
commit 41e62ddcad
33739 changed files with 4266226 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
var op = require('../lib/op');
var expect = require('chai').expect;
describe('attributes', function () {
describe('clone()', function () {
var attributes = {
bold: true,
color: 'red',
italic: null
};
it('undefined', function () {
expect(op.attributes.clone(undefined)).to.deep.equal({});
});
it('keep null', function () {
var clone = op.attributes.clone(attributes, true);
expect(clone === attributes).to.equal(false);
expect(clone).to.deep.equal(attributes);
});
it('dont keep null', function () {
var clone = op.attributes.clone(attributes, false);
expect(clone === attributes).to.equal(false);
expect(clone).to.deep.equal({
bold: true,
color: 'red'
});
});
});
describe('compose()', function () {
var attributes = { bold: true, color: 'red' };
it('left is undefined', function () {
expect(op.attributes.compose(undefined, attributes)).to.deep.equal(attributes);
});
it('right is undefined', function () {
expect(op.attributes.compose(attributes, undefined)).to.deep.equal(attributes);
});
it('both are undefined', function () {
expect(op.attributes.compose(undefined, undefined)).to.equal(undefined);
});
it('missing', function () {
expect(op.attributes.compose(attributes, { italic: true })).to.deep.equal({
bold: true,
italic: true,
color: 'red'
});
});
it('overwrite', function () {
expect(op.attributes.compose(attributes, { bold: false, color: 'blue' })).to.deep.equal({
bold: false,
color: 'blue'
});
});
it('remove', function () {
expect(op.attributes.compose(attributes, { bold: null })).to.deep.equal({
color: 'red'
});
});
it('remove to none', function () {
expect(op.attributes.compose(attributes, { bold: null, color: null })).to.equal(undefined);
});
it('remove missing', function () {
expect(op.attributes.compose(attributes, { italic: null })).to.deep.equal(attributes);
});
});
describe('diff()', function () {
var format = { bold: true, color: 'red' };
it('left is undefined', function () {
expect(op.attributes.diff(undefined, format)).to.deep.equal(format);
});
it('right is undefined', function () {
var expected = { bold: null, color: null };
expect(op.attributes.diff(format, undefined)).to.deep.equal(expected);
});
it('same format', function () {
expect(op.attributes.diff(format, format)).to.equal(undefined);
});
it('add format', function () {
var added = { bold: true, italic: true, color: 'red' };
var expected = { italic: true };
expect(op.attributes.diff(format, added)).to.deep.equal(expected);
});
it('remove format', function () {
var removed = { bold: true };
var expected = { color: null };
expect(op.attributes.diff(format, removed)).to.deep.equal(expected);
});
it('overwrite format', function () {
var overwritten = { bold: true, color: 'blue' };
var expected = { color: 'blue' };
expect(op.attributes.diff(format, overwritten)).to.deep.equal(expected);
});
});
describe('transform()', function () {
var left = { bold: true, color: 'red', font: null };
var right = { color: 'blue', font: 'serif', italic: true };
it('left is undefined', function () {
expect(op.attributes.transform(undefined, left, false)).to.deep.equal(left);
});
it('right is undefined', function () {
expect(op.attributes.transform(left, undefined, false)).to.equal(undefined);
});
it('both are undefined', function () {
expect(op.attributes.transform(undefined, undefined, false)).to.equal(undefined);
});
it('with priority', function () {
expect(op.attributes.transform(left, right, true)).to.deep.equal({
italic: true
});
});
it('without priority', function () {
expect(op.attributes.transform(left, right, false)).to.deep.equal(right);
});
});
});
+187
View File
@@ -0,0 +1,187 @@
var Delta = require('../../lib/delta');
var expect = require('chai').expect;
describe('constructor', function () {
var ops = [
{ insert: 'abc' },
{ retain: 1, attributes: { color: 'red' } },
{ delete: 4 },
{ insert: 'def', attributes: { bold: true } },
{ retain: 6 }
];
it('empty', function () {
var delta = new Delta();
expect(delta).to.exist;
expect(delta.ops).to.exist;
expect(delta.ops.length).to.equal(0);
});
it('empty ops', function () {
var delta = new Delta().insert('').delete(0).retain(0);
expect(delta).to.exist;
expect(delta.ops).to.exist;
expect(delta.ops.length).to.equal(0);
});
it('array of ops', function () {
var delta = new Delta(ops);
expect(delta.ops).to.deep.equal(ops);
});
it('delta in object form', function () {
var delta = new Delta({ ops: ops });
expect(delta.ops).to.deep.equal(ops);
});
it('delta', function () {
var original = new Delta(ops);
var delta = new Delta(original);
expect(delta.ops).to.deep.equal(original.ops);
expect(delta.ops).to.deep.equal(ops);
});
});
describe('insert()', function () {
it('insert(text)', function () {
var delta = new Delta().insert('test');
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ insert: 'test' });
});
it('insert(embed)', function () {
var delta = new Delta().insert(1);
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ insert: 1 });
});
it('insert(embed, attributes)', function () {
var obj = { url: 'http://quilljs.com', alt: 'Quill' };
var delta = new Delta().insert(1, obj);
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ insert: 1, attributes: obj });
});
it('insert(text, attributes)', function () {
var delta = new Delta().insert('test', { bold: true });
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ insert: 'test', attributes: { bold: true } });
});
it('insert(text) after delete', function () {
var delta = new Delta().delete(1).insert('a');
var expected = new Delta().insert('a').delete(1);
expect(delta).to.deep.equal(expected);
});
it('insert(text) after delete with merge', function () {
var delta = new Delta().insert('a').delete(1).insert('b');
var expected = new Delta().insert('ab').delete(1);
expect(delta).to.deep.equal(expected);
});
it('insert(text) after delete no merge', function () {
var delta = new Delta().insert(1).delete(1).insert('a');
var expected = new Delta().insert(1).insert('a').delete(1);
expect(delta).to.deep.equal(expected);
});
it('insert(text, {})', function () {
var delta = new Delta().insert('a', {});
var expected = new Delta().insert('a');
expect(delta).to.deep.equal(expected);
});
});
describe('delete()', function () {
it('delete(0)', function () {
var delta = new Delta().delete(0);
expect(delta.ops.length).to.equal(0);
});
it('delete(positive)', function () {
var delta = new Delta().delete(1);
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ delete: 1 });
});
});
describe('retain()', function () {
it('retain(0)', function () {
var delta = new Delta().retain(0);
expect(delta.ops.length).to.equal(0);
});
it('retain(length)', function () {
var delta = new Delta().retain(2);
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ retain: 2 });
});
it('retain(length, attributes)', function () {
var delta = new Delta().retain(1, { bold: true });
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ retain: 1, attributes: { bold: true } });
});
it('retain(length, {})', function () {
var delta = new Delta().retain(2, {}).delete(1); // Delete prevents chop
var expected = new Delta().retain(2).delete(1);
expect(delta).to.deep.equal(expected);
});
});
describe('push()', function () {
it('push(op) into empty', function () {
var delta = new Delta();
delta.push({ insert: 'test' });
expect(delta.ops.length).to.equal(1);
});
it('push(op) consecutive delete', function () {
var delta = new Delta().delete(2);
delta.push({ delete: 3 });
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ delete: 5 });
});
it('push(op) consecutive text', function () {
var delta = new Delta().insert('a');
delta.push({ insert: 'b' });
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ insert: 'ab' });
});
it('push(op) consecutive texts with matching attributes', function () {
var delta = new Delta().insert('a', { bold: true });
delta.push({ insert: 'b', attributes: { bold: true } });
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ insert: 'ab', attributes: { bold: true } });
});
it('push(op) consecutive retains with matching attributes', function () {
var delta = new Delta().retain(1, { bold: true });
delta.push({ retain: 3, attributes: { bold : true } });
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ retain: 4, attributes: { bold: true } });
});
it('push(op) consecutive texts with mismatched attributes', function () {
var delta = new Delta().insert('a', { bold: true });
delta.push({ insert: 'b' });
expect(delta.ops.length).to.equal(2);
});
it('push(op) consecutive retains with mismatched attributes', function () {
var delta = new Delta().retain(1, { bold: true });
delta.push({ retain: 3 });
expect(delta.ops.length).to.equal(2);
});
it('push(op) consecutive embeds with matching attributes', function () {
var delta = new Delta().insert({ url: 'http://quilljs.com' });
delta.push({ attributes: { url: 'http://quilljs.com' } });
expect(delta.ops.length).to.equal(2);
});
});
+127
View File
@@ -0,0 +1,127 @@
var Delta = require('../../lib/delta');
var expect = require('chai').expect;
describe('compose()', function () {
it('insert + insert', function () {
var a = new Delta().insert('A');
var b = new Delta().insert('B');
var expected = new Delta().insert('B').insert('A');
expect(a.compose(b)).to.deep.equal(expected);
});
it('insert + retain', function () {
var a = new Delta().insert('A');
var b = new Delta().retain(1, { bold: true, color: 'red', font: null });
var expected = new Delta().insert('A', { bold: true, color: 'red' });
expect(a.compose(b)).to.deep.equal(expected);
});
it('insert + delete', function () {
var a = new Delta().insert('A');
var b = new Delta().delete(1);
var expected = new Delta();
expect(a.compose(b)).to.deep.equal(expected);
});
it('delete + insert', function () {
var a = new Delta().delete(1);
var b = new Delta().insert('B');
var expected = new Delta().insert('B').delete(1);
expect(a.compose(b)).to.deep.equal(expected);
});
it('delete + retain', function () {
var a = new Delta().delete(1);
var b = new Delta().retain(1, { bold: true, color: 'red' });
var expected = new Delta().delete(1).retain(1, { bold: true, color: 'red' });
expect(a.compose(b)).to.deep.equal(expected);
});
it('delete + delete', function () {
var a = new Delta().delete(1);
var b = new Delta().delete(1);
var expected = new Delta().delete(2);
expect(a.compose(b)).to.deep.equal(expected);
});
it('retain + insert', function () {
var a = new Delta().retain(1, { color: 'blue' });
var b = new Delta().insert('B');
var expected = new Delta().insert('B').retain(1, { color: 'blue' });
expect(a.compose(b)).to.deep.equal(expected);
});
it('retain + retain', function () {
var a = new Delta().retain(1, { color: 'blue' });
var b = new Delta().retain(1, { bold: true, color: 'red', font: null });
var expected = new Delta().retain(1, { bold: true, color: 'red', font: null });
expect(a.compose(b)).to.deep.equal(expected);
});
it('retain + delete', function () {
var a = new Delta().retain(1, { color: 'blue' });
var b = new Delta().delete(1);
var expected = new Delta().delete(1);
expect(a.compose(b)).to.deep.equal(expected);
});
it('insert in middle of text', function () {
var a = new Delta().insert('Hello');
var b = new Delta().retain(3).insert('X');
var expected = new Delta().insert('HelXlo');
expect(a.compose(b)).to.deep.equal(expected);
});
it('insert and delete ordering', function () {
var a = new Delta().insert('Hello');
var b = new Delta().insert('Hello');
var insertFirst = new Delta().retain(3).insert('X').delete(1);
var deleteFirst = new Delta().retain(3).delete(1).insert('X');
var expected = new Delta().insert('HelXo');
expect(a.compose(insertFirst)).to.deep.equal(expected);
expect(b.compose(deleteFirst)).to.deep.equal(expected);
});
it('insert embed', function () {
var a = new Delta().insert(1, { src: 'http://quilljs.com/image.png' });
var b = new Delta().retain(1, { alt: 'logo' });
var expected = new Delta().insert(1, { src: 'http://quilljs.com/image.png', alt: 'logo' });
expect(a.compose(b)).to.deep.equal(expected);
});
it('delete entire text', function () {
var a = new Delta().retain(4).insert('Hello');
var b = new Delta().delete(9);
var expected = new Delta().delete(4);
expect(a.compose(b)).to.deep.equal(expected);
});
it('retain more than length of text', function () {
var a = new Delta().insert('Hello');
var b = new Delta().retain(10);
var expected = new Delta().insert('Hello');
expect(a.compose(b)).to.deep.equal(expected);
});
it('retain empty embed', function () {
var a = new Delta().insert(1);
var b = new Delta().retain(1);
var expected = new Delta().insert(1);
expect(a.compose(b)).to.deep.equal(expected);
});
it('remove all attributes', function () {
var a = new Delta().insert('A', { bold: true });
var b = new Delta().retain(1, { bold: null });
var expected = new Delta().insert('A');
expect(a.compose(b)).to.deep.equal(expected);
});
it('remove all embed attributes', function () {
var a = new Delta().insert(2, { bold: true });
var b = new Delta().retain(1, { bold: null });
var expected = new Delta().insert(2);
expect(a.compose(b)).to.deep.equal(expected);
});
});
+72
View File
@@ -0,0 +1,72 @@
var Delta = require('../../lib/delta');
var expect = require('chai').expect;
describe('diff()', function () {
it('insert', function () {
var a = new Delta().insert('A');
var b = new Delta().insert('AB');
var expected = new Delta().retain(1).insert('B');
expect(a.diff(b)).to.deep.equal(expected);
});
it('delete', function () {
var a = new Delta().insert('AB');
var b = new Delta().insert('A');
var expected = new Delta().retain(1).delete(1);
expect(a.diff(b)).to.deep.equal(expected);
});
it('retain', function () {
var a = new Delta().insert('A');
var b = new Delta().insert('A');
var expected = new Delta();
expect(a.diff(b)).to.deep.equal(expected);
});
it('format', function () {
var a = new Delta().insert('A');
var b = new Delta().insert('A', { bold: true });
var expected = new Delta().retain(1, { bold: true });
expect(a.diff(b)).to.deep.equal(expected);
});
it('embed match', function () {
var a = new Delta().insert(1);
var b = new Delta().insert(1);
var expected = new Delta();
expect(a.diff(b)).to.deep.equal(expected);
});
it('embed false positive', function () {
var a = new Delta().insert(1);
var b = new Delta().insert(String.fromCharCode(0)); // Placeholder char for embed in diff()
var expected = new Delta().insert(String.fromCharCode(0)).delete(1);
expect(a.diff(b)).to.deep.equal(expected);
});
it('error on non-documents', function () {
var a = new Delta().insert('A');
var b = new Delta().retain(1).insert('B');
expect(function () {
a.diff(b);
}).to.throw(Error);
expect(function () {
b.diff(a);
}).to.throw(Error);
});
it('inconvenient indexes', function () {
var a = new Delta().insert('12', { bold: true }).insert('34', { italic: true });
var b = new Delta().insert('123', { color: 'red' });
var expected = new Delta().retain(2, { bold: null, color: 'red' }).retain(1, { italic: null, color: 'red' }).delete(1);
expect(a.diff(b)).to.deep.equal(expected);
});
it('combination', function () {
var a = new Delta().insert('Bad', { color: 'red' }).insert('cat', { color: 'blue' });
var b = new Delta().insert('Good', { bold: true }).insert('dog', { italic: true });
var expected = new Delta().insert('Good', { bold: true }).delete(2).retain(1, { italic: true, color: null }).delete(3).insert('og', { italic: true });
expect(a.diff(b)).to.deep.equal(expected);
});
});
+81
View File
@@ -0,0 +1,81 @@
var Delta = require('../../lib/delta');
var expect = require('chai').expect;
describe('helpers', function () {
describe('chop()', function () {
it('retain', function () {
var delta = new Delta().insert('Test').retain(4);
var expected = new Delta().insert('Test');
expect(delta.chop()).to.deep.equal(expected);
});
it('insert', function () {
var delta = new Delta().insert('Test');
var expected = new Delta().insert('Test');
expect(delta.chop()).to.deep.equal(expected);
});
it('formatted retain', function () {
var delta = new Delta().insert('Test').retain(4, { bold: true });
var expected = new Delta().insert('Test').retain(4, { bold: true });
expect(delta.chop()).to.deep.equal(expected);
})
});
describe('length()', function () {
it('document', function () {
var delta = new Delta().insert('AB', { bold: true }).insert(1);
expect(delta.length()).to.equal(3);
});
it('mixed', function () {
var delta = new Delta().insert('AB', { bold: true }).insert(1).retain(2, { bold: null }).delete(1);
expect(delta.length()).to.equal(6);
});
});
describe('slice()', function () {
it('start', function () {
var slice = new Delta().retain(2).insert('A').slice(2);
var expected = new Delta().insert('A');
expect(slice).to.deep.equal(expected);
});
it('start and end chop', function () {
var slice = new Delta().insert('0123456789').slice(2, 7);
var expected = new Delta().insert('23456');
expect(slice).to.deep.equal(expected);
});
it('start and end multiple chop', function () {
var slice = new Delta().insert('0123', { bold: true }).insert('4567').slice(3, 5);
var expected = new Delta().insert('3', { bold: true }).insert('4');
expect(slice).to.deep.equal(expected);
});
it('start and end', function () {
var slice = new Delta().retain(2).insert('A', { bold: true }).insert('B').slice(2, 3);
var expected = new Delta().insert('A', { bold: true });
expect(slice).to.deep.equal(expected);
});
it('no params', function () {
var delta = new Delta().retain(2).insert('A', { bold: true }).insert('B');
var slice = delta.slice();
expect(slice).to.deep.equal(delta);
});
it('split ops', function () {
var slice = new Delta().insert('AB', { bold: true }).insert('C').slice(1, 2);
var expected = new Delta().insert('B', { bold: true });
expect(slice).to.deep.equal(expected);
});
it('split ops multiple times', function () {
var slice = new Delta().insert('ABC', { bold: true }).insert('D').slice(1, 2);
var expected = new Delta().insert('B', { bold: true });
expect(slice).to.deep.equal(expected);
});
});
});
+51
View File
@@ -0,0 +1,51 @@
var Delta = require('../../lib/delta');
var expect = require('chai').expect;
describe('transformPosition()', function () {
it('insert before position', function () {
var delta = new Delta().insert('A');
expect(delta.transform(2)).to.equal(3);
});
it('insert after position', function () {
var delta = new Delta().retain(2).insert('A');
expect(delta.transform(1)).to.equal(1);
});
it('insert at position', function () {
var delta = new Delta().retain(2).insert('A');
expect(delta.transform(2, true)).to.equal(2);
expect(delta.transform(2, false)).to.equal(3);
});
it('delete before position', function () {
var delta = new Delta().delete(2);
expect(delta.transform(4)).to.equal(2);
});
it('delete after position', function () {
var delta = new Delta().retain(4).delete(2);
expect(delta.transform(2)).to.equal(2);
});
it('delete across position', function () {
var delta = new Delta().retain(1).delete(4);
expect(delta.transform(2)).to.equal(1);
});
it('insert and delete before position', function () {
var delta = new Delta().retain(2).insert('A').delete(2);
expect(delta.transform(4)).to.equal(3);
});
it('insert before and delete across position', function () {
var delta = new Delta().retain(2).insert('A').delete(4);
expect(delta.transform(4)).to.equal(3);
});
it('delete before and delete across position', function () {
var delta = new Delta().delete(1).retain(1).delete(4);
expect(delta.transform(4)).to.equal(1);
});
});
+131
View File
@@ -0,0 +1,131 @@
var Delta = require('../../lib/delta');
var expect = require('chai').expect;
describe('transform()', function () {
it('insert + insert', function () {
var a1 = new Delta().insert('A');
var b1 = new Delta().insert('B');
var a2 = new Delta(a1);
var b2 = new Delta(b1);
var expected1 = new Delta().retain(1).insert('B');
var expected2 = new Delta().insert('B');
expect(a1.transform(b1, true)).to.deep.equal(expected1);
expect(a2.transform(b2, false)).to.deep.equal(expected2);
});
it('insert + retain', function () {
var a = new Delta().insert('A');
var b = new Delta().retain(1, { bold: true, color: 'red' });
var expected = new Delta().retain(1).retain(1, { bold: true, color: 'red' });
expect(a.transform(b, true)).to.deep.equal(expected);
});
it('insert + delete', function () {
var a = new Delta().insert('A');
var b = new Delta().delete(1);
var expected = new Delta().retain(1).delete(1);
expect(a.transform(b, true)).to.deep.equal(expected);
});
it('delete + insert', function () {
var a = new Delta().delete(1);
var b = new Delta().insert('B');
var expected = new Delta().insert('B');
expect(a.transform(b, true)).to.deep.equal(expected);
});
it('delete + retain', function () {
var a = new Delta().delete(1);
var b = new Delta().retain(1, { bold: true, color: 'red' });
var expected = new Delta();
expect(a.transform(b, true)).to.deep.equal(expected);
});
it('delete + delete', function () {
var a = new Delta().delete(1);
var b = new Delta().delete(1);
var expected = new Delta();
expect(a.transform(b, true)).to.deep.equal(expected);
});
it('retain + insert', function () {
var a = new Delta().retain(1, { color: 'blue' });
var b = new Delta().insert('B');
var expected = new Delta().insert('B');
expect(a.transform(b, true)).to.deep.equal(expected);
});
it('retain + retain', function () {
var a1 = new Delta().retain(1, { color: 'blue' });
var b1 = new Delta().retain(1, { bold: true, color: 'red' });
var a2 = new Delta().retain(1, { color: 'blue' });
var b2 = new Delta().retain(1, { bold: true, color: 'red' });
var expected1 = new Delta().retain(1, { bold: true });
var expected2 = new Delta();
expect(a1.transform(b1, true)).to.deep.equal(expected1);
expect(b2.transform(a2, true)).to.deep.equal(expected2);
});
it('retain + retain without priority', function () {
var a1 = new Delta().retain(1, { color: 'blue' });
var b1 = new Delta().retain(1, { bold: true, color: 'red' });
var a2 = new Delta().retain(1, { color: 'blue' });
var b2 = new Delta().retain(1, { bold: true, color: 'red' });
var expected1 = new Delta().retain(1, { bold: true, color: 'red' });
var expected2 = new Delta().retain(1, { color: 'blue' });
expect(a1.transform(b1, false)).to.deep.equal(expected1);
expect(b2.transform(a2, false)).to.deep.equal(expected2);
});
it('retain + delete', function () {
var a = new Delta().retain(1, { color: 'blue' });
var b = new Delta().delete(1);
var expected = new Delta().delete(1);
expect(a.transform(b, true)).to.deep.equal(expected);
});
it('alternating edits', function () {
var a1 = new Delta().retain(2).insert('si').delete(5);
var b1 = new Delta().retain(1).insert('e').delete(5).retain(1).insert('ow');
var a2 = new Delta(a1);
var b2 = new Delta(b1);
var expected1 = new Delta().retain(1).insert('e').delete(1).retain(2).insert('ow');
var expected2 = new Delta().retain(2).insert('si').delete(1);
expect(a1.transform(b1, false)).to.deep.equal(expected1);
expect(b2.transform(a2, false)).to.deep.equal(expected2);
});
it('conflicting appends', function () {
var a1 = new Delta().retain(3).insert('aa');
var b1 = new Delta().retain(3).insert('bb');
var a2 = new Delta(a1);
var b2 = new Delta(b1);
var expected1 = new Delta().retain(5).insert('bb');
var expected2 = new Delta().retain(3).insert('aa');
expect(a1.transform(b1, true)).to.deep.equal(expected1);
expect(b2.transform(a2, false)).to.deep.equal(expected2);
});
it('prepend + append', function () {
var a1 = new Delta().insert('aa');
var b1 = new Delta().retain(3).insert('bb');
var expected1 = new Delta().retain(5).insert('bb');
var a2 = new Delta(a1);
var b2 = new Delta(b1);
var expected2 = new Delta().insert('aa');
expect(a1.transform(b1, false)).to.deep.equal(expected1);
expect(b2.transform(a2, false)).to.deep.equal(expected2);
});
it('trailing deletes with differing lengths', function () {
var a1 = new Delta().retain(2).delete(1);
var b1 = new Delta().delete(3);
var expected1 = new Delta().delete(2);
var a2 = new Delta(a1);
var b2 = new Delta(b1);
var expected2 = new Delta();
expect(a1.transform(b1, false)).to.deep.equal(expected1);
expect(b2.transform(a2, false)).to.deep.equal(expected2);
});
});
+139
View File
@@ -0,0 +1,139 @@
var _ = require('lodash');
var fuzzer = require('ot-fuzzer');
var richType = require('../lib/type');
var Delta = richType.Delta;
var FORMATS = {
color: ['red', 'orange', 'yellow', 'green', 'blue', 'purple', null],
font: ['serif', 'sans-serif', 'monospace', null],
bold: [true, null],
italic: [true, null]
};
function generateRandomFormat (includeNull) {
var format = {};
for (var key in FORMATS) {
if (fuzzer.randomReal() < 0.5) {
var value = FORMATS[key][fuzzer.randomInt(FORMATS[key].length)];
if (value || includeNull) {
format[key] = value;
}
}
}
return Object.keys(format).length > 0 ? format : undefined;
};
function generateRandomOp (snapshot) {
snapshot = _.cloneDeep(snapshot);
var length = snapshot.ops.reduce(function(length, op) {
if (!op.insert) {
console.error(snapshot);
throw new Error('Snapshot should only have inserts');
}
// Snapshot should only have inserts
return length + (_.isString(op.insert) ? op.insert.length : 1);
}, 0);
var base = length > 100 ? 10 : 7; // Favor deleting on long documents
var delta = new Delta();
var result = new Delta();
do {
// Allows insert/delete to occur at the end (deletes will be noop)
var modIndex = fuzzer.randomInt(Math.min(length, 5) + 1);
length -= modIndex;
var modLength = Math.min(length, fuzzer.randomInt(4) + 1);
delta.retain(modIndex);
var ops = next(snapshot, modIndex);
for (var i in ops) {
result.push(ops[i]);
}
switch (fuzzer.randomInt(base)) {
case 0:
// Insert plain text
var word = fuzzer.randomWord();
delta.insert(word);
result.insert(word);
break;
case 1:
// Insert formatted text
var word = fuzzer.randomWord();
var formats = generateRandomFormat(false);
delta.insert(word, formats);
result.insert(word, formats);
break;
case 2:
// Insert embed
var type = fuzzer.randomInt(2) + 1;
var formats = generateRandomFormat(false);
delta.insert(type, formats);
result.insert(type, formats);
break;
case 3: case 4:
var attributes = generateRandomFormat(true);
delta.retain(modLength, attributes);
ops = next(snapshot, modLength);
for (var i in ops) {
ops[i].attributes = ops[i].attributes || {};
for (var key in attributes) {
ops[i].attributes[key] = (attributes[key] === null) ? undefined : attributes[key];
}
ops[i].attributes = _.reduce(ops[i].attributes, function (memo, value, key) {
if (value !== null && value !== undefined) {
memo[key] = value;
}
return memo;
}, {});
var newOp = { insert: ops[i].insert };
if (_.keys(ops[i].attributes).length > 0) newOp.attributes = ops[i].attributes;
result.push(newOp);
}
length -= modLength;
break;
default:
next(snapshot, modLength);
delta.delete(modLength);
length -= modLength;
break;
}
} while (length > 0 && fuzzer.randomInt(2) > 0);
for (var i in snapshot.ops) {
result.push(snapshot.ops[i]);
}
return [delta, result];
};
function next (snapshot, length) {
var ops = [];
while (length > 0) {
var opLength;
if (_.isString(snapshot.ops[0].insert)) {
if (length >= snapshot.ops[0].insert.length) {
opLength = snapshot.ops[0].insert.length;
ops.push(snapshot.ops.shift());
} else {
var insert = snapshot.ops[0].insert.substr(0, length);
snapshot.ops[0].insert = snapshot.ops[0].insert.substr(insert.length);
opLength = insert.length;
var op = { insert: insert };
if (snapshot.ops[0].attributes) {
op.attributes = _.clone(snapshot.ops[0].attributes);
}
ops.push(op);
}
} else {
ops.push(snapshot.ops.shift());
opLength = 1;
}
length -= opLength;
}
return ops;
};
fuzzer(richType, generateRandomOp, 100);
+132
View File
@@ -0,0 +1,132 @@
var is = require('../lib/is');
var expect = require('chai').expect;
describe('is', function () {
describe('equal()', function () {
it('exact objects', function () {
var obj = { a: 1, b: true, c: 'test' };
expect(is.equal(obj, obj)).to.equal(true);
});
it('deep equal objects', function () {
var obj1 = { a: 1, b: true, c: 'test' };
var obj2 = { a: 1, c: 'test', b: true };
expect(is.equal(obj1, obj2)).to.equal(true);
});
it('different keys', function () {
var obj1 = { a: 1, b: true, c: 'test' };
var obj2 = { a: 1, c: 'test', b: false };
expect(is.equal(obj1, obj2)).to.equal(false);
});
it('missing keys', function () {
var obj1 = { a: 1, b: true, c: 'test' };
var obj2 = { a: 1, c: 'test'};
expect(is.equal(obj1, obj2)).to.equal(false);
});
it('null and undefined', function () {
expect(is.equal(null, undefined)).to.equal(true);
});
it('existing with nonexisting', function () {
expect(is.equal({}, null)).to.equal(false);
});
});
describe('array()', function () {
it('literal', function () {
expect(is.array([])).to.equal(true);
});
it('instance', function () {
expect(is.array(new Array())).to.equal(true);
});
it('null', function () {
expect(is.array(null)).to.equal(false);
});
});
describe('number()', function () {
it('literal', function () {
expect(is.number(11)).to.equal(true);
});
it('object', function () {
expect(is.number(new Number(0))).to.equal(true);
});
it('NaN', function () {
expect(is.number(NaN)).to.equal(true);
});
it('Infinity', function () {
expect(is.number(Infinity)).to.equal(true);
});
it('null', function () {
expect(is.number(null)).to.equal(false);
});
it('wrong type', function () {
expect(is.number({})).to.equal(false);
});
});
describe('object()', function () {
it('literal', function () {
expect(is.object({})).to.equal(true);
});
it('instance', function () {
function obj() {};
expect(is.object(new obj)).to.equal(true);
});
it('string literal', function () {
expect(is.object('test')).to.equal(false);
});
it('string instance', function () {
expect(is.object(new String('test'))).to.equal(true);
});
it('number literal', function () {
expect(is.object(1)).to.equal(false);
});
it('number instance', function () {
expect(is.object(new Number(1))).to.equal(true);
});
it('null', function () {
expect(is.object(null)).to.equal(false);
});
it('function', function () {
expect(is.object(function () {})).to.equal(true);
});
});
describe('string()', function () {
it('literal', function () {
expect(is.string('test')).to.equal(true);
});
it('object', function () {
expect(is.string(new String('test'))).to.equal(true);
});
it('null', function () {
expect(is.string(null)).to.equal(false);
});
it('wrong type', function () {
expect(is.string({})).to.equal(false);
});
});
});
+93
View File
@@ -0,0 +1,93 @@
var Delta = require('../lib/delta');
var op = require('../lib/op');
var expect = require('chai').expect;
describe('op', function () {
describe('length()', function () {
it('delete', function () {
expect(op.length({ delete: 5 })).to.equal(5);
});
it('retain', function () {
expect(op.length({ retain: 2 })).to.equal(2);
});
it('insert text', function () {
expect(op.length({ insert: 'text' })).to.equal(4);
});
it('insert embed', function () {
expect(op.length({ insert: 2 })).to.equal(1);
});
});
describe('iterator()', function () {
beforeEach(function () {
this.delta = new Delta().insert('Hello', { bold: true }).retain(3).insert(2, { src: 'http://quilljs.com/' }).delete(4);
});
it('hasNext() true', function () {
var iter = op.iterator(this.delta.ops);
expect(iter.hasNext()).to.equal(true);
});
it('hasNext() false', function () {
var iter = op.iterator([]);
expect(iter.hasNext()).to.equal(false);
});
it('peekLength() offset === 0', function () {
var iter = op.iterator(this.delta.ops);
expect(iter.peekLength()).to.equal(5);
iter.next();
expect(iter.peekLength()).to.equal(3);
iter.next();
expect(iter.peekLength()).to.equal(1);
iter.next();
expect(iter.peekLength()).to.equal(4);
});
it('peekLength() offset > 0', function () {
var iter = op.iterator(this.delta.ops);
iter.next(2);
expect(iter.peekLength()).to.equal(5 - 2);
});
it('peekLength() no ops left', function () {
var iter = op.iterator([]);
expect(iter.peekLength()).to.equal(Infinity);
});
it('peekType()', function () {
var iter = op.iterator(this.delta.ops);
expect(iter.peekType()).to.equal('insert');
iter.next();
expect(iter.peekType()).to.equal('retain');
iter.next();
expect(iter.peekType()).to.equal('insert');
iter.next();
expect(iter.peekType()).to.equal('delete');
iter.next();
expect(iter.peekType()).to.equal('retain');
});
it('next()', function () {
var iter = op.iterator(this.delta.ops);
for (var i = 0; i < this.delta.ops.length; i += 1) {
expect(iter.next()).to.deep.equal(this.delta.ops[i]);
}
expect(iter.next()).to.deep.equal({ retain: Infinity });
expect(iter.next(4)).to.deep.equal({ retain: Infinity });
expect(iter.next()).to.deep.equal({ retain: Infinity });
});
it('next(length)', function () {
var iter = op.iterator(this.delta.ops);
expect(iter.next(2)).to.deep.equal({ insert: 'He', attributes: { bold: true }});
expect(iter.next(10)).to.deep.equal({ insert: 'llo', attributes: { bold: true }});
expect(iter.next(1)).to.deep.equal({ retain: 1 });
expect(iter.next(2)).to.deep.equal({ retain: 2 });
});
});
});