Live location sharing - stop sharing to beacons in rooms you left (#8187)
* remove beacons on membership changes * add addMembershipToMockedRoom test util Signed-off-by: Kerry Archibald <kerrya@element.io> * test remove beacons on membership changes Signed-off-by: Kerry Archibald <kerrya@element.io> * removelistener Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
e161f0b17b
commit
2adc972eec
4 changed files with 269 additions and 60 deletions
|
@ -14,7 +14,14 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { Room, Beacon, BeaconEvent, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import {
|
||||
Room,
|
||||
Beacon,
|
||||
BeaconEvent,
|
||||
MatrixEvent,
|
||||
RoomStateEvent,
|
||||
RoomMember,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { makeBeaconContent } from "matrix-js-sdk/src/content-helpers";
|
||||
import { M_BEACON, M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
@ -23,6 +30,7 @@ import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../src/stores/OwnBeaconS
|
|||
import {
|
||||
advanceDateAndTime,
|
||||
flushPromisesWithFakeTimers,
|
||||
makeMembershipEvent,
|
||||
resetAsyncStoreWithClient,
|
||||
setupAsyncStoreWithClient,
|
||||
} from "../test-utils";
|
||||
|
@ -243,6 +251,7 @@ describe('OwnBeaconStore', () => {
|
|||
|
||||
expect(removeSpy.mock.calls[0]).toEqual(expect.arrayContaining([BeaconEvent.LivenessChange]));
|
||||
expect(removeSpy.mock.calls[1]).toEqual(expect.arrayContaining([BeaconEvent.New]));
|
||||
expect(removeSpy.mock.calls[2]).toEqual(expect.arrayContaining([RoomStateEvent.Members]));
|
||||
});
|
||||
|
||||
it('destroys beacons', async () => {
|
||||
|
@ -509,6 +518,112 @@ describe('OwnBeaconStore', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('on room membership changes', () => {
|
||||
it('ignores events for rooms without beacons', async () => {
|
||||
const membershipEvent = makeMembershipEvent(room2Id, aliceId);
|
||||
// no beacons for room2
|
||||
const [, room2] = makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
const emitSpy = jest.spyOn(store, 'emit');
|
||||
const oldLiveBeaconIds = store.getLiveBeaconIds();
|
||||
|
||||
mockClient.emit(
|
||||
RoomStateEvent.Members,
|
||||
membershipEvent,
|
||||
room2.currentState,
|
||||
new RoomMember(room2Id, aliceId),
|
||||
);
|
||||
|
||||
expect(emitSpy).not.toHaveBeenCalled();
|
||||
// strictly equal
|
||||
expect(store.getLiveBeaconIds()).toBe(oldLiveBeaconIds);
|
||||
});
|
||||
|
||||
it('ignores events for membership changes that are not current user', async () => {
|
||||
// bob joins room1
|
||||
const membershipEvent = makeMembershipEvent(room1Id, bobId);
|
||||
const member = new RoomMember(room1Id, bobId);
|
||||
member.setMembershipEvent(membershipEvent);
|
||||
|
||||
const [room1] = makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
const emitSpy = jest.spyOn(store, 'emit');
|
||||
const oldLiveBeaconIds = store.getLiveBeaconIds();
|
||||
|
||||
mockClient.emit(
|
||||
RoomStateEvent.Members,
|
||||
membershipEvent,
|
||||
room1.currentState,
|
||||
member,
|
||||
);
|
||||
|
||||
expect(emitSpy).not.toHaveBeenCalled();
|
||||
// strictly equal
|
||||
expect(store.getLiveBeaconIds()).toBe(oldLiveBeaconIds);
|
||||
});
|
||||
|
||||
it('ignores events for membership changes that are not leave/ban', async () => {
|
||||
// alice joins room1
|
||||
const membershipEvent = makeMembershipEvent(room1Id, aliceId);
|
||||
const member = new RoomMember(room1Id, aliceId);
|
||||
member.setMembershipEvent(membershipEvent);
|
||||
|
||||
const [room1] = makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesRoom2BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
const emitSpy = jest.spyOn(store, 'emit');
|
||||
const oldLiveBeaconIds = store.getLiveBeaconIds();
|
||||
|
||||
mockClient.emit(
|
||||
RoomStateEvent.Members,
|
||||
membershipEvent,
|
||||
room1.currentState,
|
||||
member,
|
||||
);
|
||||
|
||||
expect(emitSpy).not.toHaveBeenCalled();
|
||||
// strictly equal
|
||||
expect(store.getLiveBeaconIds()).toBe(oldLiveBeaconIds);
|
||||
});
|
||||
|
||||
it('destroys and removes beacons when current user leaves room', async () => {
|
||||
// alice leaves room1
|
||||
const membershipEvent = makeMembershipEvent(room1Id, aliceId, 'leave');
|
||||
const member = new RoomMember(room1Id, aliceId);
|
||||
member.setMembershipEvent(membershipEvent);
|
||||
|
||||
const [room1] = makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesRoom2BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
const room1BeaconInstance = store.beacons.get(alicesRoom1BeaconInfo.getType());
|
||||
const beaconDestroySpy = jest.spyOn(room1BeaconInstance, 'destroy');
|
||||
const emitSpy = jest.spyOn(store, 'emit');
|
||||
|
||||
mockClient.emit(
|
||||
RoomStateEvent.Members,
|
||||
membershipEvent,
|
||||
room1.currentState,
|
||||
member,
|
||||
);
|
||||
|
||||
expect(emitSpy).toHaveBeenCalledWith(
|
||||
OwnBeaconStoreEvent.LivenessChange,
|
||||
// other rooms beacons still live
|
||||
[alicesRoom2BeaconInfo.getType()],
|
||||
);
|
||||
expect(beaconDestroySpy).toHaveBeenCalledTimes(1);
|
||||
expect(store.getLiveBeaconIds(room1Id)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stopBeacon()', () => {
|
||||
beforeEach(() => {
|
||||
makeRoomsWithStateEvents([
|
||||
|
|
|
@ -2,6 +2,7 @@ export * from './beacon';
|
|||
export * from './client';
|
||||
export * from './location';
|
||||
export * from './platform';
|
||||
export * from './room';
|
||||
export * from './test-utils';
|
||||
// TODO @@TR: Export voice.ts, which currently isn't exported here because it causes all tests to depend on skinning
|
||||
export * from './wrappers';
|
||||
|
|
34
test/test-utils/room.ts
Normal file
34
test/test-utils/room.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
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 {
|
||||
EventType,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { mkEvent } from "./test-utils";
|
||||
|
||||
export const makeMembershipEvent = (
|
||||
roomId: string, userId: string, membership = 'join',
|
||||
) => mkEvent({
|
||||
event: true,
|
||||
type: EventType.RoomMember,
|
||||
room: roomId,
|
||||
user: userId,
|
||||
skey: userId,
|
||||
content: { membership },
|
||||
ts: Date.now(),
|
||||
});
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue