mirror of
https://github.com/element-hq/element-web
synced 2024-11-26 03:05:51 +03:00
Unit test typescriptification - editor utils (#8226)
* editor/mock ts Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/serialize-test.js -> test/editor/serialize-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * fix ts in serialize-test Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/range-test.js -> test/editor/range-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/position-test.js -> test/editor/position-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * fix position-test Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/operations-test.js -> test/editor/operations-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/model-test.js -> test/editor/model-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * fix ts in model-test Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/history-test.js -> test/editor/history-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * fix ts in history-test Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/diff-test.js -> test/editor/diff-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/deserialize-test.js -> test/editor/deserialize-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * ts in deserialize-test Signed-off-by: Kerry Archibald <kerrya@element.io> * test/editor/caret-test.js -> test/editor/caret-test.ts Signed-off-by: Kerry Archibald <kerrya@element.io> * ts caret-test Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
efb44e1b7d
commit
b9da2255c4
11 changed files with 112 additions and 90 deletions
|
@ -24,7 +24,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const pc = createPartCreator();
|
||||
const model = new EditorModel([
|
||||
pc.plain("hello"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 0, offset: 5 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -35,7 +35,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const pc = createPartCreator();
|
||||
const model = new EditorModel([
|
||||
pc.plain("hello"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 0, offset: 0 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -46,7 +46,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const pc = createPartCreator();
|
||||
const model = new EditorModel([
|
||||
pc.plain("hello"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 0, offset: 2 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -61,7 +61,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
pc.plain("hello"),
|
||||
pc.newline(),
|
||||
pc.plain("world"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 2, offset: 5 });
|
||||
expect(lineIndex).toBe(1);
|
||||
|
@ -74,7 +74,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
pc.plain("hello"),
|
||||
pc.newline(),
|
||||
pc.plain("world"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 2, offset: 0 });
|
||||
expect(lineIndex).toBe(1);
|
||||
|
@ -88,7 +88,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
pc.newline(),
|
||||
pc.newline(),
|
||||
pc.plain("world"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 1, offset: 1 });
|
||||
expect(lineIndex).toBe(1);
|
||||
|
@ -102,7 +102,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
pc.newline(),
|
||||
pc.newline(),
|
||||
pc.plain("world"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 3, offset: 0 });
|
||||
expect(lineIndex).toBe(2);
|
||||
|
@ -117,7 +117,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
pc.plain("hello"),
|
||||
pc.userPill("Alice", "@alice:hs.tld"),
|
||||
pc.plain("!"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 1, offset: 0 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -130,7 +130,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
pc.plain("hello"),
|
||||
pc.userPill("Alice", "@alice:hs.tld"),
|
||||
pc.plain("!"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 1, offset: 2 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -141,7 +141,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const pc = createPartCreator();
|
||||
const model = new EditorModel([
|
||||
pc.userPill("Alice", "@alice:hs.tld"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 0, offset: 0 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -153,7 +153,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const pc = createPartCreator();
|
||||
const model = new EditorModel([
|
||||
pc.userPill("Alice", "@alice:hs.tld"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 0, offset: 1 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -166,7 +166,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const model = new EditorModel([
|
||||
pc.userPill("Alice", "@alice:hs.tld"),
|
||||
pc.userPill("Bob", "@bob:hs.tld"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 0, offset: 1 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -179,7 +179,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const model = new EditorModel([
|
||||
pc.userPill("Alice", "@alice:hs.tld"),
|
||||
pc.userPill("Bob", "@bob:hs.tld"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 1, offset: 0 });
|
||||
expect(lineIndex).toBe(0);
|
||||
|
@ -192,7 +192,7 @@ describe('editor/caret: DOM position for caret', function() {
|
|||
const model = new EditorModel([
|
||||
pc.userPill("Alice", "@alice:hs.tld"),
|
||||
pc.userPill("Bob", "@bob:hs.tld"),
|
||||
]);
|
||||
], pc);
|
||||
const { offset, lineIndex, nodeIndex } =
|
||||
getLineAndNodePosition(model, { index: 1, offset: 1 });
|
||||
expect(lineIndex).toBe(0);
|
|
@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
import { MatrixEvent } from 'matrix-js-sdk/src/matrix';
|
||||
|
||||
import { parseEvent } from "../../src/editor/deserialize";
|
||||
import { createPartCreator } from "./mock";
|
||||
|
@ -28,7 +29,7 @@ function htmlMessage(formattedBody, msgtype = "m.text") {
|
|||
formatted_body: formattedBody,
|
||||
};
|
||||
},
|
||||
};
|
||||
} as unknown as MatrixEvent;
|
||||
}
|
||||
|
||||
function textMessage(body, msgtype = "m.text") {
|
||||
|
@ -39,7 +40,7 @@ function textMessage(body, msgtype = "m.text") {
|
|||
body,
|
||||
};
|
||||
},
|
||||
};
|
||||
} as unknown as MatrixEvent;
|
||||
}
|
||||
|
||||
function mergeAdjacentParts(parts) {
|
|
@ -15,35 +15,37 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import HistoryManager, { MAX_STEP_LENGTH } from "../../src/editor/history";
|
||||
import EditorModel from "../../src/editor/model";
|
||||
import DocumentPosition from "../../src/editor/position";
|
||||
|
||||
describe('editor/history', function() {
|
||||
it('push, then undo', function() {
|
||||
const history = new HistoryManager();
|
||||
const parts = ["hello"];
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
const caret1 = {};
|
||||
const result1 = history.tryPush(model, caret1);
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
const caret1 = new DocumentPosition(0, 0);
|
||||
const result1 = history.tryPush(model, caret1, 'insertText', {});
|
||||
expect(result1).toEqual(true);
|
||||
parts[0] = "hello world";
|
||||
history.tryPush(model, {});
|
||||
history.tryPush(model, new DocumentPosition(0, 0), 'insertText', {});
|
||||
expect(history.canUndo()).toEqual(true);
|
||||
const undoState = history.undo(model);
|
||||
expect(undoState.caret).toEqual(caret1);
|
||||
expect(undoState.caret).toBe(caret1);
|
||||
expect(undoState.parts).toEqual(["hello"]);
|
||||
expect(history.canUndo()).toEqual(false);
|
||||
});
|
||||
it('push, undo, then redo', function() {
|
||||
const history = new HistoryManager();
|
||||
const parts = ["hello"];
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
history.tryPush(model, {});
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
history.tryPush(model, new DocumentPosition(0, 0), 'insertText', {});
|
||||
parts[0] = "hello world";
|
||||
const caret2 = {};
|
||||
history.tryPush(model, caret2);
|
||||
const caret2 = new DocumentPosition(0, 0);
|
||||
history.tryPush(model, caret2, 'insertText', {});
|
||||
history.undo(model);
|
||||
expect(history.canRedo()).toEqual(true);
|
||||
const redoState = history.redo();
|
||||
expect(redoState.caret).toEqual(caret2);
|
||||
expect(redoState.caret).toBe(caret2);
|
||||
expect(redoState.parts).toEqual(["hello world"]);
|
||||
expect(history.canRedo()).toEqual(false);
|
||||
expect(history.canUndo()).toEqual(true);
|
||||
|
@ -51,52 +53,53 @@ describe('editor/history', function() {
|
|||
it('push, undo, push, ensure you can`t redo', function() {
|
||||
const history = new HistoryManager();
|
||||
const parts = ["hello"];
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
history.tryPush(model, {});
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
history.tryPush(model, new DocumentPosition(0, 0), "insertText", {});
|
||||
parts[0] = "hello world";
|
||||
history.tryPush(model, {});
|
||||
history.tryPush(model, new DocumentPosition(0, 0), "insertText", {});
|
||||
history.undo(model);
|
||||
parts[0] = "hello world!!";
|
||||
history.tryPush(model, {});
|
||||
history.tryPush(model, new DocumentPosition(0, 0), "insertText", {});
|
||||
expect(history.canRedo()).toEqual(false);
|
||||
});
|
||||
it('not every keystroke stores a history step', function() {
|
||||
const history = new HistoryManager();
|
||||
const parts = ["hello"];
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
const firstCaret = {};
|
||||
history.tryPush(model, firstCaret);
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
const firstCaret = new DocumentPosition(0, 0);
|
||||
history.tryPush(model, firstCaret, "insertText", {});
|
||||
const diff = { added: "o" };
|
||||
let keystrokeCount = 0;
|
||||
do {
|
||||
parts[0] = parts[0] + diff.added;
|
||||
keystrokeCount += 1;
|
||||
} while (!history.tryPush(model, {}, "insertText", diff));
|
||||
} while (!history.tryPush(model, new DocumentPosition(0, 0), "insertText", diff));
|
||||
const undoState = history.undo(model);
|
||||
expect(undoState.caret).toEqual(firstCaret);
|
||||
expect(undoState.caret).toBe(firstCaret);
|
||||
expect(undoState.parts).toEqual(["hello"]);
|
||||
expect(history.canUndo()).toEqual(false);
|
||||
expect(keystrokeCount).toEqual(MAX_STEP_LENGTH + 1); // +1 before we type before checking
|
||||
});
|
||||
it('history step is added at word boundary', function() {
|
||||
const history = new HistoryManager();
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
const parts = ["h"];
|
||||
let diff = { added: "h" };
|
||||
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
|
||||
const blankCaret = new DocumentPosition(0, 0);
|
||||
expect(history.tryPush(model, blankCaret, "insertText", diff)).toEqual(false);
|
||||
diff = { added: "i" };
|
||||
parts[0] = "hi";
|
||||
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
|
||||
expect(history.tryPush(model, blankCaret, "insertText", diff)).toEqual(false);
|
||||
diff = { added: " " };
|
||||
parts[0] = "hi ";
|
||||
const spaceCaret = {};
|
||||
const spaceCaret = new DocumentPosition(1, 1);
|
||||
expect(history.tryPush(model, spaceCaret, "insertText", diff)).toEqual(true);
|
||||
diff = { added: "y" };
|
||||
parts[0] = "hi y";
|
||||
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
|
||||
expect(history.tryPush(model, blankCaret, "insertText", diff)).toEqual(false);
|
||||
diff = { added: "o" };
|
||||
parts[0] = "hi yo";
|
||||
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
|
||||
expect(history.tryPush(model, blankCaret, "insertText", diff)).toEqual(false);
|
||||
diff = { added: "u" };
|
||||
parts[0] = "hi you";
|
||||
|
||||
|
@ -108,11 +111,11 @@ describe('editor/history', function() {
|
|||
it('keystroke that didn\'t add a step can undo', function() {
|
||||
const history = new HistoryManager();
|
||||
const parts = ["hello"];
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
const firstCaret = {};
|
||||
history.tryPush(model, {});
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
const firstCaret = new DocumentPosition(0, 0);
|
||||
history.tryPush(model, firstCaret, "insertText", {});
|
||||
parts[0] = "helloo";
|
||||
const result = history.tryPush(model, {}, "insertText", { added: "o" });
|
||||
const result = history.tryPush(model, new DocumentPosition(0, 0), "insertText", { added: "o" });
|
||||
expect(result).toEqual(false);
|
||||
expect(history.canUndo()).toEqual(true);
|
||||
const undoState = history.undo(model);
|
||||
|
@ -122,25 +125,27 @@ describe('editor/history', function() {
|
|||
it('undo after keystroke that didn\'t add a step is able to redo', function() {
|
||||
const history = new HistoryManager();
|
||||
const parts = ["hello"];
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
history.tryPush(model, {});
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
history.tryPush(model, new DocumentPosition(0, 0), "insertText", {});
|
||||
parts[0] = "helloo";
|
||||
const caret = { last: true };
|
||||
const caret = new DocumentPosition(1, 1);
|
||||
history.tryPush(model, caret, "insertText", { added: "o" });
|
||||
history.undo(model);
|
||||
expect(history.canRedo()).toEqual(true);
|
||||
const redoState = history.redo();
|
||||
expect(redoState.caret).toEqual(caret);
|
||||
expect(redoState.caret).toBe(caret);
|
||||
expect(redoState.parts).toEqual(["helloo"]);
|
||||
});
|
||||
|
||||
it('overwriting text always stores a step', function() {
|
||||
const history = new HistoryManager();
|
||||
const parts = ["hello"];
|
||||
const model = { serializeParts: () => parts.slice() };
|
||||
const firstCaret = {};
|
||||
history.tryPush(model, firstCaret);
|
||||
const model = { serializeParts: () => parts.slice() } as unknown as EditorModel;
|
||||
const firstCaret = new DocumentPosition(0, 0);
|
||||
history.tryPush(model, firstCaret, 'insertText', {});
|
||||
const diff = { at: 1, added: "a", removed: "e" };
|
||||
const result = history.tryPush(model, {}, "insertText", diff);
|
||||
const secondCaret = new DocumentPosition(1, 1);
|
||||
const result = history.tryPush(model, secondCaret, "insertText", diff);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2019, 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -14,9 +14,17 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { Room, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import AutocompleteWrapperModel from "../../src/editor/autocomplete";
|
||||
import { PartCreator } from "../../src/editor/parts";
|
||||
|
||||
class MockAutoComplete {
|
||||
public _updateCallback;
|
||||
public _partCreator;
|
||||
public _completions;
|
||||
public _part;
|
||||
|
||||
constructor(updateCallback, partCreator, completions) {
|
||||
this._updateCallback = updateCallback;
|
||||
this._partCreator = partCreator;
|
||||
|
@ -52,20 +60,21 @@ class MockAutoComplete {
|
|||
|
||||
// MockClient & MockRoom are only used for avatars in room and user pills,
|
||||
// which is not tested
|
||||
class MockClient {
|
||||
getRooms() { return []; }
|
||||
getRoom() { return null; }
|
||||
}
|
||||
|
||||
class MockRoom {
|
||||
getMember() { return null; }
|
||||
}
|
||||
|
||||
export function createPartCreator(completions = []) {
|
||||
const autoCompleteCreator = (partCreator) => {
|
||||
return (updateCallback) => new MockAutoComplete(updateCallback, partCreator, completions);
|
||||
return (updateCallback) =>
|
||||
new MockAutoComplete(updateCallback, partCreator, completions) as unknown as AutocompleteWrapperModel;
|
||||
};
|
||||
return new PartCreator(new MockRoom(), new MockClient(), autoCompleteCreator);
|
||||
const room = new MockRoom() as unknown as Room;
|
||||
const client = {
|
||||
getRooms: jest.fn().mockReturnValue([]),
|
||||
getRoom: jest.fn().mockReturnValue(null),
|
||||
} as unknown as MatrixClient;
|
||||
return new PartCreator(room, client, autoCompleteCreator);
|
||||
}
|
||||
|
||||
export function createRenderer() {
|
|
@ -16,13 +16,14 @@ limitations under the License.
|
|||
|
||||
import EditorModel from "../../src/editor/model";
|
||||
import { createPartCreator, createRenderer } from "./mock";
|
||||
import DocumentOffset from "../../src/editor/offset";
|
||||
|
||||
describe('editor/model', function() {
|
||||
describe('plain text manipulation', function() {
|
||||
it('insert text into empty document', function() {
|
||||
const renderer = createRenderer();
|
||||
const model = new EditorModel([], createPartCreator(), renderer);
|
||||
model.update("hello", "insertText", { offset: 5, atNodeEnd: true });
|
||||
model.update("hello", "insertText", new DocumentOffset(5, true));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(0);
|
||||
expect(renderer.caret.offset).toBe(5);
|
||||
|
@ -34,7 +35,7 @@ describe('editor/model', function() {
|
|||
const renderer = createRenderer();
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain("hello")], pc, renderer);
|
||||
model.update("hello world", "insertText", { offset: 11, atNodeEnd: true });
|
||||
model.update("hello world", "insertText", new DocumentOffset(11, true));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(0);
|
||||
expect(renderer.caret.offset).toBe(11);
|
||||
|
@ -46,7 +47,7 @@ describe('editor/model', function() {
|
|||
const renderer = createRenderer();
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain("world")], pc, renderer);
|
||||
model.update("hello world", "insertText", { offset: 6, atNodeEnd: false });
|
||||
model.update("hello world", "insertText", new DocumentOffset(6, false));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(0);
|
||||
expect(renderer.caret.offset).toBe(6);
|
||||
|
@ -60,7 +61,7 @@ describe('editor/model', function() {
|
|||
const renderer = createRenderer();
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain("hello")], pc, renderer);
|
||||
model.update("hello\n", "insertText", { offset: 6, atNodeEnd: true });
|
||||
model.update("hello\n", "insertText", new DocumentOffset(6, true));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(1);
|
||||
expect(renderer.caret.offset).toBe(1);
|
||||
|
@ -74,7 +75,7 @@ describe('editor/model', function() {
|
|||
const renderer = createRenderer();
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain("hello")], pc, renderer);
|
||||
model.update("hello\n\n\nworld!", "insertText", { offset: 14, atNodeEnd: true });
|
||||
model.update("hello\n\n\nworld!", "insertText", new DocumentOffset(14, true));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(4);
|
||||
expect(renderer.caret.offset).toBe(6);
|
||||
|
@ -99,7 +100,7 @@ describe('editor/model', function() {
|
|||
pc.newline(),
|
||||
pc.plain("world"),
|
||||
], pc, renderer);
|
||||
model.update("hello\nwarm\nworld", "insertText", { offset: 10, atNodeEnd: true });
|
||||
model.update("hello\nwarm\nworld", "insertText", new DocumentOffset(10, true));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(2);
|
||||
expect(renderer.caret.offset).toBe(4);
|
||||
|
@ -124,7 +125,7 @@ describe('editor/model', function() {
|
|||
pc.plain("try "),
|
||||
pc.roomPill("#someroom"),
|
||||
], pc, renderer);
|
||||
model.update("try foo#someroom", "insertText", { offset: 7, atNodeEnd: false });
|
||||
model.update("try foo#someroom", "insertText", new DocumentOffset(7, false));
|
||||
expect(renderer.caret.index).toBe(0);
|
||||
expect(renderer.caret.offset).toBe(7);
|
||||
expect(model.parts.length).toBe(2);
|
||||
|
@ -141,7 +142,7 @@ describe('editor/model', function() {
|
|||
pc.roomPill("#someroom"),
|
||||
pc.plain("?"),
|
||||
], pc, renderer);
|
||||
model.update("try #some perhapsroom?", "insertText", { offset: 17, atNodeEnd: false });
|
||||
model.update("try #some perhapsroom?", "insertText", new DocumentOffset(17, false));
|
||||
expect(renderer.caret.index).toBe(2);
|
||||
expect(renderer.caret.offset).toBe(8);
|
||||
expect(model.parts.length).toBe(3);
|
||||
|
@ -156,7 +157,7 @@ describe('editor/model', function() {
|
|||
const renderer = createRenderer();
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.roomPill("#someroom")], pc, renderer);
|
||||
model.update("#someroo", "deleteContentBackward", { offset: 8, atNodeEnd: true });
|
||||
model.update("#someroo", "deleteContentBackward", new DocumentOffset(8, true));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(-1);
|
||||
expect(renderer.caret.offset).toBe(0);
|
||||
|
@ -166,7 +167,7 @@ describe('editor/model', function() {
|
|||
const renderer = createRenderer();
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.roomPill("#someroom")], pc, renderer);
|
||||
model.update("someroom", "deleteContentForward", { offset: 0, atNodeEnd: false });
|
||||
model.update("someroom", "deleteContentForward", new DocumentOffset(0, false));
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(-1);
|
||||
expect(renderer.caret.offset).toBe(0);
|
||||
|
@ -179,7 +180,7 @@ describe('editor/model', function() {
|
|||
const pc = createPartCreator([{ resourceId: "@alice", label: "Alice" }]);
|
||||
const model = new EditorModel([pc.plain("hello ")], pc, renderer);
|
||||
|
||||
model.update("hello @a", "insertText", { offset: 8, atNodeEnd: true });
|
||||
model.update("hello @a", "insertText", new DocumentOffset(8, true));
|
||||
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(1);
|
||||
|
@ -190,6 +191,8 @@ describe('editor/model', function() {
|
|||
expect(model.parts[1].type).toBe("pill-candidate");
|
||||
expect(model.parts[1].text).toBe("@a");
|
||||
|
||||
// this is a hacky mock function
|
||||
// @ts-ignore
|
||||
model.autoComplete.tryComplete(); // see MockAutoComplete
|
||||
|
||||
expect(renderer.count).toBe(2);
|
||||
|
@ -207,7 +210,7 @@ describe('editor/model', function() {
|
|||
const pc = createPartCreator([{ resourceId: "#riot-dev" }]);
|
||||
const model = new EditorModel([pc.plain("hello ")], pc, renderer);
|
||||
|
||||
model.update("hello #r", "insertText", { offset: 8, atNodeEnd: true });
|
||||
model.update("hello #r", "insertText", new DocumentOffset(8, true));
|
||||
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(renderer.caret.index).toBe(1);
|
||||
|
@ -218,6 +221,8 @@ describe('editor/model', function() {
|
|||
expect(model.parts[1].type).toBe("pill-candidate");
|
||||
expect(model.parts[1].text).toBe("#r");
|
||||
|
||||
// this is a hacky mock function
|
||||
// @ts-ignore
|
||||
model.autoComplete.tryComplete(); // see MockAutoComplete
|
||||
|
||||
expect(renderer.count).toBe(2);
|
||||
|
@ -235,9 +240,11 @@ describe('editor/model', function() {
|
|||
const pc = createPartCreator([{ resourceId: "#riot-dev" }]);
|
||||
const model = new EditorModel([pc.plain("hello ")], pc, renderer);
|
||||
|
||||
model.update("hello #r", "insertText", { offset: 8, atNodeEnd: true });
|
||||
model.update("hello #r", "insertText", new DocumentOffset(8, true));
|
||||
// this is a hacky mock function
|
||||
// @ts-ignore
|
||||
model.autoComplete.tryComplete(); // see MockAutoComplete
|
||||
model.update("hello #riot-dev!!", "insertText", { offset: 17, atNodeEnd: true });
|
||||
model.update("hello #riot-dev!!", "insertText", new DocumentOffset(17, true));
|
||||
|
||||
expect(renderer.count).toBe(3);
|
||||
expect(renderer.caret.index).toBe(2);
|
||||
|
@ -256,7 +263,7 @@ describe('editor/model', function() {
|
|||
const pc = createPartCreator([{ resourceId: "#define-room" }]);
|
||||
const model = new EditorModel([pc.plain("try ")], pc, renderer);
|
||||
|
||||
model.update("try #define", "insertFromPaste", { offset: 11, atNodeEnd: true });
|
||||
model.update("try #define", "insertFromPaste", new DocumentOffset(11, true));
|
||||
|
||||
expect(model.autoComplete).toBeFalsy();
|
||||
expect(renderer.caret.index).toBe(0);
|
||||
|
@ -271,7 +278,7 @@ describe('editor/model', function() {
|
|||
const pc = createPartCreator([{ resourceId: "#define-room" }]);
|
||||
const model = new EditorModel([pc.plain("try ")], pc, renderer);
|
||||
|
||||
model.update("try #define", "insertFromDrop", { offset: 11, atNodeEnd: true });
|
||||
model.update("try #define", "insertFromDrop", new DocumentOffset(11, true));
|
||||
|
||||
expect(model.autoComplete).toBeFalsy();
|
||||
expect(renderer.caret.index).toBe(0);
|
||||
|
@ -286,14 +293,14 @@ describe('editor/model', function() {
|
|||
const pc = createPartCreator([{ resourceId: "#room:server" }]);
|
||||
const model = new EditorModel([], pc, renderer);
|
||||
|
||||
model.update("#roo", "insertText", { offset: 4, atNodeEnd: true });
|
||||
model.update("#roo", "insertText", new DocumentOffset(4, true));
|
||||
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(model.parts.length).toBe(1);
|
||||
expect(model.parts[0].type).toBe("pill-candidate");
|
||||
expect(model.parts[0].text).toBe("#roo");
|
||||
|
||||
model.update("#room:s", "insertText", { offset: 7, atNodeEnd: true });
|
||||
model.update("#room:s", "insertText", new DocumentOffset(7, true));
|
||||
|
||||
expect(renderer.count).toBe(2);
|
||||
expect(model.parts.length).toBe(1);
|
||||
|
@ -306,7 +313,7 @@ describe('editor/model', function() {
|
|||
const pc = createPartCreator([{ resourceId: "@alice", label: "Alice" }]);
|
||||
const model = new EditorModel([], pc, renderer);
|
||||
|
||||
model.update("foo@a", "insertText", { offset: 5, atNodeEnd: true });
|
||||
model.update("foo@a", "insertText", new DocumentOffset(5, true));
|
||||
|
||||
expect(renderer.count).toBe(1);
|
||||
expect(model.parts.length).toBe(1);
|
|
@ -37,7 +37,7 @@ describe('editor/position', function() {
|
|||
it('move first position forwards in empty model', function() {
|
||||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||
const pos = model.positionForOffset(0, true);
|
||||
const pos2 = pos.forwardsWhile(() => true);
|
||||
const pos2 = pos.forwardsWhile(model, () => true);
|
||||
expect(pos).toBe(pos2);
|
||||
});
|
||||
it('move forwards within one part', function() {
|
|
@ -21,55 +21,55 @@ import { createPartCreator } from "./mock";
|
|||
describe('editor/serialize', function() {
|
||||
it('user pill turns message into html', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.userPill("Alice", "@alice:hs.tld")]);
|
||||
const model = new EditorModel([pc.userPill("Alice", "@alice:hs.tld")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("<a href=\"https://matrix.to/#/@alice:hs.tld\">Alice</a>");
|
||||
});
|
||||
it('room pill turns message into html', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.roomPill("#room:hs.tld")]);
|
||||
const model = new EditorModel([pc.roomPill("#room:hs.tld")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("<a href=\"https://matrix.to/#/#room:hs.tld\">#room:hs.tld</a>");
|
||||
});
|
||||
it('@room pill turns message into html', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.atRoomPill("@room")]);
|
||||
const model = new EditorModel([pc.atRoomPill("@room")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBeFalsy();
|
||||
});
|
||||
it('any markdown turns message into html', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain("*hello* world")]);
|
||||
const model = new EditorModel([pc.plain("*hello* world")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("<em>hello</em> world");
|
||||
});
|
||||
it('displaynames ending in a backslash work', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.userPill("Displayname\\", "@user:server")]);
|
||||
const model = new EditorModel([pc.userPill("Displayname\\", "@user:server")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("<a href=\"https://matrix.to/#/@user:server\">Displayname\\</a>");
|
||||
});
|
||||
it('displaynames containing an opening square bracket work', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.userPill("Displayname[[", "@user:server")]);
|
||||
const model = new EditorModel([pc.userPill("Displayname[[", "@user:server")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("<a href=\"https://matrix.to/#/@user:server\">Displayname[[</a>");
|
||||
});
|
||||
it('displaynames containing a closing square bracket work', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.userPill("Displayname]", "@user:server")]);
|
||||
const model = new EditorModel([pc.userPill("Displayname]", "@user:server")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("<a href=\"https://matrix.to/#/@user:server\">Displayname]</a>");
|
||||
});
|
||||
it('escaped markdown should not retain backslashes', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain('\\*hello\\* world')]);
|
||||
const model = new EditorModel([pc.plain('\\*hello\\* world')], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe('*hello* world');
|
||||
});
|
||||
it('escaped markdown should convert HTML entities', function() {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain('\\*hello\\* world < hey world!')]);
|
||||
const model = new EditorModel([pc.plain('\\*hello\\* world < hey world!')], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe('*hello* world < hey world!');
|
||||
});
|
Loading…
Reference in a new issue