Skip to content

Commit 75ea743

Browse files
author
Kerry Archibald
committed
test adding locations
Signed-off-by: Kerry Archibald <[email protected]>
1 parent d59208a commit 75ea743

File tree

6 files changed

+155
-17
lines changed

6 files changed

+155
-17
lines changed

spec/unit/models/beacon.spec.ts

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import { EventType } from "../../../src";
17+
import { EventType } from "../../../src/@types/event";
1818
import { M_BEACON_INFO } from "../../../src/@types/beacon";
1919
import {
2020
isTimestampInDuration,
2121
isBeaconInfoEventType,
2222
Beacon,
2323
BeaconEvent,
2424
} from "../../../src/models/beacon";
25-
import { makeBeaconInfoEvent } from "../../test-utils/beacon";
25+
import { makeBeaconEvent, makeBeaconInfoEvent } from "../../test-utils/beacon";
2626

2727
jest.useFakeTimers();
2828

@@ -277,5 +277,93 @@ describe('Beacon', () => {
277277
expect(emitSpy).toHaveBeenCalledTimes(1);
278278
});
279279
});
280+
281+
describe('addLocations', () => {
282+
it('ignores locations when beacon is not live', () => {
283+
const beacon = new Beacon(makeBeaconInfoEvent(userId, roomId, { isLive: false }));
284+
const emitSpy = jest.spyOn(beacon, 'emit');
285+
286+
beacon.addLocations([
287+
makeBeaconEvent(userId, { beaconInfoId: beacon.beaconInfoId, timestamp: now + 1 }),
288+
]);
289+
290+
expect(beacon.latestLocationState).toBeFalsy();
291+
expect(emitSpy).not.toHaveBeenCalled();
292+
});
293+
294+
it('ignores locations outside the beacon live duration', () => {
295+
const beacon = new Beacon(makeBeaconInfoEvent(userId, roomId, { isLive: true, timeout: 60000 }));
296+
const emitSpy = jest.spyOn(beacon, 'emit');
297+
298+
beacon.addLocations([
299+
// beacon has now + 60000 live period
300+
makeBeaconEvent(userId, { beaconInfoId: beacon.beaconInfoId, timestamp: now + 100000 }),
301+
]);
302+
303+
expect(beacon.latestLocationState).toBeFalsy();
304+
expect(emitSpy).not.toHaveBeenCalled();
305+
});
306+
307+
it('sets latest location state to most recent location', () => {
308+
const beacon = new Beacon(makeBeaconInfoEvent(userId, roomId, { isLive: true, timeout: 60000 }));
309+
const emitSpy = jest.spyOn(beacon, 'emit');
310+
311+
const locations = [
312+
// older
313+
makeBeaconEvent(
314+
userId, { beaconInfoId: beacon.beaconInfoId, uri: 'geo:foo', timestamp: now + 1 },
315+
),
316+
// newer
317+
makeBeaconEvent(
318+
userId, { beaconInfoId: beacon.beaconInfoId, uri: 'geo:bar', timestamp: now + 10000 },
319+
),
320+
// not valid
321+
makeBeaconEvent(
322+
userId, { beaconInfoId: beacon.beaconInfoId, uri: 'geo:baz', timestamp: now - 5 },
323+
),
324+
];
325+
326+
beacon.addLocations(locations);
327+
328+
const expectedLatestLocation = {
329+
description: undefined,
330+
timestamp: now + 10000,
331+
uri: 'geo:bar',
332+
};
333+
334+
// the newest valid location
335+
expect(beacon.latestLocationState).toEqual(expectedLatestLocation);
336+
expect(emitSpy).toHaveBeenCalledWith(BeaconEvent.LocationUpdate, expectedLatestLocation);
337+
});
338+
339+
it('ignores locations that are less recent that the current latest location', () => {
340+
const beacon = new Beacon(makeBeaconInfoEvent(userId, roomId, { isLive: true, timeout: 60000 }));
341+
342+
const olderLocation = makeBeaconEvent(
343+
userId, { beaconInfoId: beacon.beaconInfoId, uri: 'geo:foo', timestamp: now + 1 },
344+
);
345+
const newerLocation = makeBeaconEvent(
346+
userId, { beaconInfoId: beacon.beaconInfoId, uri: 'geo:bar', timestamp: now + 10000 },
347+
);
348+
349+
beacon.addLocations([newerLocation]);
350+
// latest location set to newerLocation
351+
expect(beacon.latestLocationState).toEqual(expect.objectContaining({
352+
uri: 'geo:bar',
353+
}));
354+
355+
const emitSpy = jest.spyOn(beacon, 'emit').mockClear();
356+
357+
// add older location
358+
beacon.addLocations([olderLocation]);
359+
360+
// no change
361+
expect(beacon.latestLocationState).toEqual(expect.objectContaining({
362+
uri: 'geo:bar',
363+
}));
364+
// no emit
365+
expect(emitSpy).not.toHaveBeenCalled();
366+
});
367+
});
280368
});
281369
});

spec/unit/room-state.spec.js

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as utils from "../test-utils/test-utils";
2-
import { makeBeaconInfoEvent } from "../test-utils/beacon";
2+
import { makeBeaconEvent, makeBeaconInfoEvent } from "../test-utils/beacon";
33
import { filterEmitCallsByEventType } from "../test-utils/emitter";
44
import { RoomState, RoomStateEvent } from "../../src/models/room-state";
55
import { BeaconEvent } from "../../src/models/beacon";
@@ -712,4 +712,56 @@ describe("RoomState", function() {
712712
expect(state.maySendEvent('m.room.other_thing', userB)).toEqual(false);
713713
});
714714
});
715+
716+
describe('processBeaconEvents', () => {
717+
const beacon1 = makeBeaconInfoEvent(userA, roomId, {}, '$beacon1', '$beacon1');
718+
const beacon2 = makeBeaconInfoEvent(userA, roomId, {}, '$beacon2', '$beacon2');
719+
720+
it('does nothing when state has no beacons', () => {
721+
const emitSpy = jest.spyOn(state, 'emit');
722+
state.processBeaconEvents([makeBeaconEvent(userA, { beaconInfoId: '$beacon1' })]);
723+
expect(emitSpy).not.toHaveBeenCalled();
724+
});
725+
726+
it('does nothing when there are no events', () => {
727+
state.setStateEvents([beacon1, beacon2]);
728+
const emitSpy = jest.spyOn(state, 'emit').mockClear();
729+
state.processBeaconEvents([]);
730+
expect(emitSpy).not.toHaveBeenCalled();
731+
});
732+
733+
it('discards events for beacons that are not in state', () => {
734+
const location = makeBeaconEvent(userA, {
735+
beaconInfoId: 'some-other-beacon',
736+
});
737+
state.setStateEvents([beacon1, beacon2]);
738+
const emitSpy = jest.spyOn(state, 'emit').mockClear();
739+
state.processBeaconEvents([location]);
740+
expect(emitSpy).not.toHaveBeenCalled();
741+
});
742+
743+
it('adds locations to beacons', () => {
744+
const location1 = makeBeaconEvent(userA, {
745+
beaconInfoId: '$beacon1', timestamp: Date.now() + 1,
746+
});
747+
const location2 = makeBeaconEvent(userA, {
748+
beaconInfoId: '$beacon1', timestamp: Date.now() + 2,
749+
});
750+
const location3 = makeBeaconEvent(userA, {
751+
beaconInfoId: 'some-other-beacon',
752+
});
753+
state.setStateEvents([beacon1, beacon2]);
754+
755+
expect(state.beacons.size).toEqual(2);
756+
757+
const beaconInstance = state.beacons.get(beacon1.getType());
758+
const addLocationsSpy = jest.spyOn(beaconInstance, 'addLocations');
759+
760+
state.processBeaconEvents([location1, location2, location3]);
761+
762+
expect(addLocationsSpy).toHaveBeenCalledTimes(1);
763+
// only called with locations for beacon1
764+
expect(addLocationsSpy).toHaveBeenCalledWith([location1, location2]);
765+
});
766+
});
715767
});

spec/unit/utils.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
prevString,
1111
simpleRetryOperation,
1212
stringToBase,
13-
sortEventsByLatestContentTimestamp
13+
sortEventsByLatestContentTimestamp,
1414
} from "../../src/utils";
1515
import { logger } from "../../src/logger";
1616
import { mkMessage } from "../test-utils/test-utils";

src/client.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8928,7 +8928,6 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
89288928
return;
89298929
}
89308930
const beaconEvents = events.filter(event => M_BEACON.matches(event.getType()));
8931-
// console.log('hhh processBeaocnEvents', room, beaconEvents);
89328931
room.currentState.processBeaconEvents(beaconEvents);
89338932
}
89348933

src/models/beacon.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ export enum BeaconEvent {
2525
New = "Beacon.new",
2626
Update = "Beacon.update",
2727
LivenessChange = "Beacon.LivenessChange",
28-
Destroy = "Destroy",
29-
LocationUpdate = "LocationUpdate",
30-
Destroy = "Destroy"
28+
Destroy = "Beacon.Destroy",
29+
LocationUpdate = "Beacon.LocationUpdate",
3130
}
3231

3332
export type BeaconEventHandlerMap = {
@@ -134,7 +133,6 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
134133
public addLocations(locationEvents: MatrixEvent[]): void {
135134
// discard locations for beacons that are not live
136135

137-
console.log('hhh addLocation', JSON.stringify(locationEvents));
138136
if (!this.isLive) {
139137
return;
140138
}
@@ -151,10 +149,10 @@ export class Beacon extends TypedEventEmitter<Exclude<BeaconEvent, BeaconEvent.N
151149
});
152150
const latestLocationEvent = validLocationEvents.sort(sortEventsByLatestContentTimestamp)?.[0];
153151

154-
this._latestLocationState = parseBeaconContent(latestLocationEvent.getContent());
155-
156-
console.log('hhh', 'emitting new latest location', this.identifier);
157-
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState);
152+
if (latestLocationEvent) {
153+
this._latestLocationState = parseBeaconContent(latestLocationEvent.getContent());
154+
this.emit(BeaconEvent.LocationUpdate, this.latestLocationState);
155+
}
158156
}
159157

160158
private setBeaconInfo(event: MatrixEvent): void {

src/models/room-state.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,11 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
405405
}
406406

407407
public processBeaconEvents(events: MatrixEvent[]): void {
408-
// discard locations if we have no beacons
409-
if (!events?.length || !this.beacons.size) {
408+
if (
409+
!events.length ||
410+
// discard locations if we have no beacons
411+
!this.beacons.size
412+
) {
410413
return;
411414
}
412415

@@ -424,7 +427,6 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
424427
}, {});
425428

426429
Object.entries(locationEventsByBeaconId).forEach(([beaconInfoEventId, events]) => {
427-
// TODO better way to find beacon by event_id
428430
const beacon = [...this.beacons.values()].find(beacon => beacon.beaconInfoId === beaconInfoEventId);
429431

430432
if (beacon) {
@@ -466,7 +468,6 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
466468
* @experimental
467469
*/
468470
private setBeacon(event: MatrixEvent): void {
469-
console.log('hhh', event.getType(), event.isRedacted(), event.isRedaction(), event);
470471
if (this.beacons.has(event.getType())) {
471472
const beacon = this.beacons.get(event.getType());
472473

0 commit comments

Comments
 (0)