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 = { ...@@ -17,27 +17,25 @@ robotController = {
return easyrtc.myEasyrtcid; return easyrtc.myEasyrtcid;
}, },
getParticipants: () => {
return easyrtc.getRoomOccupantsAsArray(room);
},
getRemoteStream: participant => { getRemoteStream: participant => {
return easyrtc.getRemoteStream(participant); return easyrtc.getRemoteStream(participant);
}, },
getRemoteStreams: () => { getRemoteParticipants: () => {
const participants = robotController.getParticipants(); const participants = easyrtc.getRoomOccupantsAsArray(room);
const res = {}; const res = [];
for (let i = 0; i < participants.length; i++) { if (participants) {
const participant = participants[i]; for (let i = 0; i < participants.length; i++) {
try { const participant = participants[i];
const mediaStream = robotController.getRemoteStream(participant); try {
if (mediaStream !== null) { const mediaStream = robotController.getRemoteStream(participant);
res[participant] = mediaStream; 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; return res;
...@@ -53,6 +51,14 @@ robotController = { ...@@ -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: () => {}, onAttendeePush: () => {},
onAttendeeRemove: () => {}, onAttendeeRemove: () => {},
onAttendeeUpdate: () => {} onAttendeeUpdate: () => {}
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// Let's do some simple mocking of client-side services // Let's do some simple mocking of client-side services
const angular = { const angular = {
disconnected: false,
registeredEvents: {}, registeredEvents: {},
element: () => ({ element: () => ({
scope: () => ({ scope: () => ({
...@@ -10,6 +11,9 @@ const angular = { ...@@ -10,6 +11,9 @@ const angular = {
$on: (event, f) => { $on: (event, f) => {
angular.registeredEvents[event] = f; angular.registeredEvents[event] = f;
} }
},
leaveConference: () => {
angular.disconnected = true;
} }
}), }),
injector: () => ({ injector: () => ({
...@@ -20,9 +24,19 @@ const angular = { ...@@ -20,9 +24,19 @@ const angular = {
}) })
}; };
const easyRTCMock = participants => ({ const easyRTCMock = (participantsWithStream, participantsWithoutStream = []) => ({
getRoomOccupantsAsArray: () => participants, getRoomOccupantsAsArray: () => participantsWithStream
getRemoteStream: participant => ({origin: participant}) .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 = { const document = {
...@@ -45,23 +59,24 @@ describe('client/controller', () => { ...@@ -45,23 +59,24 @@ describe('client/controller', () => {
}); });
test('should return the correct participants', () => { 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).toEqual(expect.arrayContaining(['p1', 'p2', 'p3']));
expect(participants).toHaveLength(3); 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', () => { test('should return the Streams of the participant', () => {
const stream = global.robotController.getRemoteStream('p2'); const stream = global.robotController.getRemoteStream('p2');
expect(stream.origin).toBe('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', () => { test('should call listener on push events', () => {
let eventFired = false; let eventFired = false;
...@@ -106,4 +121,10 @@ describe('client/controller', () => { ...@@ -106,4 +121,10 @@ describe('client/controller', () => {
expect(eventFired).toBe(true); 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 = { ...@@ -14,6 +14,7 @@ robot = {
previousReco: [], previousReco: [],
recordedParticipantsWS: {}, recordedParticipantsWS: {},
participantsMediaRecorders: {}, participantsMediaRecorders: {},
isDisconnected: false,
processAudio(stream, callback, interval) { processAudio(stream, callback, interval) {
const mediaRecorder = new MediaRecorder(stream); const mediaRecorder = new MediaRecorder(stream);
...@@ -103,6 +104,12 @@ robot = { ...@@ -103,6 +104,12 @@ robot = {
robot.recordedParticipantsWS[easyrtcid].close(); robot.recordedParticipantsWS[easyrtcid].close();
}, },
checkDisconnect() {
if (robotController.getRemoteParticipants().length === 0) {
robot.stop();
}
},
start: () => { start: () => {
robotLib.stt = robotLib.stt(config); robotLib.stt = robotLib.stt(config);
robotLib.reco = robotLib.reco(config); robotLib.reco = robotLib.reco(config);
...@@ -114,6 +121,7 @@ robot = { ...@@ -114,6 +121,7 @@ robot = {
robotController.onAttendeeRemove = (e, data) => { robotController.onAttendeeRemove = (e, data) => {
robot.stopRecordParticipant(data.easyrtcid); robot.stopRecordParticipant(data.easyrtcid);
robot.checkDisconnect();
}; };
function recoStartRetry() { function recoStartRetry() {
...@@ -132,11 +140,19 @@ robot = { ...@@ -132,11 +140,19 @@ robot = {
// Record current participants already present in the room // Record current participants already present in the room
// (except the robot itself) // (except the robot itself)
for (const participantId of robotController.getParticipants()) { for (const participantId of robotController.getRemoteParticipants()) {
if (participantId !== robotController.getMyId()) { if (participantId !== robotController.getMyId()) {
robot.recordParticipant(participantId); 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', () => { ...@@ -41,17 +41,27 @@ describe('client/robot', () => {
}; };
global.MediaRecorder.instances = {}; global.MediaRecorder.instances = {};
global._setIntervalCalls = [];
global.setInterval = function (f, timeout) {
global._setIntervalCalls.push([f, timeout]);
};
global.isDisconnected = false;
global.robotController = { global.robotController = {
external: { external: {
load: () => {} load: () => {}
}, },
getMyId: () => 'robotId', getMyId: () => 'robotId',
getParticipants: () => [ getRemoteParticipants: () => [
global.robotController.getMyId(), 'someid0',
'someid1', 'someid1',
'someid2' 'someid2'
], ],
getRemoteStream: id => ({type: 'RemoteStream', id}) getRemoteStream: id => ({type: 'RemoteStream', id}),
disconnect: () => {
global.isDisconnected = true;
}
}; };
global.robotLib = { global.robotLib = {
...@@ -72,6 +82,11 @@ describe('client/robot', () => { ...@@ -72,6 +82,11 @@ describe('client/robot', () => {
expect(global.robot).toBeDefined(); 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`', () => { test('should return a started mediaRecorder on `processAudio`', () => {
const res = global.robot.processAudio({ const res = global.robot.processAudio({
type: 'stream' type: 'stream'
...@@ -132,6 +147,23 @@ describe('client/robot', () => { ...@@ -132,6 +147,23 @@ describe('client/robot', () => {
expect(sttMock.wsMock.status).toBe('closed'); 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', () => { test('should try to reopen a stt ws on error', () => {
global.robot.start(); 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