FIX: Autocomplete incorrectly replacing text if used mid sentence.

* Adds test to document the behavior we were seeing.
This commit is contained in:
Alan Guo Xiang Tan 2022-01-18 13:13:04 +08:00
parent 232f840b60
commit 0aacd63436
2 changed files with 127 additions and 1 deletions

View File

@ -201,17 +201,22 @@ export default function (options) {
if (term) {
let text = me.val();
text =
text.substring(0, completeStart) +
(options.preserveKey ? options.key || "" : "") +
term +
" " +
text.substring(completeEnd + 1, text.length);
me.val(text);
let newCaretPos = completeStart + 1 + term.length;
if (options.key) {
newCaretPos++;
}
setCaretPosition(me[0], newCaretPos);
if (options && options.afterComplete) {
@ -487,6 +492,7 @@ export default function (options) {
if (options.key) {
if (options.onKeyUp && key !== options.key) {
let match = options.onKeyUp(me.val(), cp);
if (match) {
completeStart = cp - match[0].length;
completeEnd = completeStart + match[0].length - 1;
@ -543,26 +549,36 @@ export default function (options) {
if (!options.key) {
completeStart = 0;
}
if (e.which === keys.shift) {
return;
}
if (completeStart === null && e.which === keys.backSpace && options.key) {
c = caretPosition(me[0]);
c -= 1;
initial = c;
prevIsGood = true;
while (prevIsGood && c >= 0) {
c -= 1;
prev = me[0].value[c];
stopFound = prev === options.key;
if (stopFound) {
prev = me[0].value[c - 1];
if (
checkTriggerRule({ backSpace: true }) &&
(!prev || allowedLettersRegex.test(prev))
) {
completeStart = c;
term = me[0].value.substring(c + 1, initial);
if (!completeEnd) {
completeEnd = c + term.length;
}
updateAutoComplete(dataSource(term, options));
return true;
}
@ -640,11 +656,12 @@ export default function (options) {
return false;
case keys.backSpace:
autocompleteOptions = null;
completeEnd = cp;
cp--;
completeEnd = cp;
if (cp < 0) {
closeAutocomplete();
if (isInput) {
i = wrap.find("a:last");
if (i) {

View File

@ -0,0 +1,109 @@
import { test } from "qunit";
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
import { acceptance, query } from "discourse/tests/helpers/qunit-helpers";
import { setCaretPosition } from "discourse/lib/utilities";
const BACKSPACE_KEYCODE = 8;
acceptance("Composer - editor mentions", function (needs) {
needs.user();
needs.settings({ enable_mentions: true });
needs.pretender((server, helper) => {
server.get("/u/search/users", () => {
return helper.response({
users: [
{
username: "user",
name: "Some User",
avatar_template:
"https://avatars.discourse.org/v3/letter/t/41988e/{size}.png",
},
{
username: "user2",
name: "Some User",
avatar_template:
"https://avatars.discourse.org/v3/letter/t/41988e/{size}.png",
},
],
});
});
});
test("selecting user mentions", async function (assert) {
await visit("/");
await click("#create-topic");
// Emulate user pressing backspace in the editor
const editor = query(".d-editor-input");
await triggerKeyEvent(".d-editor-input", "keydown", "@".charCodeAt(0));
await fillIn(".d-editor-input", "abc @");
await setCaretPosition(editor, 5);
await triggerKeyEvent(".d-editor-input", "keyup", "@".charCodeAt(0));
await triggerKeyEvent(".d-editor-input", "keydown", "u".charCodeAt(0));
await fillIn(".d-editor-input", "abc @u");
await setCaretPosition(editor, 6);
await triggerKeyEvent(".d-editor-input", "keyup", "u".charCodeAt(0));
await click(".autocomplete.ac-user .selected");
assert.strictEqual(
query(".d-editor-input").value,
"abc @user ",
"should replace mention correctly"
);
});
test("selecting user mentions after deleting characters", async function (assert) {
await visit("/");
await click("#create-topic");
await fillIn(".d-editor-input", "abc @user a");
// Emulate user typing `@` and `u` in the editor
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
await fillIn(".d-editor-input", "abc @user ");
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
await fillIn(".d-editor-input", "abc @user");
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
await click(".autocomplete.ac-user .selected");
assert.strictEqual(
query(".d-editor-input").value,
"abc @user ",
"should replace mention correctly"
);
});
test("selecting user mentions after deleting characters mid sentence", async function (assert) {
await visit("/");
await click("#create-topic");
// Emulate user pressing backspace in the editor
const editor = query(".d-editor-input");
await fillIn(".d-editor-input", "abc @user 123");
await setCaretPosition(editor, 9);
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
await fillIn(".d-editor-input", "abc @use 123");
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
await setCaretPosition(editor, 8);
await triggerKeyEvent(".d-editor-input", "keydown", BACKSPACE_KEYCODE);
await fillIn(".d-editor-input", "abc @us 123");
await triggerKeyEvent(".d-editor-input", "keyup", BACKSPACE_KEYCODE);
await setCaretPosition(editor, 7);
await click(".autocomplete.ac-user .selected");
assert.strictEqual(
query(".d-editor-input").value,
"abc @user 123",
"should replace mention correctly"
);
});
});