Skip to content

Commit 3863f5b

Browse files
committed
lint
1 parent e8152f8 commit 3863f5b

File tree

4 files changed

+242
-17
lines changed

4 files changed

+242
-17
lines changed

src/WidgetApi.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,9 @@ export class WidgetApi extends EventEmitter {
441441
roomId?: string,
442442
delay?: number,
443443
parentDelayId?: string,
444+
stickyDurationMs?: number,
444445
): Promise<ISendEventFromWidgetResponseData> {
445-
return this.sendEvent(eventType, undefined, content, roomId, delay, parentDelayId);
446+
return this.sendEvent(eventType, undefined, content, roomId, delay, parentDelayId, stickyDurationMs);
446447
}
447448

448449
public sendStateEvent(
@@ -518,19 +519,6 @@ export class WidgetApi extends EventEmitter {
518519
);
519520
}
520521

521-
/**
522-
* @experimental This currently relies on an unstable MSC (MSC4157).
523-
*/
524-
public sendStickyEvent(delayId: string): Promise<IUpdateDelayedEventFromWidgetResponseData> {
525-
return this.transport.send<IUpdateDelayedEventFromWidgetRequestData, IUpdateDelayedEventFromWidgetResponseData>(
526-
WidgetApiFromWidgetAction.MSC4354SendStickyEvent,
527-
{
528-
delay_id: delayId,
529-
action: UpdateDelayedEventAction.Send,
530-
},
531-
);
532-
}
533-
534522
/**
535523
* Sends a to-device event.
536524
* @param {string} eventType The type of events being sent.

src/driver/WidgetDriver.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export abstract class WidgetDriver {
181181
* May be an empty string.
182182
* @param {string|null} roomId The room ID to send the event to. If falsy, the room the
183183
* user is currently looking at.
184-
* @returns {Promise<ISendEventDetails>} Resolves when the event has been sent with
184+
* @returns {Promise<ISendDelayedEventDetails>} Resolves when the event has been sent with
185185
* details of that event.
186186
* @throws Rejected when the event could not be sent.
187187
*/
@@ -193,7 +193,7 @@ export abstract class WidgetDriver {
193193
content: unknown,
194194
stateKey: string | null = null,
195195
roomId: string | null = null,
196-
): Promise<ISendEventDetails> {
196+
): Promise<ISendDelayedEventDetails> {
197197
throw new Error("Method not implemented.");
198198
}
199199

test/ClientWidgetApi-test.ts

Lines changed: 187 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { waitFor } from "@testing-library/dom";
2020
import { ClientWidgetApi } from "../src/ClientWidgetApi";
2121
import { WidgetDriver } from "../src/driver/WidgetDriver";
2222
import { CurrentApiVersions, UnstableApiVersion } from "../src/interfaces/ApiVersion";
23-
import { Capability } from "../src/interfaces/Capabilities";
23+
import { Capability, MatrixCapabilities } from "../src/interfaces/Capabilities";
2424
import { IRoomEvent } from "../src/interfaces/IRoomEvent";
2525
import { IWidgetApiRequest } from "../src/interfaces/IWidgetApiRequest";
2626
import { IReadRelationsFromWidgetActionRequest } from "../src/interfaces/ReadRelationsAction";
@@ -141,6 +141,8 @@ describe("ClientWidgetApi", () => {
141141
downloadFile: jest.fn(),
142142
getKnownRooms: jest.fn(() => []),
143143
processError: jest.fn(),
144+
sendStickyEvent: jest.fn(),
145+
sendDelayedStickyEvent: jest.fn(),
144146
} as Partial<WidgetDriver> as jest.Mocked<WidgetDriver>;
145147

146148
clientWidgetApi = new ClientWidgetApi(
@@ -704,6 +706,190 @@ describe("ClientWidgetApi", () => {
704706
});
705707
});
706708

709+
describe("send_event action for sticky events", () => {
710+
it("fails to send delayed events", async () => {
711+
const roomId = "!room:example.org";
712+
713+
const event: ISendEventFromWidgetActionRequest = {
714+
api: WidgetApiDirection.FromWidget,
715+
widgetId: "test",
716+
requestId: "0",
717+
action: WidgetApiFromWidgetAction.SendEvent,
718+
data: {
719+
type: "m.room.message",
720+
content: {
721+
sticky_key: "foobar",
722+
},
723+
delay: 5000,
724+
room_id: roomId,
725+
sticky_duration_ms: 5000,
726+
},
727+
};
728+
729+
await loadIframe([
730+
`org.matrix.msc2762.timeline:${event.data.room_id}`,
731+
`org.matrix.msc2762.send.event:${event.data.type}`,
732+
// Without the required capability
733+
]);
734+
735+
emitEvent(new CustomEvent("", { detail: event }));
736+
737+
await waitFor(() => {
738+
expect(transport.reply).toHaveBeenCalledWith(event, {
739+
error: { message: expect.any(String) },
740+
});
741+
});
742+
743+
expect(driver.sendDelayedEvent).not.toHaveBeenCalled();
744+
});
745+
746+
it("can send a sticky message event", async () => {
747+
const roomId = "!room:example.org";
748+
const eventId = "$evt:example.org";
749+
750+
driver.sendStickyEvent.mockResolvedValue({
751+
roomId,
752+
eventId,
753+
});
754+
755+
const event: ISendEventFromWidgetActionRequest = {
756+
api: WidgetApiDirection.FromWidget,
757+
widgetId: "test",
758+
requestId: "0",
759+
action: WidgetApiFromWidgetAction.SendEvent,
760+
data: {
761+
type: "m.room.message",
762+
content: {
763+
sticky_key: "12345",
764+
},
765+
room_id: roomId,
766+
sticky_duration_ms: 5000,
767+
},
768+
};
769+
770+
await loadIframe([
771+
`org.matrix.msc2762.timeline:${event.data.room_id}`,
772+
`org.matrix.msc2762.send.event:${event.data.type}`,
773+
MatrixCapabilities.MSC4354SendStickyEvent,
774+
]);
775+
776+
emitEvent(new CustomEvent("", { detail: event }));
777+
778+
await waitFor(() => {
779+
expect(transport.reply).toHaveBeenCalledWith(event, {
780+
room_id: roomId,
781+
event_id: eventId,
782+
});
783+
});
784+
785+
expect(driver.sendStickyEvent).toHaveBeenCalledWith(
786+
5000,
787+
event.data.type,
788+
event.data.content,
789+
null,
790+
roomId,
791+
);
792+
});
793+
794+
it.each([
795+
{ hasDelay: true, hasParent: false },
796+
{ hasDelay: false, hasParent: true },
797+
{ hasDelay: true, hasParent: true },
798+
])(
799+
"sends sticky message events with a delay (withDelay = $hasDelay, hasParent = $hasParent)",
800+
async ({ hasDelay, hasParent }) => {
801+
const roomId = "!room:example.org";
802+
const timeoutDelayId = "ft";
803+
804+
driver.sendDelayedStickyEvent.mockResolvedValue({
805+
roomId,
806+
delayId: timeoutDelayId,
807+
});
808+
809+
const event: ISendEventFromWidgetActionRequest = {
810+
api: WidgetApiDirection.FromWidget,
811+
widgetId: "test",
812+
requestId: "0",
813+
action: WidgetApiFromWidgetAction.SendEvent,
814+
data: {
815+
type: "m.room.message",
816+
content: {
817+
sticky_key: "12345",
818+
},
819+
room_id: roomId,
820+
...(hasDelay && { delay: 5000 }),
821+
...(hasParent && { parent_delay_id: "fp" }),
822+
sticky_duration_ms: 5000,
823+
},
824+
};
825+
826+
await loadIframe([
827+
`org.matrix.msc2762.timeline:${event.data.room_id}`,
828+
`org.matrix.msc2762.send.event:${event.data.type}`,
829+
MatrixCapabilities.MSC4157SendDelayedEvent,
830+
MatrixCapabilities.MSC4354SendStickyEvent,
831+
]);
832+
833+
emitEvent(new CustomEvent("", { detail: event }));
834+
835+
await waitFor(() => {
836+
expect(transport.reply).toHaveBeenCalledWith(event, {
837+
room_id: roomId,
838+
delay_id: timeoutDelayId,
839+
});
840+
});
841+
842+
expect(driver.sendDelayedStickyEvent).toHaveBeenCalledWith(
843+
event.data.delay ?? null,
844+
event.data.parent_delay_id ?? null,
845+
5000,
846+
event.data.type,
847+
event.data.content,
848+
null,
849+
roomId,
850+
);
851+
},
852+
);
853+
854+
it("does not allow sticky state events", async () => {
855+
const roomId = "!room:example.org";
856+
const timeoutDelayId = "ft";
857+
858+
driver.sendDelayedEvent.mockResolvedValue({
859+
roomId,
860+
delayId: timeoutDelayId,
861+
});
862+
863+
const event: ISendEventFromWidgetActionRequest = {
864+
api: WidgetApiDirection.FromWidget,
865+
widgetId: "test",
866+
requestId: "0",
867+
action: WidgetApiFromWidgetAction.SendEvent,
868+
data: {
869+
type: "m.room.topic",
870+
content: {},
871+
state_key: "",
872+
room_id: roomId,
873+
sticky_duration_ms: 5000,
874+
},
875+
};
876+
877+
await loadIframe([
878+
`org.matrix.msc2762.timeline:${event.data.room_id}`,
879+
`org.matrix.msc2762.send.state_event:${event.data.type}`,
880+
MatrixCapabilities.MSC4354SendStickyEvent,
881+
]);
882+
883+
emitEvent(new CustomEvent("", { detail: event }));
884+
885+
await waitFor(() => {
886+
expect(transport.reply).toHaveBeenCalledWith(event, {
887+
error: { message: "Cannot send a state event with a sticky duration" },
888+
});
889+
});
890+
});
891+
});
892+
707893
describe("receiving events", () => {
708894
const roomId = "!room:example.org";
709895
const otherRoomId = "!other-room:example.org";

test/WidgetApi-test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,57 @@ describe("WidgetApi", () => {
393393
});
394394
});
395395

396+
describe("sticky sendEvent", () => {
397+
it("sends sticky message events", async () => {
398+
widgetTransportHelper.queueResponse({
399+
room_id: "!room-id",
400+
event_id: "$event_id",
401+
} as ISendEventFromWidgetResponseData);
402+
403+
await expect(
404+
widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, undefined, 2500),
405+
).resolves.toEqual({
406+
room_id: "!room-id",
407+
event_id: "$event_id",
408+
});
409+
});
410+
411+
it("should handle an error", async () => {
412+
widgetTransportHelper.queueResponse({
413+
error: { message: "An error occurred" },
414+
} as IWidgetApiErrorResponseData);
415+
416+
await expect(
417+
widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, undefined, 2500),
418+
).rejects.toThrow("An error occurred");
419+
});
420+
421+
it("should handle an error with details", async () => {
422+
const errorDetails: IWidgetApiErrorResponseDataDetails = {
423+
matrix_api_error: {
424+
http_status: 400,
425+
http_headers: {},
426+
url: "",
427+
response: {
428+
errcode: "M_UNKNOWN",
429+
error: "Unknown error",
430+
},
431+
},
432+
};
433+
434+
widgetTransportHelper.queueResponse({
435+
error: {
436+
message: "An error occurred",
437+
...errorDetails,
438+
},
439+
} as IWidgetApiErrorResponseData);
440+
441+
await expect(
442+
widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, undefined, 2500),
443+
).rejects.toThrow(new WidgetApiResponseError("An error occurred", errorDetails));
444+
});
445+
});
446+
396447
describe("updateDelayedEvent", () => {
397448
it("updates delayed events", async () => {
398449
for (const updateDelayedEvent of [

0 commit comments

Comments
 (0)