Merge pull request #3247 from matrix-org/bwindels/editortests
Unit tests for new editor
This commit is contained in:
@@ -26,7 +26,7 @@ import {htmlSerializeIfNeeded, textSerialize} from '../../../editor/serialize';
|
||||
import {findEditableEvent} from '../../../utils/EventUtils';
|
||||
import {parseEvent} from '../../../editor/deserialize';
|
||||
import Autocomplete from '../rooms/Autocomplete';
|
||||
import {PartCreator} from '../../../editor/parts';
|
||||
import {PartCreator, autoCompleteCreator} from '../../../editor/parts';
|
||||
import {renderModel} from '../../../editor/render';
|
||||
import EditorStateTransfer from '../../../utils/EditorStateTransfer';
|
||||
import {MatrixClient} from 'matrix-js-sdk';
|
||||
@@ -303,8 +303,7 @@ export default class MessageEditor extends React.Component {
|
||||
const {editState} = this.props;
|
||||
const room = this._getRoom();
|
||||
const partCreator = new PartCreator(
|
||||
() => this._autocompleteRef,
|
||||
query => this.setState({query}),
|
||||
autoCompleteCreator(() => this._autocompleteRef, query => this.setState({query})),
|
||||
room,
|
||||
this.context.matrixClient,
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ export function setCaretPosition(editor, model, caretPosition) {
|
||||
sel.addRange(range);
|
||||
}
|
||||
|
||||
function getLineAndNodePosition(model, caretPosition) {
|
||||
export function getLineAndNodePosition(model, caretPosition) {
|
||||
const {parts} = model;
|
||||
const partIndex = caretPosition.index;
|
||||
const lineResult = findNodeInLineForPart(parts, partIndex);
|
||||
|
||||
@@ -25,16 +25,6 @@ function firstDiff(a, b) {
|
||||
return compareLen;
|
||||
}
|
||||
|
||||
function lastDiff(a, b) {
|
||||
const compareLen = Math.min(a.length, b.length);
|
||||
for (let i = 0; i < compareLen; ++i) {
|
||||
if (a[a.length - i] !== b[b.length - i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return compareLen;
|
||||
}
|
||||
|
||||
function diffStringsAtEnd(oldStr, newStr) {
|
||||
const len = Math.min(oldStr.length, newStr.length);
|
||||
const startInCommon = oldStr.substr(0, len) === newStr.substr(0, len);
|
||||
@@ -52,24 +42,25 @@ function diffStringsAtEnd(oldStr, newStr) {
|
||||
}
|
||||
}
|
||||
|
||||
// assumes only characters have been deleted at one location in the string, and none added
|
||||
export function diffDeletion(oldStr, newStr) {
|
||||
if (oldStr === newStr) {
|
||||
return {};
|
||||
}
|
||||
const firstDiffIdx = firstDiff(oldStr, newStr);
|
||||
const lastDiffIdx = oldStr.length - lastDiff(oldStr, newStr) + 1;
|
||||
return {at: firstDiffIdx, removed: oldStr.substring(firstDiffIdx, lastDiffIdx)};
|
||||
}
|
||||
|
||||
export function diffInsertion(oldStr, newStr) {
|
||||
const diff = diffDeletion(newStr, oldStr);
|
||||
if (diff.removed) {
|
||||
return {at: diff.at, added: diff.removed};
|
||||
} else {
|
||||
return diff;
|
||||
}
|
||||
const amount = oldStr.length - newStr.length;
|
||||
return {at: firstDiffIdx, removed: oldStr.substr(firstDiffIdx, amount)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates which string was added and removed around the caret position
|
||||
* @param {String} oldValue the previous value
|
||||
* @param {String} newValue the new value
|
||||
* @param {Number} caretPosition the position of the caret after `newValue` was applied.
|
||||
* @return {object} an object with `at` as the offset where characters were removed and/or added,
|
||||
* `added` with the added string (if any), and
|
||||
* `removed` with the removed string (if any)
|
||||
*/
|
||||
export function diffAtCaret(oldValue, newValue, caretPosition) {
|
||||
const diffLen = newValue.length - oldValue.length;
|
||||
const caretPositionBeforeInput = caretPosition - diffLen;
|
||||
|
||||
@@ -117,7 +117,8 @@ class BasePart {
|
||||
}
|
||||
}
|
||||
|
||||
class PlainPart extends BasePart {
|
||||
// exported for unit tests, should otherwise only be used through PartCreator
|
||||
export class PlainPart extends BasePart {
|
||||
acceptsInsertion(chr) {
|
||||
return chr !== "@" && chr !== "#" && chr !== ":" && chr !== "\n";
|
||||
}
|
||||
@@ -348,18 +349,24 @@ class PillCandidatePart extends PlainPart {
|
||||
}
|
||||
}
|
||||
|
||||
export class PartCreator {
|
||||
constructor(getAutocompleterComponent, updateQuery, room, client) {
|
||||
this._room = room;
|
||||
this._client = client;
|
||||
this._autoCompleteCreator = (updateCallback) => {
|
||||
export function autoCompleteCreator(updateQuery, getAutocompleterComponent) {
|
||||
return (partCreator) => {
|
||||
return (updateCallback) => {
|
||||
return new AutocompleteWrapperModel(
|
||||
updateCallback,
|
||||
getAutocompleterComponent,
|
||||
updateQuery,
|
||||
this,
|
||||
partCreator,
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export class PartCreator {
|
||||
constructor(autoCompleteCreator, room, client) {
|
||||
this._room = room;
|
||||
this._client = client;
|
||||
this._autoCompleteCreator = autoCompleteCreator(this);
|
||||
}
|
||||
|
||||
createPartForInput(input) {
|
||||
|
||||
@@ -56,15 +56,3 @@ export function textSerialize(model) {
|
||||
}
|
||||
}, "");
|
||||
}
|
||||
|
||||
export function requiresHtml(model) {
|
||||
return model.parts.some(part => {
|
||||
switch (part.type) {
|
||||
case "room-pill":
|
||||
case "user-pill":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user