diff --git a/Lombiq.Tests.UI/Constants/DirectoryPaths.cs b/Lombiq.Tests.UI/Constants/DirectoryPaths.cs
index f73b6db7e..d7b3b426b 100644
--- a/Lombiq.Tests.UI/Constants/DirectoryPaths.cs
+++ b/Lombiq.Tests.UI/Constants/DirectoryPaths.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Linq;
namespace Lombiq.Tests.UI.Constants;
@@ -10,8 +9,14 @@ public static class DirectoryPaths
public const string Temp = nameof(Temp);
public const string Screenshots = nameof(Screenshots);
+ public static string GetTempDirectoryPath(params string[] subDirectoryNames) =>
+ Path.Combine(
+ Path.Combine(Environment.CurrentDirectory, Temp),
+ Path.Combine(subDirectoryNames));
+
public static string GetTempSubDirectoryPath(string contextId, params string[] subDirectoryNames) =>
- Path.Combine(new[] { Environment.CurrentDirectory, Temp, contextId }.Concat(subDirectoryNames).ToArray());
+ GetTempDirectoryPath(
+ Path.Combine(contextId, Path.Combine(subDirectoryNames)));
public static string GetScreenshotsDirectoryPath(string contextId) =>
GetTempSubDirectoryPath(contextId, Screenshots);
diff --git a/Lombiq.Tests.UI/Docs/FakeVideoCaptureSource.md b/Lombiq.Tests.UI/Docs/FakeVideoCaptureSource.md
new file mode 100644
index 000000000..7aa8d7f4a
--- /dev/null
+++ b/Lombiq.Tests.UI/Docs/FakeVideoCaptureSource.md
@@ -0,0 +1,71 @@
+# Fake video capture source
+
+## Preparing video file
+
+You can use video files as a fake video capture source in Chrome browser of format `y4m` or `mjpeg`.
+
+If you have a video file in e.g., `mp4` format, use your preferred video tool to convert it to one of the formats mentioned above. If you don't have a preferred tool, simply use `ffmpeg`.
+
+_Suggestion: use `mjpeg`, it will result in a smaller file size._
+
+```bash
+# Convert mp4 to y4m.
+ffmpeg -y -i test.mp4 -pix_fmt yuv420p test.y4m
+
+# Convert with resize to 480p.
+ffmpeg -y -i test.mp4 -filter:v scale=480:-1 -pix_fmt yuv420p test.y4m
+
+# Convert mp4 to mjpeg.
+ffmpeg -y -i test.mp4 test.mjpeg
+
+# Convert with resize to 480p.
+ffmpeg -y -i test.mp4 -filter:v scale=480:-1 test.mjpeg
+
+```
+
+### Configuring test
+
+Add the prepared video file to your `csproj` project as an `EmbeddedResource`, and then configure the test method as shown below.
+
+```csharp
+using Lombiq.Tests.UI.Attributes;
+using Lombiq.Tests.UI.Constants;
+using Lombiq.Tests.UI.Extensions;
+using Lombiq.Tests.UI.Models;
+using Lombiq.Tests.UI.Services;
+using OpenQA.Selenium;
+using Shouldly;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Lombiq.Tests.UI.Samples.Tests;
+
+public class BasicTests : UITestBase
+{
+ public BasicTests(ITestOutputHelper testOutputHelper)
+ : base(testOutputHelper)
+ {
+ }
+
+ [Theory, Chrome]
+ public Task TestMethod(Browser browser) =>
+ ExecuteTestAfterSetupAsync(
+ async context =>
+ {
+ // ...
+ },
+ browser,
+ configuration =>
+ // Here we set the fake video source configuration.
+ configuration.BrowserConfiguration.FakeVideoSource = new FakeBrowserVideoSource
+ {
+ StreamProvider = () =>
+ // Load video file content from resources.
+ typeof(BasicTests).Assembly.GetManifestResourceStream(typeof(BasicTests), "BasicTest.mjpeg"),
+ // Set the video format.
+ Format = FakeBrowserVideoSourceFileFormat.MJpeg,
+ });
+}
+```
diff --git a/Lombiq.Tests.UI/Extensions/FakeBrowserVideoSourceExtensions.cs b/Lombiq.Tests.UI/Extensions/FakeBrowserVideoSourceExtensions.cs
new file mode 100644
index 000000000..829a16195
--- /dev/null
+++ b/Lombiq.Tests.UI/Extensions/FakeBrowserVideoSourceExtensions.cs
@@ -0,0 +1,30 @@
+using Lombiq.Tests.UI.Constants;
+using Lombiq.Tests.UI.Models;
+using System;
+using System.IO;
+
+namespace Lombiq.Tests.UI.Extensions;
+
+public static class FakeBrowserVideoSourceExtensions
+{
+ public static string SaveVideoToTempFolder(this FakeBrowserVideoSource source)
+ {
+ using var fakeCameraSource = source.StreamProvider();
+ var fakeCameraSourcePath = Path.ChangeExtension(
+ DirectoryPaths.GetTempDirectoryPath(Guid.NewGuid().ToString()),
+ GetExtension(source.Format));
+ using var fakeCameraSourceFile = new FileStream(fakeCameraSourcePath, FileMode.CreateNew, FileAccess.Write);
+
+ fakeCameraSource.CopyTo(fakeCameraSourceFile);
+
+ return fakeCameraSourcePath;
+ }
+
+ private static string GetExtension(FakeBrowserVideoSourceFileFormat format) =>
+ format switch
+ {
+ FakeBrowserVideoSourceFileFormat.MJpeg => "mjpeg",
+ FakeBrowserVideoSourceFileFormat.Y4m => "y4m",
+ _ => throw new ArgumentOutOfRangeException(nameof(format)),
+ };
+}
diff --git a/Lombiq.Tests.UI/Models/FakeBrowserVideoSource.cs b/Lombiq.Tests.UI/Models/FakeBrowserVideoSource.cs
new file mode 100644
index 000000000..9a869029f
--- /dev/null
+++ b/Lombiq.Tests.UI/Models/FakeBrowserVideoSource.cs
@@ -0,0 +1,19 @@
+using System;
+using System.IO;
+
+namespace Lombiq.Tests.UI.Models;
+
+public class FakeBrowserVideoSource
+{
+ ///
+ /// Gets or sets a callback that will be used to obtain the video content and will be saved and used
+ /// as a fake video capture file for the Chrome browser. The consumer will dispose of the returned
+ /// after the callback is called.
+ ///
+ public Func StreamProvider { get; set; }
+
+ ///
+ /// Gets or sets the video format of the provided stream.
+ ///
+ public FakeBrowserVideoSourceFileFormat Format { get; set; } = FakeBrowserVideoSourceFileFormat.MJpeg;
+}
diff --git a/Lombiq.Tests.UI/Models/FakeBrowserVideoSourceFileFormat.cs b/Lombiq.Tests.UI/Models/FakeBrowserVideoSourceFileFormat.cs
new file mode 100644
index 000000000..39c2c7745
--- /dev/null
+++ b/Lombiq.Tests.UI/Models/FakeBrowserVideoSourceFileFormat.cs
@@ -0,0 +1,7 @@
+namespace Lombiq.Tests.UI.Models;
+
+public enum FakeBrowserVideoSourceFileFormat
+{
+ MJpeg,
+ Y4m,
+}
diff --git a/Lombiq.Tests.UI/Services/BrowserConfiguration.cs b/Lombiq.Tests.UI/Services/BrowserConfiguration.cs
index 78fcf0adc..6a058e1aa 100644
--- a/Lombiq.Tests.UI/Services/BrowserConfiguration.cs
+++ b/Lombiq.Tests.UI/Services/BrowserConfiguration.cs
@@ -1,4 +1,5 @@
using Lombiq.Tests.UI.Constants;
+using Lombiq.Tests.UI.Models;
using SixLabors.ImageSharp;
using System;
using System.Globalization;
@@ -37,4 +38,9 @@ public class BrowserConfiguration
/// cref="CommonDisplayResolutions.Standard"/> when the setup is loaded.
///
public Size DefaultBrowserSize { get; set; } = CommonDisplayResolutions.Standard;
+
+ ///
+ /// Gets or sets the fake camera video source information. See: .
+ ///
+ public FakeBrowserVideoSource FakeVideoSource { get; set; }
}
diff --git a/Lombiq.Tests.UI/Services/WebDriverFactory.cs b/Lombiq.Tests.UI/Services/WebDriverFactory.cs
index 7a4e7bc3f..29de4ae23 100644
--- a/Lombiq.Tests.UI/Services/WebDriverFactory.cs
+++ b/Lombiq.Tests.UI/Services/WebDriverFactory.cs
@@ -1,3 +1,4 @@
+using Lombiq.Tests.UI.Extensions;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Chromium;
@@ -136,6 +137,15 @@ private static TDriverOptions SetCommonChromiumOptions(
// Disabling smooth scrolling to avoid large waiting time when taking full-page screenshots.
options.AddArgument("disable-smooth-scrolling");
+ if (configuration.FakeVideoSource is not null)
+ {
+ var fakeCameraSourceFilePath = configuration.FakeVideoSource.SaveVideoToTempFolder();
+
+ options.AddArgument("use-fake-device-for-media-stream");
+ options.AddArgument("use-fake-ui-for-media-stream");
+ options.AddArgument($"use-file-for-fake-video-capture={fakeCameraSourceFilePath}");
+ }
+
if (configuration.Headless) options.AddArgument("headless");
return options;
diff --git a/Readme.md b/Readme.md
index 58012e86a..baedb4487 100644
--- a/Readme.md
+++ b/Readme.md
@@ -24,6 +24,7 @@ Highlights:
- Ready to use GitHub Actions workflows for CI builds and support for test grouping and error annotations in [Lombiq GitHub Actions](https://github.com/features/actions). This feature is automatically enabled if a GitHub environment is detected.
- Support for [TeamCity test metadata reporting](https://www.jetbrains.com/help/teamcity/reporting-test-metadata.html) so you can see the important details and metrics of a test at a glance in a TeamCity CI/CD server.
- Visual verification testing: You can make the test fail if the look of the app changes. Demo video [here](https://www.youtube.com/watch?v=a-1zKjxTKkk).
+- Using video files as a fake video capture source in Chrome browser. Docs [here](Lombiq.Tests.UI/Docs/FakeVideoCaptureSource.md).
See a demo video of the project [here](https://www.youtube.com/watch?v=mEUg6-pad-E). Also, see our [Testing Toolbox](https://github.com/Lombiq/Testing-Toolbox) for similar features for lower-level tests.