Merge remote-tracking branch 'origin/develop' into rav/edited_events
This commit is contained in:
+112
-28
@@ -19,6 +19,7 @@ import {
|
||||
LOCAL_NOTIFICATION_SETTINGS_PREFIX,
|
||||
MatrixEvent,
|
||||
PushRuleKind,
|
||||
Room,
|
||||
RuleId,
|
||||
TweakName,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
@@ -43,6 +44,28 @@ import { Action } from "../src/dispatcher/actions";
|
||||
import { getFunctionalMembers } from "../src/utils/room/getFunctionalMembers";
|
||||
import SettingsStore from "../src/settings/SettingsStore";
|
||||
import { UIFeature } from "../src/settings/UIFeature";
|
||||
import { VoiceBroadcastInfoState, VoiceBroadcastPlayback, VoiceBroadcastRecording } from "../src/voice-broadcast";
|
||||
import { mkVoiceBroadcastInfoStateEvent } from "./voice-broadcast/utils/test-utils";
|
||||
import { SdkContextClass } from "../src/contexts/SDKContext";
|
||||
import Modal from "../src/Modal";
|
||||
|
||||
jest.mock("../src/Modal");
|
||||
|
||||
// mock VoiceRecording because it contains all the audio APIs
|
||||
jest.mock("../src/audio/VoiceRecording", () => ({
|
||||
VoiceRecording: jest.fn().mockReturnValue({
|
||||
disableMaxLength: jest.fn(),
|
||||
liveData: {
|
||||
onUpdate: jest.fn(),
|
||||
},
|
||||
off: jest.fn(),
|
||||
on: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
destroy: jest.fn(),
|
||||
contentType: "audio/ogg",
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock("../src/utils/room/getFunctionalMembers", () => ({
|
||||
getFunctionalMembers: jest.fn(),
|
||||
@@ -71,7 +94,7 @@ const VIRTUAL_ROOM_BOB = "$virtual_bob_room:example.org";
|
||||
// Bob's phone number
|
||||
const BOB_PHONE_NUMBER = "01818118181";
|
||||
|
||||
function mkStubDM(roomId, userId) {
|
||||
function mkStubDM(roomId: string, userId: string) {
|
||||
const room = mkStubRoom(roomId, "room", MatrixClientPeg.get());
|
||||
room.getJoinedMembers = jest.fn().mockReturnValue([
|
||||
{
|
||||
@@ -134,23 +157,24 @@ function untilCallHandlerEvent(callHandler: LegacyCallHandler, event: LegacyCall
|
||||
|
||||
describe("LegacyCallHandler", () => {
|
||||
let dmRoomMap;
|
||||
let callHandler;
|
||||
let callHandler: LegacyCallHandler;
|
||||
let audioElement: HTMLAudioElement;
|
||||
let fakeCall;
|
||||
let fakeCall: MatrixCall | null;
|
||||
|
||||
// what addresses the app has looked up via pstn and native lookup
|
||||
let pstnLookup: string;
|
||||
let nativeLookup: string;
|
||||
let pstnLookup: string | null;
|
||||
let nativeLookup: string | null;
|
||||
const deviceId = "my-device";
|
||||
|
||||
beforeEach(async () => {
|
||||
stubClient();
|
||||
MatrixClientPeg.get().createCall = (roomId) => {
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.get().createCall = (roomId: string): MatrixCall | null => {
|
||||
if (fakeCall && fakeCall.roomId !== roomId) {
|
||||
throw new Error("Only one call is supported!");
|
||||
}
|
||||
fakeCall = new FakeCall(roomId);
|
||||
return fakeCall;
|
||||
fakeCall = new FakeCall(roomId) as unknown as MatrixCall;
|
||||
return fakeCall as unknown as MatrixCall;
|
||||
};
|
||||
MatrixClientPeg.get().deviceId = deviceId;
|
||||
|
||||
@@ -172,7 +196,7 @@ describe("LegacyCallHandler", () => {
|
||||
const nativeRoomCharie = mkStubDM(NATIVE_ROOM_CHARLIE, NATIVE_CHARLIE);
|
||||
const virtualBobRoom = mkStubDM(VIRTUAL_ROOM_BOB, VIRTUAL_BOB);
|
||||
|
||||
MatrixClientPeg.get().getRoom = (roomId) => {
|
||||
MatrixClientPeg.get().getRoom = (roomId: string): Room | null => {
|
||||
switch (roomId) {
|
||||
case NATIVE_ROOM_ALICE:
|
||||
return nativeRoomAlice;
|
||||
@@ -183,6 +207,8 @@ describe("LegacyCallHandler", () => {
|
||||
case VIRTUAL_ROOM_BOB:
|
||||
return virtualBobRoom;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
dmRoomMap = {
|
||||
@@ -212,13 +238,13 @@ describe("LegacyCallHandler", () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
} as DMRoomMap;
|
||||
DMRoomMap.setShared(dmRoomMap);
|
||||
|
||||
pstnLookup = null;
|
||||
nativeLookup = null;
|
||||
|
||||
MatrixClientPeg.get().getThirdpartyUser = (proto, params) => {
|
||||
MatrixClientPeg.get().getThirdpartyUser = (proto: string, params: any) => {
|
||||
if ([PROTOCOL_PSTN, PROTOCOL_PSTN_PREFIXED].includes(proto)) {
|
||||
pstnLookup = params["m.id.phone"];
|
||||
return Promise.resolve([
|
||||
@@ -261,6 +287,8 @@ describe("LegacyCallHandler", () => {
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
audioElement = document.createElement("audio");
|
||||
@@ -270,10 +298,10 @@ describe("LegacyCallHandler", () => {
|
||||
|
||||
afterEach(() => {
|
||||
callHandler.stop();
|
||||
// @ts-ignore
|
||||
DMRoomMap.setShared(null);
|
||||
// @ts-ignore
|
||||
window.mxLegacyCallHandler = null;
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.unset();
|
||||
|
||||
document.body.removeChild(audioElement);
|
||||
@@ -292,25 +320,27 @@ describe("LegacyCallHandler", () => {
|
||||
|
||||
// Check that a call was started: its room on the protocol level
|
||||
// should be the virtual room
|
||||
expect(fakeCall.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall?.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
|
||||
// but it should appear to the user to be in thw native room for Bob
|
||||
expect(callHandler.roomIdForCall(fakeCall)).toEqual(NATIVE_ROOM_BOB);
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
|
||||
});
|
||||
|
||||
it("should look up the correct user and start a call in the room when a call is transferred", async () => {
|
||||
// we can pass a very minimal object as as the call since we pass consultFirst=true:
|
||||
// we don't need to actually do any transferring
|
||||
const mockTransferreeCall = { type: CallType.Voice };
|
||||
const mockTransferreeCall = { type: CallType.Voice } as unknown as MatrixCall;
|
||||
await callHandler.startTransferToPhoneNumber(mockTransferreeCall, BOB_PHONE_NUMBER, true);
|
||||
|
||||
// same checks as above
|
||||
const viewRoomPayload = await untilDispatch(Action.ViewRoom);
|
||||
expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB);
|
||||
|
||||
expect(fakeCall.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall!.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
|
||||
expect(callHandler.roomIdForCall(fakeCall)).toEqual(NATIVE_ROOM_BOB);
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
|
||||
});
|
||||
|
||||
it("should move calls between rooms when remote asserted identity changes", async () => {
|
||||
@@ -331,10 +361,11 @@ describe("LegacyCallHandler", () => {
|
||||
|
||||
// Now emit an asserted identity for Bob: this should be ignored
|
||||
// because we haven't set the config option to obey asserted identity
|
||||
fakeCall.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
expect(fakeCall).not.toBeNull();
|
||||
fakeCall!.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
id: NATIVE_BOB,
|
||||
});
|
||||
fakeCall.emit(CallEvent.AssertedIdentityChanged);
|
||||
fakeCall!.emit(CallEvent.AssertedIdentityChanged);
|
||||
|
||||
// Now set the config option
|
||||
SdkConfig.add({
|
||||
@@ -344,10 +375,10 @@ describe("LegacyCallHandler", () => {
|
||||
});
|
||||
|
||||
// ...and send another asserted identity event for a different user
|
||||
fakeCall.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
fakeCall!.getRemoteAssertedIdentity = jest.fn().mockReturnValue({
|
||||
id: NATIVE_CHARLIE,
|
||||
});
|
||||
fakeCall.emit(CallEvent.AssertedIdentityChanged);
|
||||
fakeCall!.emit(CallEvent.AssertedIdentityChanged);
|
||||
|
||||
await roomChangePromise;
|
||||
callHandler.removeAllListeners();
|
||||
@@ -362,21 +393,68 @@ describe("LegacyCallHandler", () => {
|
||||
expect(callHandler.getCallForRoom(NATIVE_ROOM_BOB)).toBeNull();
|
||||
expect(callHandler.getCallForRoom(NATIVE_ROOM_CHARLIE)).toBe(fakeCall);
|
||||
});
|
||||
|
||||
describe("when listening to a voice broadcast", () => {
|
||||
let voiceBroadcastPlayback: VoiceBroadcastPlayback;
|
||||
|
||||
beforeEach(() => {
|
||||
voiceBroadcastPlayback = new VoiceBroadcastPlayback(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
"!room:example.com",
|
||||
VoiceBroadcastInfoState.Started,
|
||||
MatrixClientPeg.get().getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
MatrixClientPeg.get(),
|
||||
);
|
||||
SdkContextClass.instance.voiceBroadcastPlaybacksStore.setCurrent(voiceBroadcastPlayback);
|
||||
jest.spyOn(voiceBroadcastPlayback, "pause").mockImplementation();
|
||||
});
|
||||
|
||||
it("and placing a call should pause the broadcast", async () => {
|
||||
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
|
||||
await untilCallHandlerEvent(callHandler, LegacyCallHandlerEvent.CallState);
|
||||
|
||||
expect(voiceBroadcastPlayback.pause).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when recording a voice broadcast", () => {
|
||||
beforeEach(() => {
|
||||
SdkContextClass.instance.voiceBroadcastRecordingsStore.setCurrent(
|
||||
new VoiceBroadcastRecording(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
"!room:example.com",
|
||||
VoiceBroadcastInfoState.Started,
|
||||
MatrixClientPeg.get().getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
MatrixClientPeg.get(),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("and placing a call should show the info dialog", async () => {
|
||||
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
|
||||
expect(Modal.createDialog).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("LegacyCallHandler without third party protocols", () => {
|
||||
let dmRoomMap;
|
||||
let callHandler: LegacyCallHandler;
|
||||
let audioElement: HTMLAudioElement;
|
||||
let fakeCall;
|
||||
let fakeCall: MatrixCall | null;
|
||||
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.get().createCall = (roomId) => {
|
||||
if (fakeCall && fakeCall.roomId !== roomId) {
|
||||
throw new Error("Only one call is supported!");
|
||||
}
|
||||
fakeCall = new FakeCall(roomId);
|
||||
fakeCall = new FakeCall(roomId) as unknown as MatrixCall;
|
||||
return fakeCall;
|
||||
};
|
||||
|
||||
@@ -389,11 +467,13 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
|
||||
const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE);
|
||||
|
||||
MatrixClientPeg.get().getRoom = (roomId) => {
|
||||
MatrixClientPeg.get().getRoom = (roomId: string): Room | null => {
|
||||
switch (roomId) {
|
||||
case NATIVE_ROOM_ALICE:
|
||||
return nativeRoomAlice;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
dmRoomMap = {
|
||||
@@ -411,7 +491,7 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
} as DMRoomMap;
|
||||
DMRoomMap.setShared(dmRoomMap);
|
||||
|
||||
MatrixClientPeg.get().getThirdpartyUser = (_proto, _params) => {
|
||||
@@ -421,14 +501,17 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
audioElement = document.createElement("audio");
|
||||
audioElement.id = "remoteAudio";
|
||||
document.body.appendChild(audioElement);
|
||||
|
||||
SdkContextClass.instance.voiceBroadcastPlaybacksStore.clearCurrent();
|
||||
SdkContextClass.instance.voiceBroadcastRecordingsStore.clearCurrent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
callHandler.stop();
|
||||
// @ts-ignore
|
||||
DMRoomMap.setShared(null);
|
||||
// @ts-ignore
|
||||
window.mxLegacyCallHandler = null;
|
||||
fakeCall = null;
|
||||
MatrixClientPeg.unset();
|
||||
|
||||
document.body.removeChild(audioElement);
|
||||
@@ -442,10 +525,11 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
|
||||
// Check that a call was started: its room on the protocol level
|
||||
// should be the virtual room
|
||||
expect(fakeCall.roomId).toEqual(NATIVE_ROOM_ALICE);
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall!.roomId).toEqual(NATIVE_ROOM_ALICE);
|
||||
|
||||
// but it should appear to the user to be in thw native room for Bob
|
||||
expect(callHandler.roomIdForCall(fakeCall)).toEqual(NATIVE_ROOM_ALICE);
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_ALICE);
|
||||
});
|
||||
|
||||
describe("incoming calls", () => {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LegacyCallHandler when recording a voice broadcast and placing a call should show the info dialog 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
[Function],
|
||||
{
|
||||
"description": <p>
|
||||
You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.
|
||||
</p>,
|
||||
"hasCloseButton": true,
|
||||
"title": "Can’t start a call",
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
import React from "react";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { act } from "react-dom/test-utils";
|
||||
import { Beacon, Room, RoomMember, MatrixEvent, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
@@ -41,7 +41,8 @@ describe("<BeaconMarker />", () => {
|
||||
|
||||
const aliceMember = new RoomMember(roomId, aliceId);
|
||||
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
getClientWellKnown: jest.fn().mockReturnValue({
|
||||
|
||||
@@ -19,7 +19,7 @@ import React from "react";
|
||||
import { mount, ReactWrapper } from "enzyme";
|
||||
import { act } from "react-dom/test-utils";
|
||||
import { MatrixClient, MatrixEvent, Room, RoomMember, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import BeaconViewDialog from "../../../../src/components/views/beacon/BeaconViewDialog";
|
||||
@@ -58,7 +58,8 @@ describe("<BeaconViewDialog />", () => {
|
||||
getVisibleRooms: jest.fn().mockReturnValue([]),
|
||||
});
|
||||
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
|
||||
// make fresh rooms every time
|
||||
// as we update room state
|
||||
@@ -91,10 +92,6 @@ describe("<BeaconViewDialog />", () => {
|
||||
component.setProps({});
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
maplibregl.AttributionControl = jest.fn();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(OwnBeaconStore.instance, "getLiveBeaconIds").mockRestore();
|
||||
jest.spyOn(OwnBeaconStore.instance, "getBeaconById").mockRestore();
|
||||
|
||||
@@ -15,7 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import { act } from "react-dom/test-utils";
|
||||
@@ -62,8 +62,9 @@ describe("LocationPicker", () => {
|
||||
wrappingComponentProps: { value: mockClient },
|
||||
});
|
||||
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mockGeolocate = new maplibregl.GeolocateControl();
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
const mockGeolocate = new maplibregl.GeolocateControl({});
|
||||
const mockMarker = new maplibregl.Marker();
|
||||
|
||||
const mockGeolocationPosition = {
|
||||
|
||||
@@ -19,7 +19,6 @@ import React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
|
||||
import maplibregl from "maplibre-gl";
|
||||
|
||||
import LocationViewDialog from "../../../../src/components/views/location/LocationViewDialog";
|
||||
import { TILE_SERVER_WK_KEY } from "../../../../src/utils/WellKnownUtils";
|
||||
@@ -42,10 +41,6 @@ describe("<LocationViewDialog />", () => {
|
||||
};
|
||||
const getComponent = (props = {}) => mount(<LocationViewDialog {...defaultProps} {...props} />);
|
||||
|
||||
beforeAll(() => {
|
||||
maplibregl.AttributionControl = jest.fn();
|
||||
});
|
||||
|
||||
it("renders map correctly", () => {
|
||||
const component = getComponent();
|
||||
expect(component.find("Map")).toMatchSnapshot();
|
||||
|
||||
@@ -18,7 +18,7 @@ import React from "react";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import { act } from "react-dom/test-utils";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { ClientEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
@@ -45,10 +45,6 @@ describe("<Map />", () => {
|
||||
wrappingComponentProps: { value: matrixClient },
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
maplibregl.AttributionControl = jest.fn();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
matrixClient.getClientWellKnown.mockReturnValue({
|
||||
@@ -58,7 +54,8 @@ describe("<Map />", () => {
|
||||
jest.spyOn(logger, "error").mockRestore();
|
||||
});
|
||||
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
|
||||
it("renders", () => {
|
||||
const component = getComponent();
|
||||
|
||||
@@ -18,7 +18,7 @@ import React from "react";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import { mocked } from "jest-mock";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
|
||||
import SmartMarker from "../../../../src/components/views/location/SmartMarker";
|
||||
|
||||
@@ -27,7 +27,8 @@ jest.mock("../../../../src/utils/location/findMapStyleUrl", () => ({
|
||||
}));
|
||||
|
||||
describe("<SmartMarker />", () => {
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
const mockMarker = new maplibregl.Marker();
|
||||
|
||||
const defaultProps = {
|
||||
|
||||
@@ -17,14 +17,15 @@ limitations under the License.
|
||||
import React from "react";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { act } from "react-dom/test-utils";
|
||||
|
||||
import ZoomButtons from "../../../../src/components/views/location/ZoomButtons";
|
||||
import { findByTestId } from "../../../test-utils";
|
||||
|
||||
describe("<ZoomButtons />", () => {
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
const defaultProps = {
|
||||
map: mockMap,
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ exports[`<LocationViewDialog /> renders map correctly 1`] = `
|
||||
"addControl": [MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
mockConstructor {},
|
||||
MockAttributionControl {},
|
||||
"top-right",
|
||||
],
|
||||
],
|
||||
@@ -94,7 +94,7 @@ exports[`<LocationViewDialog /> renders map correctly 1`] = `
|
||||
"addControl": [MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
mockConstructor {},
|
||||
MockAttributionControl {},
|
||||
"top-right",
|
||||
],
|
||||
],
|
||||
|
||||
@@ -18,7 +18,7 @@ import React from "react";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import { act } from "react-dom/test-utils";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { BeaconEvent, getBeaconInfoIdentifier, RelationType, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import { Relations } from "matrix-js-sdk/src/models/relations";
|
||||
import { M_BEACON } from "matrix-js-sdk/src/@types/beacon";
|
||||
@@ -48,7 +48,8 @@ describe("<MBeaconBody />", () => {
|
||||
const roomId = "!room:server";
|
||||
const aliceId = "@alice:server";
|
||||
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
const mockMarker = new maplibregl.Marker();
|
||||
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
@@ -81,10 +82,6 @@ describe("<MBeaconBody />", () => {
|
||||
|
||||
const modalSpy = jest.spyOn(Modal, "createDialog").mockReturnValue(undefined);
|
||||
|
||||
beforeAll(() => {
|
||||
maplibregl.AttributionControl = jest.fn();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ import React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
|
||||
import { ClientEvent, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import maplibregl from "maplibre-gl";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { act } from "react-dom/test-utils";
|
||||
import { SyncState } from "matrix-js-sdk/src/sync";
|
||||
@@ -35,6 +35,7 @@ import { makeLocationEvent } from "../../../test-utils/location";
|
||||
import { getMockClientWithEventEmitter } from "../../../test-utils";
|
||||
|
||||
describe("MLocationBody", () => {
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
describe("<MLocationBody>", () => {
|
||||
const roomId = "!room:server";
|
||||
const userId = "@user:server";
|
||||
@@ -60,7 +61,7 @@ describe("MLocationBody", () => {
|
||||
wrappingComponentProps: { value: mockClient },
|
||||
});
|
||||
const getMapErrorComponent = () => {
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
mockClient.getClientWellKnown.mockReturnValue({
|
||||
[TILE_SERVER_WK_KEY.name]: { map_style_url: "bad-tile-server.com" },
|
||||
});
|
||||
@@ -73,10 +74,6 @@ describe("MLocationBody", () => {
|
||||
return component;
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
maplibregl.AttributionControl = jest.fn();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
@@ -131,7 +128,7 @@ describe("MLocationBody", () => {
|
||||
});
|
||||
|
||||
it("renders map correctly", () => {
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
const component = getComponent();
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
@@ -154,7 +151,7 @@ describe("MLocationBody", () => {
|
||||
});
|
||||
|
||||
it("renders marker correctly for a non-self share", () => {
|
||||
const mockMap = new maplibregl.Map();
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
const component = getComponent();
|
||||
|
||||
expect(component.find("SmartMarker").at(0).props()).toEqual(
|
||||
|
||||
@@ -131,11 +131,11 @@ exports[`MLocationBody <MLocationBody> without error renders map correctly 1`] =
|
||||
"addControl": [MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
mockConstructor {},
|
||||
MockAttributionControl {},
|
||||
"top-right",
|
||||
],
|
||||
[
|
||||
mockConstructor {},
|
||||
MockAttributionControl {},
|
||||
"top-right",
|
||||
],
|
||||
],
|
||||
|
||||
+3
-3
@@ -13,11 +13,11 @@ HTMLCollection [
|
||||
class="mx_DeviceDetailHeading"
|
||||
data-testid="device-detail-heading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h3"
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
alices_device
|
||||
</h3>
|
||||
</h4>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_DeviceDetailHeading_renameCta mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
data-testid="device-heading-rename-cta"
|
||||
|
||||
+3
-3
@@ -78,11 +78,11 @@ exports[`<DeviceDetailHeading /> renders device name 1`] = `
|
||||
class="mx_DeviceDetailHeading"
|
||||
data-testid="device-detail-heading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h3"
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
My device
|
||||
</h3>
|
||||
</h4>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_DeviceDetailHeading_renameCta mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
data-testid="device-heading-rename-cta"
|
||||
|
||||
@@ -13,11 +13,11 @@ exports[`<DeviceDetails /> renders a verified device 1`] = `
|
||||
class="mx_DeviceDetailHeading"
|
||||
data-testid="device-detail-heading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h3"
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
my-device
|
||||
</h3>
|
||||
</h4>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_DeviceDetailHeading_renameCta mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
data-testid="device-heading-rename-cta"
|
||||
@@ -122,11 +122,11 @@ exports[`<DeviceDetails /> renders device with metadata 1`] = `
|
||||
class="mx_DeviceDetailHeading"
|
||||
data-testid="device-detail-heading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h3"
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
My Device
|
||||
</h3>
|
||||
</h4>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_DeviceDetailHeading_renameCta mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
data-testid="device-heading-rename-cta"
|
||||
@@ -331,11 +331,11 @@ exports[`<DeviceDetails /> renders device without metadata 1`] = `
|
||||
class="mx_DeviceDetailHeading"
|
||||
data-testid="device-detail-heading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h3"
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
my-device
|
||||
</h3>
|
||||
</h4>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_DeviceDetailHeading_renameCta mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
data-testid="device-heading-rename-cta"
|
||||
|
||||
+6
-6
@@ -18,7 +18,7 @@ exports[`<SecurityRecommendations /> renders both cards when user has both unver
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
Improve your account security by following these recommendations
|
||||
Improve your account security by following these recommendations.
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
@@ -93,7 +93,7 @@ exports[`<SecurityRecommendations /> renders both cards when user has both unver
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
Consider signing out from old sessions (90 days or older) you don't use anymore
|
||||
Consider signing out from old sessions (90 days or older) you don't use anymore.
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
@@ -139,7 +139,7 @@ exports[`<SecurityRecommendations /> renders inactive devices section when user
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
Improve your account security by following these recommendations
|
||||
Improve your account security by following these recommendations.
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
@@ -214,7 +214,7 @@ exports[`<SecurityRecommendations /> renders inactive devices section when user
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
Consider signing out from old sessions (90 days or older) you don't use anymore
|
||||
Consider signing out from old sessions (90 days or older) you don't use anymore.
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
@@ -260,7 +260,7 @@ exports[`<SecurityRecommendations /> renders unverified devices section when use
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
Improve your account security by following these recommendations
|
||||
Improve your account security by following these recommendations.
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
@@ -335,7 +335,7 @@ exports[`<SecurityRecommendations /> renders unverified devices section when use
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
Consider signing out from old sessions (90 days or older) you don't use anymore
|
||||
Consider signing out from old sessions (90 days or older) you don't use anymore.
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
|
||||
@@ -420,6 +420,21 @@ describe("<SessionManagerTab />", () => {
|
||||
|
||||
expect(getByTestId("current-session-section")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("expands current session details", async () => {
|
||||
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
|
||||
const { getByTestId } = render(getComponent());
|
||||
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
fireEvent.click(getByTestId("current-session-toggle-details"));
|
||||
|
||||
expect(getByTestId(`device-detail-${alicesDevice.device_id}`)).toBeTruthy();
|
||||
// only one security card rendered
|
||||
expect(getByTestId("current-session-section").querySelectorAll(".mx_DeviceSecurityCard").length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("device detail expansion", () => {
|
||||
|
||||
@@ -28,6 +28,17 @@ import { UPDATE_EVENT } from "../../src/stores/AsyncStore";
|
||||
import { ActiveRoomChangedPayload } from "../../src/dispatcher/payloads/ActiveRoomChangedPayload";
|
||||
import { SpaceStoreClass } from "../../src/stores/spaces/SpaceStore";
|
||||
import { TestSdkContext } from "../TestSdkContext";
|
||||
import { ViewRoomPayload } from "../../src/dispatcher/payloads/ViewRoomPayload";
|
||||
import {
|
||||
VoiceBroadcastInfoState,
|
||||
VoiceBroadcastPlayback,
|
||||
VoiceBroadcastPlaybacksStore,
|
||||
VoiceBroadcastRecording,
|
||||
} from "../../src/voice-broadcast";
|
||||
import { mkVoiceBroadcastInfoStateEvent } from "../voice-broadcast/utils/test-utils";
|
||||
import Modal from "../../src/Modal";
|
||||
|
||||
jest.mock("../../src/Modal");
|
||||
|
||||
// mock out the injected classes
|
||||
jest.mock("../../src/PosthogAnalytics");
|
||||
@@ -37,6 +48,22 @@ const MockSlidingSyncManager = <jest.Mock<SlidingSyncManager>>(<unknown>SlidingS
|
||||
jest.mock("../../src/stores/spaces/SpaceStore");
|
||||
const MockSpaceStore = <jest.Mock<SpaceStoreClass>>(<unknown>SpaceStoreClass);
|
||||
|
||||
// mock VoiceRecording because it contains all the audio APIs
|
||||
jest.mock("../../src/audio/VoiceRecording", () => ({
|
||||
VoiceRecording: jest.fn().mockReturnValue({
|
||||
disableMaxLength: jest.fn(),
|
||||
liveData: {
|
||||
onUpdate: jest.fn(),
|
||||
},
|
||||
off: jest.fn(),
|
||||
on: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
destroy: jest.fn(),
|
||||
contentType: "audio/ogg",
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock("../../src/utils/DMRoomMap", () => {
|
||||
const mock = {
|
||||
getUserIdForRoomId: jest.fn(),
|
||||
@@ -60,12 +87,24 @@ describe("RoomViewStore", function () {
|
||||
getRoom: jest.fn(),
|
||||
getRoomIdForAlias: jest.fn(),
|
||||
isGuest: jest.fn(),
|
||||
getSafeUserId: jest.fn(),
|
||||
});
|
||||
const room = new Room(roomId, mockClient, userId);
|
||||
|
||||
const viewCall = async (): Promise<void> => {
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: roomId,
|
||||
view_call: true,
|
||||
metricsTrigger: undefined,
|
||||
});
|
||||
await untilDispatch(Action.ViewRoom, dis);
|
||||
};
|
||||
|
||||
let roomViewStore: RoomViewStore;
|
||||
let slidingSyncManager: SlidingSyncManager;
|
||||
let dis: MatrixDispatcher;
|
||||
let stores: TestSdkContext;
|
||||
|
||||
beforeEach(function () {
|
||||
jest.clearAllMocks();
|
||||
@@ -73,14 +112,16 @@ describe("RoomViewStore", function () {
|
||||
mockClient.joinRoom.mockResolvedValue(room);
|
||||
mockClient.getRoom.mockReturnValue(room);
|
||||
mockClient.isGuest.mockReturnValue(false);
|
||||
mockClient.getSafeUserId.mockReturnValue(userId);
|
||||
|
||||
// Make the RVS to test
|
||||
dis = new MatrixDispatcher();
|
||||
slidingSyncManager = new MockSlidingSyncManager();
|
||||
const stores = new TestSdkContext();
|
||||
stores = new TestSdkContext();
|
||||
stores._SlidingSyncManager = slidingSyncManager;
|
||||
stores._PosthogAnalytics = new MockPosthogAnalytics();
|
||||
stores._SpaceStore = new MockSpaceStore();
|
||||
stores._VoiceBroadcastPlaybacksStore = new VoiceBroadcastPlaybacksStore();
|
||||
roomViewStore = new RoomViewStore(dis, stores);
|
||||
stores._RoomViewStore = roomViewStore;
|
||||
});
|
||||
@@ -206,6 +247,56 @@ describe("RoomViewStore", function () {
|
||||
expect(roomViewStore.getRoomId()).toBeNull();
|
||||
});
|
||||
|
||||
it("when viewing a call without a broadcast, it should not raise an error", async () => {
|
||||
await viewCall();
|
||||
});
|
||||
|
||||
describe("when listening to a voice broadcast", () => {
|
||||
let voiceBroadcastPlayback: VoiceBroadcastPlayback;
|
||||
|
||||
beforeEach(() => {
|
||||
voiceBroadcastPlayback = new VoiceBroadcastPlayback(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
roomId,
|
||||
VoiceBroadcastInfoState.Started,
|
||||
mockClient.getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
mockClient,
|
||||
);
|
||||
stores.voiceBroadcastPlaybacksStore.setCurrent(voiceBroadcastPlayback);
|
||||
jest.spyOn(voiceBroadcastPlayback, "pause").mockImplementation();
|
||||
});
|
||||
|
||||
it("and viewing a call it should pause the current broadcast", async () => {
|
||||
await viewCall();
|
||||
expect(voiceBroadcastPlayback.pause).toHaveBeenCalled();
|
||||
expect(roomViewStore.isViewingCall()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when recording a voice broadcast", () => {
|
||||
beforeEach(() => {
|
||||
stores.voiceBroadcastRecordingsStore.setCurrent(
|
||||
new VoiceBroadcastRecording(
|
||||
mkVoiceBroadcastInfoStateEvent(
|
||||
roomId,
|
||||
VoiceBroadcastInfoState.Started,
|
||||
mockClient.getSafeUserId(),
|
||||
"d42",
|
||||
),
|
||||
mockClient,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("and trying to view a call, it should not actually view it and show the info dialog", async () => {
|
||||
await viewCall();
|
||||
expect(Modal.createDialog).toMatchSnapshot();
|
||||
expect(roomViewStore.isViewingCall()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Sliding Sync", function () {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName, roomId, value) => {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RoomViewStore when recording a voice broadcast and trying to view a call, it should not actually view it and show the info dialog 1`] = `
|
||||
[MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
[Function],
|
||||
{
|
||||
"description": <p>
|
||||
You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.
|
||||
</p>,
|
||||
"hasCloseButton": true,
|
||||
"title": "Can’t start a call",
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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 { ListAlgorithm, SortAlgorithm } from "../../../src/stores/room-list/algorithms/models";
|
||||
import { OrderedDefaultTagIDs } from "../../../src/stores/room-list/models";
|
||||
import RoomListStore, { RoomListStoreClass } from "../../../src/stores/room-list/RoomListStore";
|
||||
import { stubClient } from "../../test-utils";
|
||||
|
||||
describe("RoomListStore", () => {
|
||||
beforeAll(async () => {
|
||||
const client = stubClient();
|
||||
await (RoomListStore.instance as RoomListStoreClass).makeReady(client);
|
||||
});
|
||||
|
||||
it.each(OrderedDefaultTagIDs)("defaults to importance ordering for %s=", (tagId) => {
|
||||
expect(RoomListStore.instance.getTagSorting(tagId)).toBe(SortAlgorithm.Recent);
|
||||
});
|
||||
|
||||
it.each(OrderedDefaultTagIDs)("defaults to activity ordering for %s=", (tagId) => {
|
||||
expect(RoomListStore.instance.getListOrder(tagId)).toBe(ListAlgorithm.Importance);
|
||||
});
|
||||
});
|
||||
@@ -411,6 +411,10 @@ describe("VoiceBroadcastPlayback", () => {
|
||||
stopPlayback();
|
||||
itShouldSetTheStateTo(VoiceBroadcastPlaybackState.Stopped);
|
||||
|
||||
it("should stop the playback", () => {
|
||||
expect(chunk1Playback.stop).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("and skipping to somewhere in the middle of the first chunk", () => {
|
||||
beforeEach(async () => {
|
||||
mocked(chunk1Playback.play).mockClear();
|
||||
|
||||
Reference in New Issue
Block a user