Merge branch 'develop' into florianduros/fix-white-black-theme-switch
This commit is contained in:
commit
f85685a0fb
26 changed files with 824 additions and 119 deletions
|
@ -14,28 +14,21 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { MockedObject } from "jest-mock";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
|
||||
import BasePlatform from "../src/BasePlatform";
|
||||
import { ElementCall } from "../src/models/Call";
|
||||
import Notifier from "../src/Notifier";
|
||||
import SettingsStore from "../src/settings/SettingsStore";
|
||||
import ToastStore from "../src/stores/ToastStore";
|
||||
import { getLocalNotificationAccountDataEventType } from "../src/utils/notifications";
|
||||
import { getMockClientWithEventEmitter, mkEvent, mkRoom, mockPlatformPeg } from "./test-utils";
|
||||
import { IncomingCallToast } from "../src/toasts/IncomingCallToast";
|
||||
|
||||
describe("Notifier", () => {
|
||||
let MockPlatform;
|
||||
let accountDataStore = {};
|
||||
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
getUserId: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
isGuest: jest.fn().mockReturnValue(false),
|
||||
getAccountData: jest.fn().mockImplementation(eventType => accountDataStore[eventType]),
|
||||
setAccountData: jest.fn().mockImplementation((eventType, content) => {
|
||||
accountDataStore[eventType] = new MatrixEvent({
|
||||
type: eventType,
|
||||
content,
|
||||
});
|
||||
}),
|
||||
});
|
||||
const accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId);
|
||||
const roomId = "!room1:server";
|
||||
const testEvent = mkEvent({
|
||||
event: true,
|
||||
|
@ -44,10 +37,33 @@ describe("Notifier", () => {
|
|||
room: roomId,
|
||||
content: {},
|
||||
});
|
||||
const testRoom = mkRoom(mockClient, roomId);
|
||||
|
||||
let MockPlatform: MockedObject<BasePlatform>;
|
||||
let mockClient: MockedObject<MatrixClient>;
|
||||
let testRoom: MockedObject<Room>;
|
||||
let accountDataEventKey: string;
|
||||
let accountDataStore = {};
|
||||
|
||||
beforeEach(() => {
|
||||
accountDataStore = {};
|
||||
mockClient = getMockClientWithEventEmitter({
|
||||
getUserId: jest.fn().mockReturnValue("@bob:example.org"),
|
||||
isGuest: jest.fn().mockReturnValue(false),
|
||||
getAccountData: jest.fn().mockImplementation(eventType => accountDataStore[eventType]),
|
||||
setAccountData: jest.fn().mockImplementation((eventType, content) => {
|
||||
accountDataStore[eventType] = new MatrixEvent({
|
||||
type: eventType,
|
||||
content,
|
||||
});
|
||||
}),
|
||||
decryptEventIfNeeded: jest.fn(),
|
||||
getRoom: jest.fn(),
|
||||
getPushActionsForEvent: jest.fn(),
|
||||
});
|
||||
accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId);
|
||||
|
||||
testRoom = mkRoom(mockClient, roomId);
|
||||
|
||||
MockPlatform = mockPlatformPeg({
|
||||
supportsNotifications: jest.fn().mockReturnValue(true),
|
||||
maySendNotifications: jest.fn().mockReturnValue(true),
|
||||
|
@ -55,6 +71,8 @@ describe("Notifier", () => {
|
|||
});
|
||||
|
||||
Notifier.isBodyEnabled = jest.fn().mockReturnValue(true);
|
||||
|
||||
mockClient.getRoom.mockReturnValue(testRoom);
|
||||
});
|
||||
|
||||
describe("_displayPopupNotification", () => {
|
||||
|
@ -82,4 +100,73 @@ describe("Notifier", () => {
|
|||
expect(Notifier.getSoundForRoom).toHaveBeenCalledTimes(count);
|
||||
});
|
||||
});
|
||||
|
||||
describe("group call notifications", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
|
||||
jest.spyOn(ToastStore.sharedInstance(), "addOrReplaceToast");
|
||||
|
||||
mockClient.getPushActionsForEvent.mockReturnValue({
|
||||
notify: true,
|
||||
tweaks: {},
|
||||
});
|
||||
|
||||
Notifier.onSyncStateChange("SYNCING");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
const callOnEvent = (type?: string) => {
|
||||
const callEvent = {
|
||||
getContent: () => { },
|
||||
getRoomId: () => roomId,
|
||||
isBeingDecrypted: () => false,
|
||||
isDecryptionFailure: () => false,
|
||||
getSender: () => "@alice:foo",
|
||||
getType: () => type ?? ElementCall.CALL_EVENT_TYPE.name,
|
||||
getStateKey: () => "state_key",
|
||||
} as unknown as MatrixEvent;
|
||||
|
||||
Notifier.onEvent(callEvent);
|
||||
return callEvent;
|
||||
};
|
||||
|
||||
const setGroupCallsEnabled = (val: boolean) => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((name: string) => {
|
||||
if (name === "feature_group_calls") return val;
|
||||
});
|
||||
};
|
||||
|
||||
it("should show toast when group calls are supported", () => {
|
||||
setGroupCallsEnabled(true);
|
||||
|
||||
const callEvent = callOnEvent();
|
||||
|
||||
expect(ToastStore.sharedInstance().addOrReplaceToast).toHaveBeenCalledWith(expect.objectContaining({
|
||||
key: `call_${callEvent.getStateKey()}`,
|
||||
priority: 100,
|
||||
component: IncomingCallToast,
|
||||
bodyClassName: "mx_IncomingCallToast",
|
||||
props: { callEvent },
|
||||
}));
|
||||
});
|
||||
|
||||
it("should not show toast when group calls are not supported", () => {
|
||||
setGroupCallsEnabled(false);
|
||||
|
||||
callOnEvent();
|
||||
|
||||
expect(ToastStore.sharedInstance().addOrReplaceToast).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not show toast when calling with non-group call event", () => {
|
||||
setGroupCallsEnabled(true);
|
||||
|
||||
callOnEvent("event_type");
|
||||
|
||||
expect(ToastStore.sharedInstance().addOrReplaceToast).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,15 +14,17 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { EventType, MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { EventType, MatrixClient, MatrixEvent, Room, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import TestRenderer from 'react-test-renderer';
|
||||
import { ReactElement } from "react";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import { getSenderName, textForEvent } from "../src/TextForEvent";
|
||||
import SettingsStore from "../src/settings/SettingsStore";
|
||||
import { createTestClient } from './test-utils';
|
||||
import { createTestClient, stubClient } from './test-utils';
|
||||
import { MatrixClientPeg } from '../src/MatrixClientPeg';
|
||||
import UserIdentifierCustomisations from '../src/customisations/UserIdentifier';
|
||||
import { ElementCall } from "../src/models/Call";
|
||||
|
||||
jest.mock("../src/settings/SettingsStore");
|
||||
jest.mock('../src/customisations/UserIdentifier', () => ({
|
||||
|
@ -444,4 +446,42 @@ describe('TextForEvent', () => {
|
|||
expect(textForEvent(messageEvent)).toEqual('@a: test message');
|
||||
});
|
||||
});
|
||||
|
||||
describe("textForCallEvent()", () => {
|
||||
let mockClient: MatrixClient;
|
||||
let callEvent: MatrixEvent;
|
||||
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
mockClient = MatrixClientPeg.get();
|
||||
|
||||
mocked(mockClient.getRoom).mockReturnValue({
|
||||
name: "Test room",
|
||||
} as unknown as Room);
|
||||
|
||||
callEvent = {
|
||||
getRoomId: jest.fn(),
|
||||
getType: jest.fn(),
|
||||
isState: jest.fn().mockReturnValue(true),
|
||||
} as unknown as MatrixEvent;
|
||||
});
|
||||
|
||||
describe.each(ElementCall.CALL_EVENT_TYPE.names)("eventType=%s", (eventType: string) => {
|
||||
beforeEach(() => {
|
||||
mocked(callEvent).getType.mockReturnValue(eventType);
|
||||
});
|
||||
|
||||
it("returns correct message for call event when supported", () => {
|
||||
expect(textForEvent(callEvent)).toEqual('Video call started in Test room.');
|
||||
});
|
||||
|
||||
it("returns correct message for call event when supported", () => {
|
||||
mocked(mockClient).supportsVoip.mockReturnValue(false);
|
||||
|
||||
expect(textForEvent(callEvent)).toEqual(
|
||||
'Video call started in Test room. (not supported by this browser)',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
EventType,
|
||||
} from 'matrix-js-sdk/src/matrix';
|
||||
import { ExtensibleEvent, MessageEvent, M_POLL_KIND_DISCLOSED, PollStartEvent } from 'matrix-events-sdk';
|
||||
import { Thread } from "matrix-js-sdk/src/models/thread";
|
||||
import { FeatureSupport, Thread } from "matrix-js-sdk/src/models/thread";
|
||||
import { mocked } from "jest-mock";
|
||||
import { act } from '@testing-library/react';
|
||||
|
||||
|
@ -469,7 +469,7 @@ describe('MessageContextMenu', () => {
|
|||
const eventContent = MessageEvent.from("hello");
|
||||
const mxEvent = new MatrixEvent(eventContent.serialize());
|
||||
|
||||
Thread.hasServerSideSupport = true;
|
||||
Thread.hasServerSideSupport = FeatureSupport.Stable;
|
||||
const context = {
|
||||
canSendMessages: true,
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
MsgType,
|
||||
Room,
|
||||
} from 'matrix-js-sdk/src/matrix';
|
||||
import { Thread } from 'matrix-js-sdk/src/models/thread';
|
||||
import { FeatureSupport, Thread } from 'matrix-js-sdk/src/models/thread';
|
||||
|
||||
import MessageActionBar from '../../../../src/components/views/messages/MessageActionBar';
|
||||
import {
|
||||
|
@ -388,13 +388,13 @@ describe('<MessageActionBar />', () => {
|
|||
|
||||
describe('thread button', () => {
|
||||
beforeEach(() => {
|
||||
Thread.setServerSideSupport(true, false);
|
||||
Thread.setServerSideSupport(FeatureSupport.Stable);
|
||||
});
|
||||
|
||||
describe('when threads feature is not enabled', () => {
|
||||
it('does not render thread button when threads does not have server support', () => {
|
||||
jest.spyOn(SettingsStore, 'getValue').mockReturnValue(false);
|
||||
Thread.setServerSideSupport(false, false);
|
||||
Thread.setServerSideSupport(FeatureSupport.None);
|
||||
const { queryByLabelText } = getComponent({ mxEvent: alicesMessageEvent });
|
||||
expect(queryByLabelText('Reply in thread')).toBeFalsy();
|
||||
});
|
||||
|
|
|
@ -115,10 +115,14 @@ exports[`<DevicesPanel /> renders device panel with devices 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -238,10 +242,14 @@ exports[`<DevicesPanel /> renders device panel with devices 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -320,10 +328,14 @@ exports[`<DevicesPanel /> renders device panel with devices 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -18,6 +18,7 @@ import { render } from '@testing-library/react';
|
|||
import React from 'react';
|
||||
|
||||
import { DeviceTypeIcon } from '../../../../../src/components/views/settings/devices/DeviceTypeIcon';
|
||||
import { DeviceType } from '../../../../../src/utils/device/parseUserAgent';
|
||||
|
||||
describe('<DeviceTypeIcon />', () => {
|
||||
const defaultProps = {
|
||||
|
@ -41,4 +42,33 @@ describe('<DeviceTypeIcon />', () => {
|
|||
const { container } = render(getComponent({ isSelected: true }));
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders an unknown device icon when no device type given', () => {
|
||||
const { getByLabelText } = render(getComponent());
|
||||
expect(getByLabelText('Unknown session type')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders a desktop device type', () => {
|
||||
const deviceType = DeviceType.Desktop;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Desktop session')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders a web device type', () => {
|
||||
const deviceType = DeviceType.Web;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Web session')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders a mobile device type', () => {
|
||||
const deviceType = DeviceType.Mobile;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Mobile session')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders an unknown device type', () => {
|
||||
const deviceType = DeviceType.Unknown;
|
||||
const { getByLabelText } = render(getComponent({ deviceType }));
|
||||
expect(getByLabelText('Unknown session type')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -154,10 +154,14 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -270,10 +274,14 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -10,10 +10,14 @@ exports[`<DeviceTile /> renders a device with no metadata 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -61,10 +65,14 @@ exports[`<DeviceTile /> renders a verified device with no metadata 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -112,10 +120,14 @@ exports[`<DeviceTile /> renders display name with a tooltip 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -163,10 +175,14 @@ exports[`<DeviceTile /> separates metadata with a dot 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -6,10 +6,14 @@ exports[`<DeviceTypeIcon /> renders a verified device 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Verified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon verified"
|
||||
|
@ -25,10 +29,14 @@ exports[`<DeviceTypeIcon /> renders an unverified device 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -44,10 +52,14 @@ exports[`<DeviceTypeIcon /> renders correctly when selected 1`] = `
|
|||
class="mx_DeviceTypeIcon mx_DeviceTypeIcon_selected"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -42,10 +42,14 @@ exports[`<SelectableDeviceTile /> renders unselected device tile with checkbox 1
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
|
|
@ -97,10 +97,14 @@ exports[`<SessionManagerTab /> renders current session section with a verified s
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Verified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon verified"
|
||||
|
@ -199,10 +203,14 @@ exports[`<SessionManagerTab /> renders current session section with an unverifie
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
|
@ -301,10 +309,14 @@ exports[`<SessionManagerTab /> sets device verification status correctly 1`] = `
|
|||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown device type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<div
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
role="img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Verified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon verified"
|
||||
|
|
158
test/toasts/IncomingCallToast-test.tsx
Normal file
158
test/toasts/IncomingCallToast-test.tsx
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
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 React from "react";
|
||||
import { render, screen, cleanup, fireEvent, waitFor } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom";
|
||||
import { mocked, Mocked } from "jest-mock";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||
import { ClientWidgetApi, Widget } from "matrix-widget-api";
|
||||
|
||||
import type { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import {
|
||||
useMockedCalls,
|
||||
MockedCall,
|
||||
stubClient,
|
||||
mkRoomMember,
|
||||
setupAsyncStoreWithClient,
|
||||
resetAsyncStoreWithClient,
|
||||
} from "../test-utils";
|
||||
import defaultDispatcher from "../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../src/dispatcher/actions";
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
import { CallStore } from "../../src/stores/CallStore";
|
||||
import { WidgetMessagingStore } from "../../src/stores/widgets/WidgetMessagingStore";
|
||||
import DMRoomMap from "../../src/utils/DMRoomMap";
|
||||
import ToastStore from "../../src/stores/ToastStore";
|
||||
import { getIncomingCallToastKey, IncomingCallToast } from "../../src/toasts/IncomingCallToast";
|
||||
|
||||
describe("IncomingCallEvent", () => {
|
||||
useMockedCalls();
|
||||
Object.defineProperty(navigator, "mediaDevices", { value: { enumerateDevices: () => [] } });
|
||||
jest.spyOn(HTMLMediaElement.prototype, "play").mockImplementation(async () => { });
|
||||
|
||||
let client: Mocked<MatrixClient>;
|
||||
let room: Room;
|
||||
let alice: RoomMember;
|
||||
let bob: RoomMember;
|
||||
let call: MockedCall;
|
||||
let widget: Widget;
|
||||
const dmRoomMap = {
|
||||
getUserIdForRoomId: jest.fn(),
|
||||
} as unknown as DMRoomMap;
|
||||
const toastStore = {
|
||||
dismissToast: jest.fn(),
|
||||
} as unknown as ToastStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
stubClient();
|
||||
client = mocked(MatrixClientPeg.get());
|
||||
|
||||
room = new Room("!1:example.org", client, "@alice:example.org");
|
||||
|
||||
alice = mkRoomMember(room.roomId, "@alice:example.org");
|
||||
bob = mkRoomMember(room.roomId, "@bob:example.org");
|
||||
|
||||
client.getRoom.mockImplementation(roomId => roomId === room.roomId ? room : null);
|
||||
client.getRooms.mockReturnValue([room]);
|
||||
client.reEmitter.reEmit(room, [RoomStateEvent.Events]);
|
||||
|
||||
await Promise.all([CallStore.instance, WidgetMessagingStore.instance].map(
|
||||
store => setupAsyncStoreWithClient(store, client),
|
||||
));
|
||||
|
||||
MockedCall.create(room, "1");
|
||||
const maybeCall = CallStore.instance.get(room.roomId);
|
||||
if (!(maybeCall instanceof MockedCall)) throw new Error("Failed to create call");
|
||||
call = maybeCall;
|
||||
|
||||
widget = new Widget(call.widget);
|
||||
WidgetMessagingStore.instance.storeMessaging(widget, room.roomId, {
|
||||
stop: () => { },
|
||||
} as unknown as ClientWidgetApi);
|
||||
|
||||
jest.spyOn(DMRoomMap, "shared").mockReturnValue(dmRoomMap);
|
||||
jest.spyOn(ToastStore, "sharedInstance").mockReturnValue(toastStore);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
cleanup(); // Unmount before we do any cleanup that might update the component
|
||||
call.destroy();
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, room.roomId);
|
||||
await Promise.all([CallStore.instance, WidgetMessagingStore.instance].map(resetAsyncStoreWithClient));
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
const renderToast = () => { render(<IncomingCallToast callEvent={call.event} />); };
|
||||
|
||||
it("correctly shows all the information", () => {
|
||||
call.participants = new Set([alice, bob]);
|
||||
renderToast();
|
||||
|
||||
screen.getByText("Video call started");
|
||||
screen.getByText("Video");
|
||||
screen.getByLabelText("2 participants");
|
||||
|
||||
screen.getByRole("button", { name: "Join" });
|
||||
screen.getByRole("button", { name: "Close" });
|
||||
});
|
||||
|
||||
it("correctly renders toast without a call", () => {
|
||||
call.destroy();
|
||||
renderToast();
|
||||
|
||||
screen.getByText("Video call started");
|
||||
screen.getByText("Video");
|
||||
|
||||
screen.getByRole("button", { name: "Join" });
|
||||
screen.getByRole("button", { name: "Close" });
|
||||
});
|
||||
|
||||
it("joins the call and closes the toast", async () => {
|
||||
renderToast();
|
||||
|
||||
const dispatcherSpy = jest.fn();
|
||||
const dispatcherRef = defaultDispatcher.register(dispatcherSpy);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Join" }));
|
||||
await waitFor(() => expect(dispatcherSpy).toHaveBeenCalledWith({
|
||||
action: Action.ViewRoom,
|
||||
room_id: room.roomId,
|
||||
view_call: true,
|
||||
}));
|
||||
await waitFor(() => expect(toastStore.dismissToast).toHaveBeenCalledWith(
|
||||
getIncomingCallToastKey(call.event.getStateKey()!),
|
||||
));
|
||||
|
||||
defaultDispatcher.unregister(dispatcherRef);
|
||||
});
|
||||
|
||||
it("closes the toast", async () => {
|
||||
renderToast();
|
||||
|
||||
const dispatcherSpy = jest.fn();
|
||||
const dispatcherRef = defaultDispatcher.register(dispatcherSpy);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Close" }));
|
||||
await waitFor(() => expect(toastStore.dismissToast).toHaveBeenCalledWith(
|
||||
getIncomingCallToastKey(call.event.getStateKey()!),
|
||||
));
|
||||
|
||||
defaultDispatcher.unregister(dispatcherRef);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue