@@ -15,6 +15,7 @@ limitations under the License.
1515*/
1616
1717import { Room , Beacon , BeaconEvent } from "matrix-js-sdk/src/matrix" ;
18+ import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon" ;
1819
1920import { OwnBeaconStore , OwnBeaconStoreEvent } from "../../src/stores/OwnBeaconStore" ;
2021import { resetAsyncStoreWithClient , setupAsyncStoreWithClient } from "../test-utils" ;
@@ -33,6 +34,7 @@ describe('OwnBeaconStore', () => {
3334 const mockClient = getMockClientWithEventEmitter ( {
3435 getUserId : jest . fn ( ) . mockReturnValue ( aliceId ) ,
3536 getVisibleRooms : jest . fn ( ) . mockReturnValue ( [ ] ) ,
37+ unstable_setLiveBeacon : jest . fn ( ) . mockResolvedValue ( { event_id : '1' } ) ,
3638 } ) ;
3739 const room1Id = '$room1:server.org' ;
3840 const room2Id = '$room2:server.org' ;
@@ -78,6 +80,7 @@ describe('OwnBeaconStore', () => {
7880
7981 beforeEach ( ( ) => {
8082 mockClient . getVisibleRooms . mockReturnValue ( [ ] ) ;
83+ mockClient . unstable_setLiveBeacon . mockClear ( ) . mockResolvedValue ( { event_id : '1' } ) ;
8184 jest . spyOn ( global . Date , 'now' ) . mockReturnValue ( now ) ;
8285 jest . spyOn ( OwnBeaconStore . instance , 'emit' ) . mockRestore ( ) ;
8386 } ) ;
@@ -335,7 +338,7 @@ describe('OwnBeaconStore', () => {
335338 expect ( store . getLiveBeaconIds ( ) ) . toBe ( oldLiveBeaconIds ) ;
336339 } ) ;
337340
338- it ( 'updates state and when beacon liveness changes from true to false' , async ( ) => {
341+ it ( 'updates state and emits beacon liveness changes from true to false' , async ( ) => {
339342 makeRoomsWithStateEvents ( [
340343 alicesRoom1BeaconInfo ,
341344 ] ) ;
@@ -356,6 +359,35 @@ describe('OwnBeaconStore', () => {
356359 expect ( emitSpy ) . toHaveBeenCalledWith ( OwnBeaconStoreEvent . LivenessChange , false ) ;
357360 } ) ;
358361
362+ it ( 'stops beacon when liveness changes from true to false and beacon is expired' , async ( ) => {
363+ makeRoomsWithStateEvents ( [
364+ alicesRoom1BeaconInfo ,
365+ ] ) ;
366+ await makeOwnBeaconStore ( ) ;
367+ const alicesBeacon = new Beacon ( alicesRoom1BeaconInfo ) ;
368+ const prevEventContent = alicesRoom1BeaconInfo . getContent ( ) ;
369+
370+ // time travel until beacon is expired
371+ advanceDateAndTime ( HOUR_MS * 3 ) ;
372+
373+ mockClient . emit ( BeaconEvent . LivenessChange , false , alicesBeacon ) ;
374+
375+ // matches original state of event content
376+ // except for live property
377+ const expectedUpdateContent = {
378+ ...prevEventContent ,
379+ [ M_BEACON_INFO . name ] : {
380+ ...prevEventContent [ M_BEACON_INFO . name ] ,
381+ live : false ,
382+ } ,
383+ } ;
384+ expect ( mockClient . unstable_setLiveBeacon ) . toHaveBeenCalledWith (
385+ room1Id ,
386+ alicesRoom1BeaconInfo . getType ( ) ,
387+ expectedUpdateContent ,
388+ ) ;
389+ } ) ;
390+
359391 it ( 'updates state and when beacon liveness changes from false to true' , async ( ) => {
360392 makeRoomsWithStateEvents ( [
361393 alicesOldRoomIdBeaconInfo ,
@@ -381,9 +413,75 @@ describe('OwnBeaconStore', () => {
381413 } ) ;
382414 } ) ;
383415
384- describe ( 'on LivenessChange event' , ( ) => {
385- it ( 'ignores events for irrelevant beacons' , async ( ) => {
416+ describe ( 'stopBeacon()' , ( ) => {
417+ beforeEach ( ( ) => {
418+ makeRoomsWithStateEvents ( [
419+ alicesRoom1BeaconInfo ,
420+ alicesOldRoomIdBeaconInfo ,
421+ ] ) ;
422+ } ) ;
423+
424+ it ( 'does nothing for an unknown beacon id' , async ( ) => {
425+ const store = await makeOwnBeaconStore ( ) ;
426+ await store . stopBeacon ( 'randomBeaconId' ) ;
427+ expect ( mockClient . unstable_setLiveBeacon ) . not . toHaveBeenCalled ( ) ;
428+ } ) ;
429+
430+ it ( 'does nothing for a beacon that is already not live' , async ( ) => {
431+ const store = await makeOwnBeaconStore ( ) ;
432+ await store . stopBeacon ( alicesOldRoomIdBeaconInfo . getId ( ) ) ;
433+ expect ( mockClient . unstable_setLiveBeacon ) . not . toHaveBeenCalled ( ) ;
434+ } ) ;
386435
436+ it ( 'updates beacon to live:false when it is unexpired' , async ( ) => {
437+ const store = await makeOwnBeaconStore ( ) ;
438+
439+ await store . stopBeacon ( alicesOldRoomIdBeaconInfo . getId ( ) ) ;
440+ const prevEventContent = alicesRoom1BeaconInfo . getContent ( ) ;
441+
442+ await store . stopBeacon ( alicesRoom1BeaconInfo . getId ( ) ) ;
443+
444+ // matches original state of event content
445+ // except for live property
446+ const expectedUpdateContent = {
447+ ...prevEventContent ,
448+ [ M_BEACON_INFO . name ] : {
449+ ...prevEventContent [ M_BEACON_INFO . name ] ,
450+ live : false ,
451+ } ,
452+ } ;
453+ expect ( mockClient . unstable_setLiveBeacon ) . toHaveBeenCalledWith (
454+ room1Id ,
455+ alicesRoom1BeaconInfo . getType ( ) ,
456+ expectedUpdateContent ,
457+ ) ;
458+ } ) ;
459+
460+ it ( 'updates beacon to live:false when it is expired but live property is true' , async ( ) => {
461+ const store = await makeOwnBeaconStore ( ) ;
462+
463+ await store . stopBeacon ( alicesOldRoomIdBeaconInfo . getId ( ) ) ;
464+ const prevEventContent = alicesRoom1BeaconInfo . getContent ( ) ;
465+
466+ // time travel until beacon is expired
467+ advanceDateAndTime ( HOUR_MS * 3 ) ;
468+
469+ await store . stopBeacon ( alicesRoom1BeaconInfo . getId ( ) ) ;
470+
471+ // matches original state of event content
472+ // except for live property
473+ const expectedUpdateContent = {
474+ ...prevEventContent ,
475+ [ M_BEACON_INFO . name ] : {
476+ ...prevEventContent [ M_BEACON_INFO . name ] ,
477+ live : false ,
478+ } ,
479+ } ;
480+ expect ( mockClient . unstable_setLiveBeacon ) . toHaveBeenCalledWith (
481+ room1Id ,
482+ alicesRoom1BeaconInfo . getType ( ) ,
483+ expectedUpdateContent ,
484+ ) ;
387485 } ) ;
388486 } ) ;
389487} ) ;
0 commit comments