easy-richtextarea 3.0.154 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/example.js +836 -1
- package/lib/browser.js +33 -1
- package/lib/constants.js +13 -0
- package/lib/content/transform.js +17 -0
- package/lib/main.js +45 -4
- package/lib/operation/delete.js +240 -0
- package/lib/operation/empty.js +101 -0
- package/lib/operation/insert.js +198 -0
- package/lib/operations/fromJSON.js +40 -0
- package/lib/operations/generate.js +42 -0
- package/lib/operations/toJSON.js +17 -0
- package/lib/operations/transform.js +35 -0
- package/lib/stringCompare.js +33 -0
- package/lib/types.js +34 -0
- package/package.json +6 -2
- package/src/browser.js +9 -0
- package/src/constants.js +3 -0
- package/src/content/transform.js +5 -0
- package/src/main.js +9 -0
- package/src/operation/delete.js +206 -0
- package/src/operation/empty.js +71 -0
- package/src/operation/insert.js +163 -0
- package/src/operations/fromJSON.js +34 -0
- package/src/operations/generate.js +42 -0
- package/src/operations/toJSON.js +5 -0
- package/src/operations/transform.js +57 -0
- package/src/stringCompare.js +33 -0
- package/src/types.js +11 -0
- package/test/content/transform.js +59 -0
- package/test/helpers.js +85 -0
- package/test/operation/delete.js +245 -0
- package/test/operation/empty.js +83 -0
- package/test/operation/insert.js +201 -0
- package/test/operations/generate.js +82 -0
- package/test/operations/transform.js +130 -0
package/test/helpers.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const randomSeed = require("random-seed");
|
|
4
|
+
|
|
5
|
+
const { EmptyOperation, InsertOperation, DeleteOperation } = require("../lib/main"); ///
|
|
6
|
+
|
|
7
|
+
const DEFAULT_CONTENT_LENGTH = 4,
|
|
8
|
+
DEFAULT_NUMBER_OF_OPERATIONS = 2,
|
|
9
|
+
MAXIMUM_INSERT_OPERATION_LENGTH = 4;
|
|
10
|
+
|
|
11
|
+
const random = randomSeed.create(".");
|
|
12
|
+
|
|
13
|
+
function content(length = DEFAULT_CONTENT_LENGTH) {
|
|
14
|
+
const string = generateString(length),
|
|
15
|
+
content = string; ///
|
|
16
|
+
|
|
17
|
+
return content;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function operations(content, numberOfOperations = DEFAULT_NUMBER_OF_OPERATIONS) {
|
|
21
|
+
const operations = [];
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < numberOfOperations; i++) {
|
|
24
|
+
const operation = generateOperation(content);
|
|
25
|
+
|
|
26
|
+
operations.push(operation);
|
|
27
|
+
|
|
28
|
+
content = operation.transformContent(content);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return operations;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
content,
|
|
36
|
+
operations
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function generateString(length) {
|
|
40
|
+
let string = "";
|
|
41
|
+
|
|
42
|
+
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
43
|
+
|
|
44
|
+
for (let index = 0; index < length; index++) {
|
|
45
|
+
string += characters.charAt(random(characters.length));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function generateOperation(string) {
|
|
52
|
+
if (string === "") {
|
|
53
|
+
return [
|
|
54
|
+
generateEmptyOperation,
|
|
55
|
+
generateInsertOperation
|
|
56
|
+
][random(2)](string);
|
|
57
|
+
} else {
|
|
58
|
+
return [
|
|
59
|
+
generateEmptyOperation,
|
|
60
|
+
generateInsertOperation,
|
|
61
|
+
generateDeleteOperation
|
|
62
|
+
][random(3)](string);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function generateEmptyOperation(string) {
|
|
67
|
+
return EmptyOperation.fromNothing();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function generateInsertOperation(string) {
|
|
71
|
+
const stringLength = string.length,
|
|
72
|
+
position = random(stringLength + 1);
|
|
73
|
+
|
|
74
|
+
string = generateString(MAXIMUM_INSERT_OPERATION_LENGTH); ///
|
|
75
|
+
|
|
76
|
+
return InsertOperation.fromStringAndPosition(string, position);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function generateDeleteOperation(string) {
|
|
80
|
+
const stringLength = string.length,
|
|
81
|
+
position = random(stringLength),
|
|
82
|
+
length = random(stringLength - position) + 1;
|
|
83
|
+
|
|
84
|
+
return DeleteOperation.fromLengthAndPosition(length, position);
|
|
85
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { assert } = require("chai"),
|
|
4
|
+
{ arrayUtilities } = require("necessary"),
|
|
5
|
+
{ EmptyOperation, DeleteOperation, InsertOperation } = require("../../lib/main"); ///
|
|
6
|
+
|
|
7
|
+
const helpers = require("../helpers");
|
|
8
|
+
|
|
9
|
+
const { first } = arrayUtilities;
|
|
10
|
+
|
|
11
|
+
describe("DeleteOperation", () => {
|
|
12
|
+
describe("transform", () => {
|
|
13
|
+
it("transforms an insert operation at position 2 to position 1", () => {
|
|
14
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(2, 1),
|
|
15
|
+
insertOperation2 = InsertOperation.fromStringAndPosition("b", 2),
|
|
16
|
+
transformedOperations = deleteOperation1.transformOperation(insertOperation2);
|
|
17
|
+
|
|
18
|
+
assert.lengthOf(transformedOperations, 1);
|
|
19
|
+
|
|
20
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
21
|
+
transformedOperation = firstTransformedOperation, ///
|
|
22
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
23
|
+
expectedTransformedOperation = InsertOperation.fromStringAndPosition("b", 1),
|
|
24
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
25
|
+
|
|
26
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("transforms a delete operation of length 1 at position 2 to an empty operation", () => {
|
|
30
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(2, 1),
|
|
31
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(1, 2),
|
|
32
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
33
|
+
|
|
34
|
+
assert.lengthOf(transformedOperations, 1);
|
|
35
|
+
|
|
36
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
37
|
+
transformedOperation = firstTransformedOperation, ///
|
|
38
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
39
|
+
expectedTransformedOperation = EmptyOperation.fromNothing(),
|
|
40
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
41
|
+
|
|
42
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("transforms a delete operation of length 2 at position 2 to a delete operation of length 1 at position 1", () => {
|
|
46
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(2, 1),
|
|
47
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(2, 2),
|
|
48
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
49
|
+
|
|
50
|
+
assert.lengthOf(transformedOperations, 1);
|
|
51
|
+
|
|
52
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
53
|
+
transformedOperation = firstTransformedOperation, ///
|
|
54
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
55
|
+
expectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
56
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
57
|
+
|
|
58
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("transforms an insert operation at position 0, leaving it in the same position", () => {
|
|
62
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
63
|
+
insertOperation2 = InsertOperation.fromStringAndPosition("b", 0),
|
|
64
|
+
transformedOperations = deleteOperation1.transformOperation(insertOperation2);
|
|
65
|
+
|
|
66
|
+
assert.lengthOf(transformedOperations, 1);
|
|
67
|
+
|
|
68
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
69
|
+
transformedOperation = firstTransformedOperation, ///
|
|
70
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
71
|
+
expectedTransformedOperation = insertOperation2.clone(),
|
|
72
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
73
|
+
|
|
74
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("transforms an insert operation at position 1, leaving it in the same position", () => {
|
|
78
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
79
|
+
insertOperation2 = InsertOperation.fromStringAndPosition("b", 1),
|
|
80
|
+
transformedOperations = deleteOperation1.transformOperation(insertOperation2);
|
|
81
|
+
|
|
82
|
+
assert.lengthOf(transformedOperations, 1);
|
|
83
|
+
|
|
84
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
85
|
+
transformedOperation = firstTransformedOperation, ///
|
|
86
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
87
|
+
expectedTransformedOperation = insertOperation2.clone(),
|
|
88
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
89
|
+
|
|
90
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("transforms an insert operation at position 2 to position 1", () => {
|
|
94
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
95
|
+
insertOperation2 = InsertOperation.fromStringAndPosition("b", 2),
|
|
96
|
+
transformedOperations = deleteOperation1.transformOperation(insertOperation2);
|
|
97
|
+
|
|
98
|
+
assert.lengthOf(transformedOperations, 1);
|
|
99
|
+
|
|
100
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
101
|
+
transformedOperation = firstTransformedOperation, ///
|
|
102
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
103
|
+
expectedTransformedOperation = InsertOperation.fromStringAndPosition("b", 1),
|
|
104
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
105
|
+
|
|
106
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("transforms an empty operation, leaving it the same", () => {
|
|
110
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
111
|
+
emptyOperation2 = EmptyOperation.fromNothing(),
|
|
112
|
+
transformedOperations = deleteOperation1.transformOperation(emptyOperation2);
|
|
113
|
+
|
|
114
|
+
assert.lengthOf(transformedOperations, 1);
|
|
115
|
+
|
|
116
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
117
|
+
transformedOperation = firstTransformedOperation, ///
|
|
118
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
119
|
+
expectedTransformedOperation = emptyOperation2.clone(),
|
|
120
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
121
|
+
|
|
122
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("transforms a delete operation of length 1 at position 0, leaving it the same position", () => {
|
|
126
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
127
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(1, 0),
|
|
128
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
129
|
+
|
|
130
|
+
assert.lengthOf(transformedOperations, 1);
|
|
131
|
+
|
|
132
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
133
|
+
transformedOperation = firstTransformedOperation, ///
|
|
134
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
135
|
+
expectedTransformedOperation = deleteOperation2.clone(),
|
|
136
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
137
|
+
|
|
138
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("transforms a delete operation of length 2 at position 0 to a delete operation of length 1 at position 0", () => {
|
|
142
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
143
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(2, 0),
|
|
144
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
145
|
+
|
|
146
|
+
assert.lengthOf(transformedOperations, 1);
|
|
147
|
+
|
|
148
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
149
|
+
transformedOperation = firstTransformedOperation, ///
|
|
150
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
151
|
+
expectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 0),
|
|
152
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
153
|
+
|
|
154
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("transforms a delete operation of length 3 at position 0 to a delete operation of length 2 at position 0", () => {
|
|
158
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
159
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(3, 0),
|
|
160
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
161
|
+
|
|
162
|
+
assert.lengthOf(transformedOperations, 1);
|
|
163
|
+
|
|
164
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
165
|
+
transformedOperation = firstTransformedOperation, ///
|
|
166
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
167
|
+
expectedTransformedOperation = DeleteOperation.fromLengthAndPosition(2, 0),
|
|
168
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
169
|
+
|
|
170
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("transforms a delete operation of length 1 at position 1 to an empty operation", () => {
|
|
174
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
175
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
176
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
177
|
+
|
|
178
|
+
assert.lengthOf(transformedOperations, 1);
|
|
179
|
+
|
|
180
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
181
|
+
transformedOperation = firstTransformedOperation, ///
|
|
182
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
183
|
+
expectedTransformedOperation = EmptyOperation.fromNothing(),
|
|
184
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
185
|
+
|
|
186
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it("transforms a delete operation of length 2 at position 1 to a delete operation of length 1 at position 1", () => {
|
|
190
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
191
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(2, 1),
|
|
192
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
193
|
+
|
|
194
|
+
assert.lengthOf(transformedOperations, 1);
|
|
195
|
+
|
|
196
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
197
|
+
transformedOperation = firstTransformedOperation, ///
|
|
198
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
199
|
+
expectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
200
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
201
|
+
|
|
202
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("transforms a delete operation of length 1 at position 2 to a delete operation of length 1 at position 1", () => {
|
|
206
|
+
const deleteOperation1 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
207
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(1, 2),
|
|
208
|
+
transformedOperations = deleteOperation1.transformOperation(deleteOperation2);
|
|
209
|
+
|
|
210
|
+
assert.lengthOf(transformedOperations, 1);
|
|
211
|
+
|
|
212
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
213
|
+
transformedOperation = firstTransformedOperation, ///
|
|
214
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
215
|
+
expectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
216
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
217
|
+
|
|
218
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe("transformContent", () => {
|
|
223
|
+
it("deletes the requisite characters from the content", () => {
|
|
224
|
+
const content = helpers.content(10),
|
|
225
|
+
deleteOperation = DeleteOperation.fromLengthAndPosition(6, 4),
|
|
226
|
+
transformedContent = deleteOperation.transformContent(content),
|
|
227
|
+
expectedContent = content.substring(0, 4);
|
|
228
|
+
|
|
229
|
+
assert.equal(transformedContent, expectedContent);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe("fromJSON, toJSON", () => {
|
|
234
|
+
it("transforms from and to JSON, leaving the operation unchanged", () => {
|
|
235
|
+
const expectedJSON = {
|
|
236
|
+
"type": "delete",
|
|
237
|
+
"length": 3,
|
|
238
|
+
"position": 1
|
|
239
|
+
},
|
|
240
|
+
json = DeleteOperation.fromJSON(expectedJSON).toJSON();
|
|
241
|
+
|
|
242
|
+
assert.deepEqual(json, expectedJSON);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { assert } = require("chai"),
|
|
4
|
+
{ arrayUtilities } = require("necessary"),
|
|
5
|
+
{ EmptyOperation, DeleteOperation, InsertOperation } = require("../../lib/main"); ///
|
|
6
|
+
|
|
7
|
+
const helpers = require("../helpers");
|
|
8
|
+
|
|
9
|
+
const { first } = arrayUtilities;
|
|
10
|
+
|
|
11
|
+
describe("EmptyOperation", () => {
|
|
12
|
+
describe("transform", () => {
|
|
13
|
+
it("transforms an insert operation, leaving it the same", () => {
|
|
14
|
+
const emptyOperation1 = EmptyOperation.fromNothing(),
|
|
15
|
+
insertOperation2 = InsertOperation.fromStringAndPosition(0, "b"),
|
|
16
|
+
transformedOperations = emptyOperation1.transformOperation(insertOperation2);
|
|
17
|
+
|
|
18
|
+
assert.lengthOf(transformedOperations, 1);
|
|
19
|
+
|
|
20
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
21
|
+
transformedOperation = firstTransformedOperation, ///
|
|
22
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
23
|
+
expectedTransformedOperation = insertOperation2.clone(),
|
|
24
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
25
|
+
|
|
26
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("transforms a second empty operation, leaving it the same", () => {
|
|
30
|
+
const emptyOperation1 = EmptyOperation.fromNothing(),
|
|
31
|
+
emptyOperation2 = EmptyOperation.fromNothing(),
|
|
32
|
+
transformedOperations = emptyOperation1.transformOperation(emptyOperation2);
|
|
33
|
+
|
|
34
|
+
assert.lengthOf(transformedOperations, 1);
|
|
35
|
+
|
|
36
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
37
|
+
transformedOperation = firstTransformedOperation, ///
|
|
38
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
39
|
+
expectedTransformedOperation = emptyOperation2.clone(),
|
|
40
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
41
|
+
|
|
42
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("transforms a delete operation, leaving it the same", () => {
|
|
46
|
+
const emptyOperation1 = EmptyOperation.fromNothing(),
|
|
47
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(0, 1),
|
|
48
|
+
transformedOperations = emptyOperation1.transformOperation(deleteOperation2);
|
|
49
|
+
|
|
50
|
+
assert.lengthOf(transformedOperations, 1);
|
|
51
|
+
|
|
52
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
53
|
+
transformedOperation = firstTransformedOperation, ///
|
|
54
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
55
|
+
expectedTransformedOperation = deleteOperation2.clone(),
|
|
56
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
57
|
+
|
|
58
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("transformContent", () => {
|
|
63
|
+
it("leaves the content unchanged", () => {
|
|
64
|
+
const content = helpers.content(),
|
|
65
|
+
emptyOperation = EmptyOperation.fromNothing(),
|
|
66
|
+
transformedContent = emptyOperation.transformContent(content),
|
|
67
|
+
expectedContent = content; ///
|
|
68
|
+
|
|
69
|
+
assert.equal(transformedContent, expectedContent);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("fromJSON, toJSON", () => {
|
|
74
|
+
it("transforms from and to JSON, leaving the operation unchanged", () => {
|
|
75
|
+
const expectedJSON = {
|
|
76
|
+
"type": "empty"
|
|
77
|
+
},
|
|
78
|
+
json = EmptyOperation.fromJSON(expectedJSON).toJSON();
|
|
79
|
+
|
|
80
|
+
assert.deepEqual(json, expectedJSON);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { assert } = require("chai"),
|
|
4
|
+
{ arrayUtilities } = require("necessary"),
|
|
5
|
+
{ EmptyOperation, DeleteOperation, InsertOperation } = require("../../lib/main"); ///
|
|
6
|
+
|
|
7
|
+
const helpers = require("../helpers");
|
|
8
|
+
|
|
9
|
+
const { first, second } = arrayUtilities;
|
|
10
|
+
|
|
11
|
+
describe("InsertOperation", () => {
|
|
12
|
+
describe("transform", () => {
|
|
13
|
+
it("transforms a second insert operation at position 0, leaving it in the same position", () => {
|
|
14
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
15
|
+
insertOperation2 = InsertOperation.fromStringAndPosition("b", 0),
|
|
16
|
+
transformedOperations = insertOperation1.transformOperation(insertOperation2);
|
|
17
|
+
|
|
18
|
+
assert.lengthOf(transformedOperations, 1);
|
|
19
|
+
|
|
20
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
21
|
+
transformedOperation = firstTransformedOperation, ///
|
|
22
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
23
|
+
expectedTransformedOperation = insertOperation2.clone(),
|
|
24
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
25
|
+
|
|
26
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("transforms a second, lexicographically lesser insert operation at position 1, leaving it in the same position", () => {
|
|
30
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
31
|
+
insertOperation2 = InsertOperation.fromStringAndPosition(" ", 1),
|
|
32
|
+
transformedOperations = insertOperation1.transformOperation(insertOperation2);
|
|
33
|
+
|
|
34
|
+
assert.lengthOf(transformedOperations, 1);
|
|
35
|
+
|
|
36
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
37
|
+
transformedOperation = firstTransformedOperation, ///
|
|
38
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
39
|
+
expectedTransformedOperation = insertOperation2.clone(),
|
|
40
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
41
|
+
|
|
42
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("transforms a second, equal insert operation, leaving it in the same position", () => {
|
|
46
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
47
|
+
insertOperation2 = insertOperation1.clone(),
|
|
48
|
+
transformedOperations = insertOperation1.transformOperation(insertOperation2);
|
|
49
|
+
|
|
50
|
+
assert.lengthOf(transformedOperations, 1);
|
|
51
|
+
|
|
52
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
53
|
+
transformedOperation = firstTransformedOperation, ///
|
|
54
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
55
|
+
expectedTransformedOperation = insertOperation1.clone(),
|
|
56
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
57
|
+
|
|
58
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("transforms a second, lexicographically greater insert operation at position 1 to position 2", () => {
|
|
62
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
63
|
+
insertOperation2 = InsertOperation.fromStringAndPosition("b", 1),
|
|
64
|
+
transformedOperations = insertOperation1.transformOperation(insertOperation2);
|
|
65
|
+
|
|
66
|
+
assert.lengthOf(transformedOperations, 1);
|
|
67
|
+
|
|
68
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
69
|
+
transformedOperation = firstTransformedOperation, ///
|
|
70
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
71
|
+
expectedTransformedOperation = InsertOperation.fromStringAndPosition("b", 2),
|
|
72
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
73
|
+
|
|
74
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("transforms a second insert operation at position 2 to position 3", () => {
|
|
78
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
79
|
+
insertOperation2 = InsertOperation.fromStringAndPosition("b", 2),
|
|
80
|
+
transformedOperations = insertOperation1.transformOperation(insertOperation2);
|
|
81
|
+
|
|
82
|
+
assert.lengthOf(transformedOperations, 1);
|
|
83
|
+
|
|
84
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
85
|
+
transformedOperation = firstTransformedOperation, ///
|
|
86
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
87
|
+
expectedTransformedOperation = InsertOperation.fromStringAndPosition("b", 3),
|
|
88
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
89
|
+
|
|
90
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("transforms an empty operation, leaving it the same", () => {
|
|
94
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
95
|
+
emptyOperation2 = EmptyOperation.fromNothing(),
|
|
96
|
+
transformedOperations = insertOperation1.transformOperation(emptyOperation2);
|
|
97
|
+
|
|
98
|
+
assert.lengthOf(transformedOperations, 1);
|
|
99
|
+
|
|
100
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
101
|
+
transformedOperation = firstTransformedOperation, ///
|
|
102
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
103
|
+
expectedTransformedOperation = emptyOperation2.clone(),
|
|
104
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
105
|
+
|
|
106
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON)
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("transforms a delete operation at position 0 of length 1, leaving it the same position", () => {
|
|
110
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
111
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(1, 0),
|
|
112
|
+
transformedOperations = insertOperation1.transformOperation(deleteOperation2);
|
|
113
|
+
|
|
114
|
+
assert.lengthOf(transformedOperations, 1);
|
|
115
|
+
|
|
116
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
117
|
+
transformedOperation = firstTransformedOperation, ///
|
|
118
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
119
|
+
expectedTransformedOperation = deleteOperation2.clone(),
|
|
120
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
121
|
+
|
|
122
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("transforms a delete operation at position 0 of length 2, splitting it into two delete operations of length 1, the first at position 0 and the second at position 1", () => {
|
|
126
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
127
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(2, 0),
|
|
128
|
+
transformedOperations = insertOperation1.transformOperation(deleteOperation2);
|
|
129
|
+
|
|
130
|
+
assert.lengthOf(transformedOperations, 2);
|
|
131
|
+
|
|
132
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
133
|
+
secondTransformedOperation = second(transformedOperations),
|
|
134
|
+
firstTransformedOperationJSON = firstTransformedOperation.toJSON(),
|
|
135
|
+
secondTransformedOperationJSON = secondTransformedOperation.toJSON(),
|
|
136
|
+
firstExpectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 0),
|
|
137
|
+
secondExpectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
138
|
+
firstExpectedTransformedOperationJSON = firstExpectedTransformedOperation.toJSON(),
|
|
139
|
+
secondExpectedTransformedOperationJSON = secondExpectedTransformedOperation.toJSON();
|
|
140
|
+
|
|
141
|
+
assert.deepEqual(firstTransformedOperationJSON, firstExpectedTransformedOperationJSON);
|
|
142
|
+
assert.deepEqual(secondTransformedOperationJSON, secondExpectedTransformedOperationJSON);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("transforms a delete operation at position 1 of length 1 to position 2", () => {
|
|
146
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
147
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(1, 1),
|
|
148
|
+
transformedOperations = insertOperation1.transformOperation(deleteOperation2);
|
|
149
|
+
|
|
150
|
+
assert.lengthOf(transformedOperations, 1);
|
|
151
|
+
|
|
152
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
153
|
+
transformedOperation = firstTransformedOperation, ///
|
|
154
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
155
|
+
expectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 2),
|
|
156
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
157
|
+
|
|
158
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("transforms a delete operation at position 2 of length 1 to position 3", () => {
|
|
162
|
+
const insertOperation1 = InsertOperation.fromStringAndPosition("a", 1),
|
|
163
|
+
deleteOperation2 = DeleteOperation.fromLengthAndPosition(1, 2),
|
|
164
|
+
transformedOperations = insertOperation1.transformOperation(deleteOperation2);
|
|
165
|
+
|
|
166
|
+
assert.lengthOf(transformedOperations, 1);
|
|
167
|
+
|
|
168
|
+
const firstTransformedOperation = first(transformedOperations),
|
|
169
|
+
transformedOperation = firstTransformedOperation, ///
|
|
170
|
+
transformedOperationJSON = transformedOperation.toJSON(),
|
|
171
|
+
expectedTransformedOperation = DeleteOperation.fromLengthAndPosition(1, 3),
|
|
172
|
+
expectedTransformedOperationJSON = expectedTransformedOperation.toJSON();
|
|
173
|
+
|
|
174
|
+
assert.deepEqual(transformedOperationJSON, expectedTransformedOperationJSON);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe("transformContent", () => {
|
|
179
|
+
it("inserts the requisite characters into the content", () => {
|
|
180
|
+
const content = helpers.content(),
|
|
181
|
+
emptyOperation = InsertOperation.fromStringAndPosition("123", 0),
|
|
182
|
+
transformedContent = emptyOperation.transformContent(content),
|
|
183
|
+
expectedContent = `123${content}`;
|
|
184
|
+
|
|
185
|
+
assert.equal(transformedContent, expectedContent);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe("fromJSON, toJSON", () => {
|
|
190
|
+
it("transforms from and to JSON, leaving the operation unchanged", () => {
|
|
191
|
+
const expectedJSON = {
|
|
192
|
+
"type": "insert",
|
|
193
|
+
"string": "a",
|
|
194
|
+
"position": 1
|
|
195
|
+
},
|
|
196
|
+
json = InsertOperation.fromJSON(expectedJSON).toJSON();
|
|
197
|
+
|
|
198
|
+
assert.deepEqual(json, expectedJSON);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|