Live location sharing - update beacon_info implementation to latest MSC (#8256)
* update calls to set and createLiveBeacon Signed-off-by: Kerry Archibald <kerrya@element.io> * fix stop beacon Signed-off-by: Kerry Archibald <kerrya@element.io> * remove variable event type from beacon utils Signed-off-by: Kerry Archibald <kerrya@element.io> * use beacon identifier Signed-off-by: Kerry Archibald <kerrya@element.io> * fix RoomLiveShareWarning tests Signed-off-by: Kerry Archibald <kerrya@element.io> * add case for beacon update Signed-off-by: Kerry Archibald <kerrya@element.io> * lint Signed-off-by: Kerry Archibald <kerrya@element.io> * more lint Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
610225aef2
commit
03d0969ae3
9 changed files with 123 additions and 108 deletions
|
@ -18,12 +18,13 @@ import {
|
|||
Room,
|
||||
Beacon,
|
||||
BeaconEvent,
|
||||
getBeaconInfoIdentifier,
|
||||
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 { M_BEACON } from "matrix-js-sdk/src/@types/beacon";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../src/stores/OwnBeaconStore";
|
||||
|
@ -80,32 +81,27 @@ describe('OwnBeaconStore', () => {
|
|||
const alicesRoom1BeaconInfo = makeBeaconInfoEvent(aliceId,
|
||||
room1Id,
|
||||
{ isLive: true },
|
||||
'$alice-room1-1'
|
||||
, '$alice-room1-1',
|
||||
'$alice-room1-1',
|
||||
);
|
||||
const alicesRoom2BeaconInfo = makeBeaconInfoEvent(aliceId,
|
||||
room2Id,
|
||||
{ isLive: true },
|
||||
'$alice-room2-1'
|
||||
, '$alice-room2-1',
|
||||
'$alice-room2-1',
|
||||
);
|
||||
const alicesOldRoomIdBeaconInfo = makeBeaconInfoEvent(aliceId,
|
||||
room1Id,
|
||||
{ isLive: false },
|
||||
'$alice-room1-2'
|
||||
, '$alice-room1-2',
|
||||
'$alice-room1-2',
|
||||
);
|
||||
const bobsRoom1BeaconInfo = makeBeaconInfoEvent(bobId,
|
||||
room1Id,
|
||||
{ isLive: true },
|
||||
'$bob-room1-1'
|
||||
, '$bob-room1-1',
|
||||
'$bob-room1-1',
|
||||
);
|
||||
const bobsOldRoom1BeaconInfo = makeBeaconInfoEvent(bobId,
|
||||
room1Id,
|
||||
{ isLive: false },
|
||||
'$bob-room1-2'
|
||||
, '$bob-room1-2',
|
||||
'$bob-room1-2',
|
||||
);
|
||||
|
||||
// make fresh rooms every time
|
||||
|
@ -129,7 +125,7 @@ describe('OwnBeaconStore', () => {
|
|||
};
|
||||
|
||||
const expireBeaconAndEmit = (store, beaconInfoEvent: MatrixEvent): void => {
|
||||
const beacon = store.getBeaconById(beaconInfoEvent.getType());
|
||||
const beacon = store.getBeaconById(getBeaconInfoIdentifier(beaconInfoEvent));
|
||||
// time travel until beacon is expired
|
||||
advanceDateAndTime(beacon.beaconInfo.timeout + 100);
|
||||
|
||||
|
@ -141,16 +137,14 @@ describe('OwnBeaconStore', () => {
|
|||
};
|
||||
|
||||
const updateBeaconLivenessAndEmit = (store, beaconInfoEvent: MatrixEvent, isLive: boolean): void => {
|
||||
const beacon = store.getBeaconById(beaconInfoEvent.getType());
|
||||
const beacon = store.getBeaconById(getBeaconInfoIdentifier(beaconInfoEvent));
|
||||
// matches original state of event content
|
||||
// except for live property
|
||||
const updateEvent = makeBeaconInfoEvent(
|
||||
beaconInfoEvent.getSender(),
|
||||
beaconInfoEvent.getRoomId(),
|
||||
{ isLive, timeout: beacon.beaconInfo.timeout },
|
||||
undefined,
|
||||
);
|
||||
updateEvent.event.type = beaconInfoEvent.getType();
|
||||
beacon.update(updateEvent);
|
||||
|
||||
mockClient.emit(BeaconEvent.Update, beaconInfoEvent, beacon);
|
||||
|
@ -197,15 +191,14 @@ describe('OwnBeaconStore', () => {
|
|||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesRoom2BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
expect(store.hasLiveBeacons()).toBe(true);
|
||||
expect(store.getLiveBeaconIds()).toEqual([
|
||||
alicesRoom1BeaconInfo.getType(),
|
||||
alicesRoom2BeaconInfo.getType(),
|
||||
getBeaconInfoIdentifier(alicesRoom1BeaconInfo),
|
||||
getBeaconInfoIdentifier(alicesRoom2BeaconInfo),
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -251,7 +244,8 @@ 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]));
|
||||
expect(removeSpy.mock.calls[2]).toEqual(expect.arrayContaining([BeaconEvent.Update]));
|
||||
expect(removeSpy.mock.calls[3]).toEqual(expect.arrayContaining([RoomStateEvent.Members]));
|
||||
});
|
||||
|
||||
it('destroys beacons', async () => {
|
||||
|
@ -259,7 +253,7 @@ describe('OwnBeaconStore', () => {
|
|||
alicesRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
const beacon = room1.currentState.beacons.get(alicesRoom1BeaconInfo.getType());
|
||||
const beacon = room1.currentState.beacons.get(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
|
||||
const destroySpy = jest.spyOn(beacon, 'destroy');
|
||||
// @ts-ignore
|
||||
store.onNotReady();
|
||||
|
@ -273,7 +267,6 @@ describe('OwnBeaconStore', () => {
|
|||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesRoom2BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
|
@ -282,7 +275,6 @@ describe('OwnBeaconStore', () => {
|
|||
it('returns true when user has live beacons', async () => {
|
||||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
|
@ -302,7 +294,6 @@ describe('OwnBeaconStore', () => {
|
|||
it('returns true when user has live beacons for roomId', async () => {
|
||||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
|
@ -313,7 +304,6 @@ describe('OwnBeaconStore', () => {
|
|||
it('returns false when user does not have live beacons for roomId', async () => {
|
||||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
|
@ -327,7 +317,6 @@ describe('OwnBeaconStore', () => {
|
|||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesRoom2BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
|
@ -336,13 +325,12 @@ describe('OwnBeaconStore', () => {
|
|||
it('returns live beacons when user has live beacons', async () => {
|
||||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
expect(store.getLiveBeaconIds()).toEqual([
|
||||
alicesRoom1BeaconInfo.getType(),
|
||||
getBeaconInfoIdentifier(alicesRoom1BeaconInfo),
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -359,23 +347,21 @@ describe('OwnBeaconStore', () => {
|
|||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesRoom2BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
expect(store.getLiveBeaconIds(room1Id)).toEqual([
|
||||
alicesRoom1BeaconInfo.getType(),
|
||||
getBeaconInfoIdentifier(alicesRoom1BeaconInfo),
|
||||
]);
|
||||
expect(store.getLiveBeaconIds(room2Id)).toEqual([
|
||||
alicesRoom2BeaconInfo.getType(),
|
||||
getBeaconInfoIdentifier(alicesRoom2BeaconInfo),
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns empty array when user does not have live beacons for roomId', async () => {
|
||||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
alicesOldRoomIdBeaconInfo,
|
||||
bobsRoom1BeaconInfo,
|
||||
bobsOldRoom1BeaconInfo,
|
||||
]);
|
||||
|
@ -419,7 +405,7 @@ describe('OwnBeaconStore', () => {
|
|||
|
||||
mockClient.emit(BeaconEvent.New, alicesRoom1BeaconInfo, alicesLiveBeacon);
|
||||
|
||||
expect(emitSpy).toHaveBeenCalledWith(OwnBeaconStoreEvent.LivenessChange, [alicesRoom1BeaconInfo.getType()]);
|
||||
expect(emitSpy).toHaveBeenCalledWith(OwnBeaconStoreEvent.LivenessChange, [alicesLiveBeacon.identifier]);
|
||||
});
|
||||
|
||||
it('emits a liveness change event when new beacons do not change live state', async () => {
|
||||
|
@ -485,14 +471,10 @@ describe('OwnBeaconStore', () => {
|
|||
// except for live property
|
||||
const expectedUpdateContent = {
|
||||
...prevEventContent,
|
||||
[M_BEACON_INFO.name]: {
|
||||
...prevEventContent[M_BEACON_INFO.name],
|
||||
live: false,
|
||||
},
|
||||
live: false,
|
||||
};
|
||||
expect(mockClient.unstable_setLiveBeacon).toHaveBeenCalledWith(
|
||||
room1Id,
|
||||
alicesRoom1BeaconInfo.getType(),
|
||||
expectedUpdateContent,
|
||||
);
|
||||
});
|
||||
|
@ -513,7 +495,7 @@ describe('OwnBeaconStore', () => {
|
|||
expect(store.hasLiveBeacons(room1Id)).toBe(true);
|
||||
expect(emitSpy).toHaveBeenCalledWith(
|
||||
OwnBeaconStoreEvent.LivenessChange,
|
||||
[alicesOldRoomIdBeaconInfo.getType()],
|
||||
[getBeaconInfoIdentifier(alicesOldRoomIdBeaconInfo)],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -603,7 +585,7 @@ describe('OwnBeaconStore', () => {
|
|||
alicesRoom2BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
const room1BeaconInstance = store.beacons.get(alicesRoom1BeaconInfo.getType());
|
||||
const room1BeaconInstance = store.beacons.get(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
|
||||
const beaconDestroySpy = jest.spyOn(room1BeaconInstance, 'destroy');
|
||||
const emitSpy = jest.spyOn(store, 'emit');
|
||||
|
||||
|
@ -617,7 +599,7 @@ describe('OwnBeaconStore', () => {
|
|||
expect(emitSpy).toHaveBeenCalledWith(
|
||||
OwnBeaconStoreEvent.LivenessChange,
|
||||
// other rooms beacons still live
|
||||
[alicesRoom2BeaconInfo.getType()],
|
||||
[getBeaconInfoIdentifier(alicesRoom2BeaconInfo)],
|
||||
);
|
||||
expect(beaconDestroySpy).toHaveBeenCalledTimes(1);
|
||||
expect(store.getLiveBeaconIds(room1Id)).toEqual([]);
|
||||
|
@ -640,57 +622,53 @@ describe('OwnBeaconStore', () => {
|
|||
|
||||
it('does nothing for a beacon that is already not live', async () => {
|
||||
const store = await makeOwnBeaconStore();
|
||||
await store.stopBeacon(alicesOldRoomIdBeaconInfo.getId());
|
||||
await store.stopBeacon(getBeaconInfoIdentifier(alicesOldRoomIdBeaconInfo));
|
||||
expect(mockClient.unstable_setLiveBeacon).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('updates beacon to live:false when it is unexpired', async () => {
|
||||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
|
||||
await store.stopBeacon(alicesOldRoomIdBeaconInfo.getType());
|
||||
const prevEventContent = alicesRoom1BeaconInfo.getContent();
|
||||
|
||||
await store.stopBeacon(alicesRoom1BeaconInfo.getType());
|
||||
await store.stopBeacon(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
|
||||
|
||||
// matches original state of event content
|
||||
// except for live property
|
||||
const expectedUpdateContent = {
|
||||
...prevEventContent,
|
||||
[M_BEACON_INFO.name]: {
|
||||
...prevEventContent[M_BEACON_INFO.name],
|
||||
live: false,
|
||||
},
|
||||
live: false,
|
||||
};
|
||||
expect(mockClient.unstable_setLiveBeacon).toHaveBeenCalledWith(
|
||||
room1Id,
|
||||
alicesRoom1BeaconInfo.getType(),
|
||||
expectedUpdateContent,
|
||||
);
|
||||
});
|
||||
|
||||
it('updates beacon to live:false when it is expired but live property is true', async () => {
|
||||
makeRoomsWithStateEvents([
|
||||
alicesRoom1BeaconInfo,
|
||||
]);
|
||||
const store = await makeOwnBeaconStore();
|
||||
|
||||
await store.stopBeacon(alicesOldRoomIdBeaconInfo.getType());
|
||||
const prevEventContent = alicesRoom1BeaconInfo.getContent();
|
||||
|
||||
// time travel until beacon is expired
|
||||
advanceDateAndTime(HOUR_MS * 3);
|
||||
|
||||
await store.stopBeacon(alicesRoom1BeaconInfo.getType());
|
||||
await store.stopBeacon(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
|
||||
|
||||
// matches original state of event content
|
||||
// except for live property
|
||||
const expectedUpdateContent = {
|
||||
...prevEventContent,
|
||||
[M_BEACON_INFO.name]: {
|
||||
...prevEventContent[M_BEACON_INFO.name],
|
||||
live: false,
|
||||
},
|
||||
live: false,
|
||||
};
|
||||
expect(mockClient.unstable_setLiveBeacon).toHaveBeenCalledWith(
|
||||
room1Id,
|
||||
alicesRoom1BeaconInfo.getType(),
|
||||
expectedUpdateContent,
|
||||
);
|
||||
});
|
||||
|
@ -863,7 +841,7 @@ describe('OwnBeaconStore', () => {
|
|||
|
||||
// called for each position from watchPosition
|
||||
expect(mockClient.sendEvent).toHaveBeenCalledTimes(5);
|
||||
expect(store.beaconHasWireError(alicesRoom1BeaconInfo.getType())).toBe(false);
|
||||
expect(store.beaconHasWireError(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))).toBe(false);
|
||||
expect(store.hasWireErrors()).toBe(false);
|
||||
});
|
||||
|
||||
|
@ -890,10 +868,10 @@ describe('OwnBeaconStore', () => {
|
|||
|
||||
// called for each position from watchPosition
|
||||
expect(mockClient.sendEvent).toHaveBeenCalledTimes(5);
|
||||
expect(store.beaconHasWireError(alicesRoom1BeaconInfo.getType())).toBe(false);
|
||||
expect(store.beaconHasWireError(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))).toBe(false);
|
||||
expect(store.hasWireErrors()).toBe(false);
|
||||
expect(emitSpy).not.toHaveBeenCalledWith(
|
||||
OwnBeaconStoreEvent.WireError, alicesRoom1BeaconInfo.getType(),
|
||||
OwnBeaconStoreEvent.WireError, getBeaconInfoIdentifier(alicesRoom1BeaconInfo),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -913,10 +891,10 @@ describe('OwnBeaconStore', () => {
|
|||
|
||||
// only two allowed failures
|
||||
expect(mockClient.sendEvent).toHaveBeenCalledTimes(2);
|
||||
expect(store.beaconHasWireError(alicesRoom1BeaconInfo.getType())).toBe(true);
|
||||
expect(store.beaconHasWireError(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))).toBe(true);
|
||||
expect(store.hasWireErrors()).toBe(true);
|
||||
expect(emitSpy).toHaveBeenCalledWith(
|
||||
OwnBeaconStoreEvent.WireError, alicesRoom1BeaconInfo.getType(),
|
||||
OwnBeaconStoreEvent.WireError, getBeaconInfoIdentifier(alicesRoom1BeaconInfo),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -936,18 +914,18 @@ describe('OwnBeaconStore', () => {
|
|||
|
||||
// only two allowed failures
|
||||
expect(mockClient.sendEvent).toHaveBeenCalledTimes(2);
|
||||
expect(store.beaconHasWireError(alicesRoom1BeaconInfo.getType())).toBe(true);
|
||||
expect(store.beaconHasWireError(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))).toBe(true);
|
||||
expect(store.hasWireErrors()).toBe(true);
|
||||
expect(store.hasWireErrors(room1Id)).toBe(true);
|
||||
expect(emitSpy).toHaveBeenCalledWith(
|
||||
OwnBeaconStoreEvent.WireError, alicesRoom1BeaconInfo.getType(),
|
||||
OwnBeaconStoreEvent.WireError, getBeaconInfoIdentifier(alicesRoom1BeaconInfo),
|
||||
);
|
||||
|
||||
// reset emitSpy mock counts to asser on wireError again
|
||||
emitSpy.mockClear();
|
||||
store.resetWireError(alicesRoom1BeaconInfo.getType());
|
||||
store.resetWireError(getBeaconInfoIdentifier(alicesRoom1BeaconInfo));
|
||||
|
||||
expect(store.beaconHasWireError(alicesRoom1BeaconInfo.getType())).toBe(false);
|
||||
expect(store.beaconHasWireError(getBeaconInfoIdentifier(alicesRoom1BeaconInfo))).toBe(false);
|
||||
|
||||
// 2 more positions from watchPosition in this period
|
||||
await advanceAndFlushPromises(10000);
|
||||
|
@ -955,7 +933,7 @@ describe('OwnBeaconStore', () => {
|
|||
// 2 from before, 2 new ones
|
||||
expect(mockClient.sendEvent).toHaveBeenCalledTimes(4);
|
||||
expect(emitSpy).toHaveBeenCalledWith(
|
||||
OwnBeaconStoreEvent.WireError, alicesRoom1BeaconInfo.getType(),
|
||||
OwnBeaconStoreEvent.WireError, getBeaconInfoIdentifier(alicesRoom1BeaconInfo),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue