diff --git a/src/ClientWidgetApi.ts b/src/ClientWidgetApi.ts index 75ec2a6..260504d 100644 --- a/src/ClientWidgetApi.ts +++ b/src/ClientWidgetApi.ts @@ -626,8 +626,8 @@ export class ClientWidgetApi extends EventEmitter { }); } - const isDelayedEvent = request.data.delay !== undefined || request.data.parent_delay_id !== undefined; - if (isDelayedEvent && !this.hasCapability(MatrixCapabilities.MSC4157SendDelayedEvent)) { + const delay = request.data.delay; + if (delay !== undefined && !this.hasCapability(MatrixCapabilities.MSC4157SendDelayedEvent)) { return this.transport.reply(request, { error: { message: `Missing capability for ${MatrixCapabilities.MSC4157SendDelayedEvent}` }, }); @@ -653,10 +653,9 @@ export class ClientWidgetApi extends EventEmitter { }); } - if (isDelayedEvent) { + if (delay !== undefined) { sendEventPromise = this.driver.sendDelayedEvent( - request.data.delay ?? null, - request.data.parent_delay_id ?? null, + delay, request.data.type, request.data.content || {}, request.data.state_key, @@ -690,21 +689,16 @@ export class ClientWidgetApi extends EventEmitter { request.data.room_id, ]; - if (isDelayedEvent && request.data.sticky_duration_ms) { + if (delay !== undefined && request.data.sticky_duration_ms) { sendEventPromise = this.driver.sendDelayedStickyEvent( - request.data.delay ?? null, - request.data.parent_delay_id ?? null, + delay, request.data.sticky_duration_ms, request.data.type, content, request.data.room_id, ); - } else if (isDelayedEvent) { - sendEventPromise = this.driver.sendDelayedEvent( - request.data.delay ?? null, - request.data.parent_delay_id ?? null, - ...params, - ); + } else if (delay !== undefined) { + sendEventPromise = this.driver.sendDelayedEvent(delay, ...params); } else if (request.data.sticky_duration_ms) { sendEventPromise = this.driver.sendStickyEvent( request.data.sticky_duration_ms, diff --git a/src/WidgetApi.ts b/src/WidgetApi.ts index 7b4db62..3ae2b36 100644 --- a/src/WidgetApi.ts +++ b/src/WidgetApi.ts @@ -440,10 +440,9 @@ export class WidgetApi extends EventEmitter { content: unknown, roomId?: string, delay?: number, - parentDelayId?: string, stickyDurationMs?: number, ): Promise { - return this.sendEvent(eventType, undefined, content, roomId, delay, parentDelayId, stickyDurationMs); + return this.sendEvent(eventType, undefined, content, roomId, delay, stickyDurationMs); } public sendStateEvent( @@ -452,9 +451,8 @@ export class WidgetApi extends EventEmitter { content: unknown, roomId?: string, delay?: number, - parentDelayId?: string, ): Promise { - return this.sendEvent(eventType, stateKey, content, roomId, delay, parentDelayId); + return this.sendEvent(eventType, stateKey, content, roomId, delay); } private sendEvent( @@ -463,7 +461,6 @@ export class WidgetApi extends EventEmitter { content: unknown, roomId?: string, delay?: number, - parentDelayId?: string, stickyDurationMs?: number, ): Promise { return this.transport.send( @@ -474,7 +471,6 @@ export class WidgetApi extends EventEmitter { ...(stateKey !== undefined && { state_key: stateKey }), ...(roomId !== undefined && { room_id: roomId }), ...(delay !== undefined && { delay }), - ...(parentDelayId !== undefined && { parent_delay_id: parentDelayId }), ...(stickyDurationMs !== undefined && { sticky_duration_ms: stickyDurationMs }), }, ); diff --git a/src/driver/WidgetDriver.ts b/src/driver/WidgetDriver.ts index 94ef7f8..afaf411 100644 --- a/src/driver/WidgetDriver.ts +++ b/src/driver/WidgetDriver.ts @@ -138,10 +138,7 @@ export abstract class WidgetDriver { * Sends a delayed event into a room. If `roomId` is falsy, the client should send it * into the room the user is currently looking at. The widget API will have already * verified that the widget is capable of sending the event to that room. - * @param {number|null} delay How much later to send the event, or null to not send the - * event automatically. May not be null if {@link parentDelayId} is null. - * @param {string|null} parentDelayId The ID of the delayed event this one is grouped with, - * or null if it will be put in a new group. May not be null if {@link delay} is null. + * @param {number} delay How much later to send the event. * @param {string} eventType The event type of the event to be sent. * @param {*} content The content for the event to be sent. * @param {string|null} stateKey The state key if the event to be sent a state event, @@ -153,8 +150,7 @@ export abstract class WidgetDriver { * @throws Rejected when the delayed event could not be sent. */ public sendDelayedEvent( - delay: number | null, - parentDelayId: string | null, + delay: number, eventType: string, content: unknown, stateKey: string | null = null, @@ -169,10 +165,7 @@ export abstract class WidgetDriver { * into the room the user is currently looking at. The widget API will have already * verified that the widget is capable of sending the event to that room. * @param {number} stickyDurationMs The length of time a sticky event may remain sticky, in milliseconds. - * @param {number|null} delay How much later to send the event, or null to not send the - * event automatically. May not be null if {@link parentDelayId} is null. - * @param {string|null} parentDelayId The ID of the delayed event this one is grouped with, - * or null if it will be put in a new group. May not be null if {@link delay} is null. + * @param {number} delay How much later to send the event. * @param {string} eventType The event type to be sent. * @param {*} content The content for the event. * @param {string|null} roomId The room ID to send the event to. If falsy, the room the @@ -182,8 +175,7 @@ export abstract class WidgetDriver { * @throws Rejected when the event could not be sent. */ public sendDelayedStickyEvent( - delay: number | null, - parentDelayId: string | null, + delay: number, stickyDurationMs: number, eventType: string, content: unknown, diff --git a/src/interfaces/SendEventAction.ts b/src/interfaces/SendEventAction.ts index a78e38d..514dde6 100644 --- a/src/interfaces/SendEventAction.ts +++ b/src/interfaces/SendEventAction.ts @@ -27,7 +27,6 @@ export interface ISendEventFromWidgetRequestData extends IWidgetApiRequestData { // MSC4157 delay?: number; // eslint-disable-line camelcase - parent_delay_id?: string; // eslint-disable-line camelcase // MSC4407 sticky_duration_ms?: number; diff --git a/test/ClientWidgetApi-test.ts b/test/ClientWidgetApi-test.ts index 5615795..d0e5c96 100644 --- a/test/ClientWidgetApi-test.ts +++ b/test/ClientWidgetApi-test.ts @@ -509,116 +509,98 @@ describe("ClientWidgetApi", () => { expect(driver.sendDelayedEvent).not.toHaveBeenCalled(); }); - it.each([ - { hasDelay: true, hasParent: false }, - { hasDelay: false, hasParent: true }, - { hasDelay: true, hasParent: true }, - ])( - "sends delayed message events (hasDelay = $hasDelay, hasParent = $hasParent)", - async ({ hasDelay, hasParent }) => { - const roomId = "!room:example.org"; - const timeoutDelayId = "ft"; - - driver.sendDelayedEvent.mockResolvedValue({ - roomId, - delayId: timeoutDelayId, - }); - - const event: ISendEventFromWidgetActionRequest = { - api: WidgetApiDirection.FromWidget, - widgetId: "test", - requestId: "0", - action: WidgetApiFromWidgetAction.SendEvent, - data: { - type: "m.room.message", - content: {}, - room_id: roomId, - ...(hasDelay && { delay: 5000 }), - ...(hasParent && { parent_delay_id: "fp" }), - }, - }; - - await loadIframe([ - `org.matrix.msc2762.timeline:${event.data.room_id}`, - `org.matrix.msc2762.send.event:${event.data.type}`, - "org.matrix.msc4157.send.delayed_event", - ]); - - emitEvent(new CustomEvent("", { detail: event })); - - await waitFor(() => { - expect(transport.reply).toHaveBeenCalledWith(event, { - room_id: roomId, - delay_id: timeoutDelayId, - }); - }); - - expect(driver.sendDelayedEvent).toHaveBeenCalledWith( - event.data.delay ?? null, - event.data.parent_delay_id ?? null, - event.data.type, - event.data.content, - null, - roomId, - ); - }, - ); + it("sends delayed message events", async () => { + const roomId = "!room:example.org"; + const timeoutDelayId = "ft"; - it.each([ - { hasDelay: true, hasParent: false }, - { hasDelay: false, hasParent: true }, - { hasDelay: true, hasParent: true }, - ])( - "sends delayed state events (hasDelay = $hasDelay, hasParent = $hasParent)", - async ({ hasDelay, hasParent }) => { - const roomId = "!room:example.org"; - const timeoutDelayId = "ft"; - - driver.sendDelayedEvent.mockResolvedValue({ - roomId, - delayId: timeoutDelayId, - }); - - const event: ISendEventFromWidgetActionRequest = { - api: WidgetApiDirection.FromWidget, - widgetId: "test", - requestId: "0", - action: WidgetApiFromWidgetAction.SendEvent, - data: { - type: "m.room.topic", - content: {}, - state_key: "", - room_id: roomId, - ...(hasDelay && { delay: 5000 }), - ...(hasParent && { parent_delay_id: "fp" }), - }, - }; - - await loadIframe([ - `org.matrix.msc2762.timeline:${event.data.room_id}`, - `org.matrix.msc2762.send.state_event:${event.data.type}`, - "org.matrix.msc4157.send.delayed_event", - ]); - - emitEvent(new CustomEvent("", { detail: event })); - - await waitFor(() => { - expect(transport.reply).toHaveBeenCalledWith(event, { - room_id: roomId, - delay_id: timeoutDelayId, - }); - }); - - expect(driver.sendDelayedEvent).toHaveBeenCalledWith( - event.data.delay ?? null, - event.data.parent_delay_id ?? null, - event.data.type, - event.data.content, - "", - roomId, - ); - }, - ); + driver.sendDelayedEvent.mockResolvedValue({ + roomId, + delayId: timeoutDelayId, + }); + + const event: ISendEventFromWidgetActionRequest = { + api: WidgetApiDirection.FromWidget, + widgetId: "test", + requestId: "0", + action: WidgetApiFromWidgetAction.SendEvent, + data: { + type: "m.room.message", + content: {}, + room_id: roomId, + delay: 5000, + }, + }; + + await loadIframe([ + `org.matrix.msc2762.timeline:${event.data.room_id}`, + `org.matrix.msc2762.send.event:${event.data.type}`, + "org.matrix.msc4157.send.delayed_event", + ]); + + emitEvent(new CustomEvent("", { detail: event })); + + await waitFor(() => { + expect(transport.reply).toHaveBeenCalledWith(event, { + room_id: roomId, + delay_id: timeoutDelayId, + }); + }); + + expect(driver.sendDelayedEvent).toHaveBeenCalledWith( + event.data.delay, + event.data.type, + event.data.content, + null, + roomId, + ); + }); + + it("sends delayed state events", async () => { + const roomId = "!room:example.org"; + const timeoutDelayId = "ft"; + + driver.sendDelayedEvent.mockResolvedValue({ + roomId, + delayId: timeoutDelayId, + }); + + const event: ISendEventFromWidgetActionRequest = { + api: WidgetApiDirection.FromWidget, + widgetId: "test", + requestId: "0", + action: WidgetApiFromWidgetAction.SendEvent, + data: { + type: "m.room.topic", + content: {}, + state_key: "", + room_id: roomId, + delay: 5000, + }, + }; + + await loadIframe([ + `org.matrix.msc2762.timeline:${event.data.room_id}`, + `org.matrix.msc2762.send.state_event:${event.data.type}`, + "org.matrix.msc4157.send.delayed_event", + ]); + + emitEvent(new CustomEvent("", { detail: event })); + + await waitFor(() => { + expect(transport.reply).toHaveBeenCalledWith(event, { + room_id: roomId, + delay_id: timeoutDelayId, + }); + }); + + expect(driver.sendDelayedEvent).toHaveBeenCalledWith( + event.data.delay ?? null, + event.data.type, + event.data.content, + "", + roomId, + ); + }); it("should reject requests when the driver throws an exception", async () => { const roomId = "!room:example.org"; @@ -635,7 +617,6 @@ describe("ClientWidgetApi", () => { content: "hello", room_id: roomId, delay: 5000, - parent_delay_id: "fp", }, }; @@ -675,7 +656,6 @@ describe("ClientWidgetApi", () => { content: "hello", room_id: roomId, delay: 5000, - parent_delay_id: "fp", }, }; @@ -786,64 +766,55 @@ describe("ClientWidgetApi", () => { expect(driver.sendStickyEvent).toHaveBeenCalledWith(5000, event.data.type, event.data.content, roomId); }); - it.each([ - { hasDelay: true, hasParent: false }, - { hasDelay: false, hasParent: true }, - { hasDelay: true, hasParent: true }, - ])( - "sends sticky message events with a delay (withDelay = $hasDelay, hasParent = $hasParent)", - async ({ hasDelay, hasParent }) => { - const roomId = "!room:example.org"; - const timeoutDelayId = "ft"; - - driver.sendDelayedStickyEvent.mockResolvedValue({ - roomId, - delayId: timeoutDelayId, - }); - - const event: ISendEventFromWidgetActionRequest = { - api: WidgetApiDirection.FromWidget, - widgetId: "test", - requestId: "0", - action: WidgetApiFromWidgetAction.SendEvent, - data: { - type: "m.room.message", - content: { - sticky_key: "12345", - }, - room_id: roomId, - ...(hasDelay && { delay: 5000 }), - ...(hasParent && { parent_delay_id: "fp" }), - sticky_duration_ms: 5000, + it("sends sticky message events with a delay", async () => { + const roomId = "!room:example.org"; + const timeoutDelayId = "ft"; + + driver.sendDelayedStickyEvent.mockResolvedValue({ + roomId, + delayId: timeoutDelayId, + }); + + const event: ISendEventFromWidgetActionRequest = { + api: WidgetApiDirection.FromWidget, + widgetId: "test", + requestId: "0", + action: WidgetApiFromWidgetAction.SendEvent, + data: { + type: "m.room.message", + content: { + sticky_key: "12345", }, - }; - - await loadIframe([ - `org.matrix.msc2762.timeline:${event.data.room_id}`, - `org.matrix.msc2762.send.event:${event.data.type}`, - MatrixCapabilities.MSC4157SendDelayedEvent, - MatrixCapabilities.MSC4407SendStickyEvent, - ]); - - emitEvent(new CustomEvent("", { detail: event })); - - await waitFor(() => { - expect(transport.reply).toHaveBeenCalledWith(event, { - room_id: roomId, - delay_id: timeoutDelayId, - }); - }); - - expect(driver.sendDelayedStickyEvent).toHaveBeenCalledWith( - event.data.delay ?? null, - event.data.parent_delay_id ?? null, - 5000, - event.data.type, - event.data.content, - roomId, - ); - }, - ); + room_id: roomId, + delay: 5000, + sticky_duration_ms: 5000, + }, + }; + + await loadIframe([ + `org.matrix.msc2762.timeline:${event.data.room_id}`, + `org.matrix.msc2762.send.event:${event.data.type}`, + MatrixCapabilities.MSC4157SendDelayedEvent, + MatrixCapabilities.MSC4407SendStickyEvent, + ]); + + emitEvent(new CustomEvent("", { detail: event })); + + await waitFor(() => { + expect(transport.reply).toHaveBeenCalledWith(event, { + room_id: roomId, + delay_id: timeoutDelayId, + }); + }); + + expect(driver.sendDelayedStickyEvent).toHaveBeenCalledWith( + event.data.delay ?? null, + 5000, + event.data.type, + event.data.content, + roomId, + ); + }); it("does not allow sticky state events", async () => { const roomId = "!room:example.org"; diff --git a/test/WidgetApi-test.ts b/test/WidgetApi-test.ts index 68704d2..3ece656 100644 --- a/test/WidgetApi-test.ts +++ b/test/WidgetApi-test.ts @@ -329,34 +329,6 @@ describe("WidgetApi", () => { }); }); - it("sends delayed child action message events", async () => { - widgetTransportHelper.queueResponse({ - room_id: "!room-id", - delay_id: "id", - } as ISendEventFromWidgetResponseData); - - await expect(widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", 1000, "parent-id")).resolves.toEqual( - { - room_id: "!room-id", - delay_id: "id", - }, - ); - }); - - it("sends delayed child action state events", async () => { - widgetTransportHelper.queueResponse({ - room_id: "!room-id", - delay_id: "id", - } as ISendEventFromWidgetResponseData); - - await expect( - widgetApi.sendStateEvent("m.room.topic", "", {}, "!room-id", 1000, "parent-id"), - ).resolves.toEqual({ - room_id: "!room-id", - delay_id: "id", - }); - }); - it("should handle an error", async () => { widgetTransportHelper.queueResponse({ error: { message: "An error occurred" }, @@ -400,9 +372,7 @@ describe("WidgetApi", () => { event_id: "$event_id", } as ISendEventFromWidgetResponseData); - await expect( - widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, undefined, 2500), - ).resolves.toEqual({ + await expect(widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, 2500)).resolves.toEqual({ room_id: "!room-id", event_id: "$event_id", }); @@ -413,9 +383,9 @@ describe("WidgetApi", () => { error: { message: "An error occurred" }, } as IWidgetApiErrorResponseData); - await expect( - widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, undefined, 2500), - ).rejects.toThrow("An error occurred"); + await expect(widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, 2500)).rejects.toThrow( + "An error occurred", + ); }); it("should handle an error with details", async () => { @@ -438,9 +408,9 @@ describe("WidgetApi", () => { }, } as IWidgetApiErrorResponseData); - await expect( - widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, undefined, 2500), - ).rejects.toThrow(new WidgetApiResponseError("An error occurred", errorDetails)); + await expect(widgetApi.sendRoomEvent("m.room.message", {}, "!room-id", undefined, 2500)).rejects.toThrow( + new WidgetApiResponseError("An error occurred", errorDetails), + ); }); });