Skip to content

Commit

Permalink
Screen recording implemented (#277)
Browse files Browse the repository at this point in the history
* Screen recording implemented

* Сopy-paste parameter is deleted. Missing spaces are added.

* Some tests are added.

* Rename static methods for using static import. Removed BrowserName from android capability.
  • Loading branch information
y-kebets-sdg authored and laolubenson committed Oct 25, 2018
1 parent 27820f9 commit 509247a
Show file tree
Hide file tree
Showing 15 changed files with 511 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using OpenQA.Selenium.Appium.ScreenRecording;

namespace OpenQA.Selenium.Appium.Android
{
public class AndroidStartScreenRecordingOptions : BaseStartScreenRecordingOptions<AndroidStartScreenRecordingOptions>
{
public static AndroidStartScreenRecordingOptions GetAndroidStartScreenRecordingOptions()
{
return new AndroidStartScreenRecordingOptions();
}

/// <summary>
/// The video bit rate for the video, in megabits per second.
/// The default value is 4000000 (4 Mb/s) for Android API level below 27
/// and 20000000 (20 Mb/s) for API level 27 and above.
/// You can increase the bit rate to improve video quality,
/// but doing so results in larger movie files.
/// </summary>
/// <param name="bitRate">The actual bit rate (Mb/s).</param>
/// <returns>self instance for chaining.</returns>
public AndroidStartScreenRecordingOptions WithBitRate(int bitRate)
{
Parameters["bitRate"] = bitRate;
return this;
}

/// <summary>
/// The video size of the generated media file. The format is WIDTHxHEIGHT.
/// The default value is the device's native display resolution (if supported),
/// 1280x720 if not. For best results,
/// use a size supported by your device's Advanced Video Coding (AVC) encoder.
/// </summary>
/// <param name="videoSize">The actual video size: WIDTHxHEIGHT.</param>
/// <returns>self instance for chaining.</returns>
public AndroidStartScreenRecordingOptions WithVideoSize(string videoSize)
{
Parameters["videoSize"] = videoSize;
return this;
}

/// <summary>
/// Makes the recorder to display an additional information on the video overlay,
/// such as a timestamp, that is helpful in videos captured to illustrate bugs.
/// This option is only supported since API level 27 (Android P).
/// </summary>
/// <returns>self instance for chaining.</returns>
public AndroidStartScreenRecordingOptions EnableBugReport()
{
Parameters["isBugReportEnabled"] = true;
return this;
}

/// <summary>
/// The maximum recording time.The default and maximum value is 180 seconds (3 minutes).
/// Setting values greater than this or less than zero will cause an exception. The minimum
/// time resolution unit is one second.
///
/// Since Appium 1.8.2 the time limit can be up to 1800 seconds (30 minutes).
/// Appium will automatically try to merge the 3-minutes chunks recorded
/// by the screenrecord utility, however, this requires FFMPEG utility
/// to be installed and available in PATH on the server machine. If the utility is not
/// present then the most recent screen recording chunk is going to be returned as the result.
/// </summary>
/// <param name="timeLimit">The actual time limit of the recorded video.</param>
/// <returns>self instance for chaining.</returns>
public new AndroidStartScreenRecordingOptions WithTimeLimit(TimeSpan timeLimit)
{
return base.WithTimeLimit(timeLimit);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using OpenQA.Selenium.Appium.ScreenRecording;

namespace OpenQA.Selenium.Appium.Android
{
public class AndroidStopScreenRecordingOptions : BaseStopScreenRecordingOptions<AndroidStopScreenRecordingOptions>
{
public static AndroidStopScreenRecordingOptions StopScreenRecordingOptions()
{
return new AndroidStopScreenRecordingOptions();
}
}
}
9 changes: 8 additions & 1 deletion appium-dotnet-driver/Appium/AppiumCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,17 @@ public class AppiumCommand

#region SeassionData

new AppiumCommand(CommandInfo.GetCommand, AppiumDriverCommand.GetSession, "/session/{sessionId}/")
new AppiumCommand(CommandInfo.GetCommand, AppiumDriverCommand.GetSession, "/session/{sessionId}/"),

#endregion SeassionData

#region Recording Screen

new AppiumCommand(CommandInfo.PostCommand, AppiumDriverCommand.StartRecordingScreen, "/session/{sessionId}/appium/start_recording_screen"),
new AppiumCommand(CommandInfo.PostCommand, AppiumDriverCommand.StopRecordingScreen, "/session/{sessionId}/appium/stop_recording_screen")

#endregion Recording Screen

#endregion JSON Wire Protocol Commands
};

Expand Down
22 changes: 22 additions & 0 deletions appium-dotnet-driver/Appium/AppiumDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Castle.Core.Internal;
using OpenQA.Selenium.Appium.ScreenRecording;

namespace OpenQA.Selenium.Appium
{
Expand Down Expand Up @@ -429,6 +431,26 @@ public object GetSessionDetail(string detail)

#endregion Session Data

#region Recording Screen

public string StartRecordingScreen() => ((IExecuteMethod)this).Execute(AppiumDriverCommand.StartRecordingScreen).Value.ToString();

public string StartRecordingScreen(IScreenRecordingOptions options)
{
var parameters = new Dictionary<string, object> {{"options", options.GetParameters()} };
return Execute(AppiumDriverCommand.StartRecordingScreen, parameters).Value.ToString();
}

public string StopRecordingScreen() => ((IExecuteMethod)this).Execute(AppiumDriverCommand.StopRecordingScreen).Value.ToString();

public string StopRecordingScreen(IScreenRecordingOptions options)
{
var parameters = new Dictionary<string, object> { { "options", options.GetParameters() } };
return Execute(AppiumDriverCommand.StopRecordingScreen, parameters).Value.ToString();
}

#endregion Recording Screen

#endregion Public Methods

#region Support methods
Expand Down
4 changes: 4 additions & 0 deletions appium-dotnet-driver/Appium/AppiumDriverCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ public class AppiumDriverCommand

public const string GetSession = "getSession";

public const string StartRecordingScreen = "startRecordingScreen";

public const string StopRecordingScreen = "stopRecordingScreen";

#endregion JSON Wire Protocol
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace OpenQA.Selenium.Appium.Interfaces
{
public interface IScreenRecordingOptions
{
Dictionary<string, object> GetParameters();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Collections.Generic;
using OpenQA.Selenium.Appium.Interfaces;

namespace OpenQA.Selenium.Appium.ScreenRecording
{
public abstract class BaseScreenRecordingOptions<T> : IScreenRecordingOptions where T : BaseScreenRecordingOptions<T>
{
protected Dictionary<string, object> Parameters;

protected BaseScreenRecordingOptions()
{
Parameters = new Dictionary<string, object>();
}

/// <summary>
/// Upload options set for the recorded screen capture.
/// </summary>
/// <param name="uploadOptions">Upload options</param>
/// <returns></returns>
public T WithUploadOptions(ScreenRecordingUploadOptions uploadOptions)
{
foreach (var parameter in uploadOptions.GetParameters())
{
Parameters[parameter.Key] = parameter.Value;
}

return (T) this;
}

/// <summary>
/// Get all setted parameters
/// </summary>
/// <returns></returns>
public Dictionary<string, object> GetParameters()
{
return Parameters;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;

namespace OpenQA.Selenium.Appium.ScreenRecording
{
public abstract class BaseStartScreenRecordingOptions<T> : BaseScreenRecordingOptions<T> where T : BaseStartScreenRecordingOptions<T>
{
/// <summary>
/// The maximum recording time.
/// </summary>
/// <param name="timeLimit">The actual time limit of the recorded video.</param>
/// <returns>self instance for chaining.</returns>
public T WithTimeLimit(TimeSpan timeLimit)
{
Parameters["timeLimit"] = (int) timeLimit.TotalSeconds;
return (T) this;
}

/// <summary>
/// Whether to ignore the result of previous capture and start a new recording
/// immediately. By default the endpoint will try to catch and return the result of
/// the previous capture if it's still available.
/// </summary>
/// <returns>self instance for chaining.</returns>
public T EnableForcedRestart()
{
Parameters["forceRestart"] = true;
return (T) this;
}

/// <summary>
/// The remotePath upload option is the path to the remote location,
/// where the resulting video should be uploaded.
/// The following protocols are supported: http/https (multipart), ftp.
///
/// Missing value (the default setting) means the content of the resulting
/// file should be encoded as Base64 and passed as the endpoint response value, but
/// an exception will be thrown if the generated media file is too big to
/// fit into the available process memory.
/// This option only has an effect if there is a screen recording session in progress
/// and forced restart is not enabled (the default setting).
/// </summary>
/// <param name="uploadOptions">Upload options</param>
/// <returns>self instance for chaining.</returns>
public new T WithUploadOptions(ScreenRecordingUploadOptions uploadOptions)
{
return base.WithUploadOptions(uploadOptions);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace OpenQA.Selenium.Appium.ScreenRecording
{
public abstract class BaseStopScreenRecordingOptions<T> : BaseScreenRecordingOptions<T> where T : BaseStopScreenRecordingOptions<T>
{
/// <summary>
/// The remotePath upload option is the path to the remote location,
/// where the resulting video should be uploaded.
/// The following protocols are supported: http/https (multipart), ftp.
/// Missing value (the default setting) means the content of resulting
/// file should be encoded as Base64 and passed as the endpoint response value, but
/// an exception will be thrown if the generated media file is too big to
/// fit into the available process memory.
/// </summary>
/// <param name="uploadOptions">Upload options</param>
/// <returns>self instance for chaining.</returns>
public new T WithUploadOptions(ScreenRecordingUploadOptions uploadOptions)
{
return base.WithUploadOptions(uploadOptions);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Collections.Generic;

namespace OpenQA.Selenium.Appium.ScreenRecording
{
public class ScreenRecordingUploadOptions
{
protected Dictionary<string, object> Parameters;

/// <summary>
/// The path to the remote location, where the resulting video should be uploaded.
/// </summary>
/// <param name="remotePath">The path to a writable remote location.</param>
/// <returns>self instance for chaining.</returns>
public ScreenRecordingUploadOptions WithRemotePath(string remotePath)
{
Parameters["remotePath"] = remotePath;
return this;
}

/// <summary>
/// Sets the credentials for remote ftp/http authentication (if needed).
/// This option only has an effect if remotePath is provided.
/// </summary>
/// <param name="user">The name of the user for the remote authentication.</param>
/// <param name="pass">The password for the remote authentication.</param>
/// <returns>self instance for chaining.</returns>
public ScreenRecordingUploadOptions WithAuthCredentials(string user, string pass)
{
Parameters["user"] = user;
Parameters["pass"] = pass;
return this;
}

public enum RequestMethod
{
POST, PUT
}

/// <summary>
/// Sets the method name for http(s) upload. PUT is used by default.
/// This option only has an effect if remotePath is provided.
/// </summary>
/// <param name="method">method The HTTP method name.</param>
/// <returns>self instance for chaining.</returns>
public ScreenRecordingUploadOptions WithHttpMethod(RequestMethod method)
{
Parameters["method"] = method.ToString();
return this;
}

/// <summary>
/// Get all setted parameters
/// </summary>
/// <returns></returns>
public Dictionary<string, object> GetParameters()
{
return Parameters;
}
}
}
61 changes: 61 additions & 0 deletions appium-dotnet-driver/Appium/iOS/IOSStartScreenRecordingOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using OpenQA.Selenium.Appium.ScreenRecording;

namespace OpenQA.Selenium.Appium.iOS
{
public class IOSStartScreenRecordingOptions : BaseStartScreenRecordingOptions<IOSStartScreenRecordingOptions>
{
public static IOSStartScreenRecordingOptions GetIosStartScreenRecordingOptions()
{
return new IOSStartScreenRecordingOptions();
}

public enum VideoType
{
H264, MP4, FMP4
}

/// <summary>
/// The format of the screen capture to be recorded.
/// Available formats: "h264", "mp4" or "fmp4". Default is "mp4".
/// Only works for Simulator.
/// </summary>
/// <param name="videoType">one of available format names.</param>
/// <returns>self instance for chaining.</returns>
public IOSStartScreenRecordingOptions WithVideoType(VideoType videoType)
{
Parameters["videoType"] = videoType.ToString().ToLower();
return this;
}

public enum VideoQuality
{
LOW, MEDIUM, HIGH, PHOTO
}

/// <summary>
/// The video encoding quality (low, medium, high, photo - defaults to medium).
/// Only works for real devices.
/// </summary>
/// <param name="videoQuality"></param>
/// <returns></returns>
public IOSStartScreenRecordingOptions WithVideoQuality(VideoQuality videoQuality)
{
Parameters["videoQuality"] = videoQuality.ToString().ToLower();
return this;
}

/// <summary>
/// The maximum recording time.The default value is 180 seconds (3 minutes).
/// The maximum value is 10 minutes.
/// Setting values greater than this or less than zero will cause an exception. The minimum
/// time resolution unit is one second.
/// </summary>
/// <param name="timeLimit">The actual time limit of the recorded video.</param>
/// <returns>self instance for chaining.</returns>
public new IOSStartScreenRecordingOptions WithTimeLimit(TimeSpan timeLimit)
{
return base.WithTimeLimit(timeLimit);
}
}
}
Loading

0 comments on commit 509247a

Please sign in to comment.