Support delayed events (MSC4140) for call widget (#12714)

The Widget API spec for delayed events is defined by MSC4157.

Also support "parent" delayed events, which were in a previous version
of MSC4140 and may be reintroduced or be part of a new MSC later.
This commit is contained in:
Andrew Ferrazzutti 2024-08-07 11:06:30 -04:00 committed by GitHub
parent a35bf68f22
commit a437c677bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 230 additions and 11 deletions

View file

@ -35,6 +35,7 @@ import {
SimpleObservable,
OpenIDRequestState,
IOpenIDUpdate,
UpdateDelayedEventAction,
} from "matrix-widget-api";
import {
ApprovalOpts,
@ -122,6 +123,8 @@ describe("StopGapWidgetDriver", () => {
"org.matrix.msc3819.receive.to_device:org.matrix.call.sdp_stream_metadata_changed",
"org.matrix.msc3819.send.to_device:m.call.replaces",
"org.matrix.msc3819.receive.to_device:m.call.replaces",
"org.matrix.msc4157.send.delayed_event",
"org.matrix.msc4157.update_delayed_event",
]);
// As long as this resolves, we'll know that it didn't try to pop up a modal
@ -388,6 +391,125 @@ describe("StopGapWidgetDriver", () => {
});
});
describe("sendDelayedEvent", () => {
let driver: WidgetDriver;
const roomId = "!this-room-id";
beforeEach(() => {
driver = mkDefaultDriver();
});
it("cannot send delayed events with missing arguments", async () => {
await expect(driver.sendDelayedEvent(null, null, EventType.RoomMessage, {})).rejects.toThrow(
"Must provide at least one of",
);
});
it("sends delayed message events", async () => {
client._unstable_sendDelayedEvent.mockResolvedValue({
delay_id: "id",
});
await expect(driver.sendDelayedEvent(2000, null, EventType.RoomMessage, {})).resolves.toEqual({
roomId,
delayId: "id",
});
expect(client._unstable_sendDelayedEvent).toHaveBeenCalledWith(
roomId,
{ delay: 2000 },
null,
EventType.RoomMessage,
{},
);
});
it("sends child action delayed message events", async () => {
client._unstable_sendDelayedEvent.mockResolvedValue({
delay_id: "id-child",
});
await expect(driver.sendDelayedEvent(null, "id-parent", EventType.RoomMessage, {})).resolves.toEqual({
roomId,
delayId: "id-child",
});
expect(client._unstable_sendDelayedEvent).toHaveBeenCalledWith(
roomId,
{ parent_delay_id: "id-parent" },
null,
EventType.RoomMessage,
{},
);
});
it("sends delayed state events", async () => {
client._unstable_sendDelayedStateEvent.mockResolvedValue({
delay_id: "id",
});
await expect(driver.sendDelayedEvent(2000, null, EventType.RoomTopic, {}, "")).resolves.toEqual({
roomId,
delayId: "id",
});
expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledWith(
roomId,
{ delay: 2000 },
EventType.RoomTopic,
{},
"",
);
});
it("sends child action delayed state events", async () => {
client._unstable_sendDelayedStateEvent.mockResolvedValue({
delay_id: "id-child",
});
await expect(driver.sendDelayedEvent(null, "id-parent", EventType.RoomTopic, {}, "")).resolves.toEqual({
roomId,
delayId: "id-child",
});
expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledWith(
roomId,
{ parent_delay_id: "id-parent" },
EventType.RoomTopic,
{},
"",
);
});
});
describe("updateDelayedEvent", () => {
let driver: WidgetDriver;
beforeEach(() => {
driver = mkDefaultDriver();
});
it("updates delayed events", async () => {
client._unstable_updateDelayedEvent.mockResolvedValue({});
for (const action of [
UpdateDelayedEventAction.Cancel,
UpdateDelayedEventAction.Restart,
UpdateDelayedEventAction.Send,
]) {
await expect(driver.updateDelayedEvent("id", action)).resolves.toBeUndefined();
expect(client._unstable_updateDelayedEvent).toHaveBeenCalledWith("id", action);
}
});
it("fails to update delayed events", async () => {
const errorMessage = "Cannot restart this delayed event";
client._unstable_updateDelayedEvent.mockRejectedValue(new Error(errorMessage));
await expect(driver.updateDelayedEvent("id", UpdateDelayedEventAction.Restart)).rejects.toThrow(
errorMessage,
);
});
});
describe("If the feature_dynamic_room_predecessors feature is not enabled", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);

View file

@ -252,6 +252,10 @@ export function createTestClient(): MatrixClient {
});
}),
_unstable_sendDelayedEvent: jest.fn(),
_unstable_sendDelayedStateEvent: jest.fn(),
_unstable_updateDelayedEvent: jest.fn(),
searchUserDirectory: jest.fn().mockResolvedValue({ limited: false, results: [] }),
setDeviceVerified: jest.fn(),
joinRoom: jest.fn(),