diff --git a/src/state/CallViewModel.test.ts b/src/state/CallViewModel.test.ts index 6adaa4bac..fec6b8cf3 100644 --- a/src/state/CallViewModel.test.ts +++ b/src/state/CallViewModel.test.ts @@ -281,7 +281,7 @@ interface CallViewModelInputs { initialSyncState: SyncState; } -function withCallViewModel( +export function withCallViewModel( { remoteParticipants$ = constant([]), rtcMembers$ = constant([localRtcMember]), diff --git a/src/state/CallViewModel.ts b/src/state/CallViewModel.ts index 1483cfc84..d7735b260 100644 --- a/src/state/CallViewModel.ts +++ b/src/state/CallViewModel.ts @@ -1053,8 +1053,12 @@ export class CallViewModel { fromEvent( widget.lazyActions, ElementWidgetActions.HangupCall, - ) as Observable<[CustomEvent]> - ).pipe(tap(([ev]) => widget!.api.transport.reply(ev.detail, {}))); + ) as Observable> + ).pipe( + tap((ev) => { + widget!.api.transport.reply(ev.detail, {}); + }), + ); public readonly leave$: Observable< "user" | "timeout" | "decline" | "allOthersLeft" diff --git a/src/state/CallViewModelWidget.test.ts b/src/state/CallViewModelWidget.test.ts new file mode 100644 index 000000000..045e24726 --- /dev/null +++ b/src/state/CallViewModelWidget.test.ts @@ -0,0 +1,66 @@ +/* +Copyright 2025 Element Creations Ltd. + + SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { test, vi, expect } from "vitest"; +import EventEmitter from "events"; + +import { constant } from "./Behavior.ts"; +import { withCallViewModel } from "./CallViewModel.test.ts"; +import { aliceParticipant, localRtcMember } from "../utils/test-fixtures.ts"; +import { ElementWidgetActions, widget } from "../widget.ts"; +import { E2eeType } from "../e2ee/e2eeType.ts"; +import { type CallViewModel } from "./CallViewModel.ts"; + +vi.mock("../widget", () => ({ + ElementWidgetActions: { + HangupCall: "HangupCall", + // Add other actions if needed + }, + widget: { + api: { + transport: { + send: vi.fn().mockResolvedValue(undefined), + reply: vi.fn().mockResolvedValue(undefined), + }, + }, + lazyActions: new EventEmitter(), + }, +})); + +test("expect leave when ElementWidgetActions.HangupCall is called", async () => { + const pr = Promise.withResolvers(); + withCallViewModel( + { + remoteParticipants$: constant([aliceParticipant]), + rtcMembers$: constant([localRtcMember]), + }, + (vm: CallViewModel) => { + vm.leave$.subscribe((s: string) => { + pr.resolve(s); + }); + + widget!.lazyActions!.emit( + ElementWidgetActions.HangupCall, + new CustomEvent(ElementWidgetActions.HangupCall, { + detail: { + action: "im.vector.hangup", + api: "toWidget", + data: {}, + requestId: "widgetapi-1761237395918", + widgetId: "mrUjS9T6uKUOWHMxXvLbSv0F", + }, + }), + ); + }, + { + encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, + }, + ); + + const source = await pr.promise; + expect(source).toBe("user"); +});