All Downloads are FREE. Search and download functionalities are using the official Maven repository.

core.helpers.ScreenRecorderHelper Maven / Gradle / Ivy

package core.helpers;

import static org.monte.media.FormatKeys.EncodingKey;
import static org.monte.media.FormatKeys.FrameRateKey;
import static org.monte.media.FormatKeys.KeyFrameIntervalKey;
import static org.monte.media.FormatKeys.MediaTypeKey;
import static org.monte.media.FormatKeys.MimeTypeKey;
import static org.monte.media.VideoFormatKeys.CompressorNameKey;
import static org.monte.media.VideoFormatKeys.DepthKey;
import static org.monte.media.VideoFormatKeys.ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE;
import static org.monte.media.VideoFormatKeys.QualityKey;

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.monte.media.Format;
import org.monte.media.FormatKeys;
import org.monte.media.VideoFormatKeys;
import org.monte.media.math.Rational;
import org.monte.screenrecorder.ScreenRecorder;

import core.support.configReader.Config;
import core.support.logger.ExtentManager;
import core.support.logger.TestLog;
import core.support.objects.TestObject;
import io.appium.java_client.android.AndroidStartScreenRecordingOptions;
import io.appium.java_client.ios.IOSStartScreenRecordingOptions;
import io.appium.java_client.ios.IOSStartScreenRecordingOptions.VideoQuality;

public class ScreenRecorderHelper {
	
	public static final String RECORDER_ENABLE_RECORDING = "recorder.enableRecording";
	public static final String RECORDER_ON_FAIL_TEST_ONLY = "recorder.onFailedTestsOnly";

	public static final String RECORDER_MAX_TIME_SECONDS = "recorder.maxTimeInSeconds";
	public static final String RECORDER_ANDROID_VIDEO_SIZE = "recorder.android.videoSize";
	public static final String RECORDER_IOS_QUALITY = "recorder.ios.quality";
	public static final String RECORDER_IOS_TYPE = "recorder.ios.type";

	
	/**
	 * start screen recording
	 * works for ios, android and web
	 */
	public synchronized static void startRecording() {
		
		// return if enableRecording is false
		if(!Config.getBooleanValue(RECORDER_ENABLE_RECORDING))
			return;
		
		// if record on fail only, then only start on retry after failure
		if(Config.getBooleanValue(RECORDER_ON_FAIL_TEST_ONLY) && !TestObject.getTestInfo().isTestFail)
			return;
		
		// bring the browser to front for recording
		Helper.bringPageToFront();
		
		TestLog.ConsoleLog("initiating screen recording");
		TestObject.getTestInfo().isScreenRecorderInitiated = true;
		
		int maxTime = Config.getIntValue(RECORDER_MAX_TIME_SECONDS);
		String androidVideoSize = Config.getValue(RECORDER_ANDROID_VIDEO_SIZE);
		VideoQuality iosQuality = VideoQuality.valueOf(Config.getValue(RECORDER_IOS_QUALITY));

		if(Helper.mobile.isAndroid()) {
			// if ongoing recording, stop
			Helper.mobile.getAndroidDriver().stopRecordingScreen();
			
			// set recording options
			AndroidStartScreenRecordingOptions record = new AndroidStartScreenRecordingOptions();
			record.withTimeLimit(Duration.ofSeconds(maxTime)); 
			record.withVideoSize(androidVideoSize);
			Helper.mobile.getAndroidDriver().startRecordingScreen(record);
		}else if(Helper.mobile.isIOS()) {
			// if ongoing recording, stop
			Helper.mobile.getiOSDriver().stopRecordingScreen();
			
			// set recording options
			IOSStartScreenRecordingOptions record = new IOSStartScreenRecordingOptions();
			record.withTimeLimit(Duration.ofSeconds(maxTime));
			record.withVideoQuality(iosQuality);
			record.withVideoType("libx264");
			Helper.mobile.getiOSDriver().startRecordingScreen(record);
		}else if(Helper.mobile.isWebDriver()) {
			startWebScreenRecording();
		}
	}
	
	/**
	 * stops screen recording
	 * works for ios, android and web
	 */
	public synchronized static void stopRecording() {
		
		// if screen recorder not initiated, return
		if(!TestObject.getTestInfo().isScreenRecorderInitiated)
			return;

		// return if enableRecording is false 
		if (!Config.getBooleanValue(RECORDER_ENABLE_RECORDING))
			return;
		
		// if record on fail only is true and test passes, then return
		if(Config.getBooleanValue(RECORDER_ON_FAIL_TEST_ONLY) && (TestObject.getTestInfo().isTestPass))
			return;

		TestLog.ConsoleLog("stopping screen recording");

		if (Helper.mobile.isMobile()) {
			stopMobileScreenRecorder();
		} else if (Helper.mobile.isWebDriver()) {
			stopWebScreenRecorder();
		}
	}
	
	private static void startWebScreenRecording() {
	
		File output = new File(getScreenRecorderTempDir().getAbsoluteFile() + File.separator + TestObject.getTestInfo().getTestName());
		output.deleteOnExit();

		GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
				.getDefaultConfiguration();

		// Create a instance of ScreenRecorder with the required configurations
		try {
            TestObject.getTestInfo().screenRecorder = new ScreenRecorder(gc,null,
                    new Format(MediaTypeKey, FormatKeys.MediaType.FILE,
                            MimeTypeKey, FormatKeys.MIME_AVI),
                    new Format(MediaTypeKey, FormatKeys.MediaType.VIDEO,
                            EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
                            CompressorNameKey, VideoFormatKeys.COMPRESSOR_NAME_AVI_TECHSMITH_SCREEN_CAPTURE,
                            DepthKey, 24,
                            FrameRateKey, Rational.valueOf(15),
                            QualityKey, 1.0f,
                            KeyFrameIntervalKey, (15 * 60)),
                    new Format(MediaTypeKey, FormatKeys.MediaType.VIDEO,
                            EncodingKey, "black",
                            FrameRateKey, Rational.valueOf(30)),
                    null,output);
            TestObject.getTestInfo().screenRecorder.start();

        } catch (Exception e) {
            TestLog.ConsoleLog("Recorder Object cannot be intialized " + e);
        }

	}
	
	private static void stopMobileScreenRecorder() {
		String recording = null;
		if (Helper.mobile.isAndroid())
			recording = Helper.mobile.getAndroidDriver().stopRecordingScreen();
		else if (Helper.mobile.isIOS()) 
			recording = Helper.mobile.getiOSDriver().stopRecordingScreen();
		
			// Decode String To Video With mig Base64.
			byte[] decodedBytes = Base64.decodeBase64(recording.getBytes());

			try {
				String mediaName = getMediaName() + ".mp4";
				
				// relative path for extent report attachment
				String extentMediaRelativePathFromReport = ExtentManager.getMediaFolderRelativePathFromHtmlReport()
						+ mediaName;
				
				// full path for file creation
				String extentReportImageFullPath = ExtentManager.getMediaFolderFullPath()
						+ mediaName;
				
				File media = new File(extentReportImageFullPath);

				// create directories and files in path
				Helper.createFileFromPath(media.getAbsolutePath());
				
				// save to file
				FileOutputStream out = new FileOutputStream(media, false);
				out.write(decodedBytes);
				out.close();
				TestLog.ConsoleLog("Test Recording is saved at: " + extentReportImageFullPath);
				
				// attach video to extent report
				TestLog.attachVideoLog(extentMediaRelativePathFromReport, true);
				
				// link video to report portal
				TestLog.attachVideoLogToReportPortal(media);

			} catch (Exception e) {
				e.printStackTrace();
			}
	}

	/**
	 * if screen recorder is active, stop recording
	 */
	private static void stopWebScreenRecorder() {
		if (TestObject.getTestInfo().screenRecorder != null) {
			try {
				TestObject.getTestInfo().screenRecorder.stop();

				List createdMovieFiles = TestObject.getTestInfo().screenRecorder.getCreatedMovieFiles();
				

				for (File movie : createdMovieFiles) {
	
					File dir = new File(ExtentManager.getMediaFolderFullPath()) ;
					dir.mkdirs(); // if dir already exists will do nothing
					
					String mediaName = getMediaName() + ".avi";
					try {
						Path path = Files.move(movie.toPath(), dir.toPath().resolve(mediaName),
								StandardCopyOption.REPLACE_EXISTING);
						TestLog.ConsoleLog("Test Recording is saved at: " + path);
						
						String extentReportImageRelativePath = ExtentManager.getMediaFolderRelativePathFromHtmlReport()
								+ mediaName;
						
						// attach video to extent report
						TestLog.attachVideoLog(extentReportImageRelativePath, false);
						
						// link video to report portal
						TestLog.attachVideoLogToReportPortal(path.toFile());

					}catch(Exception e) {
						e.printStackTrace();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * gets the video name
	 * @return
	 */
	private static String getMediaName() {
		String format = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", Locale.ENGLISH).format(new Date());
		String fileName = TestObject.getTestInfo().testName + "-" + format;
		return fileName;
	}
	
	/**
	 * gets the temp dir for screen recorder videos. created on start recording.
	 * @return
	 */
	public static File getScreenRecorderTempDir() {
		File output = new File(System.getProperty("java.io.tmpdir") + File.separator + "screenrecorder" + File.separator);
		return output;
	}
	
	/**
	 * delete screen recorder temp folder
	 */
	public static void deleteScreenRecorderTempDir() {
		try {
			FileUtils.deleteDirectory( getScreenRecorderTempDir());
		} catch (IOException e) {
			TestLog.ConsoleLogDebug(e.getMessage());
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy