Merge branch 'v2.5.x-release' into test-suite-youtube-title

This commit is contained in:
Anton Georgiev 2022-07-06 10:26:40 -04:00 committed by GitHub
commit e37b9b6b4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 778 additions and 523 deletions

View File

@ -1 +1 @@
git clone --branch v2.8.2 --depth 1 https://github.com/bigbluebutton/bbb-webrtc-sfu bbb-webrtc-sfu
git clone --branch v2.8.5 --depth 1 https://github.com/bigbluebutton/bbb-webrtc-sfu bbb-webrtc-sfu

View File

@ -1 +1 @@
BIGBLUEBUTTON_RELEASE=2.5.2
BIGBLUEBUTTON_RELEASE=2.5.3

View File

@ -420,7 +420,15 @@ start_bigbluebutton () {
TOMCAT_SERVICE=$TOMCAT_USER
fi
systemctl start $TOMCAT_SERVICE nginx freeswitch $REDIS_SERVICE bbb-apps-akka bbb-fsesl-akka bbb-rap-resque-worker bbb-rap-starter.service bbb-rap-caption-inbox.service $HTML5 $WEBHOOKS $ETHERPAD $PADS $BBB_WEB $BBB_LTI
systemctl start $TOMCAT_SERVICE || {
echo
echo "# Warning: $TOMCAT_SERVICE could not be started. Please, check BBB-LTI or BBB-Demo."
echo "# Run the command:"
echo "# sudo journalctl -u $TOMCAT_SERVICE"
echo "# To better understand the ERROR"
}
systemctl start nginx freeswitch $REDIS_SERVICE bbb-apps-akka bbb-fsesl-akka bbb-rap-resque-worker bbb-rap-starter.service bbb-rap-caption-inbox.service $HTML5 $WEBHOOKS $ETHERPAD $PADS $BBB_WEB $BBB_LTI
if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
systemctl start mongod
@ -1133,10 +1141,19 @@ check_state() {
fi
if bbb-conf --status | grep -q inactive; then
echo "# Error: Detected some processes have not started correctly"
echo "#"
echo "# $(bbb-conf --status | grep inactive)"
echo "#"
if bbb-conf --status | grep -q tomcat9; then
echo "# Warning: $TOMCAT_SERVICE is not started correctly"
echo "#"
echo "# $(bbb-conf --status | grep inactive | grep $TOMCAT_SERVICE)"
echo "#"
fi
if bbb-conf --status | grep inactive | grep -vq tomcat9; then
echo "# Error: Detected some processes have not started correctly"
echo "#"
echo "# $(bbb-conf --status | grep inactive | grep -v $TOMCAT_SERVICE)"
echo "#"
fi
fi
if systemctl status freeswitch | grep -q SETSCHEDULER; then

View File

@ -1,4 +1,5 @@
import addSystemMsg from '../../../group-chat-msg/server/modifiers/addSystemMsg';
import caseInsensitiveReducer from '/imports/utils/caseInsensitiveReducer';
export default function sendPollChatMsg({ body }, meetingId) {
const { poll } = body;
@ -10,9 +11,14 @@ export default function sendPollChatMsg({ body }, meetingId) {
const SYSTEM_CHAT_TYPE = CHAT_CONFIG.type_system;
const pollResultData = poll;
const answers = pollResultData.answers.reduce(caseInsensitiveReducer, []);
const extra = {
type: 'poll',
pollResultData,
pollResultData: {
...pollResultData,
answers,
},
};
const payload = {

View File

@ -10,7 +10,7 @@ const getSlideText = async (url) => {
let content = '';
try {
const request = await axios(url);
content = request.data;
content = request.data.toString();
} catch (error) {
Logger.error(`No file found. ${error}`);
}

View File

@ -31,10 +31,6 @@ const intlMessages = defineMessages({
id: 'app.actionsBar.actionsDropdown.desktopShareLabel',
description: 'Desktop Share option label',
},
lockedDesktopShareLabel: {
id: 'app.actionsBar.actionsDropdown.lockedDesktopShareLabel',
description: 'Desktop locked Share option label',
},
stopDesktopShareLabel: {
id: 'app.actionsBar.actionsDropdown.stopDesktopShareLabel',
description: 'Stop Desktop Share option label',
@ -151,11 +147,10 @@ const ScreenshareButton = ({
</Styled.ScreenShareModal>,
);
const screenshareLocked = screenshareDataSavingSetting
? intlMessages.desktopShareLabel : intlMessages.lockedDesktopShareLabel;
const screenshareLabel = intlMessages.desktopShareLabel;
const vLabel = isVideoBroadcasting
? intlMessages.stopDesktopShareLabel : screenshareLocked;
? intlMessages.stopDesktopShareLabel : screenshareLabel;
const vDescr = isVideoBroadcasting
? intlMessages.stopDesktopShareDesc : intlMessages.desktopShareDesc;
@ -164,13 +159,12 @@ const ScreenshareButton = ({
&& !isMobile
&& amIPresenter;
const dataTest = !screenshareDataSavingSetting ? 'screenshareLocked'
: isVideoBroadcasting ? 'stopScreenShare' : 'startScreenShare';
const dataTest = isVideoBroadcasting ? 'stopScreenShare' : 'startScreenShare';
return shouldAllowScreensharing
? (
<Styled.ScreenShareButton
disabled={(!isMeteorConnected && !isVideoBroadcasting) || !screenshareDataSavingSetting}
disabled={(!isMeteorConnected && !isVideoBroadcasting)}
icon={isVideoBroadcasting ? 'desktop' : 'desktop_off'}
data-test={dataTest}
label={intl.formatMessage(vLabel)}

View File

@ -26,6 +26,7 @@ const AudioModalButton = styled(Button)`
// Modifies the audio button icon colour
& span:first-child {
display: inline-block;
color: #1b3c4b;
background-color: #f1f8ff;
box-shadow: none;
@ -46,6 +47,7 @@ const AudioModalButton = styled(Button)`
// Modifies the button label text
& span:last-child {
display: block;
color: black;
font-size: 1rem;
font-weight: 600;

View File

@ -627,6 +627,7 @@ class ConnectionStatusComponent extends PureComponent {
<Styled.Copy
disabled={!hasNetworkData}
role="button"
data-test="copyStats"
onClick={this.copyNetworkData.bind(this)}
onKeyPress={this.copyNetworkData.bind(this)}
tabIndex={0}

View File

@ -5,6 +5,10 @@ import logger from '/imports/startup/client/logger';
const Cursor = new Mongo.Collection(null);
let cursorStreamListener = null;
export const clearCursors = () => {
Cursor.remove({});
};
function updateCursor(userId, payload) {
const selector = {
userId,

View File

@ -5,6 +5,7 @@ import Settings from '/imports/ui/services/settings';
import getFromUserSettings from '/imports/ui/services/users-settings';
import { isExternalVideoEnabled, isScreenSharingEnabled } from '/imports/ui/services/features';
import { ACTIONS } from '../layout/enums';
import UserService from '/imports/ui/components/user-list/service';
const LAYOUT_CONFIG = Meteor.settings.public.layout;
const KURENTO_CONFIG = Meteor.settings.public.kurento;
@ -26,7 +27,7 @@ function shouldShowWhiteboard() {
function shouldShowScreenshare() {
const { viewScreenshare } = Settings.dataSaving;
return isScreenSharingEnabled() && viewScreenshare && isVideoBroadcasting();
return isScreenSharingEnabled() && (viewScreenshare || UserService.isUserPresenter()) && isVideoBroadcasting();
}
function shouldShowExternalVideo() {

View File

@ -1,7 +1,6 @@
import Auth from '/imports/ui/services/auth';
import { CurrentPoll } from '/imports/api/polls';
import { escapeHtml } from '/imports/utils/string-utils';
import caseInsensitiveReducer from '/imports/utils/caseInsensitiveReducer';
import { defineMessages } from 'react-intl';
const POLL_AVATAR_COLOR = '#3B48A9';
@ -89,7 +88,7 @@ const getPollResultsText = (isDefaultPoll, answers, numRespondents, intl) => {
answers.map((item) => {
responded += item.numVotes;
return item;
}).reduce(caseInsensitiveReducer, []).forEach((item) => {
}).forEach((item) => {
const numResponded = responded === numRespondents ? numRespondents : responded;
const pct = Math.round((item.numVotes / numResponded) * 100);
const pctBars = '|'.repeat((pct * MAX_POLL_RESULT_BARS) / 100);

View File

@ -25,6 +25,7 @@ import { colorContentBackground } from '/imports/ui/stylesheets/styled-component
import browserInfo from '/imports/utils/browserInfo';
import PresentationMenu from './presentation-menu/container';
import { addNewAlert } from '../screenreader-alert/service';
import { clearCursors } from '/imports/ui/components/cursor/service';
const intlMessages = defineMessages({
presentationLabel: {
@ -156,6 +157,8 @@ class Presentation extends PureComponent {
presentationBounds,
numCameras,
intl,
multiUser,
clearFakeAnnotations,
} = this.props;
const { presentationWidth, presentationHeight } = this.state;
@ -163,8 +166,14 @@ class Presentation extends PureComponent {
const {
numCameras: prevNumCameras,
presentationBounds: prevPresentationBounds,
multiUser: prevMultiUser,
} = prevProps;
if (prevMultiUser && !multiUser) {
clearFakeAnnotations();
clearCursors();
}
if (numCameras !== prevNumCameras) {
this.onResize();
}

View File

@ -138,5 +138,6 @@ export default withTracker(({ podId }) => {
'bbb_force_restore_presentation_on_new_events',
Meteor.settings.public.presentation.restoreOnUpdate,
),
clearFakeAnnotations: WhiteboardService.clearFakeAnnotations,
};
})(PresentationContainer);

View File

@ -6,6 +6,7 @@ import lockContextContainer from "/imports/ui/components/lock-viewers/context/co
import { UsersContext } from "/imports/ui/components/components-data/users-context/context";
import CursorService from "./service";
import Cursor from "./component";
import WhiteboardService from "/imports/ui/components/whiteboard/service";
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
@ -34,10 +35,12 @@ const CursorContainer = (props) => {
export default lockContextContainer(
withTracker((params) => {
const { cursorId, userLocks } = params;
const { cursorId, userLocks, whiteboardId, presenter } = params;
const isViewersCursorLocked = userLocks?.hideViewersCursor;
const cursor = CursorService.getCurrentCursor(cursorId);
if (cursor) {
const hasPermission = presenter || WhiteboardService.hasMultiUserAccess(whiteboardId, cursor.userId);
if (cursor&& hasPermission) {
const {
xPercent: cursorX,
yPercent: cursorY,

View File

@ -349,6 +349,7 @@ class PresentationToolbar extends PureComponent {
}
<Styled.FitToWidthButton
role="button"
data-test="fitToWidthButton"
aria-describedby={fitToWidth ? 'fitPageDesc' : 'fitWidthDesc'}
aria-label={fitToWidth
? `${intl.formatMessage(intlMessages.presentationLabel)} ${intl.formatMessage(intlMessages.fitToPage)}`

View File

@ -628,7 +628,7 @@ const sortUsersByLastName = (a, b) => {
return sortUsersByName(aUser, bUser);
};
const isUserPresenter = (userId) => {
const isUserPresenter = (userId = Auth.userID) => {
const user = Users.findOne({ userId },
{ fields: { presenter: 1 } });
return user ? user.presenter : false;

View File

@ -25,7 +25,7 @@ const clearPreview = (annotation) => {
UnsentAnnotations.remove({ id: annotation });
};
function clearFakeAnnotations() {
const clearFakeAnnotations = () => {
UnsentAnnotations.remove({});
Annotations.remove({ id: /-fake/g });
}
@ -398,4 +398,5 @@ export {
addIndividualAccess,
removeGlobalAccess,
removeIndividualAccess,
clearFakeAnnotations,
};

View File

@ -420,7 +420,7 @@
"app.settings.main.save.label.description": "Saves the changes and closes the settings menu",
"app.settings.dataSavingTab.label": "Data savings",
"app.settings.dataSavingTab.webcam": "Enable other participants webcams",
"app.settings.dataSavingTab.screenShare": "Enable desktop sharing",
"app.settings.dataSavingTab.screenShare": "Enable other participants desktop sharing",
"app.settings.dataSavingTab.description": "To save your bandwidth adjust what's currently being displayed.",
"app.settings.save-notification.label": "Settings have been saved",
"app.statusNotifier.lowerHands": "Lower Hands",
@ -440,7 +440,6 @@
"app.actionsBar.actionsDropdown.presentationLabel": "Manage presentations",
"app.actionsBar.actionsDropdown.initPollLabel": "Initiate a poll",
"app.actionsBar.actionsDropdown.desktopShareLabel": "Share your screen",
"app.actionsBar.actionsDropdown.lockedDesktopShareLabel": "Screenshare locked",
"app.actionsBar.actionsDropdown.stopDesktopShareLabel": "Stop sharing your screen",
"app.actionsBar.actionsDropdown.presentationDesc": "Upload your presentation",
"app.actionsBar.actionsDropdown.initPollDesc": "Initiate a poll",

View File

@ -173,6 +173,7 @@
"app.presentation.options.fullscreen": "Täisekraan",
"app.presentation.options.exitFullscreen": "Välju täisekraanilt",
"app.presentation.options.minimize": "Minimeeri",
"app.presentation.options.snapshot": "Praeguse slaidi hetktõmmis",
"app.presentation.options.downloading": "Allalaadimine...",
"app.presentation.options.downloaded": "Aktiivne esitlus laaditi alla",
"app.presentation.options.downloadFailed": "Ei saa aktiivset esitlust alla laadida",

View File

@ -173,6 +173,7 @@
"app.presentation.options.fullscreen": "Pantaila osoa",
"app.presentation.options.exitFullscreen": "Irten pantaila osotik",
"app.presentation.options.minimize": "Minimizatu",
"app.presentation.options.snapshot": "Oraingo diapositibaren pantaila-argazkia",
"app.presentation.options.downloading": "Deskargatzen...",
"app.presentation.options.downloaded": "Uneko aurkezpena deskargatu da",
"app.presentation.options.downloadFailed": "Ezin izan da uneko aurkezpena deskargatu",
@ -505,6 +506,8 @@
"app.breakoutJoinConfirmation.freeJoinMessage": "Aukeratu azpitalde baten gela bertara sartzeko",
"app.breakoutTimeRemainingMessage": "Azpitaldearen gelari geratzen zaion denbora: {0}",
"app.breakoutWillCloseMessage": "Denbora agortu da. Azpitaldearen gela laster itxiko da",
"app.breakout.dropdown.manageDuration": "Aldatu iraupena",
"app.breakout.dropdown.destroyAll": "Amaitu banaketa-gelak",
"app.breakout.dropdown.options": "Azpitaldeen aukerak",
"app.calculatingBreakoutTimeRemaining": "Geratzen den denbora kalkulatzen...",
"app.audioModal.ariaTitle": "Erabili audio modala",
@ -600,6 +603,7 @@
"app.error.500": "Ups, zerbait oker joan da",
"app.error.userLoggedOut": "Erabiltzaileak saio-token baliogabea du saioa utzi duelako",
"app.error.ejectedUser": "Erabiltzaileak saio-token baliogabea du kanporatua izan delako",
"app.error.joinedAnotherWindow": "Saio hau beste nabigatzaile-leiho batean ireki dela dirudi.",
"app.error.userBanned": "Erabiltzailea debekatuta dago",
"app.error.leaveLabel": "Hasi saioa berriro",
"app.error.fallback.presentation.title": "Errore bat gertatu da",

File diff suppressed because it is too large Load Diff

View File

@ -132,8 +132,8 @@
"app.userList.userOptions.savedNames.title": "Liste des utilisateurs de la conférence {0} à {1}",
"app.userList.userOptions.sortedFirstName.heading": "Trié par prénom :",
"app.userList.userOptions.sortedLastName.heading": "Trié par nom :",
"app.userList.userOptions.hideViewersCursor": "Les pointeurs des participants ont été rendus inopérants ",
"app.userList.userOptions.showViewersCursor": "Les pointeurs des participants sont à nouveau opérationnels",
"app.userList.userOptions.hideViewersCursor": "Les pointeurs des participants ont été verrouillés ",
"app.userList.userOptions.showViewersCursor": "Les pointeurs des participants sont déverrouillés",
"app.media.label": "Média",
"app.media.autoplayAlertDesc": "Autoriser l'accès",
"app.media.screenshare.start": "Partage d'écran commencé",
@ -173,7 +173,7 @@
"app.presentation.options.fullscreen": "Plein écran",
"app.presentation.options.exitFullscreen": "Sortir du plein écran",
"app.presentation.options.minimize": "Réduire",
"app.presentation.options.snapshot": "Instantané de la présentation courante",
"app.presentation.options.snapshot": "Capture de la présentation courante",
"app.presentation.options.downloading": "Téléchargement en cours...",
"app.presentation.options.downloaded": "La présentation courante a été téléchargée",
"app.presentation.options.downloadFailed": "Impossible de télécharger la présentation courante",
@ -1046,7 +1046,7 @@
"app.learningDashboard.statusTimelineTable.thumbnail": "Vignette de présentation",
"app.learningDashboard.errors.invalidToken": "Jeton de session invalide",
"app.learningDashboard.errors.dataUnavailable": "Les données ne sont plus disponibles",
"mobileApp.portals.list.empty.addFirstPortal.label": "Ajoutez votre premier portail en utilisant le bouton ci-dessus,",
"mobileApp.portals.list.empty.addFirstPortal.label": "Ajoutez votre premier portail en utilisant le bouton ci-dessus",
"mobileApp.portals.list.empty.orUseOurDemoServer.label": "ou utilisez notre serveur de démo.",
"mobileApp.portals.list.add.button.label": "Ajouter un portail",
"mobileApp.portals.fields.name.label": "Nom du portail",

View File

@ -1,6 +1,7 @@
{
"app.home.greeting": "Vaša prezentacija započet će uskoro ...",
"app.chat.submitLabel": "Pošalji poruku",
"app.chat.inputPlaceholder": "Poruke {0}",
"app.chat.titlePublic": "Javni chat",
"app.chat.titlePrivate": "Privatni chat s {0}",
"app.chat.partnerDisconnected": "{0} je napustio sastanak",
@ -22,14 +23,25 @@
"app.captions.label": "Titlovi",
"app.captions.menu.close": "Zatvori",
"app.captions.menu.start": "Pokreni",
"app.captions.menu.ariaStart": "Počni pisati titlove",
"app.captions.menu.select": "Odaberite dostupni jezik",
"app.captions.menu.ariaSelect": "Jezik titlova",
"app.captions.menu.title": "Titlovi",
"app.captions.menu.fontSize": "Veličina",
"app.captions.menu.fontColor": "Boja teksta",
"app.captions.menu.fontFamily": "Font",
"app.captions.menu.backgroundColor": "Boja pozadine",
"app.captions.menu.previewLabel": "Pregled",
"app.captions.menu.cancelLabel": "Odustani",
"app.captions.hide": "Skrij titlove",
"app.captions.ownership": "Preuzmite",
"app.captions.dictationStart": "Pokreni diktiranje",
"app.captions.dictationStop": "Zaustavi diktiranje",
"app.textInput.sendLabel": "Pošalji",
"app.notes.title": "Dijeljene bilješke",
"app.notes.label": "Bilješke",
"app.notes.hide": "Skrij bilješke",
"app.notes.locked": "Zaključano",
"app.user.activityCheck": "Provjera aktivnosti sudionika",
"app.user.activityCheck.check": "Provjeri",
"app.userList.usersTitle": "Korisnici",
@ -56,6 +68,7 @@
"app.userList.menu.muteUserAudio.label": "Stišaj sudionika",
"app.userList.menu.giveWhiteboardAccess.label" : "Daj pristup bijeloj ploči",
"app.userList.menu.removeWhiteboardAccess.label": "Oduzmi pristup bijeloj ploči",
"app.userList.menu.ejectUserCameras.label": "Zatvori kamere",
"app.userList.menu.promoteUser.label": "Postavi za moderatora",
"app.userList.menu.demoteUser.label": "Vrati u ulogu gledatelja",
"app.userList.menu.makePresenter.label": "Postavi za prezentera",
@ -92,10 +105,15 @@
"app.meeting.meetingTimeRemaining": "Preostalo vrijeme sastanka: {0}",
"app.meeting.alertMeetingEndsUnderMinutesSingular": "Sastanak prestaje za jednu minutu.",
"app.meeting.alertMeetingEndsUnderMinutesPlural": "Sastanak prestaje za {0} minuta/e.",
"app.meeting.alertBreakoutEndsUnderMinutesPlural": "Breakout soba se zatvara za {0} minuta/e.",
"app.meeting.alertBreakoutEndsUnderMinutesSingular": "Breakout soba se zatvara za 1 minutu.",
"app.presentation.hide": "Skrij prezentaciju",
"app.presentation.notificationLabel": "Trenutačna prezentacija",
"app.presentation.downloadLabel": "Preuzmi",
"app.presentation.slideContent": "Sadržaj slajda",
"app.presentation.options.fullscreen": "Preko cijelog zaslona",
"app.presentation.options.exitFullscreen": "Izađi iz prikaza preko cijelog zaslona",
"app.presentation.options.downloading": "Preuzimanje u tijeku...",
"app.presentation.presentationToolbar.noNextSlideDesc": "Kraj prezentacije",
"app.presentation.presentationToolbar.noPrevSlideDesc": "Početak prezentacije",
"app.presentation.presentationToolbar.zoomLabel": "Zoom",
@ -113,14 +131,17 @@
"app.presentationUploder.genericError": "Nešto je pošlo po krivu...",
"app.presentationUploder.conversion.conversionProcessingSlides": "Obrada stranice {0} od {1}",
"app.presentationUploder.conversion.genericConversionStatus": "Konverzija datoteke ...",
"app.presentationUploder.conversion.generatingSvg": "Stvaranje SVG slika ...",
"app.presentationUploder.conversion.unsupportedDocument": "Ekstenzija datoteke nije podržana",
"app.presentationUploder.removePresentationLabel": "Uklonite prezentaciju",
"app.presentationUploder.setAsCurrentPresentation": "Postavi prezentaciju kao aktivnu",
"app.presentationUploder.tableHeading.filename": "Datoteka",
"app.presentationUploder.tableHeading.options": "Postavke",
"app.presentationUploder.tableHeading.status": "Status",
"app.presentationUploder.uploading": "Prijenos na poslužitelj {0} {1}",
"app.presentationUploder.item" : "Stavka",
"app.presentationUploder.itemPlural" : "Stavke",
"app.presentationUploder.clearErrors": "Ukloni pogreške",
"app.presentationUploder.uploadViewTitle": "Prijenos prezentacije",
"app.poll.pollPaneTitle": "Anketa",
"app.poll.quickPollTitle": "Brza anketa",
@ -129,6 +150,7 @@
"app.poll.backLabel": "Pokreni anketu",
"app.poll.closeLabel": "Zatvori",
"app.poll.waitingLabel": "Čekanje na odgovore ({0}/{1})",
"app.poll.customPlaceholder": "Dodaj opciju / odgovor ankete",
"app.poll.clickHereToSelect": "Kliknite ovdje za odabir",
"app.poll.question.label" : "Napišite svoje pitanje...",
"app.poll.optionalQuestion.label" : "Napišite svoje pitanje (opcionalno)...",
@ -143,6 +165,8 @@
"app.poll.tf": "Točno / Netočno",
"app.poll.y": "Da",
"app.poll.n": "Ne",
"app.poll.abstention": "Suzdržano",
"app.poll.yna": "Da/Ne/Suzdržano",
"app.poll.a2": "A / B",
"app.poll.a3": "A / B / C",
"app.poll.a4": "A / B / C / D",
@ -151,6 +175,7 @@
"app.poll.answer.false": "Netočno",
"app.poll.answer.yes": "Da",
"app.poll.answer.no": "Ne",
"app.poll.answer.abstention": "Suzdržano",
"app.poll.answer.a": "A",
"app.poll.answer.b": "B",
"app.poll.answer.c": "C",
@ -163,6 +188,7 @@
"app.polling.pollQuestionTitle": "Anketno pitanje",
"app.polling.submitLabel": "Predaj",
"app.polling.responsePlaceholder": "Unesite odgovor",
"app.polling.pollAnswerLabel": "Odgovor na anketu {0}",
"app.downloadPresentationButton.label": "Preuzmi originalnu prezentaciju",
"app.connectingMessage": "Spajanje ...",
"app.retryNow": "Pokušajte ponovno",
@ -240,6 +266,7 @@
"app.actionsBar.actionsDropdown.presentationLabel": "Upravljanje prezentacijama",
"app.actionsBar.actionsDropdown.initPollLabel": "Pokreni anketu",
"app.actionsBar.actionsDropdown.desktopShareLabel": "Podijeli zaslon",
"app.actionsBar.actionsDropdown.lockedDesktopShareLabel": "Dijeljenje zaslona je zaključano",
"app.actionsBar.actionsDropdown.stopDesktopShareLabel": "Zaustavite dijeljenje vašeg zaslona",
"app.actionsBar.actionsDropdown.presentationDesc": "Prenesite svoju prezentaciju",
"app.actionsBar.actionsDropdown.initPollDesc": "Pokreni anketu",
@ -272,9 +299,13 @@
"app.actionsBar.emojiMenu.thumbsUpDesc": "Promijenite svoj status u 'Palac gore'",
"app.actionsBar.emojiMenu.thumbsDownLabel": "Palac dolje",
"app.actionsBar.emojiMenu.thumbsDownDesc": "Promijenite svoj status u 'Palac dolje'",
"app.actionsBar.currentStatusDesc": "trenutačni status {0}",
"app.audioNotification.closeLabel": "Zatvori",
"app.breakoutJoinConfirmation.title": "Priključi se u breakout sobu",
"app.breakoutJoinConfirmation.message": "Želite li se priključiti",
"app.breakoutJoinConfirmation.dismissLabel": "Odustani",
"app.breakout.dropdown.manageDuration": "Promijeni trajanje",
"app.breakout.dropdown.options": "Opcije za breakout sobe",
"app.audioModal.microphoneLabel": "Mikrofon",
"app.audioModal.listenOnlyLabel": "Samo slušanje",
"app.audioModal.microphoneDesc": "Priključit se zvučnoj konferenciji s mikrofonom",
@ -350,6 +381,7 @@
"app.userList.guest.denyEveryone": "Odbij svima",
"app.userList.guest.pendingUsers": "Korisnici na čekanju: {0}",
"app.userList.guest.rememberChoice": "Zapamti odabir",
"app.userList.guest.privateMessageLabel": "Poruka",
"app.userList.guest.acceptLabel": "Prihvati",
"app.userList.guest.denyLabel": "Odbij",
"app.toast.chat.public": "Nova poruka u javnom chatu",
@ -376,6 +408,8 @@
"app.shortcut-help.closePrivateChat": "Zatvori privatni chat",
"app.shortcut-help.raiseHand": "Digni/spusti ruku",
"app.shortcut-help.openStatus": "Otvori izbornik sa statusima",
"app.shortcut-help.nextSlideKey": "Desna strelica",
"app.shortcut-help.previousSlideKey": "Lijeva strelica",
"app.lock-viewers.title": "Zaključaj gledatelje",
"app.lock-viewers.featuresLable": "Značajka",
"app.lock-viewers.lockStatusLabel": "Status",
@ -404,6 +438,9 @@
"app.connection-status.lostPackets": "Izgubljeni paketi",
"app.connection-status.usingTurn": "Korištenje TURN",
"app.connection-status.yes": "Da",
"app.connection-status.myLogs": "Moji zapisi",
"app.connection-status.next": "Sljedeća stranica",
"app.connection-status.prev": "Prethodna stranica",
"app.learning-dashboard.label": "Kontrolna ploča analitike učenja",
"app.learning-dashboard.description": "Otvori kontrolnu ploču s korisničkom aktivnošću",
"app.learning-dashboard.clickHereToOpen": "Otvori kontrolnu ploču analitike učenja",
@ -451,6 +488,7 @@
"app.video.virtualBackground.coffeeshop": "Kafić",
"app.video.virtualBackground.background": "Pozadina",
"app.meeting.endNotification.ok.label": "U redu",
"app.whiteboard.annotations.poll": "Rezultati ankete su objavljeni",
"app.whiteboard.annotations.pollResult": "Rezultati ankete",
"app.whiteboard.annotations.noResponses": "Bez odgovora",
"app.whiteboard.toolbar.tools": "Alati",
@ -470,8 +508,12 @@
"app.whiteboard.toolbar.color.blue": "Plava",
"app.whiteboard.toolbar.color.silver": "Srebrna",
"app.feedback.sendFeedback": "Pošalji povratnu informaciju",
"app.videoDock.webcamMirrorLabel": "Zrcaljenje",
"app.videoDock.webcamMirrorDesc": "Prikaži odabranu kameru zrcalno",
"app.videoDock.webcamFocusLabel": "Izoštravanje",
"app.videoDock.autoplayAllowLabel": "Prikaži web kamere",
"app.invitation.confirm": "Pozovi",
"app.createBreakoutRoom.title": "Breakout sobe",
"app.createBreakoutRoom.generatingURL": "Stvaranje URL",
"app.createBreakoutRoom.duration": "Trajanje {0}",
"app.createBreakoutRoom.room": "Soba {0}",
@ -482,16 +524,21 @@
"app.createBreakoutRoom.numberOfRooms": "Broj soba",
"app.createBreakoutRoom.durationInMinutes": "Trajanje (u minutama)",
"app.createBreakoutRoom.randomlyAssign": "Rasporedi slučajno",
"app.createBreakoutRoom.chatTitleMsgAllRooms": "sve sobe",
"app.createBreakoutRoom.doneLabel": "Gotovo",
"app.createBreakoutRoom.nextLabel": "Sljedeća",
"app.createBreakoutRoom.addParticipantLabel": "+ Dodaj sudionika",
"app.createBreakoutRoom.numberOfRoomsError": "Broj soba nije valjan.",
"app.createBreakoutRoom.setTimeLabel": "Primjeni",
"app.createBreakoutRoom.setTimeCancel": "Odustani",
"app.externalVideo.start": "Podijeli novi video",
"app.externalVideo.title": "Podijeli vanjski video",
"app.externalVideo.input": "URL vanjskog videa",
"app.externalVideo.urlInput": "Dodaj URL videa",
"app.externalVideo.urlError": "Video URL nije dozvoljen",
"app.externalVideo.close": "Zatvori",
"app.externalVideo.subtitlesOn": "Isključi",
"app.externalVideo.subtitlesOff": "Uključi (ako je moguće)",
"app.actionsBar.actionsDropdown.shareExternalVideo": "Podijeli vanjski video",
"app.actionsBar.actionsDropdown.stopShareExternalVideo": "Zaustavi dijeljenje vanjskog videa",
"app.iOSWarning.label": "Molimo nadogradite svoj operativni sustav na iOS 12.2 ili noviji",
@ -533,6 +580,7 @@
"playback.player.search.modal.title": "Pretraživanje",
"playback.player.webcams.wrapper.aria": "Područje s kamerama",
"app.learningDashboard.dashboardTitle": "Kontrolna ploča analitike učenja",
"app.learningDashboard.sessionDataDownloadedLabel": "Preuzeto!",
"app.learningDashboard.user": "Sudionik",
"app.learningDashboard.indicators.meetingStatusEnded": "Završeno",
"app.learningDashboard.indicators.meetingStatusActive": "Aktivno",
@ -541,6 +589,12 @@
"app.learningDashboard.indicators.polls": "Ankete",
"app.learningDashboard.indicators.activityScore": "Rezultat aktivnosti",
"app.learningDashboard.indicators.duration": "Trajanje",
"app.learningDashboard.userDetails.startTime": "Vrijeme početka",
"app.learningDashboard.userDetails.endTime": "Vrijeme završetka",
"app.learningDashboard.userDetails.average": "Prosječno",
"app.learningDashboard.userDetails.activityPoints": "Bodovi za aktivnosti",
"app.learningDashboard.userDetails.poll": "Anketa",
"app.learningDashboard.userDetails.response": "Odgovor",
"app.learningDashboard.usersTable.title": "Pregled",
"app.learningDashboard.usersTable.colOnline": "Vrijeme online",
"app.learningDashboard.usersTable.colTalk": "Trajanje govora",
@ -553,7 +607,23 @@
"app.learningDashboard.usersTable.userStatusOnline": "Online",
"app.learningDashboard.usersTable.userStatusOffline": "Offline",
"app.learningDashboard.usersTable.noUsers": "Još nema korisnika",
"app.learningDashboard.pollsTable.anonymousRowName": "Anonimno"
"app.learningDashboard.usersTable.name": "Ime",
"app.learningDashboard.usersTable.moderator": "Moderator",
"app.learningDashboard.usersTable.pollVotes": "Glasovi u anketi",
"app.learningDashboard.usersTable.join": "Priključio/la se sesiji",
"app.learningDashboard.usersTable.left": "Napustio/la sesiju",
"app.learningDashboard.usersTable.notAvailable": "nije dostupno",
"app.learningDashboard.pollsTable.title": "Ankete",
"app.learningDashboard.pollsTable.anonymousRowName": "Anonimno",
"app.learningDashboard.pollsTable.noPollsCreatedHeading": "Nije stvorena nijedna anketa",
"mobileApp.portals.list.add.button.label": "Dodaj portal",
"mobileApp.portals.fields.name.label": "Naziv portala",
"mobileApp.portals.fields.name.placeholder": "BigBlueButton demo",
"mobileApp.portals.fields.url.label": "URL poslužitelja",
"mobileApp.portals.addPortalPopup.confirm.button.label": "Pohrani",
"mobileApp.portals.drawerNavigation.button.label": "Portali",
"mobileApp.portals.addPortalPopup.validation.emptyFields": "Obavezna polja",
"mobileApp.portals.addPortalPopup.validation.portalNameAlreadyExists": "Naziv već u uporabi"
}

View File

@ -173,6 +173,7 @@
"app.presentation.options.fullscreen": "Teljes képernyő",
"app.presentation.options.exitFullscreen": "Teljes képernyő bezárása",
"app.presentation.options.minimize": "Kis méret",
"app.presentation.options.snapshot": "Pillanatkép az aktuális diáról",
"app.presentation.options.downloading": "Letöltés...",
"app.presentation.options.downloaded": "Az aktuális előadás letöltve",
"app.presentation.options.downloadFailed": "Az aktuális előadás nem tölthető le",
@ -193,9 +194,9 @@
"app.presentation.presentationToolbar.zoomDesc": "A prezentáció nagyítási szintjének módosítása",
"app.presentation.presentationToolbar.zoomInLabel": "Nagyítás",
"app.presentation.presentationToolbar.zoomInDesc": "A prezentációra nagyítás",
"app.presentation.presentationToolbar.zoomOutLabel": "Kicsinyítése",
"app.presentation.presentationToolbar.zoomOutLabel": "Kicsinyítés",
"app.presentation.presentationToolbar.zoomOutDesc": "A prezentációról kicsinyítés",
"app.presentation.presentationToolbar.zoomReset": "Nagyítás szint visszaállítása",
"app.presentation.presentationToolbar.zoomReset": "Nagyítási szint visszaállítása",
"app.presentation.presentationToolbar.zoomIndicator": "Jelenlegi nagyítás százaléka",
"app.presentation.presentationToolbar.fitToWidth": "A szélességhez illeszkedjen",
"app.presentation.presentationToolbar.fitToPage": "Az oldalhoz illeszkedjen",
@ -456,7 +457,7 @@
"app.actionsBar.actionsDropdown.takePresenterDesc": "Legyek én az új előadó",
"app.actionsBar.actionsDropdown.selectRandUserLabel": "Résztvevők közül véletlenszerű választás",
"app.actionsBar.actionsDropdown.selectRandUserDesc": "Elérhető résztvevők közül véletlenszerű választás",
"app.actionsBar.emojiMenu.statusTriggerLabel": "Hangulatod kifejezése",
"app.actionsBar.emojiMenu.statusTriggerLabel": "Hangulatom kifejezése",
"app.actionsBar.emojiMenu.awayLabel": "Nem vagyok a gépnél",
"app.actionsBar.emojiMenu.awayDesc": "Hangulatjeled 'Nem vagyok a gépnél'-re módosítod",
"app.actionsBar.emojiMenu.raiseHandLabel": "Jelentkezés",
@ -505,6 +506,8 @@
"app.breakoutJoinConfirmation.freeJoinMessage": "Csoportterem választása",
"app.breakoutTimeRemainingMessage": "Csoport hátralévő ideje: {0}",
"app.breakoutWillCloseMessage": "Az idő lejárt. A csoportterem hamarosan bezárul",
"app.breakout.dropdown.manageDuration": "Időtartam módosítása",
"app.breakout.dropdown.destroyAll": "Csoporttermek bezárása",
"app.breakout.dropdown.options": "Csoporttermek beállításai",
"app.calculatingBreakoutTimeRemaining": "Hátralévő idő számítása ...",
"app.audioModal.ariaTitle": "Csatlakozás hangablak",
@ -600,6 +603,7 @@
"app.error.500": "Sajnáljuk, hiba történt",
"app.error.userLoggedOut": "A felhasználónak érvénytelen munkamenet-tokenje van kijelentkezés miatt",
"app.error.ejectedUser": "A felhasználónak érvénytelen munkamenet-tokenje van kizárás miatt",
"app.error.joinedAnotherWindow": "Úgy tűnik, hogy ez a munkamenet nyitva van egy másik böngészőben.",
"app.error.userBanned": "A résztvevőt kitiltották",
"app.error.leaveLabel": "Bejelentkezés újra",
"app.error.fallback.presentation.title": "Hiba lépett fel",
@ -646,11 +650,11 @@
"app.toast.chat.private": "Új privát üzenet",
"app.toast.chat.system": "Rendszer",
"app.toast.clearedEmoji.label": "Hangulatjel-állapot törölve",
"app.toast.setEmoji.label": "Hangulatod új állapota {0}",
"app.toast.setEmoji.label": "Emoji állapota {0}",
"app.toast.meetingMuteOn.label": "Az összes résztvevőt elnémítottad",
"app.toast.meetingMuteOff.label": "A megbeszélés némaságát kikapcsoltad",
"app.toast.setEmoji.raiseHand": "Felemelted a kezed",
"app.toast.setEmoji.lowerHand": "Kezedet letették",
"app.toast.setEmoji.raiseHand": "Jelentkezel",
"app.toast.setEmoji.lowerHand": "Már nem jelentkezel",
"app.toast.promotedLabel": "Moderátorrá léptettek elő",
"app.toast.demotedLabel": "Résztvevővé fokoztak le",
"app.notification.recordingStart": "Ezt a munkamenetet rögzítjük",

View File

@ -173,6 +173,7 @@
"app.presentation.options.fullscreen": "全画面表示",
"app.presentation.options.exitFullscreen": "全画面表示解除",
"app.presentation.options.minimize": "最小化",
"app.presentation.options.snapshot": "現在のスライドのスナップショット",
"app.presentation.options.downloading": "ダウンロード中...",
"app.presentation.options.downloaded": "プレゼンファイルをダウンロードしました",
"app.presentation.options.downloadFailed": "プレゼンファイルがダウンロードできませんでした",

View File

@ -173,6 +173,7 @@
"app.presentation.options.fullscreen": "Tela cheia",
"app.presentation.options.exitFullscreen": "Sair de tela cheia",
"app.presentation.options.minimize": "Minimizar",
"app.presentation.options.snapshot": "Salvar imagem do slide atual",
"app.presentation.options.downloading": "Downloading...",
"app.presentation.options.downloaded": "Donwload da apresentação atual encerrado",
"app.presentation.options.downloadFailed": "Não foi possível fazer o download da apresentação atual",

View File

@ -1043,7 +1043,9 @@
"app.learningDashboard.errors.dataUnavailable": "Данные больше не доступны",
"mobileApp.portals.fields.url.label": "URL сервера",
"mobileApp.portals.addPortalPopup.confirm.button.label": "Сохранить",
"mobileApp.portals.addPortalPopup.validation.portalNameAlreadyExists": "Имя уже используется"
"mobileApp.portals.addPortalPopup.validation.emptyFields": "Поля, обязательные для заполнения",
"mobileApp.portals.addPortalPopup.validation.portalNameAlreadyExists": "Имя уже используется",
"mobileApp.portals.addPortalPopup.validation.urlInvalid": "Ошибка при загрузке страницы. Проверьте URL и Интернет соединение."
}

View File

@ -173,6 +173,7 @@
"app.presentation.options.fullscreen": "Tam ekrana geç",
"app.presentation.options.exitFullscreen": "Tam ekrandan çık",
"app.presentation.options.minimize": "Küçült",
"app.presentation.options.snapshot": "Geçerli slaytın ekran görüntüsü",
"app.presentation.options.downloading": "İndiriliyor...",
"app.presentation.options.downloaded": "Geçerli sunum indirildi",
"app.presentation.options.downloadFailed": "Geçerli sunum indirilemedi",

View File

@ -173,6 +173,7 @@
"app.presentation.options.fullscreen": "全螢幕",
"app.presentation.options.exitFullscreen": "離開全螢幕",
"app.presentation.options.minimize": "最小化",
"app.presentation.options.snapshot": "現有簡報的擷圖",
"app.presentation.options.downloading": "下載中...",
"app.presentation.options.downloaded": "目前的簡報已下載",
"app.presentation.options.downloadFailed": "無法下載目前的簡報",
@ -505,6 +506,8 @@
"app.breakoutJoinConfirmation.freeJoinMessage": "選擇並加入分組會議室",
"app.breakoutTimeRemainingMessage": "分組會議室時間剩餘: {0}",
"app.breakoutWillCloseMessage": "時間結束,分組會議室將很快關閉。",
"app.breakout.dropdown.manageDuration": "改變期間",
"app.breakout.dropdown.destroyAll": "結束分組討論室",
"app.breakout.dropdown.options": "分組選項",
"app.calculatingBreakoutTimeRemaining": "計算剩餘時間",
"app.audioModal.ariaTitle": "加入音訊模式",
@ -561,6 +564,7 @@
"app.audio.audioSettings.descriptionLabel": "請注意,瀏覽器彈出對話框,您必需允許分享您的麥克風。",
"app.audio.audioSettings.microphoneSourceLabel": "麥克風來源",
"app.audio.audioSettings.speakerSourceLabel": "揚聲器來源",
"app.audio.audioSettings.testSpeakerLabel": "測試您的喇叭",
"app.audio.audioSettings.microphoneStreamLabel": "您的串流音量",
"app.audio.audioSettings.retryLabel": "重試",
"app.audio.listenOnly.backLabel": "返回",
@ -599,6 +603,7 @@
"app.error.500": "哎呀,出錯了",
"app.error.userLoggedOut": "由於登出,用戶的 sessionToken 無效",
"app.error.ejectedUser": "由於跳出,用戶的 sessionToken 無效",
"app.error.joinedAnotherWindow": "此會議似乎已在另一個瀏覽器視窗打開",
"app.error.userBanned": "用戶已被禁止",
"app.error.leaveLabel": "再次登入",
"app.error.fallback.presentation.title": "發生一個錯誤",
@ -679,6 +684,10 @@
"app.shortcut-help.toggleFullscreen": "切換全螢幕(簡報者)",
"app.shortcut-help.nextSlideDesc": "下一張投影片(簡報者)",
"app.shortcut-help.previousSlideDesc": "上一張投影片(簡報者)",
"app.shortcut-help.togglePanKey": "空格鍵",
"app.shortcut-help.toggleFullscreenKey": "輸入",
"app.shortcut-help.nextSlideKey": "向右鍵",
"app.shortcut-help.previousSlideKey": "向左鍵",
"app.lock-viewers.title": "鎖定與會者",
"app.lock-viewers.description": "這些選項讓您禁止與會者使用特定功能。",
"app.lock-viewers.featuresLable": "功能",
@ -922,6 +931,8 @@
"app.externalVideo.refreshLabel": "重載影片播放器",
"app.externalVideo.fullscreenLabel": "影片播放器",
"app.externalVideo.noteLabel": "注意分享的外部影片不會出現在錄影檔案中。支援YouTube、Vimeo、Instructure Media、Twitch、Dailymotion及媒體檔案網址( 例如: https://example.com/xy.mp4 ) 。",
"app.externalVideo.subtitlesOn": "關掉",
"app.externalVideo.subtitlesOff": "打開(如果可行)",
"app.actionsBar.actionsDropdown.shareExternalVideo": "分享一個外部影片",
"app.actionsBar.actionsDropdown.stopShareExternalVideo": "停止分享外部影片。",
"app.iOSWarning.label": "請升級 iOS 12.2 或更高",
@ -1035,10 +1046,17 @@
"app.learningDashboard.statusTimelineTable.thumbnail": "簡報縮圖",
"app.learningDashboard.errors.invalidToken": "無效的連線識別碼",
"app.learningDashboard.errors.dataUnavailable": "資料不再能用",
"mobileApp.portals.list.empty.addFirstPortal.label": "使用上述按鍵新增您的首頁",
"mobileApp.portals.list.empty.orUseOurDemoServer.label": "或使用我們的展示伺服器",
"mobileApp.portals.list.add.button.label": "新增首頁",
"mobileApp.portals.fields.name.label": "門戶名稱",
"mobileApp.portals.fields.name.placeholder": "BigBlueButton demo",
"mobileApp.portals.fields.url.label": "伺服器URL",
"mobileApp.portals.drawerNavigation.button.label": "門戶"
"mobileApp.portals.addPortalPopup.confirm.button.label": "儲存",
"mobileApp.portals.drawerNavigation.button.label": "門戶",
"mobileApp.portals.addPortalPopup.validation.emptyFields": "必需的欄位",
"mobileApp.portals.addPortalPopup.validation.portalNameAlreadyExists": "名稱已被使用",
"mobileApp.portals.addPortalPopup.validation.urlInvalid": "上傳頁面錯誤 - 請檢查URL以及網路連結"
}

View File

@ -2,12 +2,14 @@ const { test } = require('@playwright/test');
const { Audio } = require('./audio');
test.describe.parallel('Audio', () => {
// https://docs.bigbluebutton.org/2.5/release-tests.html#listen-only-mode-automated
test('Join audio with Listen Only @ci', async ({ browser, page }) => {
const audio = new Audio(browser, page);
await audio.init(true, false);
await audio.joinAudio();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#join-audio-automated
test('Join audio with Microphone @ci', async ({ browser, page }) => {
const audio = new Audio(browser, page);
await audio.init(true, false);

View File

@ -9,6 +9,7 @@ test.describe.parallel('Breakout', () => {
await create.create();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#moderators-creating-breakout-rooms-and-assiging-users-automated
test('Join Breakout room @ci', async ({ browser, context, page }) => {
const join = new Join(browser, context);
await join.initPages(page);

View File

@ -3,12 +3,14 @@ const { Chat } = require('./chat');
const { PrivateChat } = require('./privateChat');
test.describe.parallel('Chat', () => {
// https://docs.bigbluebutton.org/2.5/release-tests.html#public-message-automated
test('Send public message @ci', async ({ browser, page }) => {
const chat = new Chat(browser, page);
await chat.init(true, true);
await chat.sendPublicMessage();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#private-message-automated
test('Send private message @ci', async ({ browser, context, page }) => {
const privateChat = new PrivateChat(browser, context);
await privateChat.initPages(page);
@ -34,12 +36,14 @@ test.describe.parallel('Chat', () => {
await chat.saveChat(testInfo);
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#chat-character-limit-automated
test('Verify character limit', async ({ browser, page }) => {
const chat = new Chat(browser, page);
await chat.init(true, true);
await chat.characterLimit();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#sending-empty-chat-message-automated
test('Not able to send an empty message', async ({ browser, page }) => {
const chat = new Chat(browser, page);
await chat.init(true, true);

View File

@ -3,7 +3,7 @@ const { MultiUsers } = require('../user/multiusers');
const e = require('../core/elements');
const { ELEMENT_WAIT_TIME } = require('../core/constants');
const { openConnectionStatus, checkNetworkStatus } = require('./util');
const { sleep } = require('../core/helpers');
class ConnectionStatus extends MultiUsers {
constructor(browser, context) {
@ -38,6 +38,24 @@ class ConnectionStatus extends MultiUsers {
const status = this.modPage.getLocator(e.connectionStatusItemUser);
await expect(status).toHaveCount(1);
}
async linkToSettingsTest() {
await openConnectionStatus(this.modPage);
await this.modPage.page.evaluate(() => window.dispatchEvent(new CustomEvent('socketstats', { detail: { rtt: 2000 } })));
await this.modPage.hasElement(e.connectionStatusLinkToSettings);
await this.modPage.waitAndClick(e.connectionStatusLinkToSettings);
await this.modPage.waitForSelector(e.dataSavingsTab);
}
async copyStatsTest(context) {
await openConnectionStatus(this.modPage);
await this.modPage.hasElementEnabled(e.copyStats);
await this.modPage.waitAndClick(e.copyStats);
await context.grantPermissions(['clipboard-write', 'clipboard-read'], { origin: process.env.BBB_URL });
const copiedText = await this.modPage.page.evaluate(async () => navigator.clipboard.readText());
const check = copiedText.includes("audioCurrentUploadRate");
await expect(check).toBeTruthy();
}
}
exports.ConnectionStatus = ConnectionStatus;

View File

@ -19,4 +19,17 @@ test.describe.parallel('Connection Status', () => {
await connectionStatus.initModPage(page);
await connectionStatus.reportUserInConnectionIssues();
});
test('Go to settings modal', async ({ browser, context, page }) => {
const connectionStatus = new ConnectionStatus(browser, context);
await connectionStatus.initModPage(page);
await connectionStatus.linkToSettingsTest();
});
test('Copy stats', async ({ browser, context, page }, testInfo) => {
test.fixme(testInfo.project.use.headless, 'Only works in headed mode');
const connectionStatus = new ConnectionStatus(browser, context);
await connectionStatus.initModPage(page);
await connectionStatus.copyStatsTest(context);
});
});

View File

@ -151,6 +151,7 @@ exports.pollYesNoAbstentionBtn = 'button[data-test="pollYesNoAbstentionBtn"]';
// Presentation
exports.uploadPresentationFileName = 'uploadTest.png';
exports.presentationPlaceholderLabel = 'There is no currently active presentation';
exports.noPresentationLabel = 'There is no currently active presentation';
exports.startScreenSharing = 'button[data-test="startScreenShare"]';
exports.stopScreenSharing = 'button[data-test="stopScreenShare"]';
exports.managePresentations = 'li[data-test="managePresentations"]';
@ -175,6 +176,7 @@ exports.videoModalInput = 'input[id="video-modal-input"]';
exports.startShareVideoBtn = 'button[data-test="startNewVideo"]';
exports.videoPlayer = 'div[data-test="videoPlayer"]';
exports.presentationTitle = 'h1[data-test="presentationTitle"]';
exports.fitToWidthButton = 'button[data-test="fitToWidthButton"]';
// YouTube frame
exports.youtubeLink = 'https://www.youtube.com/watch?v=Hso8yLzkqj8&ab_channel=BigBlueButton';
// The title we match for here is the title of the test video specified by youtubeLink
@ -189,9 +191,11 @@ exports.presentationUploadedToast = 'Current presentation';
exports.languageSelector = 'select[id="langSelector"]';
exports.messageTitle = 'h2[data-test="messageTitle"]';
exports.notesTitle = 'h2[data-test="notesTitle"]';
exports.dataSavingsTab = 'span[id="dataSaving"]';
// User
const userAvatar = 'div[data-test="userAvatar"]';
const networkDataContainer = 'div[data-test="networkDataContainer"]';
exports.userAvatar = userAvatar;
exports.moderatorAvatar = 'div[data-test="moderatorAvatar"]';
exports.viewerAvatar = 'div[data-test="viewerAvatar"]';
@ -209,14 +213,16 @@ exports.userListToggleBtn = 'button[data-test="toggleUserList"]';
exports.mobileUser = 'span[data-test="mobileUser"]';
exports.connectionStatusBtn = 'button[data-test="connectionStatusButton"]';
exports.connectionStatusModal = 'div[data-test="connectionStatusModal"]';
exports.copyStats = 'span[data-test="copyStats"]';
exports.dataSavingScreenshare = 'input[data-test="dataSavingScreenshare"]';
exports.screenshareLocked = 'button[data-test="screenshareLocked"]';
exports.connectionStatusItemEmpty = 'div[data-test="connectionStatusItemEmpty"]';
exports.connectionStatusTab2 = 'div[data-tab="2"]';
exports.connectionStatusItemUser = 'div[data-test="connectionStatusItemUser"]';
exports.connectionStatusLinkToSettings = `${networkDataContainer} span[role="button"]`;
exports.dataSavingWebcams = 'input[data-test="dataSavingWebcams"]';
exports.connectionStatusOfflineUser = 'div[data-test="offlineUser"]';
exports.connectionDataContainer = 'div[data-test="networkDataContainer"]';
exports.connectionDataContainer = networkDataContainer;
exports.avatarsWrapperAvatar = 'div[data-test="avatarsWrapperAvatar"]';
exports.guestPolicyLabel = 'li[data-test="guestPolicyLabel"]';
exports.downloadUserNamesList = 'li[data-test="downloadUserNamesList"]';

View File

@ -16,9 +16,9 @@ async function createMeeting(params, customParameter) {
const meetingID = `random-${getRandomInt(1000000, 10000000).toString()}`;
const mp = params.moderatorPW;
const ap = params.attendeePW;
const query = customParameter !== undefined ? `name=${meetingID}&meetingID=${meetingID}&attendeePW=${ap}&moderatorPW=${mp}&joinViaHtml5=true`
const query = customParameter !== undefined ? `name=${meetingID}&meetingID=${meetingID}&attendeePW=${ap}&moderatorPW=${mp}`
+ `&allowStartStopRecording=true&${customParameter}&autoStartRecording=false&welcome=${params.welcome}`
: `name=${meetingID}&meetingID=${meetingID}&attendeePW=${ap}&moderatorPW=${mp}&joinViaHtml5=true`
: `name=${meetingID}&meetingID=${meetingID}&attendeePW=${ap}&moderatorPW=${mp}`
+ `&allowStartStopRecording=true&autoStartRecording=false&welcome=${params.welcome}`;
const apicall = `create${query}${params.secret}`;
const checksum = sha1(apicall);
@ -29,8 +29,8 @@ async function createMeeting(params, customParameter) {
function getJoinURL(meetingID, params, moderator, customParameter) {
const pw = moderator ? params.moderatorPW : params.attendeePW;
const query = customParameter !== undefined ? `fullName=${params.fullName}&joinViaHtml5=true&meetingID=${meetingID}&password=${pw}&${customParameter}`
: `fullName=${params.fullName}&joinViaHtml5=true&meetingID=${meetingID}&password=${pw}`;
const query = customParameter !== undefined ? `fullName=${params.fullName}&meetingID=${meetingID}&password=${pw}&${customParameter}`
: `fullName=${params.fullName}&meetingID=${meetingID}&password=${pw}`;
const apicall = `join${query}${params.secret}`;
const checksum = sha1(apicall);
return `${params.server}/join?${query}&checksum=${checksum}`;

View File

@ -165,7 +165,7 @@ class Page {
}
async hasElementEnabled(selector, timeout = ELEMENT_WAIT_TIME) {
const locator = this.getLocator(selector);
const locator = this.getLocator(`${selector}:not([disabled])`);
await expect(locator).toBeEnabled({ timeout });
}

View File

@ -20,7 +20,7 @@ class PresenterNotifications extends MultiUsers {
async fileUploaderNotification() {
await util.waitAndClearDefaultPresentationNotification(this.modPage);
await utilPresentation.uploadPresentation(this.modPage, e.pdfFileName, UPLOAD_PDF_WAIT_TIME);
await utilPresentation.uploadSinglePresentation(this.modPage, e.pdfFileName, UPLOAD_PDF_WAIT_TIME);
await util.checkNotificationText(this.userPage, e.presentationUploadedToast);
}

View File

@ -29,7 +29,7 @@ class Polling extends MultiUsers {
async quickPoll() {
await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME);
await utilPresentation.uploadPresentation(this.modPage, e.questionSlideFileName);
await utilPresentation.uploadSinglePresentation(this.modPage, e.questionSlideFileName);
await this.modPage.waitAndClick(e.quickPoll);
await this.modPage.waitForSelector(e.pollMenuButton);
@ -87,7 +87,7 @@ class Polling extends MultiUsers {
await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME);
await util.startPoll(this.modPage);
await utilPresentation.uploadPresentation(this.modPage, e.questionSlideFileName);
await utilPresentation.uploadSinglePresentation(this.modPage, e.questionSlideFileName);
await this.modPage.waitAndClick(e.publishPollingLabel);
// Check poll results

View File

@ -9,12 +9,14 @@ test.describe.parallel('Polling', () => {
await polling.createPoll();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#start-an-anonymous-poll-automated
test('Create anonymous poll @ci', async ({ browser, context, page }) => {
const polling = new Polling(browser, context);
await polling.initPages(page);
await polling.pollAnonymous();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#quick-poll-option-automated
test('Create quick poll - from the slide', async ({ browser, context, page }) => {
const polling = new Polling(browser, context);
await polling.initPages(page);

View File

@ -2,7 +2,7 @@ const { expect, default: test } = require('@playwright/test');
const { MultiUsers } = require('../user/multiusers');
const Page = require('../core/page');
const e = require('../core/elements');
const { checkSvgIndex, getSvgOuterHtml, uploadPresentation } = require('./util.js');
const { checkSvgIndex, getSvgOuterHtml, uploadSinglePresentation, uploadMultiplePresentations } = require('./util.js');
const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants');
const { sleep } = require('../core/helpers');
const { getSettings } = require('../core/settings');
@ -62,7 +62,7 @@ class Presentation extends MultiUsers {
await userFrame.hasElement('video');
}
async uploadPresentationTest() {
async uploadSinglePresentationTest() {
await waitAndClearDefaultPresentationNotification(this.modPage);
await this.modPage.waitForSelector(e.skipSlide);
@ -70,7 +70,7 @@ class Presentation extends MultiUsers {
const userSlides0 = await this.userPage.page.evaluate(getSvgOuterHtml);
await expect(modSlides0).toEqual(userSlides0);
await uploadPresentation(this.modPage, e.uploadPresentationFileName);
await uploadSinglePresentation(this.modPage, e.uploadPresentationFileName);
const modSlides1 = await this.userPage.page.evaluate(async () => document.querySelector('svg g g g').outerHTML);
const userSlides1 = await this.modPage.page.evaluate(async () => document.querySelector('svg g g g').outerHTML);
@ -80,6 +80,35 @@ class Presentation extends MultiUsers {
await expect(userSlides0).not.toEqual(userSlides1);
}
async uploadMultiplePresentationsTest() {
await waitAndClearDefaultPresentationNotification(this.modPage);
await this.modPage.waitForSelector(e.skipSlide);
const modSlides0 = await this.modPage.page.evaluate(getSvgOuterHtml);
const userSlides0 = await this.userPage.page.evaluate(getSvgOuterHtml);
await expect(modSlides0).toEqual(userSlides0);
await uploadMultiplePresentations(this.modPage, [e.uploadPresentationFileName, e.questionSlideFileName]);
const modSlides1 = await this.userPage.page.evaluate(async () => document.querySelector('svg g g g').outerHTML);
const userSlides1 = await this.modPage.page.evaluate(async () => document.querySelector('svg g g g').outerHTML);
await expect(modSlides1).toEqual(userSlides1);
await expect(modSlides0).not.toEqual(modSlides1);
await expect(userSlides0).not.toEqual(userSlides1);
}
async fitToWidthTest() {
await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME);
await this.modPage.waitForSelector(e.skipSlide);
await this.modPage.waitAndClick(e.userListToggleBtn);
await uploadSinglePresentation(this.modPage, e.uploadPresentationFileName);
const width1 = await this.modPage.page.locator(e.whiteboard).getAttribute("width");
await this.modPage.waitAndClick(e.fitToWidthButton);
const width2 = await this.modPage.page.locator(e.whiteboard).getAttribute("width");
await expect(Number(width2) > Number(width1)).toBeTruthy();
}
async allowAndDisallowDownload(testInfo) {
const { presentationDownloadable } = getSettings();
test.fail(!presentationDownloadable, 'Presentation download is disable');

View File

@ -20,13 +20,28 @@ test.describe.parallel('Presentation', () => {
await presentation.startExternalVideo();
});
test('Presentation fit to width', async ({ browser, context, page }) => {
const presentation = new Presentation(browser, context);
await presentation.initPages(page);
await presentation.fitToWidthTest();
});
test.describe.parallel('Manage', () => {
test('Upload presentation @ci', async ({ browser, context, page }) => {
// https://docs.bigbluebutton.org/2.5/release-tests.html#uploading-a-presentation-automated
test('Upload single presentation @ci', async ({ browser, context, page }) => {
const presentation = new Presentation(browser, context);
await presentation.initPages(page);
await presentation.uploadPresentationTest();
await presentation.uploadSinglePresentationTest();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#uploading-multiple-presentations-automated
test('Upload multiple presentations', async ({ browser, context, page }) => {
const presentation = new Presentation(browser, context);
await presentation.initPages(page);
await presentation.uploadMultiplePresentationsTest();
});
// https://docs.bigbluebutton.org/2.5/release-tests.html#enabling-and-disabling-presentation-download-automated
test('Allow and disallow presentation download @ci', async ({ browser, context, page }, testInfo) => {
const presentation = new Presentation(browser, context);
await presentation.initPages(page);

View File

@ -14,7 +14,7 @@ function getSvgOuterHtml() {
return document.querySelector('svg g g g').outerHTML;
}
async function uploadPresentation(test, fileName, uploadTimeout = ELEMENT_WAIT_LONGER_TIME) {
async function uploadSinglePresentation(test, fileName, uploadTimeout = ELEMENT_WAIT_LONGER_TIME) {
await test.waitAndClick(e.actions);
await test.waitAndClick(e.managePresentations);
await test.waitForSelector(e.fileUpload);
@ -27,6 +27,20 @@ async function uploadPresentation(test, fileName, uploadTimeout = ELEMENT_WAIT_L
await test.hasText(e.smallToastMsg, e.presentationUploadedToast, uploadTimeout);
}
async function uploadMultiplePresentations(test, fileNames, uploadTimeout = ELEMENT_WAIT_LONGER_TIME) {
await test.waitAndClick(e.actions);
await test.waitAndClick(e.managePresentations);
await test.waitForSelector(e.fileUpload);
await test.page.setInputFiles(e.fileUpload, fileNames.map(function(fileName) { return path.join(__dirname, `../core/media/${fileName}`); }));
await test.hasText('body', e.statingUploadPresentationToast);
await test.waitAndClick(e.confirmManagePresentation);
await test.hasText(e.presentationStatusInfo, [e.convertingPresentationFileToast], uploadTimeout);
await test.hasText(e.smallToastMsg, e.presentationUploadedToast, uploadTimeout);
}
exports.checkSvgIndex = checkSvgIndex;
exports.getSvgOuterHtml = getSvgOuterHtml;
exports.uploadPresentation = uploadPresentation;
exports.uploadSinglePresentation = uploadSinglePresentation;
exports.uploadMultiplePresentations = uploadMultiplePresentations;

View File

@ -9,6 +9,7 @@ const iPhone11 = devices['iPhone 11'];
test.describe.parallel('User', () => {
test.describe.parallel('Actions', () => {
// https://docs.bigbluebutton.org/2.5/release-tests.html#set-status--raise-hand-automated
test('Raise and lower Hand Toast', async ({ browser, context, page }) => {
const multiusers = new MultiUsers(browser, context);
await multiusers.initPages(page);
@ -23,6 +24,7 @@ test.describe.parallel('User', () => {
});
test.describe.parallel('List', () => {
// https://docs.bigbluebutton.org/2.5/release-tests.html#set-status--raise-hand-automated
test('Change user status @ci', async ({ browser, page }) => {
const status = new Status(browser, page);
await status.init(true, true);

View File

@ -2,6 +2,7 @@ const { test } = require('@playwright/test');
const { Webcam } = require('./webcam');
test.describe.parallel('Webcam @ci', () => {
// https://docs.bigbluebutton.org/2.5/release-tests.html#joining-webcam-automated
test('Shares webcam', async ({ browser, page }) => {
const webcam = new Webcam(browser, page);
await webcam.init(true, true);

View File

@ -37,6 +37,6 @@ gem 'bbbevents', '~> 1.2'
gem 'rake', '>= 12.3', '<14'
group :test, optional: true do
gem 'rubocop', '~> 0.79.0'
gem 'rubocop', '~> 1.31.1'
gem 'minitest', '~> 5.14.1'
end

View File

@ -17,11 +17,11 @@ GEM
ffi (1.15.5)
i18n (1.10.0)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.4)
java_properties (0.0.4)
journald-logger (3.1.0)
journald-native (~> 1.0)
journald-native (1.0.12)
json (2.6.2)
jwt (2.3.0)
locale (2.1.3)
loofah (2.18.0)
@ -52,19 +52,26 @@ GEM
redis (4.6.0)
redis-namespace (1.8.2)
redis (>= 3.0.4)
regexp_parser (2.5.0)
resque (2.0.0)
mono_logger (~> 1.0)
multi_json (~> 1.0)
redis-namespace (~> 1.6)
sinatra (>= 0.9.2)
vegas (~> 0.1.2)
rubocop (0.79.0)
jaro_winkler (~> 1.5.1)
rexml (3.2.5)
rubocop (1.31.1)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 2.7.0.1)
parser (>= 3.1.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.18.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.18.0)
parser (>= 3.1.1.0)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
@ -77,7 +84,7 @@ GEM
tilt (2.0.10)
tzinfo (1.2.9)
thread_safe (~> 0.1)
unicode-display_width (1.6.1)
unicode-display_width (2.2.0)
vegas (0.1.11)
rack (>= 1.0.0)
@ -102,7 +109,7 @@ DEPENDENCIES
rb-inotify (~> 0.10)
redis (~> 4.1)
resque (~> 2.0.0)
rubocop (~> 0.79.0)
rubocop (~> 1.31.1)
rubyzip (~> 2.0)
BUNDLED WITH