Skip to content

Commit

Permalink
core: Attach breakoutGroup to all remote and local participants on ro…
Browse files Browse the repository at this point in the history
…om_joined and breakout_group_joined signal events
  • Loading branch information
richtrwhereby committed Nov 20, 2024
1 parent e59ee3e commit 392e210
Show file tree
Hide file tree
Showing 15 changed files with 171 additions and 56 deletions.
6 changes: 6 additions & 0 deletions .changeset/bright-grapes-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@whereby.com/core": minor
"@whereby.com/media": patch
---

Add missing `breakoutGroup` property to all in-room participants
8 changes: 7 additions & 1 deletion packages/core/src/RoomParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface RoomParticipantData {
stream?: MediaStream;
isAudioEnabled: boolean;
isVideoEnabled: boolean;
breakoutGroup: string | null;
stickyReaction?: StickyReaction | null;
isDialIn: boolean;
}
Expand All @@ -22,6 +23,7 @@ export default class RoomParticipant {
public readonly isAudioEnabled: boolean;
public readonly isLocalParticipant: boolean = false;
public readonly isVideoEnabled: boolean;
public readonly breakoutGroup;
public readonly stickyReaction?: StickyReaction | null;
public readonly isDialIn: boolean;

Expand All @@ -31,6 +33,7 @@ export default class RoomParticipant {
stream,
isAudioEnabled,
isVideoEnabled,
breakoutGroup,
stickyReaction,
isDialIn,
}: RoomParticipantData) {
Expand All @@ -39,6 +42,7 @@ export default class RoomParticipant {
this.stream = stream;
this.isAudioEnabled = isAudioEnabled;
this.isVideoEnabled = isVideoEnabled;
this.breakoutGroup = breakoutGroup;
this.stickyReaction = stickyReaction;
this.isDialIn = isDialIn;
}
Expand Down Expand Up @@ -70,6 +74,7 @@ export interface RemoteParticipant {
isAudioEnabled: boolean;
isVideoEnabled: boolean;
isLocalParticipant: boolean;
breakoutGroup: string | null;
stream: (MediaStream & { inboundId?: string }) | null;
streams: Stream[];
newJoiner: boolean;
Expand All @@ -88,10 +93,11 @@ export class LocalParticipant extends RoomParticipant {
stream,
isAudioEnabled,
isVideoEnabled,
breakoutGroup,
stickyReaction,
isDialIn,
}: RoomParticipantData) {
super({ displayName, id, stream, isAudioEnabled, isVideoEnabled, stickyReaction, isDialIn });
super({ displayName, id, stream, isAudioEnabled, isVideoEnabled, breakoutGroup, stickyReaction, isDialIn });
}
}

Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/__mocks__/appMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export const randomSignalClient = ({
streams = [],
isAudioEnabled = true,
isVideoEnabled = true,
breakoutGroup = null,
role = { roleName: "visitor" },
startedCloudRecordingAt = null,
externalId = null,
Expand All @@ -92,6 +93,7 @@ export const randomSignalClient = ({
streams,
isAudioEnabled,
isVideoEnabled,
breakoutGroup,
role,
startedCloudRecordingAt,
externalId,
Expand All @@ -105,9 +107,11 @@ export const randomLocalParticipant = ({
stream = undefined,
isAudioEnabled = true,
isVideoEnabled = true,
breakoutGroup = null,
clientClaim = randomString(),
isScreenSharing = false,
roleName = "visitor",
stickyReaction = undefined,
isDialIn = false,
}: Partial<LocalParticipantState> = {}): LocalParticipantState => {
return {
Expand All @@ -116,10 +120,12 @@ export const randomLocalParticipant = ({
stream,
isAudioEnabled,
isVideoEnabled,
breakoutGroup,
isLocalParticipant: true,
clientClaim,
isScreenSharing,
roleName,
stickyReaction,
isDialIn,
};
};
Expand All @@ -130,6 +136,7 @@ export const randomRemoteParticipant = ({
roleName = "visitor",
isAudioEnabled = true,
isVideoEnabled = true,
breakoutGroup = null,
isLocalParticipant = false,
stream = null,
streams = [],
Expand All @@ -144,6 +151,7 @@ export const randomRemoteParticipant = ({
roleName,
isAudioEnabled,
isVideoEnabled,
breakoutGroup,
isLocalParticipant,
stream,
streams,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe("authorizationSlice", () => {
undefined,
signalEvents.roomJoined({
selfId: "selfId",
breakoutGroup: null,
clientClaim: "clientClaim",
isLocked: false,
room: {
Expand All @@ -44,6 +45,7 @@ describe("authorizationSlice", () => {
streams: [],
isAudioEnabled: true,
isVideoEnabled: true,
breakoutGroup: null,
role: {
roleName: "host",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe("cloudRecordingSlice", () => {
streams: [],
isAudioEnabled: true,
isVideoEnabled: false,
breakoutGroup: null,
id: "id",
role: {
roleName: "recorder",
Expand Down
65 changes: 65 additions & 0 deletions packages/core/src/redux/slices/__tests__/localParticipant.unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { localParticipantSlice } from "../localParticipant";
import { signalEvents } from "../signalConnection/actions";
import { randomSignalClient, randomLocalParticipant } from "../../../__mocks__/appMocks";

describe("localParticipantSlice", () => {
describe("reducers", () => {
describe("signalEvents.roomJoined", () => {
it("should update state", () => {
const localClient = randomSignalClient({ role: { roleName: "visitor" }, breakoutGroup: "a" });
const remoteClient = randomSignalClient();

const localParticipant = randomLocalParticipant({
id: localClient.id,
roleName: "viewer",
breakoutGroup: "b",
});

const result = localParticipantSlice.reducer(
undefined,
signalEvents.roomJoined({
...localParticipant,
isLocked: false,
selfId: localClient.id,
room: {
clients: [remoteClient, localClient],
knockers: [],
spotlights: [],
session: null,
},
}),
);

expect(result).toEqual({
...localParticipant,
id: localParticipant.id,
displayName: "", // not set from roomJoined event
roleName: localClient.role.roleName,
breakoutGroup: localClient.breakoutGroup,
clientClaim: localParticipant.clientClaim,
});
});
});

describe("signalEvents.breakoutGroupJoined", () => {
it("should update the participant", () => {
const breakoutGroupId = "test_breakout_group";
const participant = randomLocalParticipant();
const state = { ...participant };

const result = localParticipantSlice.reducer(
state,
signalEvents.breakoutGroupJoined({
clientId: participant.id,
group: breakoutGroupId,
}),
);

expect(result).toEqual({
...participant,
breakoutGroup: breakoutGroupId,
});
});
});
});
});
94 changes: 41 additions & 53 deletions packages/core/src/redux/slices/__tests__/remoteParticipants.unit.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { remoteParticipantsSlice } from "../remoteParticipants";
import { remoteParticipantsSlice, createRemoteParticipant } from "../remoteParticipants";
import { signalEvents } from "../signalConnection/actions";
import { rtcEvents } from "../rtcConnection/actions";
import {
randomSignalClient,
randomLocalParticipant,
randomRemoteParticipant,
randomString,
randomMediaStream,
Expand All @@ -12,57 +13,35 @@ describe("remoteParticipantsSlice", () => {
describe("reducers", () => {
describe("signalEvents.roomJoined", () => {
it("should update state", () => {
const localClient = randomSignalClient();
const localParticipant = randomLocalParticipant({
id: localClient.id,
});

const remoteClient = randomSignalClient({ breakoutGroup: "b" });
const remoteParticipant = createRemoteParticipant(remoteClient);

const result = remoteParticipantsSlice.reducer(
undefined,
signalEvents.roomJoined({
...localParticipant,
isLocked: false,
selfId: "selfId",
clientClaim: "clientClaim",
selfId: localClient.id,
room: {
clients: [
{
displayName: "displayName",
id: "id",
streams: [],
isAudioEnabled: true,
isVideoEnabled: true,
role: {
roleName: "visitor",
},
startedCloudRecordingAt: null,
externalId: null,
isDialIn: false,
},
],
clients: [localClient, remoteClient],
knockers: [],
spotlights: [],
session: null,
},
}),
);

expect(result.remoteParticipants).toEqual([
{
displayName: "displayName",
id: "id",
streams: [],
isAudioEnabled: true,
isVideoEnabled: true,
isLocalParticipant: false,
stream: null,
newJoiner: false,
roleName: "visitor",
startedCloudRecordingAt: null,
presentationStream: null,
externalId: null,
isDialIn: false,
},
]);
expect(result.remoteParticipants).toEqual([remoteParticipant]);
});
});

it("signalEvents.newClient", () => {
const client = randomSignalClient();
const client = randomSignalClient({ breakoutGroup: "a" });

const result = remoteParticipantsSlice.reducer(
undefined,
Expand All @@ -71,23 +50,7 @@ describe("remoteParticipantsSlice", () => {
}),
);

expect(result.remoteParticipants).toEqual([
{
id: client.id,
displayName: client.displayName,
isAudioEnabled: client.isAudioEnabled,
isVideoEnabled: client.isVideoEnabled,
isLocalParticipant: false,
stream: null,
streams: [],
newJoiner: true,
roleName: client.role.roleName,
startedCloudRecordingAt: client.startedCloudRecordingAt,
presentationStream: null,
externalId: null,
isDialIn: false,
},
]);
expect(result.remoteParticipants).toEqual([createRemoteParticipant(client, true)]);
});

it("signalEvents.clientLeft", () => {
Expand Down Expand Up @@ -206,6 +169,31 @@ describe("remoteParticipantsSlice", () => {
});
});

describe("signalEvents.breakoutGroupJoined", () => {
it("should update the participant", () => {
const breakoutGroupId = "test_breakout_group";
const participant = randomRemoteParticipant();
const state = {
remoteParticipants: [participant],
};

const result = remoteParticipantsSlice.reducer(
state,
signalEvents.breakoutGroupJoined({
clientId: participant.id,
group: breakoutGroupId,
}),
);

expect(result.remoteParticipants).toEqual([
{
...participant,
breakoutGroup: breakoutGroupId,
},
]);
});
});

describe("signalEvents.screenshareStarted", () => {
it("should update the participant", () => {
const participant = randomRemoteParticipant();
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/redux/slices/__tests__/room.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe("roomSlice", () => {
undefined,
signalEvents.roomJoined({
selfId: "selfId",
breakoutGroup: "",
clientClaim: "clientClaim",
isLocked: true,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe("roomConnectionSlice", () => {
signalEvents.roomJoined({
error: "room_locked",
selfId: "selfId",
breakoutGroup: "",
clientClaim: "clientClaim",
isLocked: true,
}),
Expand All @@ -28,6 +29,7 @@ describe("roomConnectionSlice", () => {
undefined,
signalEvents.roomJoined({
selfId: "selfId",
breakoutGroup: "",
clientClaim: "clientClaim",
isLocked: false,
}),
Expand All @@ -46,6 +48,7 @@ describe("roomConnectionSlice", () => {
signalEvents.roomJoined({
error: "room_full",
selfId: "selfId",
breakoutGroup: "",
isLocked: false,
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ describe("reducer", () => {
signalEvents.roomJoined({
isLocked: true,
selfId: "self-id",
breakoutGroup: null,
clientClaim: "client-claim",
room: {
clients: [],
Expand Down
Loading

0 comments on commit 392e210

Please sign in to comment.