Skip to content
This repository has been archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
feat: gather participants around one on gatherAll
Browse files Browse the repository at this point in the history
  • Loading branch information
Raspincel committed Dec 13, 2023
1 parent 3fecc4d commit 34687cc
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 68 deletions.
5 changes: 4 additions & 1 deletion __mocks__/realtime.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,16 @@ export const ABLY_REALTIME_MOCK: AblyRealtimeService = {
domainRefusedObserver: MOCK_OBSERVER_HELPER,
presenceSlotsInfosObserver: MOCK_OBSERVER_HELPER,
presenceWIOObserver: MOCK_OBSERVER_HELPER,
privateModeWIOObserver: MOCK_OBSERVER_HELPER,
gatherWIOObserver: MOCK_OBSERVER_HELPER,
subscribeToParticipantUpdate: jest.fn(),
unsubscribeFromParticipantUpdate: jest.fn(),
updateMyProperties: jest.fn(),
getParticipantSlot: jest.fn(),
updateComments: jest.fn(),
updatePresenceMouse: jest.fn(),
updateWIOParticipant: jest.fn(),
setPrivateWIOParticipant: jest.fn(),
setGatherWIOParticipant: jest.fn(),
leavePresenceMouseChannel: jest.fn(),
enterPresenceMouseChannel: jest.fn(),
enterWIOChannel: jest.fn(),
Expand Down
209 changes: 146 additions & 63 deletions src/components/who-is-online/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
MOCK_ABLY_PARTICIPANT_DATA_2,
MOCK_GROUP,
MOCK_LOCAL_PARTICIPANT,
MOCK_ABLY_PARTICIPANT_DATA_1,
} from '../../../__mocks__/participants.mock';
import { ABLY_REALTIME_MOCK } from '../../../__mocks__/realtime.mock';
import { RealtimeEvent } from '../../common/types/events.types';
Expand Down Expand Up @@ -72,92 +73,94 @@ describe('Who Is Online', () => {
expect(whoIsOnlineComponent['element'].position).toBe('top: 20px; right: 40px;');
});

test('should correctly update participant list', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});
describe('onParticipantListUpdate', () => {
test('should correctly update participant list', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});

expect(whoIsOnlineComponent['participants'].length).toBe(1);
expect(whoIsOnlineComponent['participants'].length).toBe(1);

whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant2-ably-id': {
...MOCK_ABLY_PARTICIPANT,
data: MOCK_ABLY_PARTICIPANT_DATA_2,
id: 'unit-test-participant2-ably-id',
},
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant2-ably-id': {
...MOCK_ABLY_PARTICIPANT,
data: MOCK_ABLY_PARTICIPANT_DATA_2,
id: 'unit-test-participant2-ably-id',
},
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});

expect(whoIsOnlineComponent['participants'].length).toBe(2);
});

expect(whoIsOnlineComponent['participants'].length).toBe(2);
});
test('should not update participant list if participant is does not have whoIsOnline activated', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': {
...MOCK_ABLY_PARTICIPANT,
data: { ...MOCK_ABLY_PARTICIPANT, activeComponents: [] },
},
});

test('should not update participant list if participant is does not have whoIsOnline activated', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': {
...MOCK_ABLY_PARTICIPANT,
data: { ...MOCK_ABLY_PARTICIPANT, activeComponents: [] },
},
expect(whoIsOnlineComponent['participants'].length).toBe(0);
});

expect(whoIsOnlineComponent['participants'].length).toBe(0);
});
test('should not add the same participant twice', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});

test('should not add the same participant twice', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});
expect(whoIsOnlineComponent['participants'].length).toBe(1);

expect(whoIsOnlineComponent['participants'].length).toBe(1);
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});

whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
expect(whoIsOnlineComponent['participants'].length).toBe(1);
});

expect(whoIsOnlineComponent['participants'].length).toBe(1);
});
test('should not display private participants', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});

test('should not display private participants', () => {
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': MOCK_ABLY_PARTICIPANT,
});
expect(whoIsOnlineComponent['participants'].length).toBe(1);

expect(whoIsOnlineComponent['participants'].length).toBe(1);
const privateParticipant = {
...MOCK_ABLY_PARTICIPANT,
data: {
...MOCK_ABLY_PARTICIPANT.data,
isPrivate: true,
},
};

const privateParticipant = {
...MOCK_ABLY_PARTICIPANT,
data: {
...MOCK_ABLY_PARTICIPANT.data,
isPrivate: true,
},
};
whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': privateParticipant,
});

whoIsOnlineComponent['onParticipantListUpdate']({
'unit-test-participant1-ably-id': privateParticipant,
expect(whoIsOnlineComponent['participants'].length).toBe(0);
});

expect(whoIsOnlineComponent['participants'].length).toBe(0);
});

test('should display private local participant', () => {
const participantsData = {};
test('should display private local participant', () => {
const participantsData = {};

participantsData[MOCK_LOCAL_PARTICIPANT.id] = {
...MOCK_ABLY_PARTICIPANT,
data: {
...MOCK_ABLY_PARTICIPANT.data,
id: MOCK_LOCAL_PARTICIPANT.id,
},
};
participantsData[MOCK_LOCAL_PARTICIPANT.id] = {
...MOCK_ABLY_PARTICIPANT,
data: {
...MOCK_ABLY_PARTICIPANT.data,
id: MOCK_LOCAL_PARTICIPANT.id,
},
};

whoIsOnlineComponent['onParticipantListUpdate'](participantsData);
whoIsOnlineComponent['onParticipantListUpdate'](participantsData);

expect(whoIsOnlineComponent['participants'].length).toBe(1);
expect(whoIsOnlineComponent['participants'].length).toBe(1);

participantsData[MOCK_LOCAL_PARTICIPANT.id].data.isPrivate = true;
participantsData[MOCK_LOCAL_PARTICIPANT.id].data.isPrivate = true;

whoIsOnlineComponent['onParticipantListUpdate'](participantsData);
whoIsOnlineComponent['onParticipantListUpdate'](participantsData);

expect(whoIsOnlineComponent['participants'].length).toBe(1);
expect(whoIsOnlineComponent['participants'].length).toBe(1);
});
});

describe('events', () => {
Expand Down Expand Up @@ -185,7 +188,7 @@ describe('Who Is Online', () => {
false,
);

expect(whoIsOnlineComponent['realtime'].updateWIOParticipant).toHaveBeenCalledWith(
expect(whoIsOnlineComponent['realtime'].setPrivateWIOParticipant).toHaveBeenCalledWith(
MOCK_ABLY_PARTICIPANT_DATA_2.id,
false,
);
Expand Down Expand Up @@ -217,4 +220,84 @@ describe('Who Is Online', () => {
);
});
});

describe('setGather', () => {
beforeEach(() => {
whoIsOnlineComponent['followMousePointer'] = jest
.fn()
.mockImplementation(whoIsOnlineComponent['followMousePointer']);
});

afterEach(() => {
jest.clearAllMocks();
});

test('should set element.data to following.data', () => {
whoIsOnlineComponent['setGather']({ ...MOCK_ABLY_PARTICIPANT, clientId: 'ably-id' });
expect(whoIsOnlineComponent['element'].following).toBe(MOCK_ABLY_PARTICIPANT_DATA_1);
});

test('should early return if following the local participant', () => {
whoIsOnlineComponent['element'].following = MOCK_ABLY_PARTICIPANT_DATA_2;

whoIsOnlineComponent['setGather'](MOCK_ABLY_PARTICIPANT);

expect(whoIsOnlineComponent['followMousePointer']).not.toHaveBeenCalled();
expect(whoIsOnlineComponent['element'].following).toBe(MOCK_ABLY_PARTICIPANT_DATA_2);
});

test('should set element.following to undefiend return if no id is passed', () => {
whoIsOnlineComponent['element'].following = MOCK_ABLY_PARTICIPANT_DATA_2;

whoIsOnlineComponent['setGather']({
...MOCK_ABLY_PARTICIPANT,
clientId: 'ably-id',
data: { id: '' },
});

const event = {
detail: { id: '' },
};

expect(whoIsOnlineComponent['followMousePointer']).toHaveBeenCalledWith(event);
expect(whoIsOnlineComponent['element'].following).toBe(undefined);
});
});

describe('gatherAll', () => {
test('should publish detail to realtime', () => {
const event = new CustomEvent(RealtimeEvent.REALTIME_GATHER, {
detail: {
...MOCK_ABLY_PARTICIPANT_DATA_1,
},
});

whoIsOnlineComponent['gatherAll'](event);

expect(whoIsOnlineComponent['realtime'].setGatherWIOParticipant).toHaveBeenCalledWith(
event.detail,
);
});
});

describe('stopFollowing', () => {
test('should do nothing if participant leaving is not being followed', () => {
whoIsOnlineComponent['element'].following = MOCK_ABLY_PARTICIPANT_DATA_2;

whoIsOnlineComponent['stopFollowing'](MOCK_ABLY_PARTICIPANT);

expect(whoIsOnlineComponent['element'].following).toBe(MOCK_ABLY_PARTICIPANT_DATA_2);
});

test('should set element.following to undefined if following the participant who is leaving', () => {
whoIsOnlineComponent['element'].following = MOCK_ABLY_PARTICIPANT_DATA_1;

whoIsOnlineComponent['stopFollowing']({
...MOCK_ABLY_PARTICIPANT,
clientId: MOCK_ABLY_PARTICIPANT_DATA_1.id,
});

expect(whoIsOnlineComponent['element'].following).toBe(undefined);
});
});
});
39 changes: 35 additions & 4 deletions src/components/who-is-online/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class WhoIsOnline extends BaseComponent {
private element: WhoIsOnlineElement;
private position: WhoIsOnlinePosition;
private participants: Participant[] = [];
private following: string;

constructor(position?: WhoIsOnlinePosition) {
super();
Expand All @@ -33,6 +34,7 @@ export class WhoIsOnline extends BaseComponent {
this.subscribeToRealtimeEvents();
this.positionWhoIsOnline();
this.addListeners();
this.realtime.enterWIOChannel(this.localParticipant);
}

/**
Expand Down Expand Up @@ -60,6 +62,7 @@ export class WhoIsOnline extends BaseComponent {
);
this.element.addEventListener(RealtimeEvent.REALTIME_GO_TO_PARTICIPANT, this.goToMousePointer);
this.element.addEventListener(RealtimeEvent.REALTIME_PRIVATE_MODE, this.setPrivate);
this.element.addEventListener(RealtimeEvent.REALTIME_GATHER, this.gatherAll);
}

/**
Expand All @@ -77,6 +80,7 @@ export class WhoIsOnline extends BaseComponent {
this.goToMousePointer,
);
this.element.removeEventListener(RealtimeEvent.REALTIME_PRIVATE_MODE, this.setPrivate);
this.element.removeEventListener(RealtimeEvent.REALTIME_GATHER, this.gatherAll);
}

/**
Expand All @@ -86,8 +90,9 @@ export class WhoIsOnline extends BaseComponent {
*/
private subscribeToRealtimeEvents(): void {
this.realtime.participantsObserver.subscribe(this.onParticipantListUpdate);
this.realtime.enterWIOChannel(this.localParticipant);
this.realtime.presenceWIOObserver.subscribe(this.onParticipantListUpdate);
this.realtime.participantLeaveObserver.subscribe(this.stopFollowing);
this.realtime.privateModeWIOObserver.subscribe(this.onParticipantListUpdate);
this.realtime.gatherWIOObserver.subscribe(this.setGather);
}

/**
Expand All @@ -97,6 +102,9 @@ export class WhoIsOnline extends BaseComponent {
*/
private unsubscribeToRealtimeEvents(): void {
this.realtime.participantsObserver.unsubscribe(this.onParticipantListUpdate);
this.realtime.participantLeaveObserver.unsubscribe(this.stopFollowing);
this.realtime.privateModeWIOObserver.unsubscribe(this.onParticipantListUpdate);
this.realtime.gatherWIOObserver.unsubscribe(this.setGather);
}

/**
Expand All @@ -116,7 +124,7 @@ export class WhoIsOnline extends BaseComponent {
return !isPrivate || (isPrivate && id === this.localParticipant.id);
})
.map(({ data }) => {
const { slotIndex, id, name, avatar, activeComponents, isPrivate } = data as Participant;
const { slotIndex, id, name, avatar, activeComponents } = data as Participant;
const { color } = this.realtime.getSlotColor(slotIndex);
const isLocal = this.localParticipant.id === id;
const joinedPresence = activeComponents.some((component) => component.includes('presence'));
Expand Down Expand Up @@ -196,6 +204,29 @@ export class WhoIsOnline extends BaseComponent {
*/
private setPrivate = ({ detail: { isPrivate, id } }: CustomEvent) => {
this.eventBus.publish(RealtimeEvent.REALTIME_PRIVATE_MODE, isPrivate);
this.realtime.updateWIOParticipant(id, isPrivate);
this.realtime.setPrivateWIOParticipant(id, isPrivate);
};

private setGather = (following) => {
if (following.clientId === this.localParticipant.id) return;

this.followMousePointer({ detail: { id: following?.data?.id } } as CustomEvent);

if (!following.data.id) {
this.element.following = undefined;
return;
}

this.element.following = following.data;
};

private gatherAll = (data: CustomEvent) => {
this.realtime.setGatherWIOParticipant({ ...data.detail });
};

private stopFollowing = (participant: AblyParticipant) => {
if (participant.clientId === this.element.following?.id) {
this.element.following = undefined;
}
};
}

0 comments on commit 34687cc

Please sign in to comment.