Include the url preview bundle field in the devtools timeline event editor (#34289)

* added urlpreview field in event editor

* oxfmt

* claude wrote test!

* handled reviews

* oxlint fix

* formatting

* removed useless stubclient
This commit is contained in:
Sirius
2026-07-20 09:17:51 +00:00
committed by GitHub
parent d254b41eaf
commit 63eaba6b07
2 changed files with 72 additions and 28 deletions
@@ -199,6 +199,9 @@ export const TimelineEventEditor: React.FC<IEditorProps> = ({ mxEvent, onBack })
rel_type: "m.replace",
event_id: getBaseEventId(mxEvent),
},
...("com.beeper.linkpreviews" in originalContent
? { "com.beeper.linkpreviews": originalContent["com.beeper.linkpreviews"] }
: {}),
};
defaultContent = stringify(newContent);
@@ -8,54 +8,95 @@ Please see LICENSE files in the repository root for full details.
import React from "react";
import { render } from "jest-matrix-react";
import { Room, PendingEventOrdering } from "matrix-js-sdk/src/matrix";
import {
Room,
PendingEventOrdering,
EventType,
MsgType,
type MatrixClient,
type MatrixEvent,
} from "matrix-js-sdk/src/matrix";
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
import { MatrixClientPeg } from "../../../../../../src/MatrixClientPeg";
import { stubClient } from "../../../../../test-utils";
import { createTestClient, mkEvent } from "../../../../../test-utils";
import { DevtoolsContext } from "../../../../../../src/components/views/dialogs/devtools/BaseTool";
import { TimelineEventEditor } from "../../../../../../src/components/views/dialogs/devtools/Event";
describe("<EventEditor />", () => {
beforeEach(() => {
stubClient();
});
it("should render", () => {
const cli = MatrixClientPeg.safeGet();
const { asFragment } = render(
function renderTimelineEventEditor(
cli: MatrixClient,
{ mxEvent, threadRootId }: { mxEvent?: MatrixEvent; threadRootId?: string } = {},
): ReturnType<typeof render> {
function Wrapper({ children }: { children: React.ReactNode }): React.ReactNode {
return (
<MatrixClientContext.Provider value={cli}>
<DevtoolsContext.Provider
value={{
room: new Room("!roomId", cli, "@alice:example.com", {
pendingEventOrdering: PendingEventOrdering.Detached,
}),
threadRootId,
}}
>
<TimelineEventEditor onBack={() => {}} />
{children}
</DevtoolsContext.Provider>
</MatrixClientContext.Provider>,
</MatrixClientContext.Provider>
);
}
return render(<TimelineEventEditor mxEvent={mxEvent} onBack={() => {}} />, { wrapper: Wrapper });
}
describe("<EventEditor />", () => {
it("should render", () => {
const cli = createTestClient();
const { asFragment } = renderTimelineEventEditor(cli);
expect(asFragment()).toMatchSnapshot();
});
it("should preserve the com.beeper.linkpreviews field when editing an event", () => {
const cli = createTestClient();
const linkPreviews = [{ "og:title": "Example", "matrix:image:size": 1234, "og:url": "https://example.com" }];
const mxEvent = mkEvent({
event: true,
type: EventType.RoomMessage,
room: "!roomId",
user: "@alice:example.com",
content: {
"body": "https://example.com",
"msgtype": MsgType.Text,
"com.beeper.linkpreviews": linkPreviews,
},
});
const { getByLabelText } = renderTimelineEventEditor(cli, { mxEvent });
const content = getByLabelText("Event Content") as HTMLTextAreaElement;
expect(JSON.parse(content.value)["com.beeper.linkpreviews"]).toEqual(linkPreviews);
});
it("should omit the com.beeper.linkpreviews field when the edited event has none", () => {
const cli = createTestClient();
const mxEvent = mkEvent({
event: true,
type: EventType.RoomMessage,
room: "!roomId",
user: "@alice:example.com",
content: {
body: "hello world",
msgtype: MsgType.Text,
},
});
const { getByLabelText } = renderTimelineEventEditor(cli, { mxEvent });
const content = getByLabelText("Event Content") as HTMLTextAreaElement;
expect(JSON.parse(content.value)).not.toHaveProperty("com.beeper.linkpreviews");
});
describe("thread context", () => {
it("should pre-populate a thread relationship", () => {
const cli = MatrixClientPeg.safeGet();
const { asFragment } = render(
<MatrixClientContext.Provider value={cli}>
<DevtoolsContext.Provider
value={{
room: new Room("!roomId", cli, "@alice:example.com", {
pendingEventOrdering: PendingEventOrdering.Detached,
}),
threadRootId: "$this_is_a_thread_id",
}}
>
<TimelineEventEditor onBack={() => {}} />
</DevtoolsContext.Provider>
</MatrixClientContext.Provider>,
);
const cli = createTestClient();
const { asFragment } = renderTimelineEventEditor(cli, {
threadRootId: "$this_is_a_thread_id",
});
expect(asFragment()).toMatchSnapshot();
});
});