Merge remote-tracking branch 'upstream/v2.4.x-release' into improve-shortcut-test
This commit is contained in:
commit
cac21564a1
@ -15,7 +15,7 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
|
|
||||||
def handleCreateBreakoutRoomsCmdMsg(msg: CreateBreakoutRoomsCmdMsg, state: MeetingState2x): MeetingState2x = {
|
def handleCreateBreakoutRoomsCmdMsg(msg: CreateBreakoutRoomsCmdMsg, state: MeetingState2x): MeetingState2x = {
|
||||||
|
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to create breakout room for meeting."
|
val reason = "No permission to create breakout room for meeting."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId,
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId,
|
||||||
|
@ -15,7 +15,7 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
|
|
||||||
def handleSetLockSettings(msg: ChangeLockSettingsInMeetingCmdMsg): Unit = {
|
def handleSetLockSettings(msg: ChangeLockSettingsInMeetingCmdMsg): Unit = {
|
||||||
|
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to change lock settings"
|
val reason = "No permission to change lock settings"
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -12,7 +12,7 @@ trait ChangeUserRoleCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
val outGW: OutMsgRouter
|
val outGW: OutMsgRouter
|
||||||
|
|
||||||
def handleChangeUserRoleCmdMsg(msg: ChangeUserRoleCmdMsg) {
|
def handleChangeUserRoleCmdMsg(msg: ChangeUserRoleCmdMsg) {
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to change user role in meeting."
|
val reason = "No permission to change user role in meeting."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -23,7 +23,7 @@ trait EjectUserFromMeetingCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
PermissionCheck.VIEWER_LEVEL,
|
PermissionCheck.VIEWER_LEVEL,
|
||||||
liveMeeting.users2x,
|
liveMeeting.users2x,
|
||||||
msg.header.userId
|
msg.header.userId
|
||||||
)) {
|
) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
|
|
||||||
val reason = "No permission to eject user from meeting."
|
val reason = "No permission to eject user from meeting."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -15,7 +15,7 @@ trait LogoutAndEndMeetingCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
val eventBus: InternalEventBus
|
val eventBus: InternalEventBus
|
||||||
|
|
||||||
def handleLogoutAndEndMeetingCmdMsg(msg: LogoutAndEndMeetingCmdMsg, state: MeetingState2x): Unit = {
|
def handleLogoutAndEndMeetingCmdMsg(msg: LogoutAndEndMeetingCmdMsg, state: MeetingState2x): Unit = {
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to end meeting on logout."
|
val reason = "No permission to end meeting on logout."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -13,7 +13,7 @@ trait UpdateWebcamsOnlyForModeratorCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
|
|
||||||
def handleUpdateWebcamsOnlyForModeratorCmdMsg(msg: UpdateWebcamsOnlyForModeratorCmdMsg) {
|
def handleUpdateWebcamsOnlyForModeratorCmdMsg(msg: UpdateWebcamsOnlyForModeratorCmdMsg) {
|
||||||
|
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to change lock settings"
|
val reason = "No permission to change lock settings"
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -12,7 +12,7 @@ trait MuteAllExceptPresentersCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
val outGW: OutMsgRouter
|
val outGW: OutMsgRouter
|
||||||
|
|
||||||
def handleMuteAllExceptPresentersCmdMsg(msg: MuteAllExceptPresentersCmdMsg) {
|
def handleMuteAllExceptPresentersCmdMsg(msg: MuteAllExceptPresentersCmdMsg) {
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to mute all except presenters."
|
val reason = "No permission to mute all except presenters."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -13,7 +13,7 @@ trait MuteMeetingCmdMsgHdlr extends RightsManagementTrait {
|
|||||||
|
|
||||||
def handleMuteMeetingCmdMsg(msg: MuteMeetingCmdMsg): Unit = {
|
def handleMuteMeetingCmdMsg(msg: MuteMeetingCmdMsg): Unit = {
|
||||||
|
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to mute meeting."
|
val reason = "No permission to mute meeting."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -14,7 +14,7 @@ trait SetGuestPolicyMsgHdlr extends RightsManagementTrait {
|
|||||||
val outGW: OutMsgRouter
|
val outGW: OutMsgRouter
|
||||||
|
|
||||||
def handleSetGuestPolicyMsg(msg: SetGuestPolicyCmdMsg): Unit = {
|
def handleSetGuestPolicyMsg(msg: SetGuestPolicyCmdMsg): Unit = {
|
||||||
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId)) {
|
if (permissionFailed(PermissionCheck.MOD_LEVEL, PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId) || liveMeeting.props.meetingProp.isBreakout) {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val reason = "No permission to set guest policy in meeting."
|
val reason = "No permission to set guest policy in meeting."
|
||||||
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
PermissionCheck.ejectUserForFailedPermission(meetingId, msg.header.userId, reason, outGW, liveMeeting)
|
||||||
|
@ -28,6 +28,14 @@ public class LearningDashboardService {
|
|||||||
private static Logger log = LoggerFactory.getLogger(LearningDashboardService.class);
|
private static Logger log = LoggerFactory.getLogger(LearningDashboardService.class);
|
||||||
private static String learningDashboardFilesDir = "/var/bigbluebutton/learning-dashboard";
|
private static String learningDashboardFilesDir = "/var/bigbluebutton/learning-dashboard";
|
||||||
|
|
||||||
|
public File getJsonDataFile(String meetingId, String learningDashboardAccessToken) {
|
||||||
|
File baseDir = new File(this.getDestinationBaseDirectoryName(meetingId,learningDashboardAccessToken));
|
||||||
|
if (!baseDir.exists()) baseDir.mkdirs();
|
||||||
|
|
||||||
|
File jsonFile = new File(baseDir.getAbsolutePath() + File.separatorChar + "learning_dashboard_data.json");
|
||||||
|
return jsonFile;
|
||||||
|
}
|
||||||
|
|
||||||
public void writeJsonDataFile(String meetingId, String learningDashboardAccessToken, String activityJson) {
|
public void writeJsonDataFile(String meetingId, String learningDashboardAccessToken, String activityJson) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -36,10 +44,7 @@ public class LearningDashboardService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File baseDir = new File(this.getDestinationBaseDirectoryName(meetingId,learningDashboardAccessToken));
|
File jsonFile = this.getJsonDataFile(meetingId,learningDashboardAccessToken);
|
||||||
if (!baseDir.exists()) baseDir.mkdirs();
|
|
||||||
|
|
||||||
File jsonFile = new File(baseDir.getAbsolutePath() + File.separatorChar + "learning_dashboard_data.json");
|
|
||||||
|
|
||||||
FileOutputStream fileOutput = new FileOutputStream(jsonFile);
|
FileOutputStream fileOutput = new FileOutputStream(jsonFile);
|
||||||
fileOutput.write(activityJson.getBytes());
|
fileOutput.write(activityJson.getBytes());
|
||||||
|
@ -17,6 +17,7 @@ class App extends React.Component {
|
|||||||
tab: 'overview',
|
tab: 'overview',
|
||||||
meetingId: '',
|
meetingId: '',
|
||||||
learningDashboardAccessToken: '',
|
learningDashboardAccessToken: '',
|
||||||
|
sessionToken: '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ class App extends React.Component {
|
|||||||
setDashboardParams() {
|
setDashboardParams() {
|
||||||
let learningDashboardAccessToken = '';
|
let learningDashboardAccessToken = '';
|
||||||
let meetingId = '';
|
let meetingId = '';
|
||||||
|
let sessionToken = '';
|
||||||
|
|
||||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||||
const params = Object.fromEntries(urlSearchParams.entries());
|
const params = Object.fromEntries(urlSearchParams.entries());
|
||||||
@ -38,6 +40,10 @@ class App extends React.Component {
|
|||||||
meetingId = params.meeting;
|
meetingId = params.meeting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof params.sessionToken !== 'undefined') {
|
||||||
|
sessionToken = params.sessionToken;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof params.report !== 'undefined') {
|
if (typeof params.report !== 'undefined') {
|
||||||
learningDashboardAccessToken = params.report;
|
learningDashboardAccessToken = params.report;
|
||||||
} else {
|
} else {
|
||||||
@ -56,11 +62,12 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ learningDashboardAccessToken, meetingId }, this.fetchActivitiesJson);
|
this.setState({ learningDashboardAccessToken, meetingId, sessionToken },
|
||||||
|
this.fetchActivitiesJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchActivitiesJson() {
|
fetchActivitiesJson() {
|
||||||
const { learningDashboardAccessToken, meetingId } = this.state;
|
const { learningDashboardAccessToken, meetingId, sessionToken } = this.state;
|
||||||
|
|
||||||
if (learningDashboardAccessToken !== '') {
|
if (learningDashboardAccessToken !== '') {
|
||||||
fetch(`${meetingId}/${learningDashboardAccessToken}/learning_dashboard_data.json`)
|
fetch(`${meetingId}/${learningDashboardAccessToken}/learning_dashboard_data.json`)
|
||||||
@ -71,6 +78,24 @@ class App extends React.Component {
|
|||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
});
|
});
|
||||||
|
} else if (sessionToken !== '') {
|
||||||
|
const url = new URL('/bigbluebutton/api/learningDashboard', window.location);
|
||||||
|
fetch(`${url}?sessionToken=${sessionToken}`)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((json) => {
|
||||||
|
if (json.response.returncode === 'SUCCESS') {
|
||||||
|
const jsonData = JSON.parse(json.response.data);
|
||||||
|
this.setState({ activitiesJson: jsonData, loading: false });
|
||||||
|
document.title = `Learning Dashboard - ${jsonData.name}`;
|
||||||
|
} else {
|
||||||
|
// When meeting is ended the sessionToken stop working, check for new cookies
|
||||||
|
this.setDashboardParams();
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.setState({ loading: false });
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
}
|
}
|
||||||
@ -78,7 +103,7 @@ class App extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
activitiesJson, tab, learningDashboardAccessToken, loading,
|
activitiesJson, tab, meetingId, learningDashboardAccessToken, sessionToken, loading,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
@ -162,19 +187,59 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getErrorMessage() {
|
function getErrorMessage() {
|
||||||
if (learningDashboardAccessToken === '') {
|
if (learningDashboardAccessToken === '' && sessionToken === '') {
|
||||||
return intl.formatMessage({ id: 'app.learningDashboard.errors.invalidToken', defaultMessage: 'Invalid session token' });
|
return intl.formatMessage({ id: 'app.learningDashboard.errors.invalidToken', defaultMessage: 'Invalid session token' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activitiesJson === {} || typeof activitiesJson.name === 'undefined') {
|
||||||
return intl.formatMessage({ id: 'app.learningDashboard.errors.dataUnavailable', defaultMessage: 'Data is no longer available' });
|
return intl.formatMessage({ id: 'app.learningDashboard.errors.dataUnavailable', defaultMessage: 'Data is no longer available' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loading === false && typeof activitiesJson.name === 'undefined') return <ErrorMessage message={getErrorMessage()} />;
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyPublicLink() {
|
||||||
|
let url = window.location.href.split('?')[0];
|
||||||
|
url += `?meeting=${meetingId}&report=${learningDashboardAccessToken}&lang=${intl.locale}`;
|
||||||
|
navigator.clipboard.writeText(url);
|
||||||
|
const copiedMessage = intl.formatMessage({ id: 'app.learningDashboard.linkCopied', defaultMessage: 'Link successfully copied' });
|
||||||
|
alert(copiedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading === false && getErrorMessage() !== '') return <ErrorMessage message={getErrorMessage()} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-10">
|
<div className="mx-10">
|
||||||
<div className="flex items-start justify-between pb-3">
|
<div className="flex items-start justify-between pb-3">
|
||||||
<h1 className="mt-3 text-2xl font-semibold whitespace-nowrap inline-block">
|
<h1 className="mt-3 text-2xl font-semibold whitespace-nowrap inline-block">
|
||||||
<FormattedMessage id="app.learningDashboard.dashboardTitle" defaultMessage="Learning Dashboard" />
|
<FormattedMessage id="app.learningDashboard.dashboardTitle" defaultMessage="Learning Dashboard" />
|
||||||
|
|
||||||
|
{
|
||||||
|
learningDashboardAccessToken !== ''
|
||||||
|
? (
|
||||||
|
<button type="button" onClick={() => { copyPublicLink(); }} className="text-sm font-medium text-blue-500 ease-out" name="teste">
|
||||||
|
(
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className="h-4 w-4 inline"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<FormattedMessage id="app.learningDashboard.shareButton" defaultMessage="Share with others" />
|
||||||
|
)
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
<br />
|
<br />
|
||||||
<span className="text-sm font-medium">{activitiesJson.name || ''}</span>
|
<span className="text-sm font-medium">{activitiesJson.name || ''}</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
@ -60,7 +60,7 @@ class Dashboard extends React.Component {
|
|||||||
setRtl() {
|
setRtl() {
|
||||||
const { intlLocale } = this.state;
|
const { intlLocale } = this.state;
|
||||||
|
|
||||||
if (RTL_LANGUAGES.includes(intlLocale)) {
|
if (RTL_LANGUAGES.includes(intlLocale.substring(0, 2))) {
|
||||||
document.body.parentNode.setAttribute('dir', 'rtl');
|
document.body.parentNode.setAttribute('dir', 'rtl');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
git clone --branch v2.5.2 --depth 1 https://github.com/bigbluebutton/bbb-webrtc-sfu bbb-webrtc-sfu
|
git clone --branch v2.6.0-beta.5 --depth 1 https://github.com/bigbluebutton/bbb-webrtc-sfu bbb-webrtc-sfu
|
||||||
|
@ -1 +1 @@
|
|||||||
BIGBLUEBUTTON_RELEASE=2.4-rc-2
|
BIGBLUEBUTTON_RELEASE=2.4-rc-3
|
||||||
|
@ -34,15 +34,23 @@ log_history=28
|
|||||||
find /var/bigbluebutton/ -maxdepth 1 -type d -name "*-*" -mtime +$history -exec rm -rf '{}' +
|
find /var/bigbluebutton/ -maxdepth 1 -type d -name "*-*" -mtime +$history -exec rm -rf '{}' +
|
||||||
|
|
||||||
#
|
#
|
||||||
# Delete streams in kurento older than N days
|
# Delete streams from Kurento and mediasoup older than N days
|
||||||
#
|
#
|
||||||
for app in recordings screenshare; do
|
kurento_dir=/var/kurento/
|
||||||
app_dir=/var/kurento/$app
|
mediasoup_dir=/var/mediasoup/
|
||||||
|
|
||||||
|
remove_stale_sfu_raw_files() {
|
||||||
|
for app in recordings screenshare; do
|
||||||
|
app_dir="${1}${app}"
|
||||||
if [[ -d $app_dir ]]; then
|
if [[ -d $app_dir ]]; then
|
||||||
find $app_dir -name "*.mkv" -o -name "*.webm" -mtime +$history -delete
|
find "$app_dir" -name "*.mkv" -o -name "*.webm" -mtime +"$history" -delete
|
||||||
find $app_dir -type d -empty -mtime +$history -exec rmdir '{}' +
|
find "$app_dir" -type d -empty -mtime +"$history" -exec rmdir '{}' +
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_stale_sfu_raw_files "$kurento_dir"
|
||||||
|
remove_stale_sfu_raw_files "$mediasoup_dir"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Delete FreeSWITCH wav/opus recordings older than N days
|
# Delete FreeSWITCH wav/opus recordings older than N days
|
||||||
|
@ -75,8 +75,13 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea::-webkit-input-placeholder,
|
::-webkit-input-placeholder {
|
||||||
input::-webkit-input-placeholder {
|
color: var(--palette-placeholder-text);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
:-moz-placeholder, /* Firefox 4 to 18 */
|
||||||
|
::-moz-placeholder { /* Firefox 19+ */
|
||||||
color: var(--palette-placeholder-text);
|
color: var(--palette-placeholder-text);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,18 @@ export default function handleMeetingEnd({ header, body }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Meetings.find({ meetingId }).forEach((doc) => {
|
||||||
Meetings.update({ meetingId },
|
Meetings.update({ meetingId },
|
||||||
{ $set: { meetingEnded: true, meetingEndedBy: userId, meetingEndedReason: reason } },
|
{
|
||||||
|
$set: {
|
||||||
|
meetingEnded: true,
|
||||||
|
meetingEndedBy: userId,
|
||||||
|
meetingEndedReason: reason,
|
||||||
|
learningDashboardAccessToken: doc.password.learningDashboardAccessToken,
|
||||||
|
},
|
||||||
|
},
|
||||||
(err, num) => { cb(err, num, 'Meeting'); });
|
(err, num) => { cb(err, num, 'Meeting'); });
|
||||||
|
});
|
||||||
|
|
||||||
Breakouts.update({ parentMeetingId: meetingId },
|
Breakouts.update({ parentMeetingId: meetingId },
|
||||||
{ $set: { meetingEnded: true } },
|
{ $set: { meetingEnded: true } },
|
||||||
|
@ -43,10 +43,8 @@ function meetings(role) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (User.role === ROLE_MODERATOR) {
|
if (User.role !== ROLE_MODERATOR) {
|
||||||
delete options.fields.password;
|
options.fields.learningDashboardAccessToken = false;
|
||||||
options.fields['password.viewerPass'] = false;
|
|
||||||
options.fields['password.moderatorPass'] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Meetings.find(selector, options);
|
return Meetings.find(selector, options);
|
||||||
|
@ -323,30 +323,6 @@ WebApp.connectHandlers.use('/guestWait', (req, res) => {
|
|||||||
res.end(guestWaitHtml);
|
res.end(guestWaitHtml);
|
||||||
});
|
});
|
||||||
|
|
||||||
// WASM endpoint to be used to fetch the .wasm models for camera effects
|
|
||||||
// (blur, virtual background).
|
|
||||||
// See: /imports/ui/services/virtual-backgrounds/
|
|
||||||
WebApp.connectHandlers.use('/wasm', (req, res) => {
|
|
||||||
const pathname = req._parsedUrl.pathname;
|
|
||||||
let file = "";
|
|
||||||
let hasError = false;
|
|
||||||
try {
|
|
||||||
file = Assets.getBinary(pathname.substr(1, pathname.length-1));
|
|
||||||
} catch (error) {
|
|
||||||
hasError = true;
|
|
||||||
Logger.warn(`Could not find WASM file: ${error}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'application/wasm');
|
|
||||||
if (hasError) {
|
|
||||||
res.writeHead(404);
|
|
||||||
} else {
|
|
||||||
res.writeHead(200);
|
|
||||||
}
|
|
||||||
res.end(file);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
export const eventEmitter = Redis.emitter;
|
export const eventEmitter = Redis.emitter;
|
||||||
|
|
||||||
export const redisPubSub = Redis;
|
export const redisPubSub = Redis;
|
||||||
|
@ -227,7 +227,8 @@ class BreakoutRoom extends PureComponent {
|
|||||||
componentDidUpdate(prevProps, prevstate) {
|
componentDidUpdate(prevProps, prevstate) {
|
||||||
if (this.listOfUsers) {
|
if (this.listOfUsers) {
|
||||||
for (let i = 0; i < this.listOfUsers.children.length; i += 1) {
|
for (let i = 0; i < this.listOfUsers.children.length; i += 1) {
|
||||||
const roomList = this.listOfUsers.children[i].getElementsByTagName('div')[0];
|
const roomWrapperChildren = this.listOfUsers.children[i].getElementsByTagName('div');
|
||||||
|
const roomList = roomWrapperChildren[roomWrapperChildren.length > 1 ? 1 : 0];
|
||||||
roomList.addEventListener('keydown', this.handleMoveEvent, true);
|
roomList.addEventListener('keydown', this.handleMoveEvent, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ class BreakoutJoinConfirmation extends Component {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
{ waiting ? <span>{intl.formatMessage(intlMessages.generatingURL)}</span> : null}
|
{ waiting ? <span data-test="labelGeneratingURL">{intl.formatMessage(intlMessages.generatingURL)}</span> : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -536,6 +536,7 @@ class BreakoutRoom extends PureComponent {
|
|||||||
size="lg"
|
size="lg"
|
||||||
label={intl.formatMessage(intlMessages.endAllBreakouts)}
|
label={intl.formatMessage(intlMessages.endAllBreakouts)}
|
||||||
className={styles.endButton}
|
className={styles.endButton}
|
||||||
|
data-test="endBreakoutRoomsButton"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.closePanel();
|
this.closePanel();
|
||||||
endAllBreakouts();
|
endAllBreakouts();
|
||||||
|
@ -20,23 +20,45 @@ const isModerator = () => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLearningDashboardAccessToken = () => ((
|
const isLearningDashboardEnabled = () => (((
|
||||||
Meetings.findOne(
|
Meetings.findOne(
|
||||||
{ meetingId: Auth.meetingID },
|
{ meetingId: Auth.meetingID },
|
||||||
{
|
{
|
||||||
fields: { 'password.learningDashboardAccessToken': 1 },
|
fields: { 'meetingProp.learningDashboardEnabled': 1 },
|
||||||
},
|
},
|
||||||
) || {}).password || {}).learningDashboardAccessToken || null;
|
) || {}).meetingProp || {}).learningDashboardEnabled || false);
|
||||||
|
|
||||||
const openLearningDashboardUrl = (lang) => {
|
const getLearningDashboardAccessToken = () => ((
|
||||||
|
Meetings.findOne(
|
||||||
|
{ meetingId: Auth.meetingID, learningDashboardAccessToken: { $exists: true } },
|
||||||
|
{
|
||||||
|
fields: { learningDashboardAccessToken: 1 },
|
||||||
|
},
|
||||||
|
) || {}).learningDashboardAccessToken || null);
|
||||||
|
|
||||||
|
const setLearningDashboardCookie = () => {
|
||||||
|
const learningDashboardAccessToken = getLearningDashboardAccessToken();
|
||||||
|
if (learningDashboardAccessToken !== null) {
|
||||||
const cookieExpiresDate = new Date();
|
const cookieExpiresDate = new Date();
|
||||||
cookieExpiresDate.setTime(cookieExpiresDate.getTime() + (3600000 * 24 * 30)); // keep cookie 30d
|
cookieExpiresDate.setTime(cookieExpiresDate.getTime() + (3600000 * 24 * 30)); // keep cookie 30d
|
||||||
document.cookie = `learningDashboardAccessToken-${Auth.meetingID}=${getLearningDashboardAccessToken()}; expires=${cookieExpiresDate.toGMTString()}; path=/`;
|
document.cookie = `learningDashboardAccessToken-${Auth.meetingID}=${getLearningDashboardAccessToken()}; expires=${cookieExpiresDate.toGMTString()}; path=/`;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const openLearningDashboardUrl = (lang) => {
|
||||||
|
if (getLearningDashboardAccessToken() && setLearningDashboardCookie()) {
|
||||||
window.open(`/learning-dashboard/?meeting=${Auth.meetingID}&lang=${lang}`, '_blank');
|
window.open(`/learning-dashboard/?meeting=${Auth.meetingID}&lang=${lang}`, '_blank');
|
||||||
|
} else {
|
||||||
|
window.open(`/learning-dashboard/?meeting=${Auth.meetingID}&sessionToken=${Auth.sessionToken}&lang=${lang}`, '_blank');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
isModerator,
|
isModerator,
|
||||||
|
isLearningDashboardEnabled,
|
||||||
getLearningDashboardAccessToken,
|
getLearningDashboardAccessToken,
|
||||||
|
setLearningDashboardCookie,
|
||||||
openLearningDashboardUrl,
|
openLearningDashboardUrl,
|
||||||
};
|
};
|
||||||
|
@ -266,7 +266,9 @@ class MeetingEnded extends PureComponent {
|
|||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
LearningDashboardService.isModerator()
|
LearningDashboardService.isModerator()
|
||||||
&& LearningDashboardService.getLearningDashboardAccessToken() != null
|
&& LearningDashboardService.isLearningDashboardEnabled() === true
|
||||||
|
// Always set cookie in case Dashboard is already opened
|
||||||
|
&& LearningDashboardService.setLearningDashboardCookie() === true
|
||||||
? (
|
? (
|
||||||
<div className={styles.text}>
|
<div className={styles.text}>
|
||||||
<Button
|
<Button
|
||||||
|
@ -4,6 +4,7 @@ import _ from 'lodash';
|
|||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import Button from '/imports/ui/components/button/component';
|
import Button from '/imports/ui/components/button/component';
|
||||||
import { styles } from './styles';
|
import { styles } from './styles';
|
||||||
|
import Service from './service';
|
||||||
|
|
||||||
const intlMessages = defineMessages({
|
const intlMessages = defineMessages({
|
||||||
wasTalking: {
|
wasTalking: {
|
||||||
@ -22,6 +23,14 @@ const intlMessages = defineMessages({
|
|||||||
id: 'app.actionsBar.muteLabel',
|
id: 'app.actionsBar.muteLabel',
|
||||||
description: 'indicator mute label for moderators',
|
description: 'indicator mute label for moderators',
|
||||||
},
|
},
|
||||||
|
moreThanMaxIndicatorsTalking: {
|
||||||
|
id: 'app.talkingIndicator.moreThanMaxIndicatorsTalking',
|
||||||
|
description: 'indicator label for all users who is talking but not visible',
|
||||||
|
},
|
||||||
|
moreThanMaxIndicatorsWereTalking: {
|
||||||
|
id: 'app.talkingIndicator.moreThanMaxIndicatorsWereTalking',
|
||||||
|
description: 'indicator label for all users who is not talking but not visible',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
class TalkingIndicator extends PureComponent {
|
class TalkingIndicator extends PureComponent {
|
||||||
@ -39,6 +48,7 @@ class TalkingIndicator extends PureComponent {
|
|||||||
amIModerator,
|
amIModerator,
|
||||||
sidebarNavigationIsOpen,
|
sidebarNavigationIsOpen,
|
||||||
sidebarContentIsOpen,
|
sidebarContentIsOpen,
|
||||||
|
moreThanMaxIndicators,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
if (!talkers) return null;
|
if (!talkers) return null;
|
||||||
|
|
||||||
@ -76,8 +86,7 @@ class TalkingIndicator extends PureComponent {
|
|||||||
label={callerName}
|
label={callerName}
|
||||||
tooltipLabel={!muted && amIModerator
|
tooltipLabel={!muted && amIModerator
|
||||||
? `${intl.formatMessage(intlMessages.muteLabel)} ${callerName}`
|
? `${intl.formatMessage(intlMessages.muteLabel)} ${callerName}`
|
||||||
: null
|
: null}
|
||||||
}
|
|
||||||
data-test={talking ? 'isTalking' : 'wasTalking'}
|
data-test={talking ? 'isTalking' : 'wasTalking'}
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
aria-describedby={talking ? 'description' : null}
|
aria-describedby={talking ? 'description' : null}
|
||||||
@ -93,16 +102,55 @@ class TalkingIndicator extends PureComponent {
|
|||||||
<div id="description" className={styles.hidden}>
|
<div id="description" className={styles.hidden}>
|
||||||
{`${intl.formatMessage(intlMessages.ariaMuteDesc)}`}
|
{`${intl.formatMessage(intlMessages.ariaMuteDesc)}`}
|
||||||
</div>
|
</div>
|
||||||
) : null
|
) : null}
|
||||||
}
|
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const maxIndicator = () => {
|
||||||
|
if (!moreThanMaxIndicators) return null;
|
||||||
|
|
||||||
|
const nobodyTalking = Service.nobodyTalking(talkers);
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
[styles.talker]: true,
|
||||||
|
[styles.spoke]: nobodyTalking,
|
||||||
|
// [styles.muted]: false,
|
||||||
|
[styles.mobileHide]: sidebarNavigationIsOpen
|
||||||
|
&& sidebarContentIsOpen,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { moreThanMaxIndicatorsTalking, moreThanMaxIndicatorsWereTalking } = intlMessages;
|
||||||
|
|
||||||
|
const ariaLabel = intl.formatMessage(nobodyTalking
|
||||||
|
? moreThanMaxIndicatorsWereTalking : moreThanMaxIndicatorsTalking, {
|
||||||
|
0: Object.keys(talkers).length,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
key={_.uniqueId('_has__More_')}
|
||||||
|
className={cx(style)}
|
||||||
|
onClick={() => {}} // maybe add a dropdown to show the rest of the users
|
||||||
|
label="..."
|
||||||
|
tooltipLabel={ariaLabel}
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#4a148c',
|
||||||
|
border: 'solid 2px #4a148c',
|
||||||
|
cursor: 'default',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.isTalkingWrapper}>
|
<div className={styles.isTalkingWrapper}>
|
||||||
<div className={styles.speaking}>
|
<div className={styles.speaking}>
|
||||||
{talkingUserElements}
|
{talkingUserElements}
|
||||||
|
{maxIndicator()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -6,12 +6,12 @@ import { debounce } from 'lodash';
|
|||||||
import TalkingIndicator from './component';
|
import TalkingIndicator from './component';
|
||||||
import { makeCall } from '/imports/ui/services/api';
|
import { makeCall } from '/imports/ui/services/api';
|
||||||
import { meetingIsBreakout } from '/imports/ui/components/app/service';
|
import { meetingIsBreakout } from '/imports/ui/components/app/service';
|
||||||
import Service from './service';
|
|
||||||
import LayoutContext from '../../layout/context';
|
import LayoutContext from '../../layout/context';
|
||||||
|
|
||||||
const APP_CONFIG = Meteor.settings.public.app;
|
const APP_CONFIG = Meteor.settings.public.app;
|
||||||
const { enableTalkingIndicator } = APP_CONFIG;
|
const { enableTalkingIndicator } = APP_CONFIG;
|
||||||
const TALKING_INDICATOR_MUTE_INTERVAL = 500;
|
const TALKING_INDICATOR_MUTE_INTERVAL = 500;
|
||||||
|
const TALKING_INDICATORS_MAX = 8;
|
||||||
|
|
||||||
const TalkingIndicatorContainer = (props) => {
|
const TalkingIndicatorContainer = (props) => {
|
||||||
if (!enableTalkingIndicator) return null;
|
if (!enableTalkingIndicator) return null;
|
||||||
@ -50,10 +50,18 @@ export default withTracker(() => {
|
|||||||
muted: 1,
|
muted: 1,
|
||||||
intId: 1,
|
intId: 1,
|
||||||
},
|
},
|
||||||
}).fetch().sort(Service.sortVoiceUsers);
|
sort: {
|
||||||
|
startTime: 1,
|
||||||
|
},
|
||||||
|
limit: TALKING_INDICATORS_MAX + 1,
|
||||||
|
}).fetch();
|
||||||
|
|
||||||
if (usersTalking) {
|
if (usersTalking) {
|
||||||
for (let i = 0; i < usersTalking.length; i += 1) {
|
const maxNumberVoiceUsersNotification = usersTalking.length < TALKING_INDICATORS_MAX
|
||||||
|
? usersTalking.length
|
||||||
|
: TALKING_INDICATORS_MAX;
|
||||||
|
|
||||||
|
for (let i = 0; i < maxNumberVoiceUsersNotification; i += 1) {
|
||||||
const {
|
const {
|
||||||
callerName, talking, color, voiceUserId, muted, intId,
|
callerName, talking, color, voiceUserId, muted, intId,
|
||||||
} = usersTalking[i];
|
} = usersTalking[i];
|
||||||
@ -82,5 +90,6 @@ export default withTracker(() => {
|
|||||||
talkers,
|
talkers,
|
||||||
muteUser,
|
muteUser,
|
||||||
isBreakoutRoom: meetingIsBreakout(),
|
isBreakoutRoom: meetingIsBreakout(),
|
||||||
|
moreThanMaxIndicators: usersTalking.length > TALKING_INDICATORS_MAX,
|
||||||
};
|
};
|
||||||
})(TalkingIndicatorContainer);
|
})(TalkingIndicatorContainer);
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
const sortByStartTime = (a, b) => {
|
const nobodyTalking = (talkers) => {
|
||||||
if (a.startTime < b.startTime) return -1;
|
const values = Object.values(talkers);
|
||||||
if (a.startTime > b.startTime) return 1;
|
return values.every(({ talking }) => talking === false);
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortVoiceUsers = (a, b) => {
|
|
||||||
const sort = sortByStartTime(a, b);
|
|
||||||
return sort;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
sortVoiceUsers,
|
nobodyTalking,
|
||||||
};
|
};
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
max-height: var(--talker-padding-xl);
|
max-height: var(--talker-padding-xl);
|
||||||
|
scrollbar-width: 0; // firefox
|
||||||
|
scrollbar-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.speaking::-webkit-scrollbar {
|
.speaking::-webkit-scrollbar {
|
||||||
|
@ -326,7 +326,7 @@ class ApplicationMenu extends BaseMenu {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<div className={styles.col} aria-hidden="true">
|
<div className={styles.col}>
|
||||||
<div className={styles.formElement}>
|
<div className={styles.formElement}>
|
||||||
<label htmlFor="layoutList" className={styles.label}>
|
<label htmlFor="layoutList" className={styles.label}>
|
||||||
{intl.formatMessage(intlMessages.layoutOptionLabel)}
|
{intl.formatMessage(intlMessages.layoutOptionLabel)}
|
||||||
@ -412,7 +412,7 @@ class ApplicationMenu extends BaseMenu {
|
|||||||
{this.renderPaginationToggle()}
|
{this.renderPaginationToggle()}
|
||||||
|
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<div className={styles.col} aria-hidden="true">
|
<div className={styles.col}>
|
||||||
<div className={styles.formElement}>
|
<div className={styles.formElement}>
|
||||||
<label
|
<label
|
||||||
className={styles.label}
|
className={styles.label}
|
||||||
|
@ -66,6 +66,8 @@ class UserParticipants extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
document.getElementById('user-list-virtualized-scroll')?.getElementsByTagName('div')[0]?.firstElementChild?.setAttribute('aria-label', 'Users list');
|
||||||
|
|
||||||
const { compact } = this.props;
|
const { compact } = this.props;
|
||||||
if (!compact) {
|
if (!compact) {
|
||||||
this.refScrollContainer.addEventListener(
|
this.refScrollContainer.addEventListener(
|
||||||
@ -220,6 +222,8 @@ class UserParticipants extends Component {
|
|||||||
}
|
}
|
||||||
<div
|
<div
|
||||||
id={'user-list-virtualized-scroll'}
|
id={'user-list-virtualized-scroll'}
|
||||||
|
aria-label="Users list"
|
||||||
|
role="region"
|
||||||
className={styles.virtulizedScrollableList}
|
className={styles.virtulizedScrollableList}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
ref={(ref) => {
|
ref={(ref) => {
|
||||||
|
@ -214,7 +214,7 @@ class UserOptions extends PureComponent {
|
|||||||
hasBreakoutRoom,
|
hasBreakoutRoom,
|
||||||
isBreakoutEnabled,
|
isBreakoutEnabled,
|
||||||
getUsersNotAssigned,
|
getUsersNotAssigned,
|
||||||
learningDashboardAccessToken,
|
learningDashboardEnabled,
|
||||||
openLearningDashboardUrl,
|
openLearningDashboardUrl,
|
||||||
amIModerator,
|
amIModerator,
|
||||||
users,
|
users,
|
||||||
@ -326,7 +326,7 @@ class UserOptions extends PureComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (amIModerator) {
|
if (amIModerator) {
|
||||||
if (learningDashboardAccessToken != null) {
|
if (learningDashboardEnabled === true) {
|
||||||
this.menuItems.push({
|
this.menuItems.push({
|
||||||
icon: 'multi_whiteboard',
|
icon: 'multi_whiteboard',
|
||||||
iconRight: 'popout_window',
|
iconRight: 'popout_window',
|
||||||
|
@ -92,7 +92,7 @@ const UserOptionsContainer = withTracker((props) => {
|
|||||||
guestPolicy: WaitingUsersService.getGuestPolicy(),
|
guestPolicy: WaitingUsersService.getGuestPolicy(),
|
||||||
isMeteorConnected: Meteor.status().connected,
|
isMeteorConnected: Meteor.status().connected,
|
||||||
meetingName: getMeetingName(),
|
meetingName: getMeetingName(),
|
||||||
learningDashboardAccessToken: LearningDashboardService.getLearningDashboardAccessToken(),
|
learningDashboardEnabled: LearningDashboardService.isLearningDashboardEnabled(),
|
||||||
openLearningDashboardUrl: LearningDashboardService.openLearningDashboardUrl,
|
openLearningDashboardUrl: LearningDashboardService.openLearningDashboardUrl,
|
||||||
dynamicGuestPolicy,
|
dynamicGuestPolicy,
|
||||||
};
|
};
|
||||||
|
@ -98,8 +98,8 @@
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 14rem;
|
min-height: 14rem;
|
||||||
max-height: 40vh;
|
max-height: 50vh;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@ -2,8 +2,7 @@ import React, { useContext } from 'react';
|
|||||||
|
|
||||||
import { withModalMounter } from '/imports/ui/components/modal/service';
|
import { withModalMounter } from '/imports/ui/components/modal/service';
|
||||||
import { withTracker } from 'meteor/react-meteor-data';
|
import { withTracker } from 'meteor/react-meteor-data';
|
||||||
import Settings from '/imports/ui/services/settings';
|
import MediaService, { getSwapLayout } from '/imports/ui/components/media/service';
|
||||||
import MediaService, { getSwapLayout, } from '/imports/ui/components/media/service';
|
|
||||||
import Auth from '/imports/ui/services/auth';
|
import Auth from '/imports/ui/services/auth';
|
||||||
import breakoutService from '/imports/ui/components/breakout-room/service';
|
import breakoutService from '/imports/ui/components/breakout-room/service';
|
||||||
import VideoService from '/imports/ui/components/video-provider/service';
|
import VideoService from '/imports/ui/components/video-provider/service';
|
||||||
@ -16,11 +15,12 @@ const WebcamContainer = ({
|
|||||||
audioModalIsOpen,
|
audioModalIsOpen,
|
||||||
swapLayout,
|
swapLayout,
|
||||||
usersVideo,
|
usersVideo,
|
||||||
disableVideo,
|
|
||||||
}) => {
|
}) => {
|
||||||
const layoutContext = useContext(LayoutContext);
|
const layoutContext = useContext(LayoutContext);
|
||||||
const { layoutContextState, layoutContextDispatch } = layoutContext;
|
const { layoutContextState, layoutContextDispatch } = layoutContext;
|
||||||
const { fullscreen, output, input, isRTL } = layoutContextState;
|
const {
|
||||||
|
fullscreen, output, input, isRTL,
|
||||||
|
} = layoutContextState;
|
||||||
const { cameraDock, presentation } = output;
|
const { cameraDock, presentation } = output;
|
||||||
const { cameraDock: cameraDockInput } = input;
|
const { cameraDock: cameraDockInput } = input;
|
||||||
const { cameraOptimalGridSize } = cameraDockInput;
|
const { cameraOptimalGridSize } = cameraDockInput;
|
||||||
@ -30,8 +30,7 @@ const WebcamContainer = ({
|
|||||||
const { users } = usingUsersContext;
|
const { users } = usingUsersContext;
|
||||||
const currentUser = users[Auth.meetingID][Auth.userID];
|
const currentUser = users[Auth.meetingID][Auth.userID];
|
||||||
|
|
||||||
return !disableVideo
|
return !audioModalIsOpen
|
||||||
&& !audioModalIsOpen
|
|
||||||
&& usersVideo.length > 0
|
&& usersVideo.length > 0
|
||||||
? (
|
? (
|
||||||
<WebcamComponent
|
<WebcamComponent
|
||||||
@ -54,8 +53,6 @@ const WebcamContainer = ({
|
|||||||
let userWasInBreakout = false;
|
let userWasInBreakout = false;
|
||||||
|
|
||||||
export default withModalMounter(withTracker(() => {
|
export default withModalMounter(withTracker(() => {
|
||||||
const { dataSaving } = Settings;
|
|
||||||
const { viewParticipantsWebcams } = dataSaving;
|
|
||||||
const { current_presentation: hasPresentation } = MediaService.getPresentationInfo();
|
const { current_presentation: hasPresentation } = MediaService.getPresentationInfo();
|
||||||
const data = {
|
const data = {
|
||||||
audioModalIsOpen: Session.get('audioModalIsOpen'),
|
audioModalIsOpen: Session.get('audioModalIsOpen'),
|
||||||
@ -90,7 +87,6 @@ export default withModalMounter(withTracker(() => {
|
|||||||
const { streams: usersVideo } = VideoService.getVideoStreams();
|
const { streams: usersVideo } = VideoService.getVideoStreams();
|
||||||
data.usersVideo = usersVideo;
|
data.usersVideo = usersVideo;
|
||||||
data.swapLayout = getSwapLayout() || !hasPresentation;
|
data.swapLayout = getSwapLayout() || !hasPresentation;
|
||||||
data.disableVideo = !viewParticipantsWebcams;
|
|
||||||
|
|
||||||
if (data.swapLayout) {
|
if (data.swapLayout) {
|
||||||
data.floatingOverlay = true;
|
data.floatingOverlay = true;
|
||||||
|
@ -335,7 +335,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h1 id="heading">Guest Lobby</h1>
|
<h1 id="heading">BigBlueButton - Guest Lobby</h1>
|
||||||
<div class="spinner">
|
<div class="spinner">
|
||||||
<div class="bounce1"></div>
|
<div class="bounce1"></div>
|
||||||
<div class="bounce2"></div>
|
<div class="bounce2"></div>
|
||||||
|
@ -411,6 +411,8 @@
|
|||||||
"app.switch.offLabel": "OFF",
|
"app.switch.offLabel": "OFF",
|
||||||
"app.talkingIndicator.ariaMuteDesc" : "Select to mute user",
|
"app.talkingIndicator.ariaMuteDesc" : "Select to mute user",
|
||||||
"app.talkingIndicator.isTalking" : "{0} is talking",
|
"app.talkingIndicator.isTalking" : "{0} is talking",
|
||||||
|
"app.talkingIndicator.moreThanMaxIndicatorsTalking" : "{0}+ are talking",
|
||||||
|
"app.talkingIndicator.moreThanMaxIndicatorsWereTalking" : "{0}+ were talking",
|
||||||
"app.talkingIndicator.wasTalking" : "{0} stopped talking",
|
"app.talkingIndicator.wasTalking" : "{0} stopped talking",
|
||||||
"app.actionsBar.actionsDropdown.actionsLabel": "Actions",
|
"app.actionsBar.actionsDropdown.actionsLabel": "Actions",
|
||||||
"app.actionsBar.actionsDropdown.presentationLabel": "Manage presentations",
|
"app.actionsBar.actionsDropdown.presentationLabel": "Manage presentations",
|
||||||
@ -910,6 +912,8 @@
|
|||||||
"playback.player.video.wrapper.aria": "Video area",
|
"playback.player.video.wrapper.aria": "Video area",
|
||||||
"app.learningDashboard.dashboardTitle": "Learning Dashboard",
|
"app.learningDashboard.dashboardTitle": "Learning Dashboard",
|
||||||
"app.learningDashboard.user": "User",
|
"app.learningDashboard.user": "User",
|
||||||
|
"app.learningDashboard.shareButton": "Share with others",
|
||||||
|
"app.learningDashboard.shareLinkCopied": "Link successfully copied",
|
||||||
"app.learningDashboard.indicators.meetingStatusEnded": "Ended",
|
"app.learningDashboard.indicators.meetingStatusEnded": "Ended",
|
||||||
"app.learningDashboard.indicators.meetingStatusActive": "Active",
|
"app.learningDashboard.indicators.meetingStatusActive": "Active",
|
||||||
"app.learningDashboard.indicators.usersOnline": "Active Users",
|
"app.learningDashboard.indicators.usersOnline": "Active Users",
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
const Page = require('../core/page');
|
const Page = require('../core/page');
|
||||||
const e = require('../core/elements');
|
const e = require('../core/elements');
|
||||||
const { checkElement } = require('../core/util');
|
|
||||||
const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants');
|
const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants');
|
||||||
|
|
||||||
class Create {
|
class Create {
|
||||||
@ -62,7 +61,7 @@ class Create {
|
|||||||
// Check if Breakoutrooms have been created
|
// Check if Breakoutrooms have been created
|
||||||
async testCreatedBreakout(testName) {
|
async testCreatedBreakout(testName) {
|
||||||
try {
|
try {
|
||||||
const resp = await this.modPage1.page.evaluate(checkElement, e.breakoutRoomsItem);
|
const resp = await this.modPage1.hasElement(e.breakoutRoomsItem);
|
||||||
if (resp === true) {
|
if (resp === true) {
|
||||||
await this.modPage1.screenshot(`${testName}`, `05-page01-success-${testName}`);
|
await this.modPage1.screenshot(`${testName}`, `05-page01-success-${testName}`);
|
||||||
|
|
||||||
@ -88,8 +87,7 @@ class Create {
|
|||||||
await this.modPage2.waitAndClick(e.chatButton);
|
await this.modPage2.waitAndClick(e.chatButton);
|
||||||
await this.modPage2.waitAndClick(e.breakoutRoomsItem);
|
await this.modPage2.waitAndClick(e.breakoutRoomsItem);
|
||||||
|
|
||||||
await this.modPage2.waitAndClick(e.generateRoom1);
|
await this.modPage2.waitAndClick(e.askJoinRoom1);
|
||||||
await this.modPage2.waitAndClick(e.joinGeneratedRoom1);
|
|
||||||
await this.modPage2.waitForSelector(e.alreadyConnected, ELEMENT_WAIT_LONGER_TIME);
|
await this.modPage2.waitForSelector(e.alreadyConnected, ELEMENT_WAIT_LONGER_TIME);
|
||||||
|
|
||||||
const breakoutModPage2 = await this.modPage2.getLastTargetPage();
|
const breakoutModPage2 = await this.modPage2.getLastTargetPage();
|
||||||
@ -107,8 +105,7 @@ class Create {
|
|||||||
} else if (testName === 'joinBreakoutroomsWithVideo') {
|
} else if (testName === 'joinBreakoutroomsWithVideo') {
|
||||||
await this.modPage2.init(true, true, testName, 'Moderator2', this.modPage1.meetingId);
|
await this.modPage2.init(true, true, testName, 'Moderator2', this.modPage1.meetingId);
|
||||||
await this.modPage2.waitAndClick(e.breakoutRoomsButton);
|
await this.modPage2.waitAndClick(e.breakoutRoomsButton);
|
||||||
await this.modPage2.waitAndClick(e.generateRoom1);
|
await this.modPage2.waitAndClick(e.askJoinRoom1);
|
||||||
await this.modPage2.waitAndClick(e.joinGeneratedRoom1);
|
|
||||||
await this.modPage2.waitForSelector(e.alreadyConnected);
|
await this.modPage2.waitForSelector(e.alreadyConnected);
|
||||||
|
|
||||||
const breakoutModPage2 = await this.modPage2.getLastTargetPage();
|
const breakoutModPage2 = await this.modPage2.getLastTargetPage();
|
||||||
@ -116,18 +113,15 @@ class Create {
|
|||||||
|
|
||||||
await breakoutModPage2.bringToFront();
|
await breakoutModPage2.bringToFront();
|
||||||
await breakoutModPage2.closeAudioModal();
|
await breakoutModPage2.closeAudioModal();
|
||||||
await breakoutModPage2.waitAndClick(e.joinVideo);
|
|
||||||
const parsedSettings = await this.modPage2.getSettingsYaml();
|
const parsedSettings = await this.modPage2.getSettingsYaml();
|
||||||
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
||||||
await breakoutModPage2.waitAndClick(e.videoPreview, videoPreviewTimeout);
|
await breakoutModPage2.shareWebcam(true, videoPreviewTimeout);
|
||||||
await breakoutModPage2.waitAndClick(e.startSharingWebcam);
|
|
||||||
|
|
||||||
await breakoutModPage2.screenshot(testName, '00-breakout-page03-user-joined-with-webcam-before-check');
|
await breakoutModPage2.screenshot(testName, '00-breakout-page03-user-joined-with-webcam-before-check');
|
||||||
} else if (testName === 'joinBreakoutroomsAndShareScreen') {
|
} else if (testName === 'joinBreakoutroomsAndShareScreen') {
|
||||||
await this.modPage2.init(true, true, testName, 'Moderator2', this.modPage1.meetingId);
|
await this.modPage2.init(true, true, testName, 'Moderator2', this.modPage1.meetingId);
|
||||||
await this.modPage2.waitAndClick(e.breakoutRoomsButton);
|
await this.modPage2.waitAndClick(e.breakoutRoomsButton);
|
||||||
await this.modPage2.waitAndClick(e.generateRoom1);
|
await this.modPage2.waitAndClick(e.askJoinRoom1);
|
||||||
await this.modPage2.waitAndClick(e.joinGeneratedRoom1);
|
|
||||||
await this.modPage2.waitForSelector(e.alreadyConnected);
|
await this.modPage2.waitForSelector(e.alreadyConnected);
|
||||||
const breakoutModPage2 = await this.modPage2.getLastTargetPage();
|
const breakoutModPage2 = await this.modPage2.getLastTargetPage();
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ exports.CLIENT_RECONNECTION_TIMEOUT = 120000;
|
|||||||
// STRESS TESTS VARS
|
// STRESS TESTS VARS
|
||||||
exports.JOIN_AS_MODERATOR_TEST_ROUNDS = 100;
|
exports.JOIN_AS_MODERATOR_TEST_ROUNDS = 100;
|
||||||
exports.MAX_JOIN_AS_MODERATOR_FAIL_RATE = 0.05;
|
exports.MAX_JOIN_AS_MODERATOR_FAIL_RATE = 0.05;
|
||||||
|
exports.BREAKOUT_ROOM_INVITATION_TEST_ROUNDS = 20;
|
||||||
|
|
||||||
// MEDIA CONNECTION TIMEOUTS
|
// MEDIA CONNECTION TIMEOUTS
|
||||||
exports.VIDEO_LOADING_WAIT_TIME = 15000;
|
exports.VIDEO_LOADING_WAIT_TIME = 15000;
|
||||||
|
@ -49,9 +49,11 @@ exports.alreadyConnected = 'span[class^="alreadyConnected--"]';
|
|||||||
exports.breakoutJoin = '[data-test="breakoutJoin"]';
|
exports.breakoutJoin = '[data-test="breakoutJoin"]';
|
||||||
exports.userJoined = 'div[aria-label^="Moderator3"]';
|
exports.userJoined = 'div[aria-label^="Moderator3"]';
|
||||||
exports.breakoutRoomsButton = 'div[aria-label="Breakout Rooms"]';
|
exports.breakoutRoomsButton = 'div[aria-label="Breakout Rooms"]';
|
||||||
exports.generateRoom1 = 'button[aria-label="Generate URL Room 1"]';
|
exports.askJoinRoom1 = 'button[aria-label="Ask to join Room 1"]';
|
||||||
exports.joinGeneratedRoom1 = 'button[aria-label="Generated Room 1"]';
|
|
||||||
exports.joinRoom1 = 'button[aria-label="Join room Room 1"]';
|
exports.joinRoom1 = 'button[aria-label="Join room Room 1"]';
|
||||||
|
exports.allowChoiceRoom = 'input[id="freeJoinCheckbox"]';
|
||||||
|
exports.labelGeneratingURL = 'span[data-test="labelGeneratingURL"]';
|
||||||
|
exports.endBreakoutRoomsButton = 'button[data-test="endBreakoutRoomsButton"]';
|
||||||
|
|
||||||
// Chat
|
// Chat
|
||||||
exports.chatButton = 'div[data-test="chatButton"]';
|
exports.chatButton = 'div[data-test="chatButton"]';
|
||||||
@ -204,6 +206,8 @@ exports.chatPanel = 'section[data-test="chatPanel"]';
|
|||||||
exports.userListPanel = 'div[data-test="userListPanel"]';
|
exports.userListPanel = 'div[data-test="userListPanel"]';
|
||||||
exports.multiWhiteboardTool = 'span[data-test="multiWhiteboardTool"]'
|
exports.multiWhiteboardTool = 'span[data-test="multiWhiteboardTool"]'
|
||||||
exports.connectionStatusBtn = 'button[data-test="connectionStatusButton"]';
|
exports.connectionStatusBtn = 'button[data-test="connectionStatusButton"]';
|
||||||
|
exports.connectionDataContainer = '[class^=networkDataContainer--]';
|
||||||
|
exports.connectionNetwordData = '[class^=networkData--]';
|
||||||
|
|
||||||
// Webcam
|
// Webcam
|
||||||
exports.joinVideo = 'button[data-test="joinVideo"]';
|
exports.joinVideo = 'button[data-test="joinVideo"]';
|
||||||
|
@ -8,7 +8,7 @@ const path = require('path');
|
|||||||
const PuppeteerVideoRecorder = require('puppeteer-video-recorder');
|
const PuppeteerVideoRecorder = require('puppeteer-video-recorder');
|
||||||
const helper = require('./helper');
|
const helper = require('./helper');
|
||||||
const params = require('./params');
|
const params = require('./params');
|
||||||
const { ELEMENT_WAIT_TIME } = require('./constants');
|
const { ELEMENT_WAIT_TIME, VIDEO_LOADING_WAIT_TIME } = require('./constants');
|
||||||
const { getElementLength } = require('./util');
|
const { getElementLength } = require('./util');
|
||||||
const e = require('./elements');
|
const e = require('./elements');
|
||||||
const { NETWORK_PRESETS } = require('./profiles');
|
const { NETWORK_PRESETS } = require('./profiles');
|
||||||
@ -104,6 +104,17 @@ class Page {
|
|||||||
await this.waitForSelector(e.isTalking);
|
await this.waitForSelector(e.isTalking);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async shareWebcam(shouldConfirmSharing, videoPreviewTimeout = ELEMENT_WAIT_TIME) {
|
||||||
|
await this.waitAndClick(e.joinVideo);
|
||||||
|
if (shouldConfirmSharing) {
|
||||||
|
await this.waitForSelector(e.videoPreview, videoPreviewTimeout);
|
||||||
|
await this.waitAndClick(e.startSharingWebcam);
|
||||||
|
}
|
||||||
|
await this.waitForSelector(e.webcamConnecting);
|
||||||
|
await this.waitForSelector(e.webcamVideo, VIDEO_LOADING_WAIT_TIME);
|
||||||
|
await this.waitForSelector(e.leaveVideo, VIDEO_LOADING_WAIT_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
// Joining audio with microphone
|
// Joining audio with microphone
|
||||||
async joinMicrophoneWithoutEchoTest() {
|
async joinMicrophoneWithoutEchoTest() {
|
||||||
await this.waitAndClick(e.joinAudio);
|
await this.waitAndClick(e.joinAudio);
|
||||||
@ -214,16 +225,6 @@ class Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async isNotVisible(element, timeout = ELEMENT_WAIT_TIME) {
|
|
||||||
try {
|
|
||||||
await this.hasElement(element, false, timeout);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
await this.logger(err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// async emulateMobile(userAgent) {
|
// async emulateMobile(userAgent) {
|
||||||
// await this.page.setUserAgent(userAgent);
|
// await this.page.setUserAgent(userAgent);
|
||||||
// }
|
// }
|
||||||
@ -243,7 +244,7 @@ class Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async hasElement(element, visible = false, timeout = ELEMENT_WAIT_TIME) {
|
async hasElement(element, visible = true, timeout = ELEMENT_WAIT_TIME) {
|
||||||
try {
|
try {
|
||||||
await this.page.waitForSelector(element, { visible, timeout });
|
await this.page.waitForSelector(element, { visible, timeout });
|
||||||
return true;
|
return true;
|
||||||
|
@ -3,9 +3,8 @@ exports.listenOnlyMode = 'userdata-bbb_listen_only_mode=false';
|
|||||||
exports.forceListenOnly = 'userdata-bbb_force_listen_only=true';
|
exports.forceListenOnly = 'userdata-bbb_force_listen_only=true';
|
||||||
exports.skipCheck = 'userdata-bbb_skip_check_audio=true';
|
exports.skipCheck = 'userdata-bbb_skip_check_audio=true';
|
||||||
exports.skipCheckOnFirstJoin = 'userdata-bbb_skip_check_audio_on_first_join=true';
|
exports.skipCheckOnFirstJoin = 'userdata-bbb_skip_check_audio_on_first_join=true';
|
||||||
const docTitle = 'puppeteer';
|
exports.docTitle = 'puppeteer';
|
||||||
exports.docTitle = docTitle;
|
exports.clientTitle = `userdata-bbb_client_title=${this.docTitle}`;
|
||||||
exports.clientTitle = `userdata-bbb_client_title=${docTitle}`;
|
|
||||||
exports.askForFeedbackOnLogout = 'userdata-bbb_ask_for_feedback_on_logout=true';
|
exports.askForFeedbackOnLogout = 'userdata-bbb_ask_for_feedback_on_logout=true';
|
||||||
exports.displayBrandingArea = 'userdata-bbb_display_branding_area=true';
|
exports.displayBrandingArea = 'userdata-bbb_display_branding_area=true';
|
||||||
exports.logo = 'logo=https://bigbluebutton.org/wp-content/themes/bigbluebutton/library/images/bigbluebutton-logo.png';
|
exports.logo = 'logo=https://bigbluebutton.org/wp-content/themes/bigbluebutton/library/images/bigbluebutton-logo.png';
|
||||||
|
@ -3,7 +3,7 @@ const e = require('../core/elements');
|
|||||||
const c = require('./constants');
|
const c = require('./constants');
|
||||||
const util = require('./util');
|
const util = require('./util');
|
||||||
const { VIDEO_LOADING_WAIT_TIME, ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); // core constants (Timeouts vars imported)
|
const { VIDEO_LOADING_WAIT_TIME, ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); // core constants (Timeouts vars imported)
|
||||||
const { checkElementLengthEqualTo, checkElementLengthDifferentTo } = require('../core/util');
|
const { checkElementLengthEqualTo, checkElement } = require('../core/util');
|
||||||
|
|
||||||
class CustomParameters {
|
class CustomParameters {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -25,7 +25,7 @@ class CustomParameters {
|
|||||||
await this.page1.startRecording(testName);
|
await this.page1.startRecording(testName);
|
||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
await this.page1.waitForSelector(e.chatMessages);
|
await this.page1.waitForSelector(e.chatMessages);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthEqualTo, e.audioModal, 0);
|
const resp = await this.page1.wasRemoved(e.audioModal);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -96,7 +96,7 @@ class CustomParameters {
|
|||||||
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
||||||
await this.page1.waitForElementHandleToBeRemoved(e.connectingStatus, ELEMENT_WAIT_LONGER_TIME);
|
await this.page1.waitForElementHandleToBeRemoved(e.connectingStatus, ELEMENT_WAIT_LONGER_TIME);
|
||||||
await this.page1.screenshot(`${testName}`, `03-${testName}`);
|
await this.page1.screenshot(`${testName}`, `03-${testName}`);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthEqualTo, e.echoYesButton, 0);
|
const resp = await this.page1.wasRemoved(e.echoYesButton);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `04-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `04-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -118,13 +118,13 @@ class CustomParameters {
|
|||||||
await this.page1.startRecording(testName);
|
await this.page1.startRecording(testName);
|
||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
await this.page1.waitAndClick(e.microphoneButton);
|
await this.page1.waitAndClick(e.microphoneButton);
|
||||||
const firstCheck = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.connecting, 0);
|
const firstCheck = await this.page1.hasElement(e.connecting);
|
||||||
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
||||||
await this.page1.leaveAudio();
|
await this.page1.leaveAudio();
|
||||||
await this.page1.screenshot(`${testName}`, `03-${testName}`);
|
await this.page1.screenshot(`${testName}`, `03-${testName}`);
|
||||||
await this.page1.waitAndClick(e.joinAudio);
|
await this.page1.waitAndClick(e.joinAudio);
|
||||||
await this.page1.waitAndClick(e.microphoneButton);
|
await this.page1.waitAndClick(e.microphoneButton);
|
||||||
const secondCheck = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.connectingToEchoTest, 0);
|
const secondCheck = await this.page1.hasElement(e.connectingToEchoTest);
|
||||||
|
|
||||||
if (firstCheck !== secondCheck) {
|
if (firstCheck !== secondCheck) {
|
||||||
await this.page1.screenshot(`${testName}`, `04-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `04-fail-${testName}`);
|
||||||
@ -175,7 +175,7 @@ class CustomParameters {
|
|||||||
await this.page1.waitForSelector(e.meetingEndedModal);
|
await this.page1.waitForSelector(e.meetingEndedModal);
|
||||||
await this.page1.screenshot(`${testName}`, `04-${testName}`);
|
await this.page1.screenshot(`${testName}`, `04-${testName}`);
|
||||||
await this.page1.logger('audio modal closed');
|
await this.page1.logger('audio modal closed');
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.rating, 0);
|
const resp = await this.page1.hasElement(e.rating);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `05-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `05-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -199,7 +199,7 @@ class CustomParameters {
|
|||||||
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
||||||
await this.page1.logger('audio modal closed');
|
await this.page1.logger('audio modal closed');
|
||||||
await this.page1.waitForSelector(e.userListContent);
|
await this.page1.waitForSelector(e.userListContent);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.brandingAreaLogo, 0);
|
const resp = await this.page1.hasElement(e.brandingAreaLogo);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `03-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `03-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -253,7 +253,7 @@ class CustomParameters {
|
|||||||
await this.page1.init(true, true, testName, 'Moderator', undefined, customParameter);
|
await this.page1.init(true, true, testName, 'Moderator', undefined, customParameter);
|
||||||
await this.page1.startRecording(testName);
|
await this.page1.startRecording(testName);
|
||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthEqualTo, e.startScreenSharing, 0);
|
const resp = await this.page1.wasRemoved(e.startScreenSharing);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -274,7 +274,7 @@ class CustomParameters {
|
|||||||
await this.page1.init(true, true, testName, 'Moderator', undefined, customParameter);
|
await this.page1.init(true, true, testName, 'Moderator', undefined, customParameter);
|
||||||
await this.page1.startRecording(testName);
|
await this.page1.startRecording(testName);
|
||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthEqualTo, e.joinVideo, 0);
|
const resp = await this.page1.wasRemoved(e.joinVideo);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -457,7 +457,10 @@ class CustomParameters {
|
|||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
await this.page1.waitForSelector(e.actions);
|
await this.page1.waitForSelector(e.actions);
|
||||||
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.defaultContent, 0);
|
const checkPresentationButton = await this.page1.page.evaluate(checkElement, e.restorePresentation);
|
||||||
|
const checkPresentationPlaceholder = await this.page1.page.evaluate(checkElement, e.presentationPlaceholder);
|
||||||
|
const resp = !(checkPresentationButton || checkPresentationPlaceholder);
|
||||||
|
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `03-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `03-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -480,7 +483,7 @@ class CustomParameters {
|
|||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
await this.page1.waitForSelector(e.actions);
|
await this.page1.waitForSelector(e.actions);
|
||||||
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-${testName}`);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.notificationBar, 0);
|
const resp = await this.page1.hasElement(e.notificationBar);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `03-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `03-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -525,7 +528,7 @@ class CustomParameters {
|
|||||||
await this.page1.startRecording(testName);
|
await this.page1.startRecording(testName);
|
||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
await this.page1.waitForSelector(e.actions);
|
await this.page1.waitForSelector(e.actions);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.restorePresentation, 0) && await this.page1.page.evaluate(checkElementLengthDifferentTo, e.defaultContent, 0);
|
const resp = await this.page1.hasElement(e.restorePresentation) && await this.page1.hasElement(e.defaultContent);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -592,14 +595,13 @@ class CustomParameters {
|
|||||||
await this.page1.screenshot(`${testName}`, `05-page1-${testName}`);
|
await this.page1.screenshot(`${testName}`, `05-page1-${testName}`);
|
||||||
await this.page2.screenshot(`${testName}`, `06-page2-${testName}`);
|
await this.page2.screenshot(`${testName}`, `06-page2-${testName}`);
|
||||||
|
|
||||||
const test = await this.page2.page.evaluate(checkElementLengthDifferentTo, e.restorePresentation, 0);
|
const test = await this.page2.page.evaluate(checkElement, e.restorePresentation);
|
||||||
const resp = (zoomInCase && zoomOutCase && pollCase && previousSlideCase && nextSlideCase && annotationCase && test);
|
const resp = (zoomInCase && zoomOutCase && pollCase && previousSlideCase && nextSlideCase && annotationCase && test);
|
||||||
if (resp) {
|
if (resp) {
|
||||||
await this.page2.screenshot(`${testName}`, `07-page2-fail-${testName}`);
|
await this.page2.screenshot(`${testName}`, `07-page2-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
await this.page2.page.evaluate(checkElementLengthEqualTo, e.restorePresentation, 0);
|
|
||||||
await this.page2.screenshot(`${testName}`, `07-page2-success-${testName}`);
|
await this.page2.screenshot(`${testName}`, `07-page2-success-${testName}`);
|
||||||
await this.page1.logger(testName, ' passed');
|
await this.page1.logger(testName, ' passed');
|
||||||
|
|
||||||
@ -624,7 +626,7 @@ class CustomParameters {
|
|||||||
await this.page1.screenshot(`${testName}`, `02-page1-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-page1-${testName}`);
|
||||||
await this.page2.screenshot(`${testName}`, `03-page2-${testName}`);
|
await this.page2.screenshot(`${testName}`, `03-page2-${testName}`);
|
||||||
|
|
||||||
const test = await this.page2.page.evaluate(checkElementLengthDifferentTo, e.restorePresentation, 0);
|
const test = await this.page2.page.evaluate(checkElement, e.restorePresentation);
|
||||||
if (pollCase && test) {
|
if (pollCase && test) {
|
||||||
await this.page2.screenshot(`${testName}`, `04-page2-fail-${testName}`);
|
await this.page2.screenshot(`${testName}`, `04-page2-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
@ -688,31 +690,22 @@ class CustomParameters {
|
|||||||
await this.page1.init(true, true, testName, 'Moderator1', undefined, customParameter);
|
await this.page1.init(true, true, testName, 'Moderator1', undefined, customParameter);
|
||||||
await this.page1.startRecording(testName);
|
await this.page1.startRecording(testName);
|
||||||
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
await this.page1.screenshot(`${testName}`, `01-${testName}`);
|
||||||
await this.page1.waitAndClick(e.joinVideo);
|
await this.page1.shareWebcam(false);
|
||||||
const firstCheck = await this.page1.page.evaluate(checkElementLengthEqualTo, e.webcamSettingsModal, 0);
|
|
||||||
await this.page1.waitAndClick(e.leaveVideo, VIDEO_LOADING_WAIT_TIME);
|
await this.page1.waitAndClick(e.leaveVideo, VIDEO_LOADING_WAIT_TIME);
|
||||||
await this.page1.waitForElementHandleToBeRemoved(e.webcamVideo, ELEMENT_WAIT_LONGER_TIME);
|
await this.page1.waitForElementHandleToBeRemoved(e.webcamVideo, ELEMENT_WAIT_LONGER_TIME);
|
||||||
await this.page1.waitForElementHandleToBeRemoved(e.leaveVideo, ELEMENT_WAIT_LONGER_TIME);
|
await this.page1.waitForElementHandleToBeRemoved(e.leaveVideo, ELEMENT_WAIT_LONGER_TIME);
|
||||||
|
|
||||||
await this.page1.waitAndClick(e.joinVideo);
|
|
||||||
const parsedSettings = await this.page1.getSettingsYaml();
|
const parsedSettings = await this.page1.getSettingsYaml();
|
||||||
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
||||||
await this.page1.waitForSelector(e.videoPreview, videoPreviewTimeout);
|
await this.page1.shareWebcam(true, videoPreviewTimeout);
|
||||||
await this.page1.waitForSelector(e.startSharingWebcam);
|
|
||||||
const secondCheck = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.webcamSettingsModal, 0);
|
|
||||||
await this.page1.waitAndClick(e.startSharingWebcam);
|
|
||||||
await this.page1.waitForSelector(e.webcamConnecting);
|
|
||||||
|
|
||||||
if (firstCheck !== secondCheck) {
|
|
||||||
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
|
||||||
await this.page1.logger(testName, ' failed');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
await this.page1.screenshot(`${testName}`, `02-success-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-success-${testName}`);
|
||||||
await this.page1.logger(testName, ' passed');
|
await this.page1.logger(testName, ' passed');
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
||||||
await this.page1.logger(err);
|
await this.page1.logger(err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -726,7 +719,7 @@ class CustomParameters {
|
|||||||
await this.page1.waitAndClick(e.joinVideo);
|
await this.page1.waitAndClick(e.joinVideo);
|
||||||
await this.page1.waitForSelector(e.webcamMirroredVideoPreview);
|
await this.page1.waitForSelector(e.webcamMirroredVideoPreview);
|
||||||
await this.page1.waitAndClick(e.startSharingWebcam);
|
await this.page1.waitAndClick(e.startSharingWebcam);
|
||||||
const resp = await this.page1.page.evaluate(checkElementLengthDifferentTo, e.webcamMirroredVideoContainer, 0);
|
const resp = await this.page1.hasElement(e.webcamMirroredVideoContainer);
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
await this.page1.screenshot(`${testName}`, `02-fail-${testName}`);
|
||||||
await this.page1.logger(testName, ' failed');
|
await this.page1.logger(testName, ' failed');
|
||||||
|
@ -116,7 +116,7 @@ class Presentation {
|
|||||||
await this.userPage.screenshot(testName, `3-userPage-after-allow-download-and-save-[${this.modPage.meetingId}]`);
|
await this.userPage.screenshot(testName, `3-userPage-after-allow-download-and-save-[${this.modPage.meetingId}]`);
|
||||||
await this.userPage.waitForSelector(e.toastDownload);
|
await this.userPage.waitForSelector(e.toastDownload);
|
||||||
// check download button in presentation after ALLOW it - should be true
|
// check download button in presentation after ALLOW it - should be true
|
||||||
const hasPresentationDownloadBtnAfterAllow = await this.userPage.page.evaluate(checkElement, e.presentationDownloadBtn);
|
const hasPresentationDownloadBtnAfterAllow = await this.userPage.hasElement(e.presentationDownloadBtn);
|
||||||
|
|
||||||
// disallow the presentation download
|
// disallow the presentation download
|
||||||
await this.modPage.waitAndClick(e.actions);
|
await this.modPage.waitAndClick(e.actions);
|
||||||
|
@ -2,11 +2,11 @@ const Page = require('../core/page');
|
|||||||
const e = require('../core/elements');
|
const e = require('../core/elements');
|
||||||
const c = require('../core/constants');
|
const c = require('../core/constants');
|
||||||
const util = require('./util');
|
const util = require('./util');
|
||||||
const { checkElementLengthEqualTo } = require('../core/util');
|
|
||||||
|
|
||||||
class Stress extends Page {
|
class Stress {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
this.modPage = new Page();
|
||||||
|
this.userPages = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async moderatorAsPresenter(testName) {
|
async moderatorAsPresenter(testName) {
|
||||||
@ -14,26 +14,97 @@ class Stress extends Page {
|
|||||||
const maxFailRate = c.JOIN_AS_MODERATOR_TEST_ROUNDS * c.MAX_JOIN_AS_MODERATOR_FAIL_RATE;
|
const maxFailRate = c.JOIN_AS_MODERATOR_TEST_ROUNDS * c.MAX_JOIN_AS_MODERATOR_FAIL_RATE;
|
||||||
let failureCount = 0;
|
let failureCount = 0;
|
||||||
for (let i = 1; i <= c.JOIN_AS_MODERATOR_TEST_ROUNDS; i++) {
|
for (let i = 1; i <= c.JOIN_AS_MODERATOR_TEST_ROUNDS; i++) {
|
||||||
await this.init(true, true, testName, `Moderator-${i}`);
|
await this.modPage.init(true, true, testName, `Moderator-${i}`);
|
||||||
await this.waitForSelector(e.userAvatar);
|
await this.modPage.waitForSelector(e.userAvatar);
|
||||||
const hasPresenterClass = await this.page.evaluate(util.checkIncludeClass, e.userAvatar, e.presenterClassName);
|
const hasPresenterClass = await this.modPage.page.evaluate(util.checkIncludeClass, e.userAvatar, e.presenterClassName);
|
||||||
await this.waitAndClick(e.actions);
|
await this.modPage.waitAndClick(e.actions);
|
||||||
const canStartPoll = await this.page.evaluate(checkElementLengthEqualTo, e.polling, 1);
|
const canStartPoll = await this.modPage.hasElement(e.polling);
|
||||||
if (!hasPresenterClass || !canStartPoll) {
|
if (!hasPresenterClass || !canStartPoll) {
|
||||||
failureCount++;
|
failureCount++;
|
||||||
await this.screenshot(testName, `loop-${i}-failure-${testName}`);
|
await this.modPage.screenshot(testName, `loop-${i}-failure-${testName}`);
|
||||||
}
|
}
|
||||||
await this.close();
|
await this.modPage.close();
|
||||||
await this.logger(`Loop ${i} of ${c.JOIN_AS_MODERATOR_TEST_ROUNDS} completed`);
|
await this.modPage.logger(`Loop ${i} of ${c.JOIN_AS_MODERATOR_TEST_ROUNDS} completed`);
|
||||||
if (failureCount > maxFailRate) return false;
|
if (failureCount > maxFailRate) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.close();
|
await this.modPage.logger(err);
|
||||||
this.logger(err);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async breakoutRoomInvitation(testName) {
|
||||||
|
try {
|
||||||
|
await this.modPage.init(true, true, testName, 'Moderator');
|
||||||
|
for (let i = 1; i <= c.BREAKOUT_ROOM_INVITATION_TEST_ROUNDS; i++) {
|
||||||
|
const userName = `User-${i}`;
|
||||||
|
const userPage = new Page();
|
||||||
|
await userPage.init(false, true, testName, userName, this.modPage.meetingId);
|
||||||
|
await userPage.logger(`${userName} joined`);
|
||||||
|
this.userPages.push(userPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create breakout rooms with the allow choice option enabled
|
||||||
|
await this.modPage.bringToFront();
|
||||||
|
await this.modPage.waitAndClick(e.manageUsers);
|
||||||
|
await this.modPage.waitAndClick(e.createBreakoutRooms);
|
||||||
|
await this.modPage.waitAndClick(e.allowChoiceRoom);
|
||||||
|
await this.modPage.screenshot(testName, '01-modPage-before-create-breakout-rooms-allowing-choice');
|
||||||
|
await this.modPage.waitAndClick(e.modalConfirmButton);
|
||||||
|
|
||||||
|
for (const page of this.userPages) {
|
||||||
|
await page.bringToFront();
|
||||||
|
const firstCheck = await page.hasElement(e.modalConfirmButton, c.ELEMENT_WAIT_LONGER_TIME);
|
||||||
|
const secondCheck = await page.wasRemoved(e.labelGeneratingURL, c.ELEMENT_WAIT_LONGER_TIME);
|
||||||
|
|
||||||
|
if (!firstCheck || !secondCheck) {
|
||||||
|
await page.screenshot(testName, `${page.effectiveParams.fullName}-breakout-modal-failed`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
await page.screenshot(testName, `${page.effectiveParams.fullName}-breakout-modal-allowing-choice-success`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// End breakout rooms
|
||||||
|
await this.modPage.bringToFront();
|
||||||
|
await this.modPage.waitAndClick(e.breakoutRoomsItem);
|
||||||
|
await this.modPage.waitAndClick(e.endBreakoutRoomsButton);
|
||||||
|
await this.modPage.closeAudioModal();
|
||||||
|
|
||||||
|
// Create breakout rooms with the allow choice option NOT enabled (randomly assign)
|
||||||
|
await this.modPage.waitAndClick(e.manageUsers);
|
||||||
|
await this.modPage.waitAndClick(e.createBreakoutRooms);
|
||||||
|
await this.modPage.waitAndClick(e.randomlyAssign);
|
||||||
|
await this.modPage.screenshot(testName, '02-modPage-before-create-breakout-rooms-not-allowing-choice');
|
||||||
|
await this.modPage.waitAndClick(e.modalConfirmButton);
|
||||||
|
|
||||||
|
for (const page of this.userPages) {
|
||||||
|
await page.bringToFront();
|
||||||
|
const check = await page.hasElement(e.modalConfirmButton);
|
||||||
|
|
||||||
|
if (!check) {
|
||||||
|
await page.screenshot(testName, `${page.effectiveParams.fullName}-breakout-modal-not-allowing-choose-failed`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
await page.screenshot(testName, `${page.effectiveParams.fullName}-breakout-modal-not-allowing-choose-success`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
await this.modPage.logger(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async closeUserPages() {
|
||||||
|
for (const page of this.userPages) {
|
||||||
|
try {
|
||||||
|
await page.close();
|
||||||
|
} catch (err) {
|
||||||
|
await this.modPage.logger(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = exports = Stress;
|
module.exports = exports = Stress;
|
@ -7,11 +7,31 @@ const stressTest = () => {
|
|||||||
let response;
|
let response;
|
||||||
try {
|
try {
|
||||||
const testName = 'firstModeratorAsPresenter';
|
const testName = 'firstModeratorAsPresenter';
|
||||||
await test.logger('begin of ', testName);
|
await test.modPage.logger('begin of ', testName);
|
||||||
response = await test.moderatorAsPresenter(testName);
|
response = await test.moderatorAsPresenter(testName);
|
||||||
await test.logger('end of ', testName);
|
await test.modPage.logger('end of ', testName);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await test.logger(err);
|
await test.modPage.logger(err);
|
||||||
|
} finally {
|
||||||
|
await test.modPage.close();
|
||||||
|
}
|
||||||
|
expect(response).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that all users invited to a breakout room can join it
|
||||||
|
test('All users must receive breakout room invitations', async () => {
|
||||||
|
const test = new Stress();
|
||||||
|
let response;
|
||||||
|
try {
|
||||||
|
const testName = 'breakoutRoomInvitation';
|
||||||
|
await test.modPage.logger('begin of ', testName);
|
||||||
|
response = await test.breakoutRoomInvitation(testName);
|
||||||
|
await test.modPage.logger('end of ', testName);
|
||||||
|
} catch (err) {
|
||||||
|
await test.modPage.logger(err);
|
||||||
|
} finally {
|
||||||
|
await test.modPage.close();
|
||||||
|
await test.closeUserPages();
|
||||||
}
|
}
|
||||||
expect(response).toBe(true);
|
expect(response).toBe(true);
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,6 @@ const { exec } = require("child_process");
|
|||||||
const { CLIENT_RECONNECTION_TIMEOUT } = require('../core/constants'); // core constants (Timeouts vars imported)
|
const { CLIENT_RECONNECTION_TIMEOUT } = require('../core/constants'); // core constants (Timeouts vars imported)
|
||||||
const { sleep } = require('../core/helper');
|
const { sleep } = require('../core/helper');
|
||||||
const e = require('../core/elements');
|
const e = require('../core/elements');
|
||||||
const { checkElementLengthDifferentTo } = require('../core/util');
|
|
||||||
|
|
||||||
class Trigger extends Page {
|
class Trigger extends Page {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -30,7 +29,7 @@ class Trigger extends Page {
|
|||||||
await sleep(3000);
|
await sleep(3000);
|
||||||
await this.screenshot(`${testName}`, `03-after-meteor-reconnection-[${this.meetingId}]`);
|
await this.screenshot(`${testName}`, `03-after-meteor-reconnection-[${this.meetingId}]`);
|
||||||
|
|
||||||
const findUnauthorized = await this.page.evaluate(checkElementLengthDifferentTo, e.unauthorized, 0) === true;
|
const findUnauthorized = await this.hasElement(e.unauthorized);
|
||||||
await this.logger('Check if Unauthorized message appears => ', findUnauthorized);
|
await this.logger('Check if Unauthorized message appears => ', findUnauthorized);
|
||||||
return meteorStatusConfirm && getAudioButton && findUnauthorized;
|
return meteorStatusConfirm && getAudioButton && findUnauthorized;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -84,7 +83,7 @@ class Trigger extends Page {
|
|||||||
}, e.joinAudio)
|
}, e.joinAudio)
|
||||||
await this.logger('Check if Connections Buttons are disabled => ', getAudioButton);
|
await this.logger('Check if Connections Buttons are disabled => ', getAudioButton);
|
||||||
await sleep(3000);
|
await sleep(3000);
|
||||||
const findUnauthorized = await this.page.evaluate(checkElementLengthDifferentTo, e.unauthorized, 0) === true;
|
const findUnauthorized = await this.hasElement(e.unauthorized);
|
||||||
await this.logger('Check if Unauthorized message appears => ', findUnauthorized);
|
await this.logger('Check if Unauthorized message appears => ', findUnauthorized);
|
||||||
return meteorStatusConfirm && getAudioButton && findUnauthorized;
|
return meteorStatusConfirm && getAudioButton && findUnauthorized;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -2,8 +2,8 @@ const Page = require('../core/page');
|
|||||||
const util = require('../chat/util');
|
const util = require('../chat/util');
|
||||||
const utilUser = require('./util');
|
const utilUser = require('./util');
|
||||||
const e = require('../core/elements');
|
const e = require('../core/elements');
|
||||||
const { ELEMENT_WAIT_TIME } = require('../core/constants');
|
const { ELEMENT_WAIT_TIME, ELEMENT_WAIT_LONGER_TIME } = require('../core/constants');
|
||||||
const { getElementLength, checkElementLengthEqualTo, checkElementLengthDifferentTo } = require('../core/util');
|
const { getElementLength, checkElementLengthEqualTo } = require('../core/util');
|
||||||
|
|
||||||
class MultiUsers {
|
class MultiUsers {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -293,7 +293,7 @@ class MultiUsers {
|
|||||||
await this.page2.close();
|
await this.page2.close();
|
||||||
await utilUser.connectionStatus(this.page1);
|
await utilUser.connectionStatus(this.page1);
|
||||||
const connectionStatusItemEmpty = await this.page1.wasRemoved(e.connectionStatusItemEmpty);
|
const connectionStatusItemEmpty = await this.page1.wasRemoved(e.connectionStatusItemEmpty);
|
||||||
const connectionStatusOfflineUser = await this.page1.hasElement(e.connectionStatusOfflineUser, true);
|
const connectionStatusOfflineUser = await this.page1.hasElement(e.connectionStatusOfflineUser, true, ELEMENT_WAIT_LONGER_TIME);
|
||||||
|
|
||||||
return connectionStatusItemEmpty && connectionStatusOfflineUser;
|
return connectionStatusItemEmpty && connectionStatusOfflineUser;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -313,13 +313,58 @@ class MultiUsers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async usersConnectionStatus(testName) {
|
||||||
|
try {
|
||||||
|
await this.page1.shareWebcam(true);
|
||||||
|
await this.page1.screenshot(testName, '01-page1-after-share-webcam');
|
||||||
|
await this.initUserPage(false, testName);
|
||||||
|
await this.userPage.joinMicrophone();
|
||||||
|
await this.userPage.screenshot(testName, '02-userPage-after-join-microhpone');
|
||||||
|
await this.userPage.shareWebcam(true);
|
||||||
|
await this.userPage.screenshot(testName, '03-userPage-after-share-webcam');
|
||||||
|
await this.userPage.waitAndClick(e.connectionStatusBtn);
|
||||||
|
try {
|
||||||
|
await this.userPage.page.waitForFunction(utilUser.checkNetworkStatus, { timeout: ELEMENT_WAIT_TIME },
|
||||||
|
e.connectionDataContainer, e.connectionNetwordData
|
||||||
|
);
|
||||||
|
await this.userPage.screenshot(testName, '04-connection-network-success');
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
await this.userPage.screenshot(testName, '04-connection-network-failed');
|
||||||
|
this.userPage.logger(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.page1.logger(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async disableWebcamsFromConnectionStatus() {
|
||||||
|
try {
|
||||||
|
await this.page1.shareWebcam(true, ELEMENT_WAIT_LONGER_TIME);
|
||||||
|
await this.page2.shareWebcam(true, ELEMENT_WAIT_LONGER_TIME);
|
||||||
|
await utilUser.connectionStatus(this.page1);
|
||||||
|
await this.page1.waitAndClickElement(e.dataSavingWebcams);
|
||||||
|
await this.page1.waitAndClickElement(e.closeConnectionStatusModal);
|
||||||
|
await this.page1.waitForSelector(e.smallToastMsg);
|
||||||
|
const checkUserWhoHasDisabled = await this.page1.page.evaluate(checkElementLengthEqualTo, e.videoContainer, 1);
|
||||||
|
const checkSecondUser = await this.page2.page.evaluate(checkElementLengthEqualTo, e.videoContainer, 2);
|
||||||
|
|
||||||
|
return checkUserWhoHasDisabled && checkSecondUser;
|
||||||
|
} catch (err) {
|
||||||
|
await this.page1.logger(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async whiteboardNotAppearOnMobile() {
|
async whiteboardNotAppearOnMobile() {
|
||||||
try {
|
try {
|
||||||
await this.page1.waitAndClick(e.userListButton);
|
await this.page1.waitAndClick(e.userListButton);
|
||||||
await this.page2.waitAndClick(e.userListButton);
|
await this.page2.waitAndClick(e.userListButton);
|
||||||
await this.page2.waitAndClick(e.chatButtonKey);
|
await this.page2.waitAndClick(e.chatButtonKey);
|
||||||
const onUserListPanel = await this.page1.isNotVisible(e.hidePresentation);
|
const onUserListPanel = await this.page1.wasRemoved(e.hidePresentation);
|
||||||
const onChatPanel = await this.page2.isNotVisible(e.hidePresentation);
|
const onChatPanel = await this.page2.wasRemoved(e.hidePresentation);
|
||||||
|
|
||||||
return onUserListPanel && onChatPanel;
|
return onUserListPanel && onChatPanel;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -333,7 +378,7 @@ class MultiUsers {
|
|||||||
await this.page2.waitAndClick(e.userListButton);
|
await this.page2.waitAndClick(e.userListButton);
|
||||||
await this.page2.waitAndClick(e.chatButtonKey);
|
await this.page2.waitAndClick(e.chatButtonKey);
|
||||||
const whiteboard = await this.page1.page.evaluate(checkElementLengthEqualTo, e.chatButtonKey, 0);
|
const whiteboard = await this.page1.page.evaluate(checkElementLengthEqualTo, e.chatButtonKey, 0);
|
||||||
const onChatPanel = await this.page2.isNotVisible(e.chatButtonKey);
|
const onChatPanel = await this.page2.hasElement(e.chatButtonKey, false);
|
||||||
|
|
||||||
return whiteboard && onChatPanel;
|
return whiteboard && onChatPanel;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -2,10 +2,9 @@ const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants');
|
|||||||
const Page = require('../core/page');
|
const Page = require('../core/page');
|
||||||
const e = require('../core/elements');
|
const e = require('../core/elements');
|
||||||
const util = require('./util');
|
const util = require('./util');
|
||||||
const utilWebcam = require('../webcam/util');
|
|
||||||
const utilScreenshare = require('../screenshare/util');
|
const utilScreenshare = require('../screenshare/util');
|
||||||
const { sleep } = require('../core/helper');
|
const { sleep } = require('../core/helper');
|
||||||
const { checkElementLengthEqualTo, checkElementLengthDifferentTo } = require('../core/util');
|
const { checkElementLengthEqualTo } = require('../core/util');
|
||||||
|
|
||||||
class Status extends Page {
|
class Status extends Page {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -15,12 +14,11 @@ class Status extends Page {
|
|||||||
async test() {
|
async test() {
|
||||||
try {
|
try {
|
||||||
await util.setStatus(this, e.applaud);
|
await util.setStatus(this, e.applaud);
|
||||||
const resp1 = await this.page.evaluate(checkElementLengthDifferentTo, e.applauseIcon, 0);
|
const resp1 = await this.hasElement(e.applauseIcon);
|
||||||
|
await sleep(1000);
|
||||||
await util.setStatus(this, e.away);
|
await util.setStatus(this, e.away);
|
||||||
const resp2 = await this.page.evaluate(checkElementLengthDifferentTo, e.awayIcon, 0);
|
const resp2 = await this.hasElement(e.awayIcon);
|
||||||
|
|
||||||
await this.waitAndClick(e.firstUser);
|
|
||||||
await this.waitAndClick(e.clearStatus);
|
|
||||||
return resp1 === resp2;
|
return resp1 === resp2;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.logger(err);
|
await this.logger(err);
|
||||||
@ -33,7 +31,7 @@ class Status extends Page {
|
|||||||
await this.waitAndClick(e.userList);
|
await this.waitAndClick(e.userList);
|
||||||
await this.waitForSelector(e.firstUser);
|
await this.waitForSelector(e.firstUser);
|
||||||
|
|
||||||
const response = await this.page.evaluate(checkElementLengthDifferentTo, e.mobileUser, 0);
|
const response = await this.hasElement(e.mobileUser);
|
||||||
return response === true;
|
return response === true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.logger(err);
|
await this.logger(err);
|
||||||
@ -44,7 +42,7 @@ class Status extends Page {
|
|||||||
async findConnectionStatusModal() {
|
async findConnectionStatusModal() {
|
||||||
try {
|
try {
|
||||||
await util.connectionStatus(this);
|
await util.connectionStatus(this);
|
||||||
const resp = await this.page.evaluate(checkElementLengthDifferentTo, e.connectionStatusModal, 0);
|
const resp = await this.hasElement(e.connectionStatusModal);
|
||||||
return resp === true;
|
return resp === true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.logger(err);
|
await this.logger(err);
|
||||||
@ -52,21 +50,6 @@ class Status extends Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async disableWebcamsFromConnectionStatus() {
|
|
||||||
try {
|
|
||||||
await utilWebcam.enableWebcam(this, ELEMENT_WAIT_LONGER_TIME);
|
|
||||||
await util.connectionStatus(this);
|
|
||||||
await this.waitAndClickElement(e.dataSavingWebcams);
|
|
||||||
await this.waitAndClickElement(e.closeConnectionStatusModal);
|
|
||||||
await sleep(2000);
|
|
||||||
const webcamsIsDisabledInDataSaving = await this.page.evaluate(checkElementLengthDifferentTo, e.webcamsIsDisabledInDataSaving, 0);
|
|
||||||
return webcamsIsDisabledInDataSaving === true;
|
|
||||||
} catch (err) {
|
|
||||||
await this.logger(err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async disableScreenshareFromConnectionStatus() {
|
async disableScreenshareFromConnectionStatus() {
|
||||||
try {
|
try {
|
||||||
await utilScreenshare.startScreenshare(this);
|
await utilScreenshare.startScreenshare(this);
|
||||||
@ -74,8 +57,8 @@ class Status extends Page {
|
|||||||
await util.connectionStatus(this);
|
await util.connectionStatus(this);
|
||||||
await this.waitAndClickElement(e.dataSavingScreenshare);
|
await this.waitAndClickElement(e.dataSavingScreenshare);
|
||||||
await this.waitAndClickElement(e.closeConnectionStatusModal);
|
await this.waitAndClickElement(e.closeConnectionStatusModal);
|
||||||
await sleep(2000);
|
|
||||||
const webcamsIsDisabledInDataSaving = await this.page.evaluate(checkElementLengthEqualTo, e.screenshareLocked, 0);
|
const webcamsIsDisabledInDataSaving = await this.hasElement(e.screenshareLocked);
|
||||||
return webcamsIsDisabledInDataSaving === true;
|
return webcamsIsDisabledInDataSaving === true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.logger(err);
|
await this.logger(err);
|
||||||
@ -87,13 +70,13 @@ class Status extends Page {
|
|||||||
try {
|
try {
|
||||||
await this.page.evaluate(() => window.dispatchEvent(new CustomEvent('socketstats', { detail: { rtt: 2000 } })));
|
await this.page.evaluate(() => window.dispatchEvent(new CustomEvent('socketstats', { detail: { rtt: 2000 } })));
|
||||||
await this.joinMicrophone();
|
await this.joinMicrophone();
|
||||||
await utilWebcam.enableWebcam(this, ELEMENT_WAIT_LONGER_TIME);
|
await this.shareWebcam(true, ELEMENT_WAIT_LONGER_TIME);
|
||||||
await utilScreenshare.startScreenshare(this);
|
await utilScreenshare.startScreenshare(this);
|
||||||
await utilScreenshare.waitForScreenshareContainer(this);
|
await utilScreenshare.waitForScreenshareContainer(this);
|
||||||
await util.connectionStatus(this);
|
await util.connectionStatus(this);
|
||||||
await sleep(5000);
|
await sleep(5000);
|
||||||
const connectionStatusItemEmpty = await this.page.evaluate(checkElementLengthEqualTo, e.connectionStatusItemEmpty, 0);
|
const connectionStatusItemEmpty = await this.page.evaluate(checkElementLengthEqualTo, e.connectionStatusItemEmpty, 0);
|
||||||
const connectionStatusItemUser = await this.page.evaluate(checkElementLengthDifferentTo, e.connectionStatusItemUser, 0);
|
const connectionStatusItemUser = await this.hasElement(e.connectionStatusItemUser);
|
||||||
return connectionStatusItemUser && connectionStatusItemEmpty;
|
return connectionStatusItemUser && connectionStatusItemEmpty;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.logger(err);
|
await this.logger(err);
|
||||||
|
@ -112,22 +112,22 @@ const userTest = () => {
|
|||||||
// Open Connection Status Modal, start Webcam Share, disable Webcams in
|
// Open Connection Status Modal, start Webcam Share, disable Webcams in
|
||||||
// Connection Status Modal and check if webcam sharing is still available
|
// Connection Status Modal and check if webcam sharing is still available
|
||||||
test('Disable Webcams From Connection Status Modal', async () => {
|
test('Disable Webcams From Connection Status Modal', async () => {
|
||||||
const test = new Status();
|
const test = new MultiUsers();
|
||||||
let response;
|
let response;
|
||||||
let screenshot;
|
let screenshot;
|
||||||
try {
|
try {
|
||||||
const testName = 'disableWebcamsFromConnectionStatus';
|
const testName = 'disableWebcamsFromConnectionStatus';
|
||||||
await test.logger('begin of ', testName);
|
await test.page1.logger('begin of ', testName);
|
||||||
await test.init(true, true, testName);
|
await test.init(testName);
|
||||||
await test.startRecording(testName);
|
await test.page1.startRecording(testName);
|
||||||
response = await test.disableWebcamsFromConnectionStatus();
|
response = await test.disableWebcamsFromConnectionStatus();
|
||||||
await test.stopRecording();
|
await test.page1.stopRecording();
|
||||||
screenshot = await test.page.screenshot();
|
screenshot = await test.page1.screenshot();
|
||||||
await test.logger('end of ', testName);
|
await test.page1.logger('end of ', testName);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await test.logger(err);
|
await test.page1.logger(err);
|
||||||
} finally {
|
} finally {
|
||||||
await test.close();
|
await test.close(test.page1, test.page2);
|
||||||
}
|
}
|
||||||
expect(response).toBe(true);
|
expect(response).toBe(true);
|
||||||
Page.checkRegression(2.0, screenshot);
|
Page.checkRegression(2.0, screenshot);
|
||||||
@ -205,6 +205,29 @@ const userTest = () => {
|
|||||||
Page.checkRegression(2.0, screenshot);
|
Page.checkRegression(2.0, screenshot);
|
||||||
}, TEST_DURATION_TIME);
|
}, TEST_DURATION_TIME);
|
||||||
|
|
||||||
|
test('Show network data in Connection Status', async () => {
|
||||||
|
const test = new MultiUsers();
|
||||||
|
let response;
|
||||||
|
let screenshot;
|
||||||
|
try {
|
||||||
|
const testName = 'connectionNetworkStatus';
|
||||||
|
await test.page1.logger('begin of ', testName);
|
||||||
|
await test.initMod1(testName);
|
||||||
|
await test.page1.startRecording(testName);
|
||||||
|
response = await test.usersConnectionStatus(testName);
|
||||||
|
await test.page1.stopRecording();
|
||||||
|
screenshot = await test.page1.page.screenshot();
|
||||||
|
await test.page1.logger('end of ', testName);
|
||||||
|
} catch (err) {
|
||||||
|
await test.page1.logger(err);
|
||||||
|
} finally {
|
||||||
|
await test.close(test.page1, test.userPage);
|
||||||
|
}
|
||||||
|
expect(response).toBe(true);
|
||||||
|
Page.checkRegression(2.0, screenshot);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Raise and Lower Hand and make sure that the User2 Avatar color
|
// Raise and Lower Hand and make sure that the User2 Avatar color
|
||||||
// and its avatar in raised hand toast are the same
|
// and its avatar in raised hand toast are the same
|
||||||
test('Raise Hand Toast', async () => {
|
test('Raise Hand Toast', async () => {
|
||||||
|
@ -11,5 +11,15 @@ async function connectionStatus(test) {
|
|||||||
await test.waitForSelector(e.connectionStatusModal);
|
await test.waitForSelector(e.connectionStatusModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkNetworkStatus(dataContainer, networdData) {
|
||||||
|
const values = Array.from(document.querySelectorAll(`${dataContainer} > ${networdData}`));
|
||||||
|
values.splice(4, values.length - 4);
|
||||||
|
const check = values.filter(e => e.textContent.includes(' 0 k'))[0];
|
||||||
|
|
||||||
|
if (!check) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
exports.setStatus = setStatus;
|
exports.setStatus = setStatus;
|
||||||
exports.connectionStatus = connectionStatus;
|
exports.connectionStatus = connectionStatus;
|
||||||
|
exports.checkNetworkStatus = checkNetworkStatus;
|
||||||
|
@ -22,7 +22,7 @@ class Check extends Share {
|
|||||||
const parsedSettings = await this.getSettingsYaml();
|
const parsedSettings = await this.getSettingsYaml();
|
||||||
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
||||||
|
|
||||||
await util.enableWebcam(this, videoPreviewTimeout);
|
await this.shareWebcam(true, videoPreviewTimeout);
|
||||||
const respUser = await util.webcamContentCheck(this);
|
const respUser = await util.webcamContentCheck(this);
|
||||||
return respUser === true;
|
return respUser === true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
const Page = require('../core/page');
|
const Page = require('../core/page');
|
||||||
const util = require('./util');
|
|
||||||
const e = require('../core/elements');
|
const e = require('../core/elements');
|
||||||
const { checkElementLengthDifferentTo } = require('../core/util');
|
|
||||||
const { VIDEO_LOADING_WAIT_TIME } = require('../core/constants'); // core constants (Timeouts vars imported)
|
const { VIDEO_LOADING_WAIT_TIME } = require('../core/constants'); // core constants (Timeouts vars imported)
|
||||||
|
|
||||||
class Share extends Page {
|
class Share extends Page {
|
||||||
@ -13,8 +11,9 @@ class Share extends Page {
|
|||||||
try {
|
try {
|
||||||
const parsedSettings = await this.getSettingsYaml();
|
const parsedSettings = await this.getSettingsYaml();
|
||||||
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
||||||
const response = await util.enableWebcam(this, videoPreviewTimeout);
|
await this.shareWebcam(true, videoPreviewTimeout);
|
||||||
return response;
|
|
||||||
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.logger(err);
|
await this.logger(err);
|
||||||
return false;
|
return false;
|
||||||
@ -26,7 +25,7 @@ class Share extends Page {
|
|||||||
await this.joinMicrophone();
|
await this.joinMicrophone();
|
||||||
const parsedSettings = await this.getSettingsYaml();
|
const parsedSettings = await this.getSettingsYaml();
|
||||||
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
const videoPreviewTimeout = parseInt(parsedSettings.public.kurento.gUMTimeout);
|
||||||
await util.enableWebcam(this, videoPreviewTimeout);
|
await this.shareWebcam(true, videoPreviewTimeout);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await this.logger(err);
|
await this.logger(err);
|
||||||
}
|
}
|
||||||
@ -37,7 +36,7 @@ class Share extends Page {
|
|||||||
await this.waitForSelector(e.webcamVideo, VIDEO_LOADING_WAIT_TIME);
|
await this.waitForSelector(e.webcamVideo, VIDEO_LOADING_WAIT_TIME);
|
||||||
await this.waitForSelector(e.leaveVideo, VIDEO_LOADING_WAIT_TIME);
|
await this.waitForSelector(e.leaveVideo, VIDEO_LOADING_WAIT_TIME);
|
||||||
await this.waitForSelector(e.isTalking);
|
await this.waitForSelector(e.isTalking);
|
||||||
const foundTestElement = await this.page.evaluate(checkElementLengthDifferentTo, e.webcamItemTalkingUser, 0);
|
const foundTestElement = await this.hasElement(e.webcamItemTalkingUser);
|
||||||
if (foundTestElement === true) {
|
if (foundTestElement === true) {
|
||||||
await this.screenshot(`${testName}`, `success-${testName}`);
|
await this.screenshot(`${testName}`, `success-${testName}`);
|
||||||
this.logger(testName, ' passed');
|
this.logger(testName, ' passed');
|
||||||
|
@ -1,23 +1,11 @@
|
|||||||
const e = require('../core/elements');
|
const e = require('../core/elements');
|
||||||
const { sleep } = require('../core/helper');
|
const { sleep } = require('../core/helper');
|
||||||
const { checkElement, checkElementLengthDifferentTo } = require('../core/util');
|
const { checkElement } = require('../core/util');
|
||||||
const {
|
const {
|
||||||
LOOP_INTERVAL,
|
LOOP_INTERVAL,
|
||||||
VIDEO_LOADING_WAIT_TIME,
|
|
||||||
ELEMENT_WAIT_LONGER_TIME,
|
ELEMENT_WAIT_LONGER_TIME,
|
||||||
} = require('../core/constants');
|
} = require('../core/constants');
|
||||||
|
|
||||||
async function enableWebcam(test, videoPreviewTimeout) {
|
|
||||||
// Enabling webcam
|
|
||||||
await test.waitAndClick(e.joinVideo);
|
|
||||||
await test.waitForSelector(e.videoPreview, videoPreviewTimeout);
|
|
||||||
await test.waitAndClick(e.startSharingWebcam);
|
|
||||||
await test.waitForSelector(e.webcamConnecting);
|
|
||||||
await test.waitForSelector(e.webcamVideo, VIDEO_LOADING_WAIT_TIME);
|
|
||||||
await test.waitForSelector(e.leaveVideo, VIDEO_LOADING_WAIT_TIME);
|
|
||||||
return test.page.evaluate(checkElementLengthDifferentTo, e.webcamVideo, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function evaluateCheck(test) {
|
async function evaluateCheck(test) {
|
||||||
await test.waitForSelector(e.videoContainer);
|
await test.waitForSelector(e.videoContainer);
|
||||||
return test.page.evaluate(checkElement, e.presentationFullscreenButton, 1);
|
return test.page.evaluate(checkElement, e.presentationFullscreenButton, 1);
|
||||||
@ -69,4 +57,3 @@ async function webcamContentCheck(test) {
|
|||||||
exports.startAndCheckForWebcams = startAndCheckForWebcams;
|
exports.startAndCheckForWebcams = startAndCheckForWebcams;
|
||||||
exports.webcamContentCheck = webcamContentCheck;
|
exports.webcamContentCheck = webcamContentCheck;
|
||||||
exports.evaluateCheck = evaluateCheck;
|
exports.evaluateCheck = evaluateCheck;
|
||||||
exports.enableWebcam = enableWebcam;
|
|
||||||
|
@ -19,7 +19,6 @@ const webcamTest = () => {
|
|||||||
const testName = 'shareWebcam';
|
const testName = 'shareWebcam';
|
||||||
await test.logger('begin of ', testName);
|
await test.logger('begin of ', testName);
|
||||||
await test.init(true, true, testName);
|
await test.init(true, true, testName);
|
||||||
await test.closeAudioModal();
|
|
||||||
await test.startRecording(testName);
|
await test.startRecording(testName);
|
||||||
response = await test.test();
|
response = await test.test();
|
||||||
await test.stopRecording();
|
await test.stopRecording();
|
||||||
@ -42,7 +41,6 @@ const webcamTest = () => {
|
|||||||
const testName = 'checkWebcamContent';
|
const testName = 'checkWebcamContent';
|
||||||
await test.logger('begin of ', testName);
|
await test.logger('begin of ', testName);
|
||||||
await test.init(true, true, testName);
|
await test.init(true, true, testName);
|
||||||
await test.closeAudioModal();
|
|
||||||
await test.startRecording(testName);
|
await test.startRecording(testName);
|
||||||
response = await test.test();
|
response = await test.test();
|
||||||
await test.stopRecording();
|
await test.stopRecording();
|
||||||
|
@ -1056,6 +1056,120 @@ class ApiController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
* LEARNING DASHBOARD DATA
|
||||||
|
***********************************************/
|
||||||
|
def learningDashboard = {
|
||||||
|
String API_CALL = 'learningDashboard'
|
||||||
|
log.debug CONTROLLER_NAME + "#${API_CALL}"
|
||||||
|
|
||||||
|
String respMessage = ""
|
||||||
|
boolean reject = false
|
||||||
|
|
||||||
|
String sessionToken
|
||||||
|
UserSession us
|
||||||
|
Meeting meeting
|
||||||
|
|
||||||
|
String validationResponse = validateRequest(
|
||||||
|
ValidationService.ApiCall.ENTER,
|
||||||
|
request.getParameterMap(),
|
||||||
|
request.getQueryString(),
|
||||||
|
)
|
||||||
|
|
||||||
|
//Validate Session
|
||||||
|
if(!validationResponse.isEmpty()) {
|
||||||
|
respMessage = validationResponse
|
||||||
|
reject = true
|
||||||
|
} else {
|
||||||
|
sessionToken = sanitizeSessionToken(params.sessionToken)
|
||||||
|
if (!hasValidSession(sessionToken)) {
|
||||||
|
reject = true
|
||||||
|
respMessage = "Invalid Session"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validate User
|
||||||
|
if(reject == false) {
|
||||||
|
us = getUserSession(sessionToken)
|
||||||
|
|
||||||
|
if(us == null) {
|
||||||
|
reject = true;
|
||||||
|
respMessage = "Access denied"
|
||||||
|
} else if(!us.role.equals(ROLE_MODERATOR)) {
|
||||||
|
reject = true
|
||||||
|
respMessage = "Access denied"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validate Meeting
|
||||||
|
if(reject == false) {
|
||||||
|
meeting = meetingService.getMeeting(us.meetingID)
|
||||||
|
boolean isRunning = meeting != null && meeting.isRunning();
|
||||||
|
if(!isRunning) {
|
||||||
|
reject = true
|
||||||
|
respMessage = "Meeting not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
if(meeting.getLearningDashboardEnabled() == false) {
|
||||||
|
reject = true
|
||||||
|
respMessage = "Learning Dashboard disabled for this meeting"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Validate File
|
||||||
|
File jsonDataFile
|
||||||
|
if(reject == false) {
|
||||||
|
jsonDataFile = meetingService.learningDashboardService.getJsonDataFile(us.meetingID,meeting.getLearningDashboardAccessToken());
|
||||||
|
if (!jsonDataFile.exists()) {
|
||||||
|
reject = true
|
||||||
|
respMessage = "Learning Dashboard data not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reject) {
|
||||||
|
response.addHeader("Cache-Control", "no-cache")
|
||||||
|
withFormat {
|
||||||
|
json {
|
||||||
|
def builder = new JsonBuilder()
|
||||||
|
builder.response {
|
||||||
|
returncode RESP_CODE_FAILED
|
||||||
|
message respMessage
|
||||||
|
sessionToken
|
||||||
|
}
|
||||||
|
render(contentType: "application/json", text: builder.toPrettyString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Map<String, Object> logData = new HashMap<String, Object>();
|
||||||
|
logData.put("meetingid", us.meetingID);
|
||||||
|
logData.put("extMeetingid", us.externMeetingID);
|
||||||
|
logData.put("name", us.fullname);
|
||||||
|
logData.put("userid", us.internalUserId);
|
||||||
|
logData.put("sessionToken", sessionToken);
|
||||||
|
logData.put("logCode", "learningDashboard");
|
||||||
|
logData.put("description", "Request Learning Dashboard data.");
|
||||||
|
|
||||||
|
Gson gson = new Gson();
|
||||||
|
String logStr = gson.toJson(logData);
|
||||||
|
|
||||||
|
log.info(" --analytics-- data=" + logStr);
|
||||||
|
|
||||||
|
response.addHeader("Cache-Control", "no-cache")
|
||||||
|
|
||||||
|
withFormat {
|
||||||
|
json {
|
||||||
|
def builder = new JsonBuilder()
|
||||||
|
builder.response {
|
||||||
|
returncode RESP_CODE_SUCCESS
|
||||||
|
data jsonDataFile.getText()
|
||||||
|
sessionToken
|
||||||
|
}
|
||||||
|
render(contentType: "application/json", text: builder.toPrettyString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def uploadDocuments(conf) { //
|
def uploadDocuments(conf) { //
|
||||||
log.debug("ApiController#uploadDocuments(${conf.getInternalId()})");
|
log.debug("ApiController#uploadDocuments(${conf.getInternalId()})");
|
||||||
|
|
||||||
|
@ -151,6 +151,30 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"response": []
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "learningDashboard",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "{{base_url}}/{{path}}/learningDashboard?{{param_session_token}}=",
|
||||||
|
"host": [
|
||||||
|
"{{base_url}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"{{path}}",
|
||||||
|
"learningDashboard"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "{{param_session_token}}",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -108,6 +108,20 @@ if [ -f /usr/lib/systemd/system/red5.service ]; then
|
|||||||
chown root:root /usr/lib/systemd/system/red5.service
|
chown root:root /usr/lib/systemd/system/red5.service
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Verify mediasoup raw media directories ownership and perms
|
||||||
|
if [ -d /var/mediasoup ]; then
|
||||||
|
chown bigbluebutton:bigbluebutton /var/mediasoup
|
||||||
|
chmod 0700 /var/mediasoup
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d /var/mediasoup/recordings ]; then
|
||||||
|
chmod 0700 /var/mediasoup/recordings
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d /var/mediasoup/screenshare ]; then
|
||||||
|
chmod 0700 /var/mediasoup/screenshare
|
||||||
|
fi
|
||||||
|
|
||||||
sed -i 's/worker_connections 768/worker_connections 4000/g' /etc/nginx/nginx.conf
|
sed -i 's/worker_connections 768/worker_connections 4000/g' /etc/nginx/nginx.conf
|
||||||
|
|
||||||
if ! grep "worker_rlimit_nofile 10000;" /etc/nginx/nginx.conf; then
|
if ! grep "worker_rlimit_nofile 10000;" /etc/nginx/nginx.conf; then
|
||||||
|
@ -32,7 +32,9 @@ git clone https://github.com/mconf/ep_redis_publisher.git
|
|||||||
npm pack ./ep_redis_publisher
|
npm pack ./ep_redis_publisher
|
||||||
npm install ./ep_redis_publisher-*.tgz
|
npm install ./ep_redis_publisher-*.tgz
|
||||||
|
|
||||||
npm install ep_cursortrace
|
# npm install ep_cursortrace
|
||||||
|
# using mconf's fork due to https://github.com/ether/ep_cursortrace/pull/25 not being accepted upstream
|
||||||
|
npm install git+https://github.com/mconf/ep_cursortrace.git
|
||||||
npm install ep_disable_chat
|
npm install ep_disable_chat
|
||||||
|
|
||||||
# For some reason installing from github using npm 7.5.2 gives
|
# For some reason installing from github using npm 7.5.2 gives
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
/opt/freeswitch/bin/fs_cli -p $(xmlstarlet sel -t -m 'configuration/settings/param[@name="password"]' -v @value /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml)
|
# "$@" is placed at the end of the command so it can be used as "fs_clibbb -x 'show channels as json'"
|
||||||
|
# @ will be replaced by the arguments you pass in the command line.
|
||||||
|
/opt/freeswitch/bin/fs_cli -p $(xmlstarlet sel -t -m 'configuration/settings/param[@name="password"]' -v @value /opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml) "$@"
|
||||||
|
@ -18,6 +18,14 @@ location /html5client/fonts {
|
|||||||
alias /usr/share/meteor/bundle/programs/web.browser/app/fonts;
|
alias /usr/share/meteor/bundle/programs/web.browser/app/fonts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /html5client/wasm {
|
||||||
|
types {
|
||||||
|
application/wasm wasm;
|
||||||
|
}
|
||||||
|
gzip_static on;
|
||||||
|
alias /usr/share/meteor/bundle/programs/web.browser/app/wasm;
|
||||||
|
}
|
||||||
|
|
||||||
location ~ ^/html5client/ {
|
location ~ ^/html5client/ {
|
||||||
# proxy_pass http://127.0.0.1:4100; # use for development
|
# proxy_pass http://127.0.0.1:4100; # use for development
|
||||||
proxy_pass http://poolhtml5servers; # use for production
|
proxy_pass http://poolhtml5servers; # use for production
|
||||||
|
@ -84,6 +84,16 @@ if [ -f staging/usr/share/meteor/bundle/programs/web.browser/head.html ]; then
|
|||||||
sed -i "s/VERSION/$(($BUILD))/" staging/usr/share/meteor/bundle/programs/web.browser/head.html
|
sed -i "s/VERSION/$(($BUILD))/" staging/usr/share/meteor/bundle/programs/web.browser/head.html
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Compress tensorflow WASM binaries used for virtual backgrounds. Keep the
|
||||||
|
# uncompressed versions as well so it works with mismatched nginx location blocks
|
||||||
|
if [ -f staging/usr/share/meteor/bundle/programs/web.browser/app/wasm/tflite-simd.wasm ]; then
|
||||||
|
gzip -k -f -9 staging/usr/share/meteor/bundle/programs/web.browser/app/wasm/tflite-simd.wasm
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f staging/usr/share/meteor/bundle/programs/web.browser/app/wasm/tflite.wasm ]; then
|
||||||
|
gzip -k -f -9 staging/usr/share/meteor/bundle/programs/web.browser/app/wasm/tflite.wasm
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p staging/etc/nginx/sites-available
|
mkdir -p staging/etc/nginx/sites-available
|
||||||
cp bigbluebutton.nginx staging/etc/nginx/sites-available/bigbluebutton
|
cp bigbluebutton.nginx staging/etc/nginx/sites-available/bigbluebutton
|
||||||
|
|
||||||
|
@ -101,6 +101,8 @@ bbb_config() {
|
|||||||
touch /var/log/bigbluebutton/bbb-web.log
|
touch /var/log/bigbluebutton/bbb-web.log
|
||||||
chown bigbluebutton:bigbluebutton /var/log/bigbluebutton/bbb-web.log
|
chown bigbluebutton:bigbluebutton /var/log/bigbluebutton/bbb-web.log
|
||||||
|
|
||||||
|
update-java-alternatives -s java-1.8.0-openjdk-amd64
|
||||||
|
|
||||||
# Restart bbb-web to deploy new
|
# Restart bbb-web to deploy new
|
||||||
startService bbb-web.service || echo "bbb-web.service could not be registered or started"
|
startService bbb-web.service || echo "bbb-web.service could not be registered or started"
|
||||||
# sed -i 's/8080/8090/g' /etc/bigbluebutton/nginx/web
|
# sed -i 's/8080/8090/g' /etc/bigbluebutton/nginx/web
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
. ./opts-global.sh
|
. ./opts-global.sh
|
||||||
|
|
||||||
OPTS="$OPTS -t deb -d zip,unzip,imagemagick,redis-server,xpdf-utils,bbb-libreoffice-docker,psmisc,fonts-crosextra-carlito,fonts-crosextra-caladea,fonts-noto --deb-user bigbluebutton --deb-group bigbluebutton --deb-use-file-permissions"
|
OPTS="$OPTS -t deb -d zip,unzip,imagemagick,redis-server,xpdf-utils,bbb-libreoffice-docker,psmisc,fonts-crosextra-carlito,fonts-crosextra-caladea,fonts-noto,openjdk-8-jdk --deb-user bigbluebutton --deb-group bigbluebutton --deb-use-file-permissions"
|
||||||
|
@ -16,6 +16,10 @@ case "$1" in
|
|||||||
# https://github.com/bigbluebutton/bbb-webrtc-sfu/pull/37
|
# https://github.com/bigbluebutton/bbb-webrtc-sfu/pull/37
|
||||||
# yq w -i $TARGET kurento[0].url "ws://$SERVER_URL:8888/kurento"
|
# yq w -i $TARGET kurento[0].url "ws://$SERVER_URL:8888/kurento"
|
||||||
|
|
||||||
|
# Set mediasoup IPs
|
||||||
|
yq w -i $TARGET mediasoup.webrtc.listenIps[0].announcedIp "$IP"
|
||||||
|
yq w -i $TARGET mediasoup.plainRtp.listenIp.announcedIp "$IP"
|
||||||
|
|
||||||
FREESWITCH_IP=$(xmlstarlet sel -t -v '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "local_ip_v4=")]/@data' /opt/freeswitch/conf/vars.xml | sed 's/local_ip_v4=//g')
|
FREESWITCH_IP=$(xmlstarlet sel -t -v '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "local_ip_v4=")]/@data' /opt/freeswitch/conf/vars.xml | sed 's/local_ip_v4=//g')
|
||||||
if [ "$FREESWITCH_IP" != "" ]; then
|
if [ "$FREESWITCH_IP" != "" ]; then
|
||||||
yq w -i $TARGET freeswitch.ip $FREESWITCH_IP
|
yq w -i $TARGET freeswitch.ip $FREESWITCH_IP
|
||||||
@ -35,8 +39,8 @@ case "$1" in
|
|||||||
|
|
||||||
# there's a problem rebuilding bufferutil
|
# there's a problem rebuilding bufferutil
|
||||||
# do not abort in case npm rebuild return something different than 0
|
# do not abort in case npm rebuild return something different than 0
|
||||||
npm config set unsafe-perm true
|
#npm config set unsafe-perm true
|
||||||
npm rebuild || true
|
#npm rebuild || true
|
||||||
|
|
||||||
mkdir -p /var/log/bbb-webrtc-sfu/
|
mkdir -p /var/log/bbb-webrtc-sfu/
|
||||||
touch /var/log/bbb-webrtc-sfu/bbb-webrtc-sfu.log
|
touch /var/log/bbb-webrtc-sfu/bbb-webrtc-sfu.log
|
||||||
@ -77,6 +81,10 @@ case "$1" in
|
|||||||
# echo "#"
|
# echo "#"
|
||||||
# fi
|
# fi
|
||||||
|
|
||||||
|
# Creates the mediasoup raw media file dir if needed
|
||||||
|
if [ ! -d /var/mediasoup ]; then
|
||||||
|
mkdir -p /var/mediasoup
|
||||||
|
fi
|
||||||
|
|
||||||
# Create a symbolic link from /var/kurento -> /var/lib/kurento if needed
|
# Create a symbolic link from /var/kurento -> /var/lib/kurento if needed
|
||||||
if [ ! -d /var/kurento ]; then
|
if [ ! -d /var/kurento ]; then
|
||||||
|
@ -15,6 +15,9 @@ case "$1" in
|
|||||||
if [ -f /usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml ]; then
|
if [ -f /usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml ]; then
|
||||||
cp /usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml /tmp/bbb-webrtc-sfu-default.yml
|
cp /usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml /tmp/bbb-webrtc-sfu-default.yml
|
||||||
fi
|
fi
|
||||||
|
# there might be remaining files from older BBB versions
|
||||||
|
# BBB 2.3 and earlier did an npm rebuild in the after-install script.
|
||||||
|
rm -rf /usr/local/bigbluebutton/bbb-webrtc-sfu/node_modules
|
||||||
;;
|
;;
|
||||||
|
|
||||||
abort-upgrade)
|
abort-upgrade)
|
||||||
|
@ -40,6 +40,14 @@ else
|
|||||||
npm install --unsafe-perm --production
|
npm install --unsafe-perm --production
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# clean out stuff that is not required in the final package
|
||||||
|
rm -rf node_modules/mediasoup/{rust,.github,test}
|
||||||
|
rm -rf node_modules/mediasoup/worker/{deps,src,test,include,fuzzer}
|
||||||
|
rm -rf node_modules/mediasoup/worker/out/Release/*.a
|
||||||
|
rm -rf node_modules/mediasoup/worker/out/Release/.deps
|
||||||
|
rm -rf node_modules/mediasoup/worker/out/Release/obj.target
|
||||||
|
rm -rf node_modules/mediasoup/worker/out/deps
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
cp webrtc-sfu.nginx staging/etc/bigbluebutton/nginx
|
cp webrtc-sfu.nginx staging/etc/bigbluebutton/nginx
|
||||||
|
Loading…
Reference in New Issue
Block a user