mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-05 12:16:53 +02:00
Fix expand/collapse reply preview not showing in some cases (#31639)
* Fix expand/collapse reply preview not showing in some cases Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Move tests to appropriate place Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add comments Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
c078a596f9
commit
ddad82075a
@ -106,7 +106,13 @@ export default class ReplyChain extends React.Component<IProps, IState> {
|
||||
if (el) {
|
||||
const code: HTMLElement | null = el.querySelector("code");
|
||||
const isCodeEllipsisShown = code ? code.offsetHeight >= SHOW_EXPAND_QUOTE_PIXELS : false;
|
||||
const isElipsisShown = el.offsetHeight >= SHOW_EXPAND_QUOTE_PIXELS || isCodeEllipsisShown;
|
||||
const isElipsisShown =
|
||||
isCodeEllipsisShown ||
|
||||
el.offsetHeight >= SHOW_EXPAND_QUOTE_PIXELS ||
|
||||
// Check whether the body fits into it's scroll container
|
||||
el.clientHeight !== el.scrollHeight ||
|
||||
// Do the same for its children as the scroll container may be on them instead
|
||||
[...el.children].some((child) => child.clientHeight !== child.scrollHeight);
|
||||
if (isElipsisShown) {
|
||||
this.props.setQuoteExpanded(false);
|
||||
}
|
||||
|
||||
@ -1,81 +1,62 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
Copyright 2025 Element Creations Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import * as testUtils from "../../../../test-utils";
|
||||
import { getParentEventId } from "../../../../../src/utils/Reply";
|
||||
import React from "react";
|
||||
import { render, waitFor } from "jest-matrix-react";
|
||||
|
||||
import ReplyChain from "../../../../../src/components/views/elements/ReplyChain.tsx";
|
||||
import { mkEvent, stubClient, withClientContextRenderOptions } from "../../../../test-utils";
|
||||
|
||||
describe("ReplyChain", () => {
|
||||
describe("getParentEventId", () => {
|
||||
it("retrieves relation reply from unedited event", () => {
|
||||
const originalEventWithRelation = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n foo",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
event_id: "$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
},
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
it("should call setQuoteExpanded if chain is longer than 2 lines", async () => {
|
||||
// Jest/JSDOM won't set clientHeight/scrollHeight for us so we have to synthesise it
|
||||
jest.spyOn(Element.prototype, "clientHeight", "get").mockReturnValue(100);
|
||||
jest.spyOn(Element.prototype, "scrollHeight", "get").mockReturnValue(150);
|
||||
|
||||
expect(getParentEventId(originalEventWithRelation)).toStrictEqual(
|
||||
"$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
);
|
||||
const cli = stubClient();
|
||||
const { room_id: roomId } = await cli.createRoom({});
|
||||
const room = cli.getRoom(roomId)!;
|
||||
|
||||
const targetEv = mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
user: cli.getUserId()!,
|
||||
room: roomId,
|
||||
id: "$event1",
|
||||
content: {
|
||||
body: "A\nB\nC",
|
||||
msgtype: "m.text",
|
||||
},
|
||||
});
|
||||
jest.spyOn(room, "findEventById").mockReturnValue(targetEv);
|
||||
|
||||
it("retrieves relation reply from original event when edited", () => {
|
||||
const originalEventWithRelation = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n foo",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
event_id: "$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
},
|
||||
const parentEv = mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
user: cli.getUserId()!,
|
||||
room: roomId,
|
||||
id: "$event2",
|
||||
content: {
|
||||
"body": "Reply",
|
||||
"msgtype": "m.text",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
event_id: "$event1",
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
const editEvent = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n * foo bar",
|
||||
"m.new_content": {
|
||||
msgtype: "m.text",
|
||||
body: "foo bar",
|
||||
},
|
||||
"m.relates_to": {
|
||||
rel_type: "m.replace",
|
||||
event_id: originalEventWithRelation.getId(),
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
// The edit replaces the original event
|
||||
originalEventWithRelation.makeReplaced(editEvent);
|
||||
|
||||
// The relation should be pulled from the original event
|
||||
expect(getParentEventId(originalEventWithRelation)).toStrictEqual(
|
||||
"$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
);
|
||||
},
|
||||
});
|
||||
const setQuoteExpanded = jest.fn();
|
||||
const { asFragment } = render(
|
||||
<ReplyChain parentEv={parentEv} setQuoteExpanded={setQuoteExpanded} />,
|
||||
withClientContextRenderOptions(cli),
|
||||
);
|
||||
|
||||
await waitFor(() => expect(setQuoteExpanded).toHaveBeenCalledWith(false));
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`ReplyChain should call setQuoteExpanded if chain is longer than 2 lines 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_ReplyChain_wrapper"
|
||||
>
|
||||
<div />
|
||||
<div>
|
||||
<blockquote
|
||||
class="mx_ReplyChain mx_ReplyChain_color2"
|
||||
>
|
||||
<div
|
||||
class="mx_ReplyTile"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
<div
|
||||
class="mx_ReplyTile_sender"
|
||||
>
|
||||
<span
|
||||
class="_avatar_zysgz_8 mx_BaseAvatar _avatar-imageless_zysgz_55"
|
||||
data-color="2"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 16px;"
|
||||
title="@userId:matrix.org"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
<div
|
||||
class="mx_DisambiguatedProfile"
|
||||
>
|
||||
<span
|
||||
class="mx_Username_color2 mx_DisambiguatedProfile_displayName"
|
||||
dir="auto"
|
||||
>
|
||||
@userId:matrix.org
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_MTextBody mx_EventTile_content"
|
||||
>
|
||||
<div
|
||||
class="mx_EventTile_body translate"
|
||||
dir="auto"
|
||||
>
|
||||
A
|
||||
B
|
||||
C
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
@ -8,8 +8,8 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { getParentEventId, shouldDisplayReply, stripHTMLReply, stripPlainReply } from "../../src/utils/Reply";
|
||||
import { mkEvent, stubClient } from "../test-utils";
|
||||
import { getParentEventId, shouldDisplayReply, stripHTMLReply, stripPlainReply } from "../../../src/utils/Reply";
|
||||
import { mkEvent, stubClient } from "../../test-utils";
|
||||
|
||||
// don't litter test console with logs
|
||||
jest.mock("matrix-js-sdk/src/logger");
|
||||
@ -59,6 +59,51 @@ describe("Reply", () => {
|
||||
|
||||
expect(getParentEventId(event)).toBe("$event1");
|
||||
});
|
||||
|
||||
it("returns id of relation reply from original event when edited", () => {
|
||||
const originalEventWithRelation = mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n foo",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
event_id: "$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
},
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
const editEvent = mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n * foo bar",
|
||||
"m.new_content": {
|
||||
msgtype: "m.text",
|
||||
body: "foo bar",
|
||||
},
|
||||
"m.relates_to": {
|
||||
rel_type: "m.replace",
|
||||
event_id: originalEventWithRelation.getId(),
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
// The edit replaces the original event
|
||||
originalEventWithRelation.makeReplaced(editEvent);
|
||||
|
||||
// The relation should be pulled from the original event
|
||||
expect(getParentEventId(originalEventWithRelation)).toStrictEqual(
|
||||
"$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("stripPlainReply", () => {
|
||||
Loading…
x
Reference in New Issue
Block a user