diff --git a/react/src/Components/Footer/Components/RoomCreationPasswordDialog.js b/react/src/Components/Footer/Components/RoomCreationPasswordDialog.js
index 35d48d6dc..ff2857f74 100644
--- a/react/src/Components/Footer/Components/RoomCreationPasswordDialog.js
+++ b/react/src/Components/Footer/Components/RoomCreationPasswordDialog.js
@@ -65,6 +65,7 @@ export function RoomCreationPasswordDialog(props) {
placeholder="Enter room name"
/> */}
{
+
+ beforeEach(() => {
+ // Reset the mock implementation before each test
+ jest.clearAllMocks();
+ });
+
+
+ it('renders without crashing', () => {
+ render(
+
+ );
+ });
+
+});
diff --git a/react/src/__tests__/Components/DrawerButton.test.js b/react/src/__tests__/Components/DrawerButton.test.js
new file mode 100644
index 000000000..733f54b72
--- /dev/null
+++ b/react/src/__tests__/Components/DrawerButton.test.js
@@ -0,0 +1,32 @@
+// src/DrawerButton.test.js
+import React from 'react';
+import { render } from '@testing-library/react';
+import EffectsDrawer from "../../Components/EffectsDrawer";
+import BecomePublisherConfirmationDialog from "../../Components/BecomePublisherConfirmationDialog";
+import DrawerButton from "../../Components/DrawerButton";
+
+// Mock the props
+const props = {
+ handleMessageDrawerOpen: jest.fn(),
+ handleParticipantListOpen: jest.fn(),
+ handleEffectsOpen: jest.fn(),
+ setPublisherRequestListDrawerOpen: jest.fn(),
+}
+
+describe('Drawer Button Component', () => {
+
+ beforeEach(() => {
+ // Reset the mock implementation before each test
+ jest.clearAllMocks();
+ });
+
+
+ it('renders without crashing', () => {
+ render(
+
+ );
+ });
+
+});
diff --git a/react/src/__tests__/Components/Footer/Components/EffectsDrawer.test.js b/react/src/__tests__/Components/EffectsDrawer.test.js
similarity index 90%
rename from react/src/__tests__/Components/Footer/Components/EffectsDrawer.test.js
rename to react/src/__tests__/Components/EffectsDrawer.test.js
index 98c11319f..cfdcbbc62 100644
--- a/react/src/__tests__/Components/Footer/Components/EffectsDrawer.test.js
+++ b/react/src/__tests__/Components/EffectsDrawer.test.js
@@ -1,7 +1,7 @@
// src/EffectsDrawer.test.js
import React from 'react';
import { render } from '@testing-library/react';
-import EffectsDrawer from "../../../../Components/EffectsDrawer";
+import EffectsDrawer from "../../Components/EffectsDrawer";
// Mock the props
const props = {
@@ -28,7 +28,7 @@ jest.mock('react', () => ({
...jest.requireActual('react'),
}));
-describe('Camera Button Component', () => {
+describe('Effects Drawer Component', () => {
beforeEach(() => {
// Reset the mock implementation before each test
diff --git a/react/src/__tests__/Components/MessageDrawer.test.js b/react/src/__tests__/Components/MessageDrawer.test.js
new file mode 100644
index 000000000..e548c6ade
--- /dev/null
+++ b/react/src/__tests__/Components/MessageDrawer.test.js
@@ -0,0 +1,35 @@
+// src/MessageDrawer.test.js
+import React from 'react';
+import { render } from '@testing-library/react';
+import EffectsDrawer from "../../Components/EffectsDrawer";
+import BecomePublisherConfirmationDialog from "../../Components/BecomePublisherConfirmationDialog";
+import MessageDrawer from "../../Components/MessageDrawer";
+
+// Mock the props
+const props = {
+ handleMessageDrawerOpen: jest.fn(),
+ handleParticipantListOpen: jest.fn(),
+ handleEffectsOpen: jest.fn(),
+ setPublisherRequestListDrawerOpen: jest.fn(),
+ messages: [],
+ sendMessage: jest.fn(),
+ handleSetMessages: jest.fn(),
+}
+
+describe('Message Drawer Component', () => {
+
+ beforeEach(() => {
+ // Reset the mock implementation before each test
+ jest.clearAllMocks();
+ });
+
+
+ it('renders without crashing', () => {
+ render(
+
+ );
+ });
+
+});
diff --git a/test/test_join_leave.py b/test/test_join_leave.py
index 1cd554f33..babf489b3 100644
--- a/test/test_join_leave.py
+++ b/test/test_join_leave.py
@@ -1,6 +1,8 @@
from browser import Browser
from selenium.webdriver.common.by import By
from rest_helper import RestHelper
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
import subprocess
@@ -113,6 +115,16 @@ def join_room_in_new_tab(self, participant, room, play_only=False):
assert(meeting_gallery.is_displayed())
return handle
+
+ def open_home_page_in_new_tab(self, participant):
+ print("url: "+self.url+"/"+self.test_app_name+"/")
+ app = "/"+self.test_app_name
+ if self.url.endswith("localhost:3000"):
+ app = ""
+
+ handle = self.chrome.open_in_new_tab(self.url + app + "/")
+
+ return handle
def get_videoTrackAssignments(self, expected_value=None):
script = "return window.conference;"
@@ -1860,6 +1872,71 @@ def test_theme(self):
self.chrome.close_all()
+ def test_create_meeting_with_password(self):
+ wait = WebDriverWait(self.chrome, 10)
+ roomPassword = "123123"
+
+ # create room without password
+ room = "room"+str(random.randint(100, 999))
+ handle_0 = self.open_home_page_in_new_tab("participantA")
+
+ create_meeting_element = wait.until(
+ EC.element_to_be_clickable((By.XPATH, "//Typography[text()='Create Meeting']"))
+ )
+
+ create_meeting_element.click()
+
+ time.sleep(1)
+
+ localVideo = self.chrome.get_element_with_retry(By.ID, 'localVideo')
+
+ assert(localVideo.is_displayed())
+
+ self.chrome.close_all()
+
+ # join room with password
+ self.rest_helper
+ time.sleep(10)
+ app_settings = self.rest_helper.call_get_app_settings(self.test_app_name)
+ app_settings["customSettings"] = {
+ "circle":{
+ "roomCreationPassword": roomPassword
+ }
+ }
+ response = self.rest_helper.call_set_app_settings(self.test_app_name, app_settings)
+ assert(response["success"])
+ time.sleep(10)
+
+ room = "room"+str(random.randint(100, 999))
+ handle_1 = self.open_home_page_in_new_tab("participantB")
+
+ create_meeting_element = wait.until(
+ EC.element_to_be_clickable((By.XPATH, "//Typography[text()='Create Meeting']"))
+ )
+
+ create_meeting_element.click()
+
+ time.sleep(1)
+
+ input_field = wait.until(
+ EC.presence_of_element_located((By.ID, "room_creation_password"))
+ )
+
+ input_field.send_keys(roomPassword)
+
+ create_room_button = wait.until(
+ EC.element_to_be_clickable((By.ID, "create_room_button"))
+ )
+
+ create_room_button.click()
+
+ time.sleep(1)
+
+ localVideo = self.chrome.get_element_with_retry(By.ID, 'localVideo')
+
+ assert(localVideo.is_displayed())
+
+ self.chrome.close_all()
def test_language(self):
room = "room"+str(random.randint(100, 999))
diff --git a/webapp/src/main/java/io/antmedia/enterprise/streamapp/AMSBroadcastManager.java b/webapp/src/main/java/io/antmedia/enterprise/streamapp/AMSBroadcastManager.java
index 03481d3f4..44a292682 100644
--- a/webapp/src/main/java/io/antmedia/enterprise/streamapp/AMSBroadcastManager.java
+++ b/webapp/src/main/java/io/antmedia/enterprise/streamapp/AMSBroadcastManager.java
@@ -1,11 +1,14 @@
package io.antmedia.enterprise.streamapp;
+import com.google.gson.Gson;
import io.antmedia.AntMediaApplicationAdapter;
+import io.antmedia.AppSettings;
import io.antmedia.datastore.db.DataStore;
import io.antmedia.datastore.db.DataStoreFactory;
import io.antmedia.datastore.db.IDataStoreFactory;
import io.antmedia.datastore.db.types.Broadcast;
import io.antmedia.datastore.db.types.BroadcastUpdate;
+import io.antmedia.muxer.IAntMediaStreamHandler;
import io.antmedia.rest.model.Result;
import io.antmedia.rest.RestServiceBase;
import org.jetbrains.annotations.NotNull;
@@ -21,14 +24,17 @@ public class AMSBroadcastManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
private AntMediaApplicationAdapter appAdaptor;
+ private ConferenceRoomSettings conferenceRoomSettings;
+ private AppSettings appSettings;
+ private Gson gson = new Gson();
@Override
public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
- }
- public ApplicationContext getApplicationContext() {
- return applicationContext;
+ IAntMediaStreamHandler app = getApplication();
+ appSettings = app.getAppSettings();
+ fetchConferenceRoomSettings();
}
public AntMediaApplicationAdapter getApplication() {
@@ -78,4 +84,39 @@ public boolean updateBroadcastRole(String streamId, String role) {
return result;
}
+
+ public void fetchConferenceRoomSettings() {
+ Object circleSettingsString = appSettings.getCustomSetting("circle");
+ if (circleSettingsString == null) {
+ logger.error("Using default settings for Conference Room Settings because no Circle settings in the AppSettings");
+
+ conferenceRoomSettings = new ConferenceRoomSettings();
+ }
+ else {
+ try {
+ conferenceRoomSettings = gson.fromJson(circleSettingsString.toString(), ConferenceRoomSettings.class);
+ }
+ catch (Exception e)
+ {
+ logger.error("Invalid Conference room settings, using default conference room settings");
+ conferenceRoomSettings = new ConferenceRoomSettings();
+ }
+ }
+ conferenceRoomSettings.init();
+
+ String participantVisibilityMatrix = appSettings.getParticipantVisibilityMatrix().toString();
+
+ if (participantVisibilityMatrix != null && conferenceRoomSettings.getParticipantVisibilityMatrix() == null) {
+ conferenceRoomSettings.setParticipantVisibilityMatrix(participantVisibilityMatrix);
+ }
+
+ int maxVideoTrackCount = appSettings.getMaxVideoTrackCount();
+
+ conferenceRoomSettings.setMaxVideoTrackCount(maxVideoTrackCount);
+ }
+
+ public ConferenceRoomSettings getConferenceRoomSettings() {
+ return conferenceRoomSettings;
+ }
+
}
diff --git a/webapp/src/main/java/io/antmedia/enterprise/streamapp/ConferenceRoomSettings.java b/webapp/src/main/java/io/antmedia/enterprise/streamapp/ConferenceRoomSettings.java
index e96bc5c42..1cfe0f4ed 100644
--- a/webapp/src/main/java/io/antmedia/enterprise/streamapp/ConferenceRoomSettings.java
+++ b/webapp/src/main/java/io/antmedia/enterprise/streamapp/ConferenceRoomSettings.java
@@ -1,41 +1,34 @@
package io.antmedia.enterprise.streamapp;
+import com.google.gson.annotations.Expose;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.PropertySource;
-
-import com.google.gson.annotations.Expose;
import jakarta.annotation.PostConstruct;
-@PropertySource("/WEB-INF/red5-web.properties")
+
public class ConferenceRoomSettings {
protected static Logger logger = LoggerFactory.getLogger(ConferenceRoomSettings.class);
-
- @Value("${roomCreationPassword:#{null}}")
private String roomCreationPassword;
- @Expose
+ @Expose
private boolean roomCreationPasswordEnabled = false;
-
- @Expose
+
+ @Expose
private boolean isRecordingFeatureAvailable = false;
- @Expose
- private String participantVisibilityMatrix;
+ @Expose
+ private String participantVisibilityMatrix;
@Expose
private int maxVideoTrackCount = 6;
@PostConstruct
public void init() {
- roomCreationPasswordEnabled = StringUtils.isNotBlank(roomCreationPassword);
- logger.info("roomCreationPasswordEnabled is {}", StringUtils.isNotBlank(roomCreationPassword));
try {
Class.forName("io.antmedia.plugin.IMediaPushPlugin");
@@ -46,6 +39,7 @@ public void init() {
isRecordingFeatureAvailable = false;
}
+ roomCreationPasswordEnabled = StringUtils.isNotBlank(roomCreationPassword);
}
diff --git a/webapp/src/main/java/io/antmedia/enterprise/streamapp/WebSocketApplicationHandler.java b/webapp/src/main/java/io/antmedia/enterprise/streamapp/WebSocketApplicationHandler.java
index 52647405f..6e5501825 100644
--- a/webapp/src/main/java/io/antmedia/enterprise/streamapp/WebSocketApplicationHandler.java
+++ b/webapp/src/main/java/io/antmedia/enterprise/streamapp/WebSocketApplicationHandler.java
@@ -122,9 +122,8 @@ private AMSBroadcastManager getAMSBroadcastManager() {
}
private void setConferenceRoomSettings(){
- if(context != null){
- conferenceRoomSettings = (ConferenceRoomSettings) context.getBean("conferenceRoomSettings");
- }
+ getAMSBroadcastManager().fetchConferenceRoomSettings();
+ conferenceRoomSettings = getAMSBroadcastManager().getConferenceRoomSettings();
}
private void setAppSettings() {
@@ -323,17 +322,6 @@ private Object getMediaPushPlugin() {
}
private void responseRoomSettings(Session session) {
-
- String participantVisibilityMatrix = appSettings.getParticipantVisibilityMatrix().toString();
-
- if (participantVisibilityMatrix != null) {
- conferenceRoomSettings.setParticipantVisibilityMatrix(participantVisibilityMatrix);
- }
-
- int maxVideoTrackCount = appSettings.getMaxVideoTrackCount();
-
- conferenceRoomSettings.setMaxVideoTrackCount(maxVideoTrackCount);
-
JSONObject jsonResponse = new JSONObject();
jsonResponse.put(WebSocketConstants.COMMAND, WebSocketApplicationConstants.SET_SETTINGS_COMMAND);
jsonResponse.put(WebSocketApplicationConstants.SETTINGS, gsonOnlyExposedFields.toJson(conferenceRoomSettings));