Skip to content

Commit

Permalink
Room and user mentions for plain text editor (#10665)
Browse files Browse the repository at this point in the history
* update useSuggestion

* update useSuggestion-tests

* add processMention tests

* add test

* add getMentionOrCommand tests

* change mock href for codeQL reasons

* fix TS issue in test

* add a big old cypress test

* fix lint error

* update comments

* reorganise functions in order of importance

* rename functions and variables

* add endOffset to return object

* fix failing tests

* update function names and comments

* update comment, remove delay

* update comments and early return

* nest mappedSuggestion inside Suggestion state and update test

* rename suggestion => suggestionData

* update comment

* add argument to findSuggestionInText

* make findSuggestionInText return mappedSuggestion

* fix TS error

* update comments and index check from === -1 to < 0

* tidy logic in increment functions

* rename variable

* Big refactor to address multiple comments, improve behaviour and add tests

* improve comments

* tidy up comment

* extend comment

* combine similar returns

* update comment

* remove single use variable

* fix comments
  • Loading branch information
alunturner authored and richvdh committed May 12, 2023
1 parent 6711e07 commit 6cff984
Show file tree
Hide file tree
Showing 3 changed files with 505 additions and 125 deletions.
77 changes: 77 additions & 0 deletions cypress/e2e/composer/composer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ limitations under the License.
*/

/// <reference types="cypress" />
import { EventType } from "matrix-js-sdk/src/@types/event";

import { HomeserverInstance } from "../../plugins/utils/homeserver";
import { SettingLevel } from "../../../src/settings/SettingLevel";
import { MatrixClient } from "../../global";

describe("Composer", () => {
let homeserver: HomeserverInstance;
Expand Down Expand Up @@ -181,6 +183,81 @@ describe("Composer", () => {
});
});

describe("Mentions", () => {
// TODO add tests for rich text mode

describe("Plain text mode", () => {
it("autocomplete behaviour tests", () => {
// Setup a private room so we have another user to mention
const otherUserName = "Bob";
let bobClient: MatrixClient;
cy.getBot(homeserver, {
displayName: otherUserName,
}).then((bob) => {
bobClient = bob;
});
// create DM with bob
cy.getClient().then(async (cli) => {
const bobRoom = await cli.createRoom({ is_direct: true });
await cli.invite(bobRoom.room_id, bobClient.getUserId());
await cli.setAccountData("m.direct" as EventType, {
[bobClient.getUserId()]: [bobRoom.room_id],
});
});

cy.viewRoomByName("Bob");

// Select plain text mode after composer is ready
cy.get("div[contenteditable=true]").should("exist");
cy.findByRole("button", { name: "Hide formatting" }).click();

// Typing a single @ does not display the autocomplete menu and contents
cy.findByRole("textbox").type("@");
cy.findByTestId("autocomplete-wrapper").should("be.empty");

// Entering the first letter of the other user's name opens the autocomplete...
cy.findByRole("textbox").type(otherUserName.slice(0, 1));
cy.findByTestId("autocomplete-wrapper")
.should("not.be.empty")
.within(() => {
// ...with the other user name visible, and clicking that username...
cy.findByText(otherUserName).should("exist").click();
});
// ...inserts the username into the composer
cy.findByRole("textbox").within(() => {
// TODO update this test when the mentions are inserted as pills, instead
// of as text
cy.findByText(otherUserName, { exact: false }).should("exist");
});

// Send the message to clear the composer
cy.findByRole("button", { name: "Send message" }).click();

// Typing an @, then other user's name, then trailing space closes the autocomplete
cy.findByRole("textbox").type(`@${otherUserName} `);
cy.findByTestId("autocomplete-wrapper").should("be.empty");

// Send the message to clear the composer
cy.findByRole("button", { name: "Send message" }).click();

// Moving the cursor back to an "incomplete" mention opens the autocomplete
cy.findByRole("textbox").type(`initial text @${otherUserName.slice(0, 1)} abc`);
cy.findByTestId("autocomplete-wrapper").should("be.empty");
// Move the cursor left by 4 to put it to: `@B| abc`, check autocomplete displays
cy.findByRole("textbox").type(`${"{leftArrow}".repeat(4)}`);
cy.findByTestId("autocomplete-wrapper").should("not.be.empty");

// Selecting the autocomplete option using Enter inserts it into the composer
cy.findByRole("textbox").type(`{Enter}`);
cy.findByRole("textbox").within(() => {
// TODO update this test when the mentions are inserted as pills, instead
// of as text
cy.findByText(otherUserName, { exact: false }).should("exist");
});
});
});
});

it("sends a message when you click send or press Enter", () => {
// Type a message
cy.get("div[contenteditable=true]").type("my message 0");
Expand Down
Loading

0 comments on commit 6cff984

Please sign in to comment.