From 3608d52c4aced8a1c3586d1284c9b078adfcbb4d Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Thu, 14 Sep 2023 13:36:15 +0200 Subject: [PATCH] Default intentional mentions (#11602) * Default intentional mentions * wait for autocomplete to settle before submitting edit * lint * Update strings --------- Co-authored-by: Kerry Archibald --- .../views/rooms/SendMessageComposer.tsx | 7 +- src/i18n/strings/en_EN.json | 1 - src/settings/Settings.tsx | 14 - test/ContentMessages-test.ts | 5 - .../components/structures/ThreadView-test.tsx | 1 + .../views/rooms/EditMessageComposer-test.tsx | 465 +++++++++--------- .../views/rooms/SendMessageComposer-test.tsx | 59 ++- .../rooms/VoiceRecordComposerTile-test.tsx | 5 - .../tabs/user/LabsUserSettingsTab-test.tsx | 42 +- 9 files changed, 266 insertions(+), 333 deletions(-) diff --git a/src/components/views/rooms/SendMessageComposer.tsx b/src/components/views/rooms/SendMessageComposer.tsx index 14d09fd83dc..3005b279512 100644 --- a/src/components/views/rooms/SendMessageComposer.tsx +++ b/src/components/views/rooms/SendMessageComposer.tsx @@ -90,10 +90,9 @@ export function attachMentions( replyToEvent: MatrixEvent | undefined, editedContent: IContent | null = null, ): void { - // If this feature is disabled, do nothing. - if (!SettingsStore.getValue("feature_intentional_mentions")) { - return; - } + // We always attach the mentions even if the home server doesn't yet support + // intentional mentions. This is safe because m.mentions is an additive change + // that should simply be ignored by incapable home servers. // The mentions property *always* gets included to disable legacy push rules. const mentions: IMentions = (content["m.mentions"] = {}); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3511f38b58d..e95f9ee7c55 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1151,7 +1151,6 @@ "voice_broadcast": "Voice broadcast", "rust_crypto": "Rust cryptography implementation", "hidebold": "Hide notification dot (only display counters badges)", - "intentional_mentions": "Enable intentional mentions", "ask_to_join": "Enable ask to join", "new_room_decoration_ui": "New room header & details interface", "beta_feature": "This is a beta feature", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index b5e9af4913b..c5f41653311 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -531,20 +531,6 @@ export const SETTINGS: { [setting: string]: ISetting } = { labsGroup: LabGroup.Rooms, default: false, }, - // MSC3952 intentional mentions support. - "feature_intentional_mentions": { - isFeature: true, - supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - displayName: _td("labs|intentional_mentions"), - labsGroup: LabGroup.Rooms, - default: false, - controller: new ServerSupportUnstableFeatureController( - "feature_intentional_mentions", - defaultWatchManager, - [["org.matrix.msc3952_intentional_mentions"]], - "v1.7", - ), - }, "feature_ask_to_join": { default: false, displayName: _td("labs|ask_to_join"), diff --git a/test/ContentMessages-test.ts b/test/ContentMessages-test.ts index d1a4ecf72de..a54ad29ab78 100644 --- a/test/ContentMessages-test.ts +++ b/test/ContentMessages-test.ts @@ -23,7 +23,6 @@ import ContentMessages, { UploadCanceledError, uploadFile } from "../src/Content import { doMaybeLocalRoomAction } from "../src/utils/local-room"; import { createTestClient, mkEvent } from "./test-utils"; import { BlurhashEncoder } from "../src/BlurhashEncoder"; -import SettingsStore from "../src/settings/SettingsStore"; jest.mock("matrix-encrypt-attachment", () => ({ encryptAttachment: jest.fn().mockResolvedValue({}) })); @@ -278,10 +277,6 @@ describe("ContentMessages", () => { }); it("properly handles replies", async () => { - jest.spyOn(SettingsStore, "getValue").mockImplementation( - (settingName) => settingName === "feature_intentional_mentions", - ); - mocked(client.uploadContent).mockResolvedValue({ content_uri: "mxc://server/file" }); const file = new File([], "fileName", { type: "image/jpeg" }); const replyToEvent = mkEvent({ diff --git a/test/components/structures/ThreadView-test.tsx b/test/components/structures/ThreadView-test.tsx index a27b1eead12..83eed5eb9d3 100644 --- a/test/components/structures/ThreadView-test.tsx +++ b/test/components/structures/ThreadView-test.tsx @@ -112,6 +112,7 @@ describe("ThreadView", () => { "rel_type": RelationType.Thread, }, "msgtype": MsgType.Text, + "m.mentions": {}, }; } diff --git a/test/components/views/rooms/EditMessageComposer-test.tsx b/test/components/views/rooms/EditMessageComposer-test.tsx index 89cb09dd727..fce34299f69 100644 --- a/test/components/views/rooms/EditMessageComposer-test.tsx +++ b/test/components/views/rooms/EditMessageComposer-test.tsx @@ -137,13 +137,15 @@ describe("", () => { ...editedEvent.getContent(), "body": " * original message + edit", "m.new_content": { - body: "original message + edit", - msgtype: "m.text", + "body": "original message + edit", + "msgtype": "m.text", + "m.mentions": {}, }, "m.relates_to": { event_id: editedEvent.getId(), rel_type: "m.replace", }, + "m.mentions": {}, }; expect(mockClient.sendMessage).toHaveBeenCalledWith(editedEvent.getRoomId()!, null, expectedBody); }); @@ -168,13 +170,15 @@ describe("", () => { "body": " * hello world", "msgtype": "m.text", "m.new_content": { - body: "hello world", - msgtype: "m.text", + "body": "hello world", + "msgtype": "m.text", + "m.mentions": {}, }, "m.relates_to": { event_id: editedEvent.getId(), rel_type: "m.replace", }, + "m.mentions": {}, }); }); @@ -191,15 +195,17 @@ describe("", () => { "format": "org.matrix.custom.html", "formatted_body": " * hello world", "m.new_content": { - body: "hello *world*", - msgtype: "m.text", - format: "org.matrix.custom.html", - formatted_body: "hello world", + "body": "hello *world*", + "msgtype": "m.text", + "format": "org.matrix.custom.html", + "formatted_body": "hello world", + "m.mentions": {}, }, "m.relates_to": { event_id: editedEvent.getId(), rel_type: "m.replace", }, + "m.mentions": {}, }); }); @@ -216,15 +222,17 @@ describe("", () => { "format": "org.matrix.custom.html", "formatted_body": " * blinks quickly", "m.new_content": { - body: "blinks __quickly__", - msgtype: "m.emote", - format: "org.matrix.custom.html", - formatted_body: "blinks quickly", + "body": "blinks __quickly__", + "msgtype": "m.emote", + "format": "org.matrix.custom.html", + "formatted_body": "blinks quickly", + "m.mentions": {}, }, "m.relates_to": { event_id: editedEvent.getId(), rel_type: "m.replace", }, + "m.mentions": {}, }); }); @@ -240,13 +248,15 @@ describe("", () => { "body": " * ✨sparkles✨", "msgtype": "m.emote", "m.new_content": { - body: "✨sparkles✨", - msgtype: "m.emote", + "body": "✨sparkles✨", + "msgtype": "m.emote", + "m.mentions": {}, }, "m.relates_to": { event_id: editedEvent.getId(), rel_type: "m.replace", }, + "m.mentions": {}, }); }); @@ -264,166 +274,246 @@ describe("", () => { "body": " * //dev/null is my favourite place", "msgtype": "m.text", "m.new_content": { - body: "//dev/null is my favourite place", - msgtype: "m.text", + "body": "//dev/null is my favourite place", + "msgtype": "m.text", + "m.mentions": {}, }, "m.relates_to": { event_id: editedEvent.getId(), rel_type: "m.replace", }, + "m.mentions": {}, }); }); }); - describe("with feature_intentional_mentions enabled", () => { - const mockSettings = (mockValues: Record = {}) => { - const defaultMockValues = { - feature_intentional_mentions: true, - }; - jest.spyOn(SettingsStore, "getValue") - .mockClear() - .mockImplementation((settingName) => { - return { ...defaultMockValues, ...mockValues }[settingName]; - }); - }; + describe("when message is not a reply", () => { + it("should attach an empty mentions object for a message with no mentions", async () => { + const editState = new EditorStateTransfer(editedEvent); + getComponent(editState); + const editContent = " + edit"; + await editText(editContent); - beforeEach(() => { - mockSettings(); + fireEvent.click(screen.getByText("Save")); + + const messageContent = mockClient.sendMessage.mock.calls[0][2]; + + // both content.mentions and new_content.mentions are empty + expect(messageContent["m.mentions"]).toEqual({}); + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({}); }); - describe("when message is not a reply", () => { - it("should attach an empty mentions object for a message with no mentions", async () => { - const editState = new EditorStateTransfer(editedEvent); - getComponent(editState); - const editContent = " + edit"; - await editText(editContent); + it("should retain mentions in the original message that are not removed by the edit", async () => { + const editState = new EditorStateTransfer(eventWithMentions); + getComponent(editState); + // Remove charlie from the message + const editContent = "{backspace}{backspace}friends"; + await editText(editContent); - fireEvent.click(screen.getByText("Save")); + fireEvent.click(screen.getByText("Save")); - const messageContent = mockClient.sendMessage.mock.calls[0][2]; + const messageContent = mockClient.sendMessage.mock.calls[0][2]; - // both content.mentions and new_content.mentions are empty - expect(messageContent["m.mentions"]).toEqual({}); - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({}); + // no new mentions were added, so nothing in top level mentions + expect(messageContent["m.mentions"]).toEqual({}); + // bob is still mentioned, charlie removed + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ + user_ids: ["@bob:server.org"], }); + }); - it("should retain mentions in the original message that are not removed by the edit", async () => { - const editState = new EditorStateTransfer(eventWithMentions); - getComponent(editState); - // Remove charlie from the message - const editContent = "{backspace}{backspace}friends"; - await editText(editContent); + it("should remove mentions that are removed by the edit", async () => { + const editState = new EditorStateTransfer(eventWithMentions); + getComponent(editState); + const editContent = "new message!"; + // clear the original message + await editText(editContent, true); - fireEvent.click(screen.getByText("Save")); + fireEvent.click(screen.getByText("Save")); - const messageContent = mockClient.sendMessage.mock.calls[0][2]; + const messageContent = mockClient.sendMessage.mock.calls[0][2]; - // no new mentions were added, so nothing in top level mentions - expect(messageContent["m.mentions"]).toEqual({}); - // bob is still mentioned, charlie removed - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ - user_ids: ["@bob:server.org"], - }); - }); + // no new mentions were added, so nothing in top level mentions + expect(messageContent["m.mentions"]).toEqual({}); + // bob is not longer mentioned in the edited message, so empty mentions in new_content + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({}); + }); + + it("should add mentions that were added in the edit", async () => { + const editState = new EditorStateTransfer(editedEvent); + getComponent(editState); + const editContent = " and @d"; + await editText(editContent); + + // wait for autocompletion to render + await screen.findByText("Dan"); + // submit autocomplete for mention + await editText("{enter}"); - it("should remove mentions that are removed by the edit", async () => { - const editState = new EditorStateTransfer(eventWithMentions); - getComponent(editState); - const editContent = "new message!"; - // clear the original message - await editText(editContent, true); + fireEvent.click(screen.getByText("Save")); - fireEvent.click(screen.getByText("Save")); + const messageContent = mockClient.sendMessage.mock.calls[0][2]; - const messageContent = mockClient.sendMessage.mock.calls[0][2]; + // new mention in the edit + expect(messageContent["m.mentions"]).toEqual({ + user_ids: ["@dan:server.org"], + }); + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ + user_ids: ["@dan:server.org"], + }); + }); - // no new mentions were added, so nothing in top level mentions - expect(messageContent["m.mentions"]).toEqual({}); - // bob is not longer mentioned in the edited message, so empty mentions in new_content - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({}); + it("should add and remove mentions from the edit", async () => { + const editState = new EditorStateTransfer(eventWithMentions); + getComponent(editState); + // Remove charlie from the message + await editText("{backspace}{backspace}"); + // and replace with @room + await editText("@d"); + // wait for autocompletion to render + await screen.findByText("Dan"); + // submit autocomplete for @dan mention + await editText("{enter}"); + + fireEvent.click(screen.getByText("Save")); + + const messageContent = mockClient.sendMessage.mock.calls[0][2]; + + // new mention in the edit + expect(messageContent["m.mentions"]).toEqual({ + user_ids: ["@dan:server.org"], + }); + // all mentions in the edited version of the event + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ + user_ids: ["@bob:server.org", "@dan:server.org"], }); + }); + }); + + describe("when message is replying", () => { + const originalEvent = mkEvent({ + type: "m.room.message", + user: "@ernie:test", + room: roomId, + content: { body: "original message", msgtype: "m.text" }, + event: true, + }); + + const replyEvent = mkEvent({ + type: "m.room.message", + user: "@bert:test", + room: roomId, + content: { + "body": "reply with plain message", + "msgtype": "m.text", + "m.relates_to": { + "m.in_reply_to": { + event_id: originalEvent.getId(), + }, + }, + "m.mentions": { + user_ids: [originalEvent.getSender()!], + }, + }, + event: true, + }); - it("should add mentions that were added in the edit", async () => { - const editState = new EditorStateTransfer(editedEvent); - getComponent(editState); - const editContent = " and @d"; - await editText(editContent); + const replyWithMentions = mkEvent({ + type: "m.room.message", + user: "@bert:test", + room: roomId, + content: { + "body": 'reply that mentions Bob', + "msgtype": "m.text", + "m.relates_to": { + "m.in_reply_to": { + event_id: originalEvent.getId(), + }, + }, + "m.mentions": { + user_ids: [ + // sender of event we replied to + originalEvent.getSender()!, + // mentions from this event + "@bob:server.org", + ], + }, + }, + event: true, + }); - // submit autocomplete for mention - await editText("{enter}"); + beforeEach(() => { + setupRoomWithEventsTimeline(room, [originalEvent, replyEvent]); + }); - fireEvent.click(screen.getByText("Save")); + it("should retain parent event sender in mentions when editing with plain text", async () => { + const editState = new EditorStateTransfer(replyEvent); + getComponent(editState); + const editContent = " + edit"; + await editText(editContent); - const messageContent = mockClient.sendMessage.mock.calls[0][2]; + fireEvent.click(screen.getByText("Save")); - // new mention in the edit - expect(messageContent["m.mentions"]).toEqual({ - user_ids: ["@dan:server.org"], - }); - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ - user_ids: ["@dan:server.org"], - }); - }); + const messageContent = mockClient.sendMessage.mock.calls[0][2]; - it("should add and remove mentions from the edit", async () => { - const editState = new EditorStateTransfer(eventWithMentions); - getComponent(editState); - // Remove charlie from the message - await editText("{backspace}{backspace}"); - // and replace with @room - await editText("@d"); - // submit autocomplete for @dan mention - await editText("{enter}"); - - fireEvent.click(screen.getByText("Save")); - - const messageContent = mockClient.sendMessage.mock.calls[0][2]; - - // new mention in the edit - expect(messageContent["m.mentions"]).toEqual({ - user_ids: ["@dan:server.org"], - }); - // all mentions in the edited version of the event - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ - user_ids: ["@bob:server.org", "@dan:server.org"], - }); + // no new mentions from edit + expect(messageContent["m.mentions"]).toEqual({}); + // edited reply still mentions the parent event sender + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ + user_ids: [originalEvent.getSender()], }); }); - describe("when message is replying", () => { - const originalEvent = mkEvent({ - type: "m.room.message", - user: "@ernie:test", - room: roomId, - content: { body: "original message", msgtype: "m.text" }, - event: true, + it("should retain parent event sender in mentions when adding a mention", async () => { + const editState = new EditorStateTransfer(replyEvent); + getComponent(editState); + await editText(" and @d"); + // wait for autocompletion to render + await screen.findByText("Dan"); + // submit autocomplete for @dan mention + await editText("{enter}"); + + fireEvent.click(screen.getByText("Save")); + + const messageContent = mockClient.sendMessage.mock.calls[0][2]; + + // new mention in edit + expect(messageContent["m.mentions"]).toEqual({ + user_ids: ["@dan:server.org"], }); + // edited reply still mentions the parent event sender + // plus new mention @dan + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ + user_ids: [originalEvent.getSender(), "@dan:server.org"], + }); + }); - const replyEvent = mkEvent({ - type: "m.room.message", - user: "@bert:test", - room: roomId, - content: { - "body": "reply with plain message", - "msgtype": "m.text", - "m.relates_to": { - "m.in_reply_to": { - event_id: originalEvent.getId(), - }, - }, - "m.mentions": { - user_ids: [originalEvent.getSender()!], - }, - }, - event: true, + it("should retain parent event sender in mentions when removing all mentions from content", async () => { + const editState = new EditorStateTransfer(replyWithMentions); + getComponent(editState); + // replace text to remove all mentions + await editText("no mentions here", true); + + fireEvent.click(screen.getByText("Save")); + + const messageContent = mockClient.sendMessage.mock.calls[0][2]; + + // no mentions in edit + expect(messageContent["m.mentions"]).toEqual({}); + // edited reply still mentions the parent event sender + // existing @bob mention removed + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ + user_ids: [originalEvent.getSender()], }); + }); - const replyWithMentions = mkEvent({ + it("should retain parent event sender in mentions when removing mention of said user", async () => { + const replyThatMentionsParentEventSender = mkEvent({ type: "m.room.message", user: "@bert:test", room: roomId, content: { - "body": 'reply that mentions Bob', + "body": `reply that mentions the sender of the message we replied to Ernie`, "msgtype": "m.text", "m.relates_to": { "m.in_reply_to": { @@ -434,114 +524,25 @@ describe("", () => { user_ids: [ // sender of event we replied to originalEvent.getSender()!, - // mentions from this event - "@bob:server.org", ], }, }, event: true, }); + const editState = new EditorStateTransfer(replyThatMentionsParentEventSender); + getComponent(editState); + // replace text to remove all mentions + await editText("no mentions here", true); - beforeEach(() => { - setupRoomWithEventsTimeline(room, [originalEvent, replyEvent]); - }); - - it("should retain parent event sender in mentions when editing with plain text", async () => { - const editState = new EditorStateTransfer(replyEvent); - getComponent(editState); - const editContent = " + edit"; - await editText(editContent); - - fireEvent.click(screen.getByText("Save")); - - const messageContent = mockClient.sendMessage.mock.calls[0][2]; - - // no new mentions from edit - expect(messageContent["m.mentions"]).toEqual({}); - // edited reply still mentions the parent event sender - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ - user_ids: [originalEvent.getSender()], - }); - }); - - it("should retain parent event sender in mentions when adding a mention", async () => { - const editState = new EditorStateTransfer(replyEvent); - getComponent(editState); - await editText(" and @d"); - // submit autocomplete for @dan mention - await editText("{enter}"); - - fireEvent.click(screen.getByText("Save")); - - const messageContent = mockClient.sendMessage.mock.calls[0][2]; - - // new mention in edit - expect(messageContent["m.mentions"]).toEqual({ - user_ids: ["@dan:server.org"], - }); - // edited reply still mentions the parent event sender - // plus new mention @dan - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ - user_ids: [originalEvent.getSender(), "@dan:server.org"], - }); - }); - - it("should retain parent event sender in mentions when removing all mentions from content", async () => { - const editState = new EditorStateTransfer(replyWithMentions); - getComponent(editState); - // replace text to remove all mentions - await editText("no mentions here", true); - - fireEvent.click(screen.getByText("Save")); + fireEvent.click(screen.getByText("Save")); - const messageContent = mockClient.sendMessage.mock.calls[0][2]; + const messageContent = mockClient.sendMessage.mock.calls[0][2]; - // no mentions in edit - expect(messageContent["m.mentions"]).toEqual({}); - // edited reply still mentions the parent event sender - // existing @bob mention removed - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ - user_ids: [originalEvent.getSender()], - }); - }); - - it("should retain parent event sender in mentions when removing mention of said user", async () => { - const replyThatMentionsParentEventSender = mkEvent({ - type: "m.room.message", - user: "@bert:test", - room: roomId, - content: { - "body": `reply that mentions the sender of the message we replied to Ernie`, - "msgtype": "m.text", - "m.relates_to": { - "m.in_reply_to": { - event_id: originalEvent.getId(), - }, - }, - "m.mentions": { - user_ids: [ - // sender of event we replied to - originalEvent.getSender()!, - ], - }, - }, - event: true, - }); - const editState = new EditorStateTransfer(replyThatMentionsParentEventSender); - getComponent(editState); - // replace text to remove all mentions - await editText("no mentions here", true); - - fireEvent.click(screen.getByText("Save")); - - const messageContent = mockClient.sendMessage.mock.calls[0][2]; - - // no mentions in edit - expect(messageContent["m.mentions"]).toEqual({}); - // edited reply still mentions the parent event sender - expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ - user_ids: [originalEvent.getSender()], - }); + // no mentions in edit + expect(messageContent["m.mentions"]).toEqual({}); + // edited reply still mentions the parent event sender + expect(messageContent["m.new_content"]["m.mentions"]).toEqual({ + user_ids: [originalEvent.getSender()], }); }); }); diff --git a/test/components/views/rooms/SendMessageComposer-test.tsx b/test/components/views/rooms/SendMessageComposer-test.tsx index 077f09fd35a..7d47af6b65b 100644 --- a/test/components/views/rooms/SendMessageComposer-test.tsx +++ b/test/components/views/rooms/SendMessageComposer-test.tsx @@ -39,7 +39,6 @@ import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalink import { mockPlatformPeg } from "../../../test-utils/platform"; import { doMaybeLocalRoomAction } from "../../../../src/utils/local-room"; import { addTextToComposer } from "../../../test-utils/composer"; -import SettingsStore from "../../../../src/settings/SettingsStore"; jest.mock("../../../../src/utils/local-room", () => ({ doMaybeLocalRoomAction: jest.fn(), @@ -97,8 +96,9 @@ describe("", () => { const content = createMessageContent("@alice:test", model, undefined, undefined, permalinkCreator); expect(content).toEqual({ - body: "hello world", - msgtype: "m.text", + "body": "hello world", + "msgtype": "m.text", + "m.mentions": {}, }); }); @@ -110,10 +110,11 @@ describe("", () => { const content = createMessageContent("@alice:test", model, undefined, undefined, permalinkCreator); expect(content).toEqual({ - body: "hello *world*", - msgtype: "m.text", - format: "org.matrix.custom.html", - formatted_body: "hello world", + "body": "hello *world*", + "msgtype": "m.text", + "format": "org.matrix.custom.html", + "formatted_body": "hello world", + "m.mentions": {}, }); }); @@ -125,10 +126,11 @@ describe("", () => { const content = createMessageContent("@alice:test", model, undefined, undefined, permalinkCreator); expect(content).toEqual({ - body: "blinks __quickly__", - msgtype: "m.emote", - format: "org.matrix.custom.html", - formatted_body: "blinks quickly", + "body": "blinks __quickly__", + "msgtype": "m.emote", + "format": "org.matrix.custom.html", + "formatted_body": "blinks quickly", + "m.mentions": {}, }); }); @@ -141,8 +143,9 @@ describe("", () => { const content = createMessageContent("@alice:test", model, undefined, undefined, permalinkCreator); expect(content).toEqual({ - body: "✨sparkles✨", - msgtype: "m.emote", + "body": "✨sparkles✨", + "msgtype": "m.emote", + "m.mentions": {}, }); }); @@ -155,23 +158,14 @@ describe("", () => { const content = createMessageContent("@alice:test", model, undefined, undefined, permalinkCreator); expect(content).toEqual({ - body: "/dev/null is my favourite place", - msgtype: "m.text", + "body": "/dev/null is my favourite place", + "msgtype": "m.text", + "m.mentions": {}, }); }); }); describe("attachMentions", () => { - beforeEach(() => { - jest.spyOn(SettingsStore, "getValue").mockImplementation( - (settingName) => settingName === "feature_intentional_mentions", - ); - }); - - afterEach(() => { - jest.spyOn(SettingsStore, "getValue").mockReset(); - }); - const partsCreator = createPartCreator(); it("no mentions", () => { @@ -488,8 +482,9 @@ describe("", () => { fireEvent.keyDown(container.querySelector(".mx_SendMessageComposer")!, { key: "Enter" }); expect(mockClient.sendMessage).toHaveBeenCalledWith("myfakeroom", null, { - body: "test message", - msgtype: MsgType.Text, + "body": "test message", + "msgtype": MsgType.Text, + "m.mentions": {}, }); }); @@ -507,8 +502,9 @@ describe("", () => { fireEvent.keyDown(container.querySelector(".mx_SendMessageComposer")!, { key: "Enter" }); expect(mockClient.sendMessage).toHaveBeenCalledWith("myfakeroom", null, { - body: "test message", - msgtype: MsgType.Text, + "body": "test message", + "msgtype": MsgType.Text, + "m.mentions": {}, }); expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: `effects.confetti` }); @@ -534,8 +530,9 @@ describe("", () => { fireEvent.keyDown(container.querySelector(".mx_SendMessageComposer")!, { key: "Enter" }); expect(mockClient.sendMessage).toHaveBeenCalledWith("myfakeroom", null, { - body: "test message", - msgtype: MsgType.Text, + "body": "test message", + "msgtype": MsgType.Text, + "m.mentions": {}, }); expect(defaultDispatcher.dispatch).not.toHaveBeenCalledWith({ action: `effects.confetti` }); diff --git a/test/components/views/rooms/VoiceRecordComposerTile-test.tsx b/test/components/views/rooms/VoiceRecordComposerTile-test.tsx index 6171fd6bd2c..72456f3c190 100644 --- a/test/components/views/rooms/VoiceRecordComposerTile-test.tsx +++ b/test/components/views/rooms/VoiceRecordComposerTile-test.tsx @@ -27,7 +27,6 @@ import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalink import { VoiceRecordingStore } from "../../../../src/stores/VoiceRecordingStore"; import { PlaybackClock } from "../../../../src/audio/PlaybackClock"; import { mkEvent } from "../../../test-utils"; -import SettingsStore from "../../../../src/settings/SettingsStore"; jest.mock("../../../../src/utils/local-room", () => ({ doMaybeLocalRoomAction: jest.fn(), @@ -103,10 +102,6 @@ describe("", () => { return fn(roomId); }, ); - - jest.spyOn(SettingsStore, "getValue").mockImplementation( - (settingName) => settingName === "feature_intentional_mentions", - ); }); describe("send", () => { diff --git a/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx b/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx index 63c11290bef..ac832b88b21 100644 --- a/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx +++ b/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx @@ -15,18 +15,11 @@ limitations under the License. */ import React from "react"; -import { render, screen, waitFor } from "@testing-library/react"; -import { defer } from "matrix-js-sdk/src/utils"; +import { render, screen } from "@testing-library/react"; import LabsUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/LabsUserSettingsTab"; import SettingsStore from "../../../../../../src/settings/SettingsStore"; -import { - getMockClientWithEventEmitter, - mockClientMethodsServer, - mockClientMethodsUser, -} from "../../../../../test-utils"; import SdkConfig from "../../../../../../src/SdkConfig"; -import MatrixClientBackedController from "../../../../../../src/settings/controllers/MatrixClientBackedController"; describe("", () => { const sdkConfigSpy = jest.spyOn(SdkConfig, "get"); @@ -36,12 +29,6 @@ describe("", () => { }; const getComponent = () => ; - const userId = "@alice:server.org"; - const cli = getMockClientWithEventEmitter({ - ...mockClientMethodsUser(userId), - ...mockClientMethodsServer(), - }); - const settingsValueSpy = jest.spyOn(SettingsStore, "getValue"); beforeEach(() => { @@ -73,31 +60,4 @@ describe("", () => { const labsSections = container.getElementsByClassName("mx_SettingsSubsection"); expect(labsSections).toHaveLength(9); }); - - it("allow setting a labs flag which requires unstable support once support is confirmed", async () => { - // enable labs - sdkConfigSpy.mockImplementation((configName) => configName === "show_labs_settings"); - - const deferred = defer(); - cli.doesServerSupportUnstableFeature.mockImplementation(async (featureName) => { - return featureName === "org.matrix.msc3952_intentional_mentions" ? deferred.promise : false; - }); - MatrixClientBackedController.matrixClient = cli; - - const { queryByText } = render(getComponent()); - - expect( - queryByText("Enable intentional mentions")! - .closest(".mx_SettingsFlag")! - .querySelector(".mx_AccessibleButton"), - ).toHaveAttribute("aria-disabled", "true"); - deferred.resolve(true); - await waitFor(() => { - expect( - queryByText("Enable intentional mentions")! - .closest(".mx_SettingsFlag")! - .querySelector(".mx_AccessibleButton"), - ).toHaveAttribute("aria-disabled", "false"); - }); - }); });