Commit dd4f172e authored by Tom JORQUERA's avatar Tom JORQUERA
Browse files

Merge branch 'Issue_34' into 'master'

[issue-34] Disconnect on meeting ending

Closes #34

See merge request !31
parents 58d4877f eea67458
Pipeline #3894 passed with stage
in 1 minute and 37 seconds
......@@ -17,27 +17,25 @@ robotController = {
return easyrtc.myEasyrtcid;
},
getParticipants: () => {
return easyrtc.getRoomOccupantsAsArray(room);
},
getRemoteStream: participant => {
return easyrtc.getRemoteStream(participant);
},
getRemoteStreams: () => {
const participants = robotController.getParticipants();
const res = {};
for (let i = 0; i < participants.length; i++) {
const participant = participants[i];
try {
const mediaStream = robotController.getRemoteStream(participant);
if (mediaStream !== null) {
res[participant] = mediaStream;
getRemoteParticipants: () => {
const participants = easyrtc.getRoomOccupantsAsArray(room);
const res = [];
if (participants) {
for (let i = 0; i < participants.length; i++) {
const participant = participants[i];
try {
const mediaStream = robotController.getRemoteStream(participant);
if (mediaStream !== null) {
res.push(participant);
}
} catch (err) {
console.error('could not get remote stream for %s', participant);
console.error(err);
}
} catch (err) {
console.error('could not get remote stream for %s', participant);
console.error(err);
}
}
return res;
......@@ -53,6 +51,14 @@ robotController = {
});
},
getDisconnectButton: () => {
return document.getElementsByClassName('conference-user-control-bar')[0].childNodes[0].childNodes[2].childNodes[0]; // Check issue #53
},
disconnect: () => {
angular.element(robotController.getDisconnectButton()).scope().leaveConference();
},
onAttendeePush: () => {},
onAttendeeRemove: () => {},
onAttendeeUpdate: () => {}
......
......@@ -3,6 +3,7 @@
// Let's do some simple mocking of client-side services
const angular = {
disconnected: false,
registeredEvents: {},
element: () => ({
scope: () => ({
......@@ -10,6 +11,9 @@ const angular = {
$on: (event, f) => {
angular.registeredEvents[event] = f;
}
},
leaveConference: () => {
angular.disconnected = true;
}
}),
injector: () => ({
......@@ -20,9 +24,19 @@ const angular = {
})
};
const easyRTCMock = participants => ({
getRoomOccupantsAsArray: () => participants,
getRemoteStream: participant => ({origin: participant})
const easyRTCMock = (participantsWithStream, participantsWithoutStream = []) => ({
getRoomOccupantsAsArray: () => participantsWithStream
.concat(participantsWithoutStream),
getRemoteStream: participant => {
// Participant must be in list of participants AND not be in the list
// of participants without stream.
if (participantsWithStream.indexOf(participant) !== -1) {
return {
origin: participant
};
}
return null;
}
});
const document = {
......@@ -45,23 +59,24 @@ describe('client/controller', () => {
});
test('should return the correct participants', () => {
const participants = global.robotController.getParticipants();
const participants = global.robotController.getRemoteParticipants();
expect(participants).toEqual(expect.arrayContaining(['p1', 'p2', 'p3']));
expect(participants).toHaveLength(3);
});
test('should not return participants without stream', () => {
global.easyrtc = easyRTCMock(['p1', 'p2', 'p3'], ['nostream']);
const participants = global.robotController.getRemoteParticipants();
expect(participants).not.toEqual(expect.arrayContaining(['nostream']));
expect(participants).toHaveLength(3);
});
test('should return the Streams of the participant', () => {
const stream = global.robotController.getRemoteStream('p2');
expect(stream.origin).toBe('p2');
});
test('should return the Streams of all the participants', () => {
const streams = global.robotController.getRemoteStreams();
expect(streams).toHaveProperty('p1');
expect(streams).toHaveProperty('p2');
expect(streams).toHaveProperty('p3');
});
test('should call listener on push events', () => {
let eventFired = false;
......@@ -106,4 +121,10 @@ describe('client/controller', () => {
expect(eventFired).toBe(true);
});
test('should be disconnected on disconnect', () => {
global.robotController.getDisconnectButton = () => {}; // Mock of hubl.in getDisconnectButton
global.robotController.disconnect();
expect(angular.disconnected).toBe(true);
});
});
......@@ -14,6 +14,7 @@ robot = {
previousReco: [],
recordedParticipantsWS: {},
participantsMediaRecorders: {},
isDisconnected: false,
processAudio(stream, callback, interval) {
const mediaRecorder = new MediaRecorder(stream);
......@@ -103,6 +104,12 @@ robot = {
robot.recordedParticipantsWS[easyrtcid].close();
},
checkDisconnect() {
if (robotController.getRemoteParticipants().length === 0) {
robot.stop();
}
},
start: () => {
robotLib.stt = robotLib.stt(config);
robotLib.reco = robotLib.reco(config);
......@@ -114,6 +121,7 @@ robot = {
robotController.onAttendeeRemove = (e, data) => {
robot.stopRecordParticipant(data.easyrtcid);
robot.checkDisconnect();
};
function recoStartRetry() {
......@@ -132,11 +140,19 @@ robot = {
// Record current participants already present in the room
// (except the robot itself)
for (const participantId of robotController.getParticipants()) {
for (const participantId of robotController.getRemoteParticipants()) {
if (participantId !== robotController.getMyId()) {
robot.recordParticipant(participantId);
}
}
// Wait 5 minute before leaving a room if alone
setInterval(robot.checkDisconnect, 300000);
},
stop: () => {
robot.isDisconnected = true;
robotController.disconnect();
}
};
......
......@@ -41,17 +41,27 @@ describe('client/robot', () => {
};
global.MediaRecorder.instances = {};
global._setIntervalCalls = [];
global.setInterval = function (f, timeout) {
global._setIntervalCalls.push([f, timeout]);
};
global.isDisconnected = false;
global.robotController = {
external: {
load: () => {}
},
getMyId: () => 'robotId',
getParticipants: () => [
global.robotController.getMyId(),
getRemoteParticipants: () => [
'someid0',
'someid1',
'someid2'
],
getRemoteStream: id => ({type: 'RemoteStream', id})
getRemoteStream: id => ({type: 'RemoteStream', id}),
disconnect: () => {
global.isDisconnected = true;
}
};
global.robotLib = {
......@@ -72,6 +82,11 @@ describe('client/robot', () => {
expect(global.robot).toBeDefined();
});
test('should set a interval for disconnection', () => {
global.robot.start();
expect.arrayContaining([[global.robot.checkDisconnect, 300000]]);
});
test('should return a started mediaRecorder on `processAudio`', () => {
const res = global.robot.processAudio({
type: 'stream'
......@@ -132,6 +147,23 @@ describe('client/robot', () => {
expect(sttMock.wsMock.status).toBe('closed');
});
test('should not disconnected with more than one user', () => {
global.robot.start();
global.robotController.onAttendeeRemove({}, {easyrtcid: 'someid1'});
expect(global.isDisconnected).toBe(false);
});
test('should disconnected without user', () => {
global.robotController.getRemoteParticipants = function () { // Redefine getRemoteParticipants for no user
return [];
};
global.robot.start();
global.robotController.onAttendeeRemove({}, {easyrtcid: 'someid1'});
expect(global.isDisconnected).toBe(true);
});
test('should try to reopen a stt ws on error', () => {
global.robot.start();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment