element-web/test/stores/widgets/StopGapWidgetDriver-test.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

620 lines
22 KiB
TypeScript
Raw Normal View History

/*
Copyright 2022 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { mocked, MockedObject } from "jest-mock";
import {
MatrixClient,
ClientEvent,
ITurnServer as IClientTurnServer,
Direction,
EventType,
MatrixEvent,
MsgType,
RelationType,
} from "matrix-js-sdk/src/matrix";
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
import {
Widget,
MatrixWidgetType,
WidgetKind,
WidgetDriver,
ITurnServer,
SimpleObservable,
OpenIDRequestState,
IOpenIDUpdate,
UpdateDelayedEventAction,
} from "matrix-widget-api";
import {
ApprovalOpts,
CapabilitiesOpts,
WidgetLifecycle,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/WidgetLifecycle";
Store refactor: use non-global stores in components (#9293) * Add Stores and StoresContext and use it in MatrixChat and RoomView Added a new kind of class: - Add God object `Stores` which will hold refs to all known stores and the `MatrixClient`. This object is NOT a singleton. - Add `StoresContext` to hold onto a ref of `Stores` for use inside components. `StoresContext` is created via: - Create `Stores` in `MatrixChat`, assigning the `MatrixClient` when we have one set. Currently sets the RVS to `RoomViewStore.instance`. - Wrap `MatrixChat`s `render()` function in a `StoresContext.Provider` so it can be used anywhere. `StoresContext` is currently only used in `RoomView` via the following changes: - Remove the HOC, which redundantly set `mxClient` as a prop. We don't need this as `RoomView` was using the client from `this.context`. - Change the type of context accepted from `MatrixClientContext` to `StoresContext`. - Modify alllll the places where `this.context` is used to interact with the client and suffix `.client`. - Modify places where we use `RoomViewStore.instance` and replace them with `this.context.roomViewStore`. This makes `RoomView` use a non-global instance of RVS. * Linting * SDKContext and make client an optional constructor arg * Move SDKContext to /src/contexts * Inject all RVS deps * Linting * Remove reset calls; deep copy the INITIAL_STATE to avoid test pollution * DI singletons used in RoomView; DI them in RoomView-test too * Initial RoomViewStore.instance after all files are imported to avoid cyclical deps * Lazily init stores to allow for circular dependencies Rather than stores accepting a list of other stores in their constructors, which doesn't work when A needs B and B needs A, make new-style stores simply accept Stores. When a store needs another store, they access it via `Stores` which then lazily constructs that store if it needs it. This breaks the circular dependency at constructor time, without needing to introduce wiring diagrams or any complex DI framework. * Delete RoomViewStore.instance Replaced with Stores.instance.roomViewStore * Linting * Move OverridableStores to test/TestStores * Rejig how eager stores get made; don't automatically do it else tests break * Linting * Linting and review comments * Fix new code to use Stores.instance * s/Stores/SdkContextClass/g * Update docs * Remove unused imports * Update src/stores/RoomViewStore.tsx Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * Remove empty c'tor to make sonar happy Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2022-10-19 12:07:03 +00:00
import { SdkContextClass } from "../../../src/contexts/SDKContext";
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
import { StopGapWidgetDriver } from "../../../src/stores/widgets/StopGapWidgetDriver";
import { stubClient } from "../../test-utils";
import { ModuleRunner } from "../../../src/modules/ModuleRunner";
import dis from "../../../src/dispatcher/dispatcher";
import Modal from "../../../src/Modal";
import SettingsStore from "../../../src/settings/SettingsStore";
describe("StopGapWidgetDriver", () => {
let client: MockedObject<MatrixClient>;
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
const mkDefaultDriver = (): WidgetDriver =>
new StopGapWidgetDriver(
[],
new Widget({
id: "test",
creatorUserId: "@alice:example.org",
type: "example",
url: "https://example.org",
}),
WidgetKind.Room,
false,
"!1:example.org",
);
jest.spyOn(Modal, "createDialog").mockImplementation(() => {
throw new Error("Should not have to create a dialog");
});
beforeEach(() => {
stubClient();
client = mocked(MatrixClientPeg.safeGet());
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
client.getUserId.mockReturnValue("@alice:example.org");
client.getSafeUserId.mockReturnValue("@alice:example.org");
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
});
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
it("auto-approves capabilities of virtual Element Call widgets", async () => {
const driver = new StopGapWidgetDriver(
[],
new Widget({
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
id: "group_call",
creatorUserId: "@alice:example.org",
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
type: MatrixWidgetType.Custom,
url: "https://call.element.io",
}),
WidgetKind.Room,
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
true,
"!1:example.org",
);
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
// These are intentionally raw identifiers rather than constants, so it's obvious what's being requested
const requestedCapabilities = new Set([
"m.always_on_screen",
"town.robin.msc3846.turn_servers",
"org.matrix.msc2762.timeline:!1:example.org",
"org.matrix.msc2762.send.event:org.matrix.rageshake_request",
"org.matrix.msc2762.receive.event:org.matrix.rageshake_request",
"org.matrix.msc2762.receive.state_event:m.room.create",
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
"org.matrix.msc2762.receive.state_event:m.room.member",
"org.matrix.msc2762.receive.state_event:org.matrix.msc3401.call",
"org.matrix.msc2762.send.state_event:org.matrix.msc3401.call.member#@alice:example.org",
"org.matrix.msc2762.receive.state_event:org.matrix.msc3401.call.member",
`org.matrix.msc2762.send.state_event:org.matrix.msc3401.call.member#_@alice:example.org_${client.deviceId}`,
`org.matrix.msc2762.send.state_event:org.matrix.msc3401.call.member#@alice:example.org_${client.deviceId}`,
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
"org.matrix.msc3819.send.to_device:m.call.invite",
"org.matrix.msc3819.receive.to_device:m.call.invite",
"org.matrix.msc3819.send.to_device:m.call.candidates",
"org.matrix.msc3819.receive.to_device:m.call.candidates",
"org.matrix.msc3819.send.to_device:m.call.answer",
"org.matrix.msc3819.receive.to_device:m.call.answer",
"org.matrix.msc3819.send.to_device:m.call.hangup",
"org.matrix.msc3819.receive.to_device:m.call.hangup",
"org.matrix.msc3819.send.to_device:m.call.reject",
"org.matrix.msc3819.receive.to_device:m.call.reject",
"org.matrix.msc3819.send.to_device:m.call.select_answer",
"org.matrix.msc3819.receive.to_device:m.call.select_answer",
"org.matrix.msc3819.send.to_device:m.call.negotiate",
"org.matrix.msc3819.receive.to_device:m.call.negotiate",
"org.matrix.msc3819.send.to_device:m.call.sdp_stream_metadata_changed",
"org.matrix.msc3819.receive.to_device:m.call.sdp_stream_metadata_changed",
"org.matrix.msc3819.send.to_device:org.matrix.call.sdp_stream_metadata_changed",
"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",
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
]);
const approvedCapabilities = await driver.validateCapabilities(requestedCapabilities);
expect(approvedCapabilities).toEqual(requestedCapabilities);
});
it("approves capabilities via module api", async () => {
const driver = mkDefaultDriver();
const requestedCapabilities = new Set(["org.matrix.msc2931.navigate", "org.matrix.msc2762.timeline:*"]);
jest.spyOn(ModuleRunner.instance, "invoke").mockImplementation(
(lifecycleEvent, opts, widgetInfo, requested) => {
if (lifecycleEvent === WidgetLifecycle.CapabilitiesRequest) {
(opts as CapabilitiesOpts).approvedCapabilities = requested;
}
},
);
const approvedCapabilities = await driver.validateCapabilities(requestedCapabilities);
expect(approvedCapabilities).toEqual(requestedCapabilities);
});
it("approves identity via module api", async () => {
const driver = mkDefaultDriver();
jest.spyOn(ModuleRunner.instance, "invoke").mockImplementation((lifecycleEvent, opts, widgetInfo) => {
if (lifecycleEvent === WidgetLifecycle.IdentityRequest) {
(opts as ApprovalOpts).approved = true;
}
});
const listener = jest.fn();
const observer = new SimpleObservable<IOpenIDUpdate>();
observer.onUpdate(listener);
await driver.askOpenID(observer);
const openIdUpdate: IOpenIDUpdate = {
state: OpenIDRequestState.Allowed,
token: await client.getOpenIdToken(),
};
2023-03-01 15:23:35 +00:00
expect(listener).toHaveBeenCalledWith(openIdUpdate);
});
describe("sendToDevice", () => {
const contentMap = {
"@alice:example.org": {
"*": {
hello: "alice",
},
},
"@bob:example.org": {
bobDesktop: {
hello: "bob",
},
},
};
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
let driver: WidgetDriver;
beforeEach(() => {
driver = mkDefaultDriver();
});
it("sends unencrypted messages", async () => {
await driver.sendToDevice("org.example.foo", false, contentMap);
expect(client.queueToDevice.mock.calls).toMatchSnapshot();
});
it("sends encrypted messages", async () => {
const aliceWeb = new DeviceInfo("aliceWeb");
const aliceMobile = new DeviceInfo("aliceMobile");
const bobDesktop = new DeviceInfo("bobDesktop");
mocked(client.crypto!.deviceList).downloadKeys.mockResolvedValue(
2023-03-28 10:23:16 +00:00
new Map([
[
"@alice:example.org",
new Map([
["aliceWeb", aliceWeb],
["aliceMobile", aliceMobile],
]),
],
["@bob:example.org", new Map([["bobDesktop", bobDesktop]])],
]),
);
await driver.sendToDevice("org.example.foo", true, contentMap);
expect(client.encryptAndSendToDevices.mock.calls).toMatchSnapshot();
});
});
describe("getTurnServers", () => {
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
let driver: WidgetDriver;
beforeEach(() => {
driver = mkDefaultDriver();
});
it("stops if VoIP isn't supported", async () => {
jest.spyOn(client, "pollingTurnServers", "get").mockReturnValue(false);
const servers = driver.getTurnServers();
expect(await servers.next()).toEqual({ value: undefined, done: true });
});
it("stops if the homeserver provides no TURN servers", async () => {
const servers = driver.getTurnServers();
expect(await servers.next()).toEqual({ value: undefined, done: true });
});
it("gets TURN servers", async () => {
const server1: ITurnServer = {
uris: [
"turn:turn.example.com:3478?transport=udp",
"turn:10.20.30.40:3478?transport=tcp",
"turns:10.20.30.40:443?transport=tcp",
],
username: "1443779631:@user:example.com",
password: "JlKfBy1QwLrO20385QyAtEyIv0=",
};
const server2: ITurnServer = {
uris: [
"turn:turn.example.com:3478?transport=udp",
"turn:10.20.30.40:3478?transport=tcp",
"turns:10.20.30.40:443?transport=tcp",
],
username: "1448999322:@user:example.com",
password: "hunter2",
};
const clientServer1: IClientTurnServer = {
urls: server1.uris,
username: server1.username,
credential: server1.password,
};
const clientServer2: IClientTurnServer = {
urls: server2.uris,
username: server2.username,
credential: server2.password,
};
client.getTurnServers.mockReturnValue([clientServer1]);
const servers = driver.getTurnServers();
expect(await servers.next()).toEqual({ value: server1, done: false });
const nextServer = servers.next();
client.getTurnServers.mockReturnValue([clientServer2]);
client.emit(ClientEvent.TurnServers, [clientServer2]);
expect(await nextServer).toEqual({ value: server2, done: false });
await servers.return(undefined);
});
});
describe("readEventRelations", () => {
Element Call video rooms (#9267) * Add an element_call_url config option * Add a labs flag for Element Call video rooms * Add Element Call as another video rooms backend * Consolidate event power level defaults * Remember to clean up participantsExpirationTimer * Fix a code smell * Test the clean method * Fix some strict mode errors * Test that clean still works when there are no state events * Test auto-approval of Element Call widget capabilities * Deduplicate some code to placate SonarCloud * Fix more strict mode errors * Test that calls disconnect when leaving the room * Test the get methods of JitsiCall and ElementCall more * Test Call.ts even more * Test creation of Element video rooms * Test that createRoom works for non-video-rooms * Test Call's get method rather than the methods of derived classes * Ensure that the clean method is able to preserve devices * Remove duplicate clean method * Fix lints * Fix some strict mode errors in RoomPreviewCard * Test RoomPreviewCard changes * Quick and dirty hotfix for the community testing session * Revert "Quick and dirty hotfix for the community testing session" This reverts commit 37056514fbc040aaf1bff2539da770a1c8ba72a2. * Fix the event schema for org.matrix.msc3401.call.member devices * Remove org.matrix.call_duplicate_session from Element Call capabilities It's no longer used by Element Call when running as a widget. * Replace element_call_url with a map * Make PiPs work for virtual widgets * Auto-approve room timeline capability Because Element Call uses this now * Create a reusable isVideoRoom util
2022-09-16 15:12:27 +00:00
let driver: WidgetDriver;
beforeEach(() => {
driver = mkDefaultDriver();
});
it("reads related events from the current room", async () => {
Store refactor: use non-global stores in components (#9293) * Add Stores and StoresContext and use it in MatrixChat and RoomView Added a new kind of class: - Add God object `Stores` which will hold refs to all known stores and the `MatrixClient`. This object is NOT a singleton. - Add `StoresContext` to hold onto a ref of `Stores` for use inside components. `StoresContext` is created via: - Create `Stores` in `MatrixChat`, assigning the `MatrixClient` when we have one set. Currently sets the RVS to `RoomViewStore.instance`. - Wrap `MatrixChat`s `render()` function in a `StoresContext.Provider` so it can be used anywhere. `StoresContext` is currently only used in `RoomView` via the following changes: - Remove the HOC, which redundantly set `mxClient` as a prop. We don't need this as `RoomView` was using the client from `this.context`. - Change the type of context accepted from `MatrixClientContext` to `StoresContext`. - Modify alllll the places where `this.context` is used to interact with the client and suffix `.client`. - Modify places where we use `RoomViewStore.instance` and replace them with `this.context.roomViewStore`. This makes `RoomView` use a non-global instance of RVS. * Linting * SDKContext and make client an optional constructor arg * Move SDKContext to /src/contexts * Inject all RVS deps * Linting * Remove reset calls; deep copy the INITIAL_STATE to avoid test pollution * DI singletons used in RoomView; DI them in RoomView-test too * Initial RoomViewStore.instance after all files are imported to avoid cyclical deps * Lazily init stores to allow for circular dependencies Rather than stores accepting a list of other stores in their constructors, which doesn't work when A needs B and B needs A, make new-style stores simply accept Stores. When a store needs another store, they access it via `Stores` which then lazily constructs that store if it needs it. This breaks the circular dependency at constructor time, without needing to introduce wiring diagrams or any complex DI framework. * Delete RoomViewStore.instance Replaced with Stores.instance.roomViewStore * Linting * Move OverridableStores to test/TestStores * Rejig how eager stores get made; don't automatically do it else tests break * Linting * Linting and review comments * Fix new code to use Stores.instance * s/Stores/SdkContextClass/g * Update docs * Remove unused imports * Update src/stores/RoomViewStore.tsx Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * Remove empty c'tor to make sonar happy Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2022-10-19 12:07:03 +00:00
jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId").mockReturnValue("!this-room-id");
client.relations.mockResolvedValue({
originalEvent: new MatrixEvent(),
events: [],
});
await expect(driver.readEventRelations("$event")).resolves.toEqual({
chunk: [],
nextBatch: undefined,
prevBatch: undefined,
});
2023-03-01 15:23:35 +00:00
expect(client.relations).toHaveBeenCalledWith("!this-room-id", "$event", null, null, {});
});
it("reads related events from a selected room", async () => {
client.relations.mockResolvedValue({
originalEvent: new MatrixEvent(),
events: [new MatrixEvent(), new MatrixEvent()],
nextBatch: "next-batch-token",
});
await expect(driver.readEventRelations("$event", "!room-id")).resolves.toEqual({
chunk: [expect.objectContaining({ content: {} }), expect.objectContaining({ content: {} })],
nextBatch: "next-batch-token",
prevBatch: undefined,
});
2023-03-01 15:23:35 +00:00
expect(client.relations).toHaveBeenCalledWith("!room-id", "$event", null, null, {});
});
it("reads related events with custom parameters", async () => {
client.relations.mockResolvedValue({
originalEvent: new MatrixEvent(),
events: [],
});
await expect(
driver.readEventRelations(
"$event",
"!room-id",
"m.reference",
"m.room.message",
"from-token",
"to-token",
25,
2022-12-12 11:24:14 +00:00
"f",
),
).resolves.toEqual({
chunk: [],
nextBatch: undefined,
prevBatch: undefined,
});
2023-03-01 15:23:35 +00:00
expect(client.relations).toHaveBeenCalledWith("!room-id", "$event", "m.reference", "m.room.message", {
limit: 25,
from: "from-token",
to: "to-token",
dir: Direction.Forward,
});
});
});
describe("chat effects", () => {
let driver: WidgetDriver;
// let client: MatrixClient;
beforeEach(() => {
stubClient();
driver = mkDefaultDriver();
jest.spyOn(dis, "dispatch").mockReset();
});
it("sends chat effects", async () => {
await driver.sendEvent(
EventType.RoomMessage,
{
msgtype: MsgType.Text,
body: "🎉",
},
null,
);
expect(dis.dispatch).toHaveBeenCalled();
});
it("does not send chat effects in threads", async () => {
await driver.sendEvent(
EventType.RoomMessage,
{
"body": "🎉",
"m.relates_to": {
rel_type: RelationType.Thread,
event_id: "$123",
},
},
null,
);
expect(dis.dispatch).not.toHaveBeenCalled();
});
});
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);
});
it("passes the flag through to getVisibleRooms", () => {
const driver = mkDefaultDriver();
driver.readRoomEvents(EventType.CallAnswer, "", 0, ["*"]);
expect(client.getVisibleRooms).toHaveBeenCalledWith(false);
});
});
describe("If the feature_dynamic_room_predecessors is enabled", () => {
beforeEach(() => {
// Turn on feature_dynamic_room_predecessors setting
jest.spyOn(SettingsStore, "getValue").mockImplementation(
(settingName) => settingName === "feature_dynamic_room_predecessors",
);
});
it("passes the flag through to getVisibleRooms", () => {
const driver = mkDefaultDriver();
driver.readRoomEvents(EventType.CallAnswer, "", 0, ["*"]);
expect(client.getVisibleRooms).toHaveBeenCalledWith(true);
});
});
describe("searchUserDirectory", () => {
let driver: WidgetDriver;
beforeEach(() => {
driver = mkDefaultDriver();
});
it("searches for users in the user directory", async () => {
client.searchUserDirectory.mockResolvedValue({
limited: false,
results: [{ user_id: "@user", display_name: "Name", avatar_url: "mxc://" }],
});
await expect(driver.searchUserDirectory("foo")).resolves.toEqual({
limited: false,
results: [{ userId: "@user", displayName: "Name", avatarUrl: "mxc://" }],
});
expect(client.searchUserDirectory).toHaveBeenCalledWith({ term: "foo", limit: undefined });
});
it("searches for users with a custom limit", async () => {
client.searchUserDirectory.mockResolvedValue({
limited: true,
results: [],
});
await expect(driver.searchUserDirectory("foo", 25)).resolves.toEqual({
limited: true,
results: [],
});
expect(client.searchUserDirectory).toHaveBeenCalledWith({ term: "foo", limit: 25 });
});
});
describe("getMediaConfig", () => {
let driver: WidgetDriver;
beforeEach(() => {
driver = mkDefaultDriver();
});
it("gets the media configuration", async () => {
client.getMediaConfig.mockResolvedValue({
"m.upload.size": 1000,
});
await expect(driver.getMediaConfig()).resolves.toEqual({
"m.upload.size": 1000,
});
expect(client.getMediaConfig).toHaveBeenCalledWith();
});
});
describe("uploadFile", () => {
let driver: WidgetDriver;
beforeEach(() => {
driver = mkDefaultDriver();
});
it("uploads a file", async () => {
client.uploadContent.mockResolvedValue({
content_uri: "mxc://...",
});
await expect(driver.uploadFile("data")).resolves.toEqual({
contentUri: "mxc://...",
});
expect(client.uploadContent).toHaveBeenCalledWith("data");
});
});
});