From 5bc8f87144b7fe273259c3e5031446d7d07e4b35 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 28 Feb 2022 14:03:08 -0500 Subject: [PATCH 01/13] Hide unpinnable pinned messages in more cases Signed-off-by: Robin Townsend --- src/components/views/right_panel/PinnedMessagesCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/right_panel/PinnedMessagesCard.tsx b/src/components/views/right_panel/PinnedMessagesCard.tsx index 7e4bc3a7ae6..69f27d0546f 100644 --- a/src/components/views/right_panel/PinnedMessagesCard.tsx +++ b/src/components/views/right_panel/PinnedMessagesCard.tsx @@ -99,7 +99,7 @@ const PinnedMessagesCard = ({ room, onClose }: IProps) => { const promises = pinnedEventIds.map(async eventId => { const timelineSet = room.getUnfilteredTimelineSet(); const localEvent = timelineSet?.getTimelineForEvent(eventId)?.getEvents().find(e => e.getId() === eventId); - if (localEvent) return localEvent; + if (localEvent && PinningUtils.isPinnable(event)) return localEvent; try { const evJson = await cli.fetchRoomEvent(room.roomId, eventId); From f4dad43b27a0d1293958a9a50b574cfd1649700e Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 28 Feb 2022 14:13:25 -0500 Subject: [PATCH 02/13] Fix typo Signed-off-by: Robin Townsend --- src/components/views/right_panel/PinnedMessagesCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/right_panel/PinnedMessagesCard.tsx b/src/components/views/right_panel/PinnedMessagesCard.tsx index 69f27d0546f..e221dd0ce65 100644 --- a/src/components/views/right_panel/PinnedMessagesCard.tsx +++ b/src/components/views/right_panel/PinnedMessagesCard.tsx @@ -99,7 +99,7 @@ const PinnedMessagesCard = ({ room, onClose }: IProps) => { const promises = pinnedEventIds.map(async eventId => { const timelineSet = room.getUnfilteredTimelineSet(); const localEvent = timelineSet?.getTimelineForEvent(eventId)?.getEvents().find(e => e.getId() === eventId); - if (localEvent && PinningUtils.isPinnable(event)) return localEvent; + if (localEvent && PinningUtils.isPinnable(localEvent)) return localEvent; try { const evJson = await cli.fetchRoomEvent(room.roomId, eventId); From 19fdbece1bec4d01cc43c1d429d56247a67e0a62 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 14:43:38 -0500 Subject: [PATCH 03/13] Test that unpinnable pinned messages get hidden Signed-off-by: Robin Townsend --- .../views/right_panel/PinnedMessagesCard.tsx | 2 +- .../right_panel/PinnedMessagesCard-test.tsx | 91 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 test/components/views/right_panel/PinnedMessagesCard-test.tsx diff --git a/src/components/views/right_panel/PinnedMessagesCard.tsx b/src/components/views/right_panel/PinnedMessagesCard.tsx index b74090449a0..1b110a76c32 100644 --- a/src/components/views/right_panel/PinnedMessagesCard.tsx +++ b/src/components/views/right_panel/PinnedMessagesCard.tsx @@ -99,7 +99,7 @@ const PinnedMessagesCard = ({ room, onClose }: IProps) => { const promises = pinnedEventIds.map(async eventId => { const timelineSet = room.getUnfilteredTimelineSet(); const localEvent = timelineSet?.getTimelineForEvent(eventId)?.getEvents().find(e => e.getId() === eventId); - if (localEvent && PinningUtils.isPinnable(localEvent)) return localEvent; + if (localEvent) return PinningUtils.isPinnable(localEvent) ? localEvent : null; try { // Fetch the event and latest edit in parallel diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx new file mode 100644 index 00000000000..23051216c4c --- /dev/null +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -0,0 +1,91 @@ +/* +Copyright 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. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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 React from "react"; +import { mount } from "enzyme"; +import { act } from "react-dom/test-utils"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { EventType } from "matrix-js-sdk/src/@types/event"; + +import "../../../skinned-sdk"; +import { stubClient, wrapInMatrixClientContext, mkStubRoom, mkEvent } from "../../../test-utils"; +import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; +import _PinnedMessagesCard from "../../../../src/components/views/right_panel/PinnedMessagesCard"; + +describe("", () => { + stubClient(); + const cli = MatrixClientPeg.get(); + cli.setRoomAccountData = () => {}; + const PinnedMessagesCard = wrapInMatrixClientContext(_PinnedMessagesCard); + + const mkRoom = (localPins: MatrixEvent[], nonLocalPins: MatrixEvent[]) => { + const pins = [...localPins, ...nonLocalPins]; + const room = mkStubRoom(); + + // Insert pin IDs into room state + const pinState = new MatrixEvent(mkEvent({ + type: EventType.RoomPinnedEvents, + content: { + pinned: pins.map(e => e.getId()), + }, + })); + room.currentState.getStateEvents.mockReturnValue(pinState); + + // Insert local pins into local timeline set + room.getUnfilteredTimelineSet = () => ({ + getTimelineForEvent: () => ({ + getEvents: () => localPins, + }), + }); + + // Return all pins over fetchRoomEvent + cli.fetchRoomEvent = (roomId, eventId) => pins.find(e => e.getId() === eventId); + + return room; + }; + + it("hides unpinnable events found in local timeline", async () => { + const pin = new MatrixEvent(mkEvent({ + type: EventType.RoomMessage, + content: {}, + })); + pin.isRedacted = () => true; // Redacted messages are unpinnable + + let pins; + await act(async () => { + pins = mount( {}} />); + // Wait a tick for state updates + await new Promise(resolve => setImmediate(resolve)); + }); + expect(pins.find("PinnedEventTile").length).toBe(0); + }); + + it("hides unpinnable events not found in local timeline", async () => { + const pin = new MatrixEvent(mkEvent({ + type: EventType.RoomMessage, + content: {}, + })); + pin.isRedacted = () => true; // Redacted messages are unpinnable + + let pins; + await act(async () => { + pins = mount( {}} />); + // Wait a tick for state updates + await new Promise(resolve => setImmediate(resolve)); + }); + expect(pins.find("PinnedEventTile").length).toBe(0); + }); +}); From ecb9c0bd886a21ce5f6e9e41611ab256f0b5998c Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 15:47:29 -0500 Subject: [PATCH 04/13] Fix cli.relations error in test Signed-off-by: Robin Townsend --- test/components/views/right_panel/PinnedMessagesCard-test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 23051216c4c..d4323e62936 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -29,6 +29,7 @@ describe("", () => { stubClient(); const cli = MatrixClientPeg.get(); cli.setRoomAccountData = () => {}; + cli.relations = jest.fn().mockReturnValue({ events: [] }); const PinnedMessagesCard = wrapInMatrixClientContext(_PinnedMessagesCard); const mkRoom = (localPins: MatrixEvent[], nonLocalPins: MatrixEvent[]) => { From 0527a02235f5a419ba39aef40f2386763f0e9dc5 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 15:47:45 -0500 Subject: [PATCH 05/13] Use event: true shortcut when calling mkEvent Signed-off-by: Robin Townsend --- .../views/right_panel/PinnedMessagesCard-test.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index d4323e62936..564aab1a5a2 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -37,12 +37,13 @@ describe("", () => { const room = mkStubRoom(); // Insert pin IDs into room state - const pinState = new MatrixEvent(mkEvent({ + const pinState = mkEvent({ + event: true, type: EventType.RoomPinnedEvents, content: { pinned: pins.map(e => e.getId()), }, - })); + }); room.currentState.getStateEvents.mockReturnValue(pinState); // Insert local pins into local timeline set @@ -59,10 +60,11 @@ describe("", () => { }; it("hides unpinnable events found in local timeline", async () => { - const pin = new MatrixEvent(mkEvent({ + const pin = mkEvent({ + event: true, type: EventType.RoomMessage, content: {}, - })); + }); pin.isRedacted = () => true; // Redacted messages are unpinnable let pins; @@ -75,10 +77,11 @@ describe("", () => { }); it("hides unpinnable events not found in local timeline", async () => { - const pin = new MatrixEvent(mkEvent({ + const pin = mkEvent({ + event: true, type: EventType.RoomMessage, content: {}, - })); + }); pin.isRedacted = () => true; // Redacted messages are unpinnable let pins; From e8b3d4293fc370db112a76d44a1c2d7d9efe7cbd Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 15:51:52 -0500 Subject: [PATCH 06/13] Use mockResolvedValue instead of mockReturnValue for async mock Signed-off-by: Robin Townsend --- test/components/views/right_panel/PinnedMessagesCard-test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 564aab1a5a2..034644e24ab 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -29,7 +29,7 @@ describe("", () => { stubClient(); const cli = MatrixClientPeg.get(); cli.setRoomAccountData = () => {}; - cli.relations = jest.fn().mockReturnValue({ events: [] }); + cli.relations = jest.fn().mockResolvedValue({ events: [] }); const PinnedMessagesCard = wrapInMatrixClientContext(_PinnedMessagesCard); const mkRoom = (localPins: MatrixEvent[], nonLocalPins: MatrixEvent[]) => { From dc938fe5cd7e2b29bba150f503a661d71e7dc0e4 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 16:33:54 -0500 Subject: [PATCH 07/13] Actually mock redacted messages correctly Signed-off-by: Robin Townsend --- .../views/right_panel/PinnedMessagesCard-test.tsx | 8 +++++--- test/test-utils/test-utils.ts | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 034644e24ab..01e01da3a61 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -54,18 +54,19 @@ describe("", () => { }); // Return all pins over fetchRoomEvent - cli.fetchRoomEvent = (roomId, eventId) => pins.find(e => e.getId() === eventId); + cli.fetchRoomEvent = (roomId, eventId) => pins.find(e => e.getId() === eventId)?.event; return room; }; it("hides unpinnable events found in local timeline", async () => { + // Redacted messages are unpinnable const pin = mkEvent({ event: true, type: EventType.RoomMessage, content: {}, + unsigned: { redacted_because: {} }, }); - pin.isRedacted = () => true; // Redacted messages are unpinnable let pins; await act(async () => { @@ -77,12 +78,13 @@ describe("", () => { }); it("hides unpinnable events not found in local timeline", async () => { + // Redacted messages are unpinnable const pin = mkEvent({ event: true, type: EventType.RoomMessage, content: {}, + unsigned: { redacted_because: {} }, }); - pin.isRedacted = () => true; // Redacted messages are unpinnable let pins; await act(async () => { diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index a894faf5500..747aa9ab1b9 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -172,6 +172,7 @@ export function mkEvent(opts: MakeEventProps): MatrixEvent { prev_content: opts.prev_content, event_id: "$" + Math.random() + "-" + Math.random(), origin_server_ts: opts.ts, + unsigned: opts.unsigned, }; if (opts.skey) { event.state_key = opts.skey; From 93a8011d7fd8bd68912598752f04e49d0546459a Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 17:51:20 -0500 Subject: [PATCH 08/13] Ensure that panel is updated before assertions are made Signed-off-by: Robin Townsend --- .../views/right_panel/PinnedMessagesCard-test.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 01e01da3a61..972465e873d 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -24,6 +24,7 @@ import "../../../skinned-sdk"; import { stubClient, wrapInMatrixClientContext, mkStubRoom, mkEvent } from "../../../test-utils"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import _PinnedMessagesCard from "../../../../src/components/views/right_panel/PinnedMessagesCard"; +import PinnedEventTile from "../../../../src/components/views/rooms/PinnedEventTile"; describe("", () => { stubClient(); @@ -73,8 +74,9 @@ describe("", () => { pins = mount( {}} />); // Wait a tick for state updates await new Promise(resolve => setImmediate(resolve)); + pins.update(); }); - expect(pins.find("PinnedEventTile").length).toBe(0); + expect(pins.find(PinnedEventTile).length).toBe(0); }); it("hides unpinnable events not found in local timeline", async () => { @@ -91,7 +93,8 @@ describe("", () => { pins = mount( {}} />); // Wait a tick for state updates await new Promise(resolve => setImmediate(resolve)); + pins.update(); }); - expect(pins.find("PinnedEventTile").length).toBe(0); + expect(pins.find(PinnedEventTile).length).toBe(0); }); }); From 9e2eb4660ea4a8cfb9e4f364e2eff8b770edad45 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 17:54:06 -0500 Subject: [PATCH 09/13] Test that pinned messages reflect edits correctly Signed-off-by: Robin Townsend --- .../right_panel/PinnedMessagesCard-test.tsx | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 972465e873d..163fba3d376 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -18,10 +18,16 @@ import React from "react"; import { mount } from "enzyme"; import { act } from "react-dom/test-utils"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; -import { EventType } from "matrix-js-sdk/src/@types/event"; +import { EventType, RelationType, MsgType } from "matrix-js-sdk/src/@types/event"; import "../../../skinned-sdk"; -import { stubClient, wrapInMatrixClientContext, mkStubRoom, mkEvent } from "../../../test-utils"; +import { + stubClient, + wrapInMatrixClientContext, + mkStubRoom, + mkEvent, + mkMessage, +} from "../../../test-utils"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import _PinnedMessagesCard from "../../../../src/components/views/right_panel/PinnedMessagesCard"; import PinnedEventTile from "../../../../src/components/views/rooms/PinnedEventTile"; @@ -35,7 +41,7 @@ describe("", () => { const mkRoom = (localPins: MatrixEvent[], nonLocalPins: MatrixEvent[]) => { const pins = [...localPins, ...nonLocalPins]; - const room = mkStubRoom(); + const room = mkStubRoom("!room:example.org"); // Insert pin IDs into room state const pinState = mkEvent({ @@ -97,4 +103,45 @@ describe("", () => { }); expect(pins.find(PinnedEventTile).length).toBe(0); }); + + it("accounts for edits", async () => { + const pin = mkMessage({ + event: true, + room: "!room:example.org", + user: "@alice:example.org", + msg: "Hello!", + }); + cli.relations.mockResolvedValue({ + events: [mkEvent({ + event: true, + type: EventType.RoomMessage, + room: "!room:example.org", + user: "@alice:example.org", + content: { + msgtype: MsgType.Text, + body: " * Hello again!", + "m.new_content": { + msgtype: MsgType.Text, + body: "Hello again!", + }, + "m.relates_to": { + rel_type: RelationType.Replace, + event_id: pin.getId(), + }, + }, + })], + }); + + let pins; + await act(async () => { + pins = mount( {}} />); + // Wait a tick for state updates + await new Promise(resolve => setImmediate(resolve)); + pins.update(); + }); + + const pinTile = pins.find(PinnedEventTile); + expect(pinTile.length).toBe(1); + expect(pinTile.find(".mx_EventTile_body").text()).toEqual("Hello again!"); + }); }); From ad2ca3e377f9e14027caefb124efe69a606301b6 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 17:54:41 -0500 Subject: [PATCH 10/13] Fix warning about missing date Signed-off-by: Robin Townsend --- test/test-utils/test-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 747aa9ab1b9..0aa4dbdc343 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -171,7 +171,7 @@ export function mkEvent(opts: MakeEventProps): MatrixEvent { content: opts.content, prev_content: opts.prev_content, event_id: "$" + Math.random() + "-" + Math.random(), - origin_server_ts: opts.ts, + origin_server_ts: opts.ts ?? 0, unsigned: opts.unsigned, }; if (opts.skey) { From 312949dc0cc10229c0f4d3461dbd4ca2012fad55 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 18:24:19 -0500 Subject: [PATCH 11/13] Move calls to update out of act They don't need to be there. Signed-off-by: Robin Townsend --- test/components/views/right_panel/PinnedMessagesCard-test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 972465e873d..3c0fb73aa12 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -74,8 +74,8 @@ describe("", () => { pins = mount( {}} />); // Wait a tick for state updates await new Promise(resolve => setImmediate(resolve)); - pins.update(); }); + pins.update(); expect(pins.find(PinnedEventTile).length).toBe(0); }); @@ -93,8 +93,8 @@ describe("", () => { pins = mount( {}} />); // Wait a tick for state updates await new Promise(resolve => setImmediate(resolve)); - pins.update(); }); + pins.update(); expect(pins.find(PinnedEventTile).length).toBe(0); }); }); From ef6be4216e110512789326d55f8dc09498dfab7e Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 18:25:24 -0500 Subject: [PATCH 12/13] Move calls to update out of act They don't need to be there. Signed-off-by: Robin Townsend --- test/components/views/right_panel/PinnedMessagesCard-test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 34c62445647..21dc5861cef 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -137,8 +137,8 @@ describe("", () => { pins = mount( {}} />); // Wait a tick for state updates await new Promise(resolve => setImmediate(resolve)); - pins.update(); }); + pins.update(); const pinTile = pins.find(PinnedEventTile); expect(pinTile.length).toBe(1); From 94efa24738d4d1bf0fbfdee70c6a34fc3e862c26 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 2 Mar 2022 18:37:19 -0500 Subject: [PATCH 13/13] Fix lint Signed-off-by: Robin Townsend --- test/components/views/right_panel/PinnedMessagesCard-test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index 21dc5861cef..511db660869 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -118,8 +118,8 @@ describe("", () => { room: "!room:example.org", user: "@alice:example.org", content: { - msgtype: MsgType.Text, - body: " * Hello again!", + "msgtype": MsgType.Text, + "body": " * Hello again!", "m.new_content": { msgtype: MsgType.Text, body: "Hello again!",