This commit is contained in:
Half-Shot 2026-04-23 17:49:56 +01:00
parent 4c203d3842
commit 5a64f243dd
3 changed files with 117 additions and 5 deletions

View File

@ -168,14 +168,13 @@ export default class ThreadView extends React.Component<IProps, IState> {
switch (payload.action) {
case Action.ComposerInsert: {
const insertPayload = payload as ComposerInsertPayload;
const timelineRenderingType = insertPayload.timelineRenderingType;
if (insertPayload.composerType) break;
if (timelineRenderingType !== TimelineRenderingType.Thread) break;
if (insertPayload.timelineRenderingType !== TimelineRenderingType.Thread) break;
// re-dispatch to the correct composer
dis.dispatch<ComposerInsertPayload>({
...insertPayload,
timelineRenderingType,
timelineRenderingType: TimelineRenderingType.Thread,
composerType: this.state.editState ? ComposerType.Edit : ComposerType.Send,
});
break;

View File

@ -1078,7 +1078,6 @@ describe("RoomView", () => {
describe("handles Action.ComposerInsert", () => {
it("redispatches an empty composerType, timelineRenderingType with the current state", async () => {
jest.spyOn(defaultDispatcher, "dispatch");
await mountRoomView();
const promise = untilDispatch((payload) => {
try {
@ -1100,7 +1099,6 @@ describe("RoomView", () => {
await promise;
});
it("redispatches an empty composerType with the current state", async () => {
jest.spyOn(defaultDispatcher, "dispatch");
await mountRoomView();
const promise = untilDispatch((payload) => {
try {
@ -1122,6 +1120,34 @@ describe("RoomView", () => {
} satisfies ComposerInsertPayload);
await promise;
});
it("ignores payloads with a timelineRenderingType != TimelineRenderingType.Thread", async () => {
await mountRoomView();
const promise = untilDispatch(
(payload) => {
try {
expect(payload).toStrictEqual({
action: Action.ComposerInsert,
text: "Hello world",
timelineRenderingType: TimelineRenderingType.Thread,
composerType: ComposerType.Send,
});
} catch {
return false;
}
return true;
},
defaultDispatcher,
500,
);
defaultDispatcher.dispatch({
action: Action.ComposerInsert,
text: "Hello world",
composerType: ComposerType.Send,
timelineRenderingType: TimelineRenderingType.Room,
viaTest: true,
} satisfies ComposerInsertPayload);
await expect(promise).rejects.toThrow();
});
});
describe("when there is a RoomView", () => {

View File

@ -34,6 +34,10 @@ import { getRoomContext } from "../../../test-utils/room";
import { mkMessage, stubClient } from "../../../test-utils/test-utils";
import { mkThread } from "../../../test-utils/threads";
import { ScopedRoomContextProvider } from "../../../../src/contexts/ScopedRoomContext.tsx";
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
import { untilDispatch } from "../../../test-utils/utilities.ts";
import { TimelineRenderingType } from "../../../../src/contexts/RoomContext.ts";
import { ComposerInsertPayload, ComposerType } from "../../../../src/dispatcher/payloads/ComposerInsertPayload.ts";
describe("ThreadView", () => {
const ROOM_ID = "!roomId:example.org";
@ -209,4 +213,87 @@ describe("ThreadView", () => {
metricsTrigger: undefined,
});
});
describe("handles Action.ComposerInsert", () => {
it("redispatches a payload of timelineRenderingType=Thread", async () => {
await getComponent();
const promise = untilDispatch((payload) => {
try {
expect(payload).toEqual({
action: Action.ComposerInsert,
text: "Hello world",
timelineRenderingType: TimelineRenderingType.Thread,
composerType: ComposerType.Send,
});
} catch {
return false;
}
return true;
}, defaultDispatcher);
defaultDispatcher.dispatch({
action: Action.ComposerInsert,
text: "Hello world",
timelineRenderingType: TimelineRenderingType.Thread,
} satisfies ComposerInsertPayload);
await promise;
});
it("ignores payloads with a composerType", async () => {
await getComponent();
const promise = untilDispatch(
(payload) => {
try {
expect(payload).toStrictEqual({
action: Action.ComposerInsert,
text: "Hello world",
timelineRenderingType: TimelineRenderingType.Thread,
composerType: ComposerType.Send,
});
} catch {
return false;
}
return true;
},
defaultDispatcher,
500,
);
defaultDispatcher.dispatch({
action: Action.ComposerInsert,
text: "Hello world",
composerType: ComposerType.Send,
timelineRenderingType: TimelineRenderingType.Thread,
// Ensure we don't accidentally pick up this emit by strictly checking above.
viaTest: true,
} satisfies ComposerInsertPayload);
await expect(promise).rejects.toThrow();
});
it("ignores payloads with a timelineRenderingType != TimelineRenderingType.Thread", async () => {
await getComponent();
const promise = untilDispatch(
(payload) => {
try {
expect(payload).toStrictEqual({
action: Action.ComposerInsert,
text: "Hello world",
timelineRenderingType: TimelineRenderingType.Thread,
composerType: ComposerType.Send,
});
} catch {
return false;
}
return true;
},
defaultDispatcher,
500,
);
defaultDispatcher.dispatch({
action: Action.ComposerInsert,
text: "Hello world",
composerType: ComposerType.Send,
timelineRenderingType: TimelineRenderingType.Room,
// Ensure we don't accidentally pick up this emit by strictly checking above.
viaTest: true,
} satisfies ComposerInsertPayload);
await expect(promise).rejects.toThrow();
});
});
});