Skip to content

Commit

Permalink
feat(page): introduce Page.Video (#958)
Browse files Browse the repository at this point in the history
  • Loading branch information
kblok authored Oct 20, 2020
1 parent 7927c3b commit afacf03
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/PlaywrightSharp.Tests/ScreencastTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,50 @@ public async Task ShouldCaptureStaticPage()
Assert.NotEmpty(new DirectoryInfo(tempDirectory.Path).GetFiles("*.webm"));
}

///<playwright-file>screencast.spec.js</playwright-file>
///<playwright-it>should expose video path</playwright-it>
[Fact(Timeout = PlaywrightSharp.Playwright.DefaultTimeout)]
public async Task ShouldExposeVideoPath()
{
using var tempDirectory = new TempDirectory();
var context = await Browser.NewContextAsync(
videosPath: tempDirectory.Path,
videoSize: new ViewportSize { Width = 100, Height = 100 });

var page = await context.NewPageAsync();
await page.EvaluateAsync("() => document.body.style.backgroundColor = 'red'");
string path = await page.Video.GetPathAsync();
Assert.Contains(tempDirectory.Path, path);
await context.CloseAsync();

Assert.True(new FileInfo(path).Exists);
}

///<playwright-file>screencast.spec.js</playwright-file>
///<playwright-it>should expose video path blank page</playwright-it>
[Fact(Timeout = PlaywrightSharp.Playwright.DefaultTimeout)]
public async Task ShouldExposeVideoPathBlankPage()
{
using var tempDirectory = new TempDirectory();
var context = await Browser.NewContextAsync(
videosPath: tempDirectory.Path,
videoSize: new ViewportSize { Width = 100, Height = 100 });

var page = await context.NewPageAsync();
string path = await page.Video.GetPathAsync();
Assert.Contains(tempDirectory.Path, path);
await context.CloseAsync();

Assert.True(new FileInfo(path).Exists);
}

///<playwright-file>screencast.spec.js</playwright-file>
///<playwright-it>should expose video path blank popup</playwright-it>
[Fact(Skip = "We don't need to test video details")]
public void ShouldExposeVideoPathBlankPopup()
{
}

///<playwright-file>screencast.spec.js</playwright-file>
///<playwright-it>should capture navigation</playwright-it>
[Fact(Skip = "We don't need to test video details")]
Expand Down
1 change: 1 addition & 0 deletions src/PlaywrightSharp/Browser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public Task<IBrowserContext> NewContextAsync(
public async Task<IBrowserContext> NewContextAsync(BrowserContextOptions options)
{
var context = (await Channel.NewContextAsync(options ?? new BrowserContextOptions()).ConfigureAwait(false)).Object;
context.Options = options;
BrowserContextsList.Add(context);
return context;
}
Expand Down
2 changes: 2 additions & 0 deletions src/PlaywrightSharp/BrowserContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public int DefaultNavigationTimeout

internal string BrowserName => _initializer.BrowserName;

internal BrowserContextOptions Options { get; set; }

/// <inheritdoc />
public async Task<IPage> NewPageAsync(string url = null)
{
Expand Down
5 changes: 5 additions & 0 deletions src/PlaywrightSharp/IPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ public interface IPage
/// </summary>
ICoverage Coverage { get; }

/// <summary>
/// Video object associated with this page.
/// </summary>
IVideo Video { get; }

/// <summary>
/// Returns page's title.
/// </summary>
Expand Down
17 changes: 17 additions & 0 deletions src/PlaywrightSharp/IVideo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Threading.Tasks;

namespace PlaywrightSharp
{
/// <summary>
/// When browser context is created with the videosPath option, each page has a video object associated with it.
/// </summary>
public interface IVideo
{
/// <summary>
/// Returns the file system path this video will be recorded to.
/// The video is guaranteed to be written to the filesystem upon closing the browser context.
/// </summary>
/// <returns>A <see cref="Task"/> that completes when the path has been resolved.</returns>
Task<string> GetPathAsync();
}
}
29 changes: 29 additions & 0 deletions src/PlaywrightSharp/Page.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class Page : ChannelOwnerBase, IChannelOwner<Page>, IPage
private List<RouteSetting> _routes = new List<RouteSetting>();
private EventHandler<FileChooserEventArgs> _fileChooserEventHandler;
private bool _fileChooserIntercepted;
private IVideo _video;

internal Page(IChannelOwner parent, string guid, PageInitializer initializer) : base(parent, guid)
{
Expand Down Expand Up @@ -68,6 +69,14 @@ internal Page(IChannelOwner parent, string guid, PageInitializer initializer) :
_channel.Download += (sender, e) => Download?.Invoke(this, e);
_channel.PageError += (sender, e) => PageError?.Invoke(this, e);
_channel.Load += (sender, e) => Load?.Invoke(this, e);
_channel.Video += (sender, e) =>
{
if (Video != null)
{
((Video)Video).SetRelativePath(e.RelativePath);
}
};

_channel.FileChooser += (sender, e) =>
{
_fileChooserEventHandler?.Invoke(this, new FileChooserEventArgs(this, e.Element.Object, e.IsMultiple));
Expand Down Expand Up @@ -234,6 +243,26 @@ public int DefaultNavigationTimeout
/// <inheritdoc />
public ICoverage Coverage { get; }

/// <inheritdoc />
public IVideo Video
{
get
{
if (_video != null)
{
return _video;
}

if (string.IsNullOrEmpty(BrowserContext.Options?.VideosPath))
{
return null;
}

_video = new Video(this);
return _video;
}
}

internal BrowserContext OwnedContext { get; set; }

internal Dictionary<string, Delegate> Bindings { get; } = new Dictionary<string, Delegate>();
Expand Down
5 changes: 5 additions & 0 deletions src/PlaywrightSharp/Transport/Channels/PageChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public PageChannel(string guid, Connection connection, Page owner) : base(guid,

internal event EventHandler<WorkerChannelEventArgs> Worker;

internal event EventHandler<VideoEventArgs> Video;

internal override void OnMessage(string method, JsonElement? serverParams)
{
switch (method)
Expand Down Expand Up @@ -125,6 +127,9 @@ internal override void OnMessage(string method, JsonElement? serverParams)
case "download":
Download?.Invoke(this, new DownloadEventArgs() { Download = serverParams?.GetProperty("download").ToObject<DownloadChannel>(Connection.GetDefaultJsonSerializerOptions()).Object });
break;
case "video":
Video?.Invoke(this, new VideoEventArgs() { RelativePath = serverParams?.GetProperty("relativePath").ToString() });
break;
case "worker":
Worker?.Invoke(
this,
Expand Down
9 changes: 9 additions & 0 deletions src/PlaywrightSharp/Transport/Channels/VideoEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace PlaywrightSharp.Transport.Channels
{
internal class VideoEventArgs : EventArgs
{
public string RelativePath { get; set; }
}
}
22 changes: 22 additions & 0 deletions src/PlaywrightSharp/Video.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.IO;
using System.Threading.Tasks;
using PlaywrightSharp.Transport;
using PlaywrightSharp.Transport.Channels;

namespace PlaywrightSharp
{
internal class Video : IVideo
{
private readonly Page _page;
private readonly TaskCompletionSource<string> _pathTask = new TaskCompletionSource<string>();

public Video(Page page) => _page = page;

/// <inheritdoc/>
public Task<string> GetPathAsync() => _pathTask.Task;

internal void SetRelativePath(string relativePath)
=> _pathTask.TrySetResult(Path.Combine(_page.BrowserContext.Options.VideosPath, relativePath));
}
}

0 comments on commit afacf03

Please sign in to comment.