mirror of https://github.com/OpenVidu/openvidu.git
openvidu-test-e2e: custom layout recording test
parent
6a8670304f
commit
3056d21320
|
@ -220,7 +220,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService
|
||||||
containers.remove(containerId);
|
containers.remove(containerId);
|
||||||
sessionsContainers.remove(session.getSessionId());
|
sessionsContainers.remove(session.getSessionId());
|
||||||
}
|
}
|
||||||
log.error("Error while launchig container for COMPOSED_QUICK_START: ({})", e.getMessage());
|
log.error("Error while launching container for COMPOSED_QUICK_START: ({})", e.getMessage());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
return containerId;
|
return containerId;
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package io.openvidu.test.browsers.utils.layout;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class CustomLayoutHandler extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
private static ConfigurableApplicationContext context;
|
||||||
|
public static CountDownLatch initLatch;
|
||||||
|
|
||||||
|
public static void main(String[] args, CountDownLatch initLatch) {
|
||||||
|
CustomLayoutHandler.initLatch = initLatch;
|
||||||
|
CustomLayoutHandler.context = new SpringApplicationBuilder(CustomLayoutHandler.class)
|
||||||
|
.properties("spring.config.location:classpath:aplication-pro-layout-handler.properties").build()
|
||||||
|
.run(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity security) throws Exception {
|
||||||
|
security.httpBasic().disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener(ApplicationReadyEvent.class)
|
||||||
|
public void afterStartup() {
|
||||||
|
CustomLayoutHandler.initLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shutDown() {
|
||||||
|
CustomLayoutHandler.context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.openvidu.test.browsers.utils;
|
package io.openvidu.test.browsers.utils.webhook;
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -24,7 +24,6 @@ import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
@ -39,7 +38,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
public class CustomWebhook {
|
public class CustomWebhook {
|
||||||
|
|
||||||
private static ConfigurableApplicationContext context;
|
private static ConfigurableApplicationContext context;
|
|
@ -0,0 +1,3 @@
|
||||||
|
server.port=5555
|
||||||
|
server.ssl.enabled=false
|
||||||
|
security.basic.enabled=false
|
|
@ -0,0 +1,55 @@
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
const xmlHttp = new XMLHttpRequest();
|
||||||
|
xmlHttp.open('GET', 'https://api.github.com/repos/OpenVidu/openvidu/releases/latest', false);
|
||||||
|
xmlHttp.send(null);
|
||||||
|
const response = JSON.parse(xmlHttp.responseText);
|
||||||
|
const version = response.tag_name.replace(/^v/, '');
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
newScript.src = 'https://github.com/OpenVidu/openvidu/releases/download/v' + version +
|
||||||
|
'/openvidu-browser-' + version + '.min.js';
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(newScript);
|
||||||
|
newScript.onload = () => {
|
||||||
|
startOpenVidu();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
video {
|
||||||
|
height: 5px !important;
|
||||||
|
width: 10px !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style='background-color: red'>
|
||||||
|
<div id='videos'></div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function startOpenVidu() {
|
||||||
|
var url = new URL(window.location.href);
|
||||||
|
var SESSION_ID = url.searchParams.get('sessionId');
|
||||||
|
var SECRET = url.searchParams.get('secret');
|
||||||
|
var TOKEN = 'wss://' + location.hostname + ':4443?sessionId=' + SESSION_ID + '&secret=' + SECRET +
|
||||||
|
'&recorder=true';
|
||||||
|
|
||||||
|
var OV = new OpenVidu();
|
||||||
|
var session = OV.initSession();
|
||||||
|
|
||||||
|
session.on('streamCreated', (event) => {
|
||||||
|
session.subscribe(event.stream, 'videos');
|
||||||
|
});
|
||||||
|
session.connect(TOKEN)
|
||||||
|
.then(() => {
|
||||||
|
console.log('Recorder participant connected')
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
|
@ -6,6 +6,7 @@ node('container') {
|
||||||
sh 'rm -rf /opt/openvidu/* || true'
|
sh 'rm -rf /opt/openvidu/* || true'
|
||||||
sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu'
|
sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu'
|
||||||
sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu'
|
sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu'
|
||||||
|
sh 'wget --directory-prefix=/opt/openvidu/test-layouts/layout1 https://github.com/OpenVidu/openvidu/blob/master/openvidu-test-e2e/docker/my-custom-layout/index.html'
|
||||||
docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d ->
|
docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d ->
|
||||||
def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO')
|
def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO')
|
||||||
mycontainer.pull()
|
mycontainer.pull()
|
||||||
|
@ -93,10 +94,10 @@ node('container') {
|
||||||
sh(script: '''#!/bin/bash
|
sh(script: '''#!/bin/bash
|
||||||
if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then
|
if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then
|
||||||
echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION"
|
echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION"
|
||||||
java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log &
|
java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log &
|
||||||
else
|
else
|
||||||
echo "Using default openvidu-recording tag"
|
echo "Using default openvidu-recording tag"
|
||||||
java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log &
|
java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log &
|
||||||
fi
|
fi
|
||||||
'''.stripIndent())
|
'''.stripIndent())
|
||||||
sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done'
|
sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done'
|
||||||
|
|
|
@ -42,6 +42,7 @@ import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
@ -103,9 +104,10 @@ import io.openvidu.test.browsers.FirefoxUser;
|
||||||
import io.openvidu.test.browsers.OperaUser;
|
import io.openvidu.test.browsers.OperaUser;
|
||||||
import io.openvidu.test.browsers.utils.CommandLineExecutor;
|
import io.openvidu.test.browsers.utils.CommandLineExecutor;
|
||||||
import io.openvidu.test.browsers.utils.CustomHttpClient;
|
import io.openvidu.test.browsers.utils.CustomHttpClient;
|
||||||
import io.openvidu.test.browsers.utils.CustomWebhook;
|
|
||||||
import io.openvidu.test.browsers.utils.MultimediaFileMetadata;
|
import io.openvidu.test.browsers.utils.MultimediaFileMetadata;
|
||||||
import io.openvidu.test.browsers.utils.Unzipper;
|
import io.openvidu.test.browsers.utils.Unzipper;
|
||||||
|
import io.openvidu.test.browsers.utils.layout.CustomLayoutHandler;
|
||||||
|
import io.openvidu.test.browsers.utils.webhook.CustomWebhook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* E2E tests for openvidu-testapp.
|
* E2E tests for openvidu-testapp.
|
||||||
|
@ -1208,9 +1210,10 @@ public class OpenViduTestAppE2eTest {
|
||||||
Assert.assertTrue("File " + file3.getAbsolutePath() + " does not exist or is empty",
|
Assert.assertTrue("File " + file3.getAbsolutePath() + " does not exist or is empty",
|
||||||
file3.exists() && file3.length() > 0);
|
file3.exists() && file3.length() > 0);
|
||||||
|
|
||||||
Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine",
|
Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", this.recordedGreenFileFine(file1,
|
||||||
this.recordedFileFine(file1, new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(sessionName)));
|
new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(sessionName)));
|
||||||
Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine", this.thumbnailIsFine(file3));
|
Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine",
|
||||||
|
this.thumbnailIsFine(file3, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen));
|
||||||
|
|
||||||
// Try to get the stopped recording
|
// Try to get the stopped recording
|
||||||
user.getDriver().findElement(By.id("get-recording-btn")).click();
|
user.getDriver().findElement(By.id("get-recording-btn")).click();
|
||||||
|
@ -1247,7 +1250,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
log.info("Composed quick start record");
|
log.info("Composed quick start record");
|
||||||
|
|
||||||
CountDownLatch initLatch = new CountDownLatch(1);
|
CountDownLatch initLatch = new CountDownLatch(1);
|
||||||
io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch);
|
io.openvidu.test.browsers.utils.webhook.CustomWebhook.main(new String[0], initLatch);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -1520,7 +1523,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Record cross-browser audio-only and video-only")
|
@DisplayName("Record cross-browser audio-only and video-only")
|
||||||
void recordAudioOnlyVideoOnlyTest() throws Exception {
|
void audioOnlyVideoOnlyRecordTest() throws Exception {
|
||||||
isRecordingTest = true;
|
isRecordingTest = true;
|
||||||
|
|
||||||
setupBrowser("chromeAlternateScreenShare");
|
setupBrowser("chromeAlternateScreenShare");
|
||||||
|
@ -1750,6 +1753,128 @@ public class OpenViduTestAppE2eTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Custom layout recording")
|
||||||
|
void customLayoutRecordTest() throws Exception {
|
||||||
|
isRecordingTest = true;
|
||||||
|
|
||||||
|
setupBrowser("chrome");
|
||||||
|
|
||||||
|
log.info("Custom layout recording");
|
||||||
|
|
||||||
|
final String SESSION_NAME = "CUSTOM_LAYOUT_SESSION";
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.id("add-user-btn")).click();
|
||||||
|
user.getDriver().findElement(By.id("session-name-input-0")).clear();
|
||||||
|
user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(SESSION_NAME);
|
||||||
|
|
||||||
|
// Custom layout from local storage
|
||||||
|
user.getDriver().findElement(By.id("session-settings-btn-0")).click();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
user.getDriver().findElement(By.id("recording-mode-select")).click();
|
||||||
|
Thread.sleep(500);
|
||||||
|
user.getDriver().findElement(By.id("option-ALWAYS")).click();
|
||||||
|
Thread.sleep(500);
|
||||||
|
user.getDriver().findElement(By.id("recording-layout-select")).click();
|
||||||
|
Thread.sleep(500);
|
||||||
|
user.getDriver().findElement(By.id("option-CUSTOM")).click();
|
||||||
|
Thread.sleep(500);
|
||||||
|
WebElement tokeInput = user.getDriver().findElement(By.id("default-custom-layout-input"));
|
||||||
|
tokeInput.clear();
|
||||||
|
tokeInput.sendKeys("layout1");
|
||||||
|
user.getDriver().findElement(By.id("save-btn")).click();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.className("join-btn")).sendKeys(Keys.ENTER);
|
||||||
|
|
||||||
|
user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("accessAllowed", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamCreated", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamPlaying", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("recordingStarted", 1);
|
||||||
|
|
||||||
|
Thread.sleep(4000);
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.id("session-api-btn-0")).click();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.id("recording-id-field")).clear();
|
||||||
|
user.getDriver().findElement(By.id("recording-id-field")).sendKeys(SESSION_NAME);
|
||||||
|
user.getDriver().findElement(By.id("stop-recording-btn")).click();
|
||||||
|
user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value",
|
||||||
|
"Recording stopped [" + SESSION_NAME + "]"));
|
||||||
|
user.getEventManager().waitUntilEventReaches("recordingStopped", 1);
|
||||||
|
user.getDriver().findElement(By.id("close-session-btn")).click();
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamDestroyed", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("sessionDisconnected", 1);
|
||||||
|
user.getDriver().findElement(By.id("close-dialog-btn")).click();
|
||||||
|
|
||||||
|
String recordingsPath = "/opt/openvidu/recordings/" + SESSION_NAME + "/";
|
||||||
|
File file1 = new File(recordingsPath + SESSION_NAME + ".mp4");
|
||||||
|
File file2 = new File(recordingsPath + SESSION_NAME + ".jpg");
|
||||||
|
|
||||||
|
Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", this.recordedRedFileFine(file1,
|
||||||
|
new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(SESSION_NAME)));
|
||||||
|
Assert.assertTrue("Thumbnail " + file2.getAbsolutePath() + " is not fine",
|
||||||
|
this.thumbnailIsFine(file2, OpenViduTestAppE2eTest::checkVideoAverageRgbRed));
|
||||||
|
|
||||||
|
// Custom layout from external URL
|
||||||
|
CountDownLatch initLatch = new CountDownLatch(1);
|
||||||
|
CustomLayoutHandler.main(new String[0], initLatch);
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!initLatch.await(30, TimeUnit.SECONDS)) {
|
||||||
|
Assert.fail("Timeout waiting for webhook springboot app to start");
|
||||||
|
CustomLayoutHandler.shutDown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.id("session-settings-btn-0")).click();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
tokeInput = user.getDriver().findElement(By.id("default-custom-layout-input"));
|
||||||
|
tokeInput.clear();
|
||||||
|
tokeInput.sendKeys("http://localhost:5555?sessionId=CUSTOM_LAYOUT_SESSION&secret=MY_SECRET");
|
||||||
|
user.getDriver().findElement(By.id("save-btn")).click();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.className("join-btn")).sendKeys(Keys.ENTER);
|
||||||
|
|
||||||
|
user.getEventManager().waitUntilEventReaches("connectionCreated", 2);
|
||||||
|
user.getEventManager().waitUntilEventReaches("accessAllowed", 2);
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamCreated", 2);
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamPlaying", 2);
|
||||||
|
user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
|
||||||
|
|
||||||
|
Thread.sleep(4000);
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.id("session-api-btn-0")).click();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
user.getDriver().findElement(By.id("recording-id-field")).clear();
|
||||||
|
user.getDriver().findElement(By.id("recording-id-field")).sendKeys(SESSION_NAME + "-1");
|
||||||
|
user.getDriver().findElement(By.id("stop-recording-btn")).click();
|
||||||
|
user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value",
|
||||||
|
"Recording stopped [" + SESSION_NAME + "-1]"));
|
||||||
|
user.getEventManager().waitUntilEventReaches("recordingStopped", 2);
|
||||||
|
user.getDriver().findElement(By.id("close-session-btn")).click();
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamDestroyed", 2);
|
||||||
|
user.getEventManager().waitUntilEventReaches("sessionDisconnected", 2);
|
||||||
|
user.getDriver().findElement(By.id("close-dialog-btn")).click();
|
||||||
|
|
||||||
|
recordingsPath = "/opt/openvidu/recordings/" + SESSION_NAME + "-1/";
|
||||||
|
file1 = new File(recordingsPath + SESSION_NAME + "-1.mp4");
|
||||||
|
file2 = new File(recordingsPath + SESSION_NAME + "-1.jpg");
|
||||||
|
|
||||||
|
Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", this.recordedRedFileFine(
|
||||||
|
file1, new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(SESSION_NAME + "-1")));
|
||||||
|
Assert.assertTrue("Thumbnail " + file2.getAbsolutePath() + " is not fine",
|
||||||
|
this.thumbnailIsFine(file2, OpenViduTestAppE2eTest::checkVideoAverageRgbRed));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
CustomLayoutHandler.shutDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("REST API: Fetch all, fetch one, force disconnect, force unpublish, close session")
|
@DisplayName("REST API: Fetch all, fetch one, force disconnect, force unpublish, close session")
|
||||||
void restApiFetchForce() throws Exception {
|
void restApiFetchForce() throws Exception {
|
||||||
|
@ -2490,8 +2615,9 @@ public class OpenViduTestAppE2eTest {
|
||||||
file3.exists() && file3.length() > 0);
|
file3.exists() && file3.length() > 0);
|
||||||
|
|
||||||
Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine",
|
Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine",
|
||||||
this.recordedFileFine(file1, recording2));
|
this.recordedGreenFileFine(file1, recording2));
|
||||||
Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine", this.thumbnailIsFine(file3));
|
Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine",
|
||||||
|
this.thumbnailIsFine(file3, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
OV.deleteRecording("NOT_EXISTS");
|
OV.deleteRecording("NOT_EXISTS");
|
||||||
|
@ -2506,12 +2632,12 @@ public class OpenViduTestAppE2eTest {
|
||||||
try {
|
try {
|
||||||
session.forceUnpublish("NOT_EXISTS");
|
session.forceUnpublish("NOT_EXISTS");
|
||||||
} catch (OpenViduHttpException e) {
|
} catch (OpenViduHttpException e) {
|
||||||
Assert.assertEquals("Wrong HTTP status on Session.fetch()", 404, e.getStatus());
|
Assert.assertEquals("Wrong HTTP status on Session.forceUnpublish()", 404, e.getStatus());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
session.forceDisconnect("NOT_EXISTS");
|
session.forceDisconnect("NOT_EXISTS");
|
||||||
} catch (OpenViduHttpException e) {
|
} catch (OpenViduHttpException e) {
|
||||||
Assert.assertEquals("Wrong HTTP status on Session.fetch()", 404, e.getStatus());
|
Assert.assertEquals("Wrong HTTP status on Session.forceDisconnect()", 404, e.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpenViduRole.MODERATOR.equals(session.getActiveConnections().get(0).getRole())) {
|
if (OpenViduRole.MODERATOR.equals(session.getActiveConnections().get(0).getRole())) {
|
||||||
|
@ -3051,7 +3177,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
log.info("Webhook test");
|
log.info("Webhook test");
|
||||||
|
|
||||||
CountDownLatch initLatch = new CountDownLatch(1);
|
CountDownLatch initLatch = new CountDownLatch(1);
|
||||||
io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch);
|
io.openvidu.test.browsers.utils.webhook.CustomWebhook.main(new String[0], initLatch);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -3204,7 +3330,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
log.info("IP camera test");
|
log.info("IP camera test");
|
||||||
|
|
||||||
CountDownLatch initLatch = new CountDownLatch(1);
|
CountDownLatch initLatch = new CountDownLatch(1);
|
||||||
io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch);
|
io.openvidu.test.browsers.utils.webhook.CustomWebhook.main(new String[0], initLatch);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -3464,12 +3590,12 @@ public class OpenViduTestAppE2eTest {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkVideoAverageRgbGreen(Map<String, Long> rgb) {
|
private static boolean checkVideoAverageRgbGreen(Map<String, Long> rgb) {
|
||||||
// GREEN color: {r < 15, g > 130, b <15}
|
// GREEN color: {r < 15, g > 130, b <15}
|
||||||
return (rgb.get("r") < 15) && (rgb.get("g") > 130) && (rgb.get("b") < 15);
|
return (rgb.get("r") < 15) && (rgb.get("g") > 130) && (rgb.get("b") < 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkVideoAverageRgbGray(Map<String, Long> rgb) {
|
private static boolean checkVideoAverageRgbGray(Map<String, Long> rgb) {
|
||||||
// GRAY color: {r < 50, g < 50, b < 50} and the absolute difference between them
|
// GRAY color: {r < 50, g < 50, b < 50} and the absolute difference between them
|
||||||
// not greater than 2
|
// not greater than 2
|
||||||
return (rgb.get("r") < 50) && (rgb.get("g") < 50) && (rgb.get("b") < 50)
|
return (rgb.get("r") < 50) && (rgb.get("g") < 50) && (rgb.get("b") < 50)
|
||||||
|
@ -3477,6 +3603,11 @@ public class OpenViduTestAppE2eTest {
|
||||||
&& (Math.abs(rgb.get("b") - rgb.get("g")) <= 2);
|
&& (Math.abs(rgb.get("b") - rgb.get("g")) <= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean checkVideoAverageRgbRed(Map<String, Long> rgb) {
|
||||||
|
// RED color: {r > 240, g < 15, b <15}
|
||||||
|
return (rgb.get("r") > 240) && (rgb.get("g") < 15) && (rgb.get("b") < 15);
|
||||||
|
}
|
||||||
|
|
||||||
private void gracefullyLeaveParticipants(int numberOfParticipants) throws Exception {
|
private void gracefullyLeaveParticipants(int numberOfParticipants) throws Exception {
|
||||||
int accumulatedConnectionDestroyed = 0;
|
int accumulatedConnectionDestroyed = 0;
|
||||||
for (int j = 1; j <= numberOfParticipants; j++) {
|
for (int j = 1; j <= numberOfParticipants; j++) {
|
||||||
|
@ -3494,7 +3625,8 @@ public class OpenViduTestAppE2eTest {
|
||||||
return "data:image/png;base64," + screenshotBase64;
|
return "data:image/png;base64," + screenshotBase64;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean recordedFileFine(File file, Recording recording) throws IOException {
|
private boolean recordedFileFine(File file, Recording recording,
|
||||||
|
Function<Map<String, Long>, Boolean> colorCheckFunction) throws IOException {
|
||||||
this.checkMultimediaFile(file, recording.hasAudio(), recording.hasVideo(), recording.getDuration(),
|
this.checkMultimediaFile(file, recording.hasAudio(), recording.hasVideo(), recording.getDuration(),
|
||||||
recording.getResolution(), "aac", "h264", true);
|
recording.getResolution(), "aac", "h264", true);
|
||||||
|
|
||||||
|
@ -3515,7 +3647,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
log.info("Recording map color: {}", colorMap.toString());
|
log.info("Recording map color: {}", colorMap.toString());
|
||||||
log.info("Recording frame below");
|
log.info("Recording frame below");
|
||||||
System.out.println(bufferedImageToBase64PngString(image));
|
System.out.println(bufferedImageToBase64PngString(image));
|
||||||
isFine = this.checkVideoAverageRgbGreen(colorMap);
|
isFine = colorCheckFunction.apply(colorMap);
|
||||||
} catch (IOException | JCodecException e) {
|
} catch (IOException | JCodecException e) {
|
||||||
log.warn("Error getting frame from video recording: {}", e.getMessage());
|
log.warn("Error getting frame from video recording: {}", e.getMessage());
|
||||||
isFine = false;
|
isFine = false;
|
||||||
|
@ -3523,6 +3655,14 @@ public class OpenViduTestAppE2eTest {
|
||||||
return isFine;
|
return isFine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean recordedGreenFileFine(File file, Recording recording) throws IOException {
|
||||||
|
return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean recordedRedFileFine(File file, Recording recording) throws IOException {
|
||||||
|
return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbRed);
|
||||||
|
}
|
||||||
|
|
||||||
private String bufferedImageToBase64PngString(BufferedImage image) {
|
private String bufferedImageToBase64PngString(BufferedImage image) {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
String imageString = null;
|
String imageString = null;
|
||||||
|
@ -3654,7 +3794,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
Math.abs((metadata.getDuration() - duration)) < difference);
|
Math.abs((metadata.getDuration() - duration)) < difference);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean thumbnailIsFine(File file) {
|
private boolean thumbnailIsFine(File file, Function<Map<String, Long>, Boolean> colorCheckFunction) {
|
||||||
boolean isFine = false;
|
boolean isFine = false;
|
||||||
BufferedImage image = null;
|
BufferedImage image = null;
|
||||||
try {
|
try {
|
||||||
|
@ -3666,7 +3806,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
log.info("Recording thumbnail dimensions: {}x{}", image.getWidth(), image.getHeight());
|
log.info("Recording thumbnail dimensions: {}x{}", image.getWidth(), image.getHeight());
|
||||||
Map<String, Long> colorMap = this.averageColor(image);
|
Map<String, Long> colorMap = this.averageColor(image);
|
||||||
log.info("Thumbnail map color: {}", colorMap.toString());
|
log.info("Thumbnail map color: {}", colorMap.toString());
|
||||||
isFine = this.checkVideoAverageRgbGreen(colorMap);
|
isFine = colorCheckFunction.apply(colorMap);
|
||||||
return isFine;
|
return isFine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,16 +27,17 @@
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngIf="this.sessionProperties.defaultOutputMode === 'COMPOSED'">
|
<mat-form-field *ngIf="this.sessionProperties.defaultOutputMode === 'COMPOSED'">
|
||||||
<mat-select placeholder="DefaultRecordingLayout" [(ngModel)]="sessionProperties.defaultRecordingLayout">
|
<mat-select placeholder="DefaultRecordingLayout" [(ngModel)]="sessionProperties.defaultRecordingLayout"
|
||||||
|
id="recording-layout-select">
|
||||||
<mat-option *ngFor="let enumerator of enumToArray(defaultRecordingLayout)" [value]="enumerator">
|
<mat-option *ngFor="let enumerator of enumToArray(defaultRecordingLayout)" [value]="enumerator">
|
||||||
{{ enumerator }}
|
<span [attr.id]="'option-' + enumerator">{{ enumerator }}</span>
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field
|
<mat-form-field
|
||||||
*ngIf="this.sessionProperties.defaultOutputMode === 'COMPOSED' && this.sessionProperties.defaultRecordingLayout === 'CUSTOM'">
|
*ngIf="this.sessionProperties.defaultOutputMode === 'COMPOSED' && this.sessionProperties.defaultRecordingLayout === 'CUSTOM'">
|
||||||
<input matInput placeholder="DefaultCustomLayout" type="text"
|
<input matInput placeholder="DefaultCustomLayout" type="text"
|
||||||
[(ngModel)]="sessionProperties.defaultCustomLayout">
|
[(ngModel)]="sessionProperties.defaultCustomLayout" id="default-custom-layout-input">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input matInput placeholder="CustomSessionId" type="text" [(ngModel)]="sessionProperties.customSessionId">
|
<input matInput placeholder="CustomSessionId" type="text" [(ngModel)]="sessionProperties.customSessionId">
|
||||||
|
|
Loading…
Reference in New Issue