/*
* MIT License
*
* Copyright (c) 2020 DarÃo Kondratiuk
* Copyright (c) 2020 Meir Blachman
* Modifications copyright (c) Microsoft Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Playwright.Helpers;
using Microsoft.Playwright.Transport;
using Microsoft.Playwright.Transport.Channels;
using Microsoft.Playwright.Transport.Protocol;
namespace Microsoft.Playwright.Core
{
internal partial class Page : ChannelOwnerBase, IChannelOwner<Page>, IPage
{
private readonly PageChannel _channel;
private readonly List<Frame> _frames = new();
private readonly List<(IEvent PageEvent, TaskCompletionSource<bool> WaitTcs)> _waitForCancellationTcs = new();
private readonly object _fileChooserEventLock = new();
private readonly IAccessibility _accessibility;
private readonly IMouse _mouse;
private readonly IKeyboard _keyboard;
private readonly ITouchscreen _touchscreen;
private readonly PageInitializer _initializer;
private List<RouteSetting> _routes = new();
private EventHandler<IFileChooser> _fileChooserEventHandler;
private bool _fileChooserIntercepted;
private Video _video;
private float _defaultNavigationTimeout;
private float _defaultTimeout;
internal Page(IChannelOwner parent, string guid, PageInitializer initializer) : base(parent, guid)
{
Context = (BrowserContext)parent;
_channel = new(guid, parent.Connection, this);
MainFrame = initializer.MainFrame;
MainFrame.Page = this;
_frames.Add(MainFrame);
if (initializer.ViewportSize != null)
{
ViewportSize = new() { Width = initializer.ViewportSize.Width, Height = initializer.ViewportSize.Height };
}
IsClosed = initializer.IsClosed;
_accessibility = new Accessibility(_channel);
_keyboard = new Keyboard(_channel);
_touchscreen = new Touchscreen(_channel);
_mouse = new Mouse(_channel);
_channel.Closed += (_, _) => OnClose();
_channel.Crashed += Channel_Crashed;
_channel.Popup += (_, e) => Popup?.Invoke(this, e.Page);
_channel.WebSocket += (_, e) => WebSocket?.Invoke(this, e);
_channel.BindingCall += Channel_BindingCall;
_channel.Route += (_, e) => OnRoute(e.Route, e.Request);
_channel.FrameAttached += Channel_FrameAttached;
_channel.FrameDetached += Channel_FrameDetached;
_channel.Dialog += (_, e) =>
{
if (Dialog == null)
{
if ("beforeunload".Equals(e.Type, StringComparison.Ordinal))
{
e.AcceptAsync(null).IgnoreException();
}
else
{
e.DismissAsync().IgnoreException();
}
}
else
{
Dialog?.Invoke(this, e);
}
};
_channel.Console += (_, e) => Console?.Invoke(this, e);
_channel.DOMContentLoaded += (_, _) => DOMContentLoaded?.Invoke(this, this);
_channel.Download += (_, e) => Download?.Invoke(this, new Download(this, e.Url, e.SuggestedFilename, e.Artifact.Object));
_channel.PageError += (_, e) => PageError?.Invoke(this, e.ToString());
_channel.Load += (_, _) => Load?.Invoke(this, this);
_channel.Video += (_, e) => ForceVideo().ArtifactReady(e.Artifact);
_channel.FileChooser += (_, e) => _fileChooserEventHandler?.Invoke(this, new FileChooser(this, e.Element.Object, e.IsMultiple));
_channel.Worker += (_, e) =>
{
WorkersList.Add(e.WorkerChannel.Object);
e.WorkerChannel.Object.Page = this;
Worker?.Invoke(this, e.WorkerChannel.Object);
};
_defaultNavigationTimeout = Context.DefaultNavigationTimeout;
_defaultTimeout = Context.DefaultTimeout;
_initializer = initializer;
Close += (_, _) => ClosedOrCrashedTcs.TrySetResult(true);
Crash += (_, _) => ClosedOrCrashedTcs.TrySetResult(true);
}
public event EventHandler<IConsoleMessage> Console;
public event EventHandler<IPage> Popup;
public event EventHandler<IRequest> Request;
public event EventHandler<IWebSocket> WebSocket;
public event EventHandler<IResponse> Response;
public event EventHandler<IRequest> RequestFinished;
public event EventHandler<IRequest> RequestFailed;
public event EventHandler<IDialog> Dialog;
public event EventHandler<IFrame> FrameAttached;
public event EventHandler<IFrame> FrameDetached;
public event EventHandler<IFrame> FrameNavigated;
public event EventHandler<IFileChooser> FileChooser
{
add
{
lock (_fileChooserEventLock)
{
_fileChooserEventHandler += value;
_fileChooserIntercepted = true;
_channel.SetFileChooserInterceptedNoReplyAsync(true).IgnoreException();
}
}
remove
{
lock (_fileChooserEventLock)
{
_fileChooserEventHandler -= value;
if (_fileChooserIntercepted)
{
_fileChooserIntercepted = false;
_channel.SetFileChooserInterceptedNoReplyAsync(false).IgnoreException();
}
}
}
}
public event EventHandler<IPage> Load;
public event EventHandler<IPage> DOMContentLoaded;
public event EventHandler<IPage> Close;
public event EventHandler<IPage> Crash;
public event EventHandler<string> PageError;
public event EventHandler<IWorker> Worker;
public event EventHandler<IDownload> Download;
ChannelBase IChannelOwner.Channel => _channel;
IChannel<Page> IChannelOwner<Page>.Channel => _channel;
public bool IsClosed { get; private set; }
IFrame IPage.MainFrame => MainFrame;
public Frame MainFrame { get; }
IBrowserContext IPage.Context => Context;
public BrowserContext Context { get; set; }
public PageViewportSizeResult ViewportSize { get; private set; }
public IAccessibility Accessibility
{
get => _accessibility;
set => throw new NotSupportedException();
}
public IMouse Mouse
{
get => _mouse;
set => throw new NotSupportedException();
}
public string Url => MainFrame.Url;
public IReadOnlyList<IFrame> Frames => _frames.AsReadOnly();
public IKeyboard Keyboard
{
get => _keyboard;
}
public ITouchscreen Touchscreen
{
get => _touchscreen;
}
public IReadOnlyList<IWorker> Workers => WorkersList;
public IVideo Video
{
get
{
if (Context.Options.RecordVideoDir == null)
{
return null;
}
return ForceVideo();
}
set => _video = value as Video;
}
internal BrowserContext OwnedContext { get; set; }
internal Dictionary<string, Delegate> Bindings { get; } = new();
internal List<Worker> WorkersList { get; } = new();
internal Page Opener => _initializer.Opener;
internal PageChannel Channel => _channel;
internal float DefaultTimeout
{
get => _defaultTimeout;
set
{
_defaultTimeout = value;
_channel.SetDefaultTimeoutNoReplyAsync(value).IgnoreException();
}
}
internal float DefaultNavigationTimeout
{
get => _defaultNavigationTimeout;
set
{
_defaultNavigationTimeout = value;
_channel.SetDefaultNavigationTimeoutNoReplyAsync(value).IgnoreException();
}
}
internal TaskCompletionSource<bool> ClosedOrCrashedTcs { get; } = new();
public IFrame Frame(string name)
=> Frames.FirstOrDefault(f => f.Name == name);
public IFrame FrameByUrl(string urlString) => Frames.FirstOrDefault(f => Context.UrlMatches(urlString, f.Url));
public IFrame FrameByUrl(Regex urlRegex) => Frames.FirstOrDefault(f => urlRegex.IsMatch(f.Url));
public IFrame FrameByUrl(Func<string, bool> urlFunc) => Frames.FirstOrDefault(f => urlFunc(f.Url));
IFrameLocator IPage.FrameLocator(string selector) => MainFrame.FrameLocator(selector);
public Task<string> TitleAsync() => MainFrame.TitleAsync();
public Task BringToFrontAsync() => _channel.BringToFrontAsync();
public Task<IPage> OpenerAsync() => Task.FromResult<IPage>(Opener?.IsClosed == false ? Opener : null);
public Task EmulateMediaAsync(PageEmulateMediaOptions options = default)
{
var args = new Dictionary<string, object>
{
["media"] = options?.Media,
["colorScheme"] = options?.ColorScheme,
["reducedMotion"] = options?.ReducedMotion,
["forcedColors"] = options?.ForcedColors,
};
return _channel.EmulateMediaAsync(args);
}
public Task<IResponse> GotoAsync(string url, PageGotoOptions options = default)
=> MainFrame.GotoAsync(url, new() { WaitUntil = options?.WaitUntil, Timeout = options?.Timeout, Referer = options?.Referer });
public Task WaitForURLAsync(string url, PageWaitForURLOptions options = default)
=> MainFrame.WaitForURLAsync(url, new() { WaitUntil = options?.WaitUntil, Timeout = options?.Timeout });
public Task WaitForURLAsync(Regex url, PageWaitForURLOptions options = default)
=> MainFrame.WaitForURLAsync(url, new() { WaitUntil = options?.WaitUntil, Timeout = options?.Timeout });
public Task WaitForURLAsync(Func<string, bool> url, PageWaitForURLOptions options = default)
=> MainFrame.WaitForURLAsync(url, new() { WaitUntil = options?.WaitUntil, Timeout = options?.Timeout });
public Task<IConsoleMessage> WaitForConsoleMessageAsync(PageWaitForConsoleMessageOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Console, null, options?.Predicate, options?.Timeout);
public Task<IFileChooser> WaitForFileChooserAsync(PageWaitForFileChooserOptions options = default)
=> InnerWaitForEventAsync(PageEvent.FileChooser, null, options?.Predicate, options?.Timeout);
public Task<IPage> WaitForPopupAsync(PageWaitForPopupOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Popup, null, options?.Predicate, options?.Timeout);
public Task<IWebSocket> WaitForWebSocketAsync(PageWaitForWebSocketOptions options = default)
=> InnerWaitForEventAsync(PageEvent.WebSocket, null, options?.Predicate, options?.Timeout);
public Task<IWorker> WaitForWorkerAsync(PageWaitForWorkerOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Worker, null, options?.Predicate, options?.Timeout);
public Task<IResponse> WaitForNavigationAsync(PageWaitForNavigationOptions options = default)
=> MainFrame.WaitForNavigationAsync(new()
{
UrlString = options?.UrlString,
UrlRegex = options?.UrlRegex,
UrlFunc = options?.UrlFunc,
WaitUntil = options?.WaitUntil,
Timeout = options?.Timeout,
});
public Task<IResponse> RunAndWaitForNavigationAsync(Func<Task> action, PageRunAndWaitForNavigationOptions options = default)
=> MainFrame.RunAndWaitForNavigationAsync(action, new()
{
UrlString = options?.UrlString,
UrlRegex = options?.UrlRegex,
UrlFunc = options?.UrlFunc,
WaitUntil = options?.WaitUntil,
Timeout = options?.Timeout,
});
public Task<IRequest> WaitForRequestAsync(string urlOrPredicate, PageWaitForRequestOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Request, null, e => Context.UrlMatches(e.Url, urlOrPredicate), options?.Timeout);
public Task<IRequest> WaitForRequestAsync(Regex urlOrPredicate, PageWaitForRequestOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Request, null, e => urlOrPredicate.IsMatch(e.Url), options?.Timeout);
public Task<IRequest> WaitForRequestAsync(Func<IRequest, bool> urlOrPredicate, PageWaitForRequestOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Request, null, e => urlOrPredicate(e), options?.Timeout);
public Task<IRequest> WaitForRequestFinishedAsync(PageWaitForRequestFinishedOptions options = default)
=> InnerWaitForEventAsync(PageEvent.RequestFinished, null, options?.Predicate, options?.Timeout);
public Task<IResponse> WaitForResponseAsync(string urlOrPredicate, PageWaitForResponseOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Response, null, e => Context.UrlMatches(e.Url, urlOrPredicate), options?.Timeout);
public Task<IResponse> WaitForResponseAsync(Regex urlOrPredicate, PageWaitForResponseOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Response, null, e => urlOrPredicate.IsMatch(e.Url), options?.Timeout);
public Task<IResponse> WaitForResponseAsync(Func<IResponse, bool> urlOrPredicate, PageWaitForResponseOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Response, null, e => urlOrPredicate(e), options?.Timeout);
public Task<IConsoleMessage> RunAndWaitForConsoleMessageAsync(Func<Task> action, PageRunAndWaitForConsoleMessageOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Console, action, options?.Predicate, options?.Timeout);
public Task<IDownload> WaitForDownloadAsync(PageWaitForDownloadOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Download, null, options?.Predicate, options?.Timeout);
public Task<IDownload> RunAndWaitForDownloadAsync(Func<Task> action, PageRunAndWaitForDownloadOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Download, action, options?.Predicate, options?.Timeout);
public Task<IFileChooser> RunAndWaitForFileChooserAsync(Func<Task> action, PageRunAndWaitForFileChooserOptions options = default)
=> InnerWaitForEventAsync(PageEvent.FileChooser, action, options?.Predicate, options?.Timeout);
public Task<IPage> RunAndWaitForPopupAsync(Func<Task> action, PageRunAndWaitForPopupOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Popup, action, options?.Predicate, options?.Timeout);
public Task<IRequest> RunAndWaitForRequestFinishedAsync(Func<Task> action, PageRunAndWaitForRequestFinishedOptions options = default)
=> InnerWaitForEventAsync(PageEvent.RequestFinished, action, options?.Predicate, options?.Timeout);
public Task<IWebSocket> RunAndWaitForWebSocketAsync(Func<Task> action, PageRunAndWaitForWebSocketOptions options = default)
=> InnerWaitForEventAsync(PageEvent.WebSocket, action, options?.Predicate, options?.Timeout);
public Task<IWorker> RunAndWaitForWorkerAsync(Func<Task> action, PageRunAndWaitForWorkerOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Worker, action, options?.Predicate, options?.Timeout);
public Task<IRequest> RunAndWaitForRequestAsync(Func<Task> action, string urlOrPredicate, PageRunAndWaitForRequestOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Request, action, e => Context.UrlMatches(e.Url, urlOrPredicate), options?.Timeout);
public Task<IRequest> RunAndWaitForRequestAsync(Func<Task> action, Regex urlOrPredicate, PageRunAndWaitForRequestOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Request, action, e => urlOrPredicate.IsMatch(e.Url), options?.Timeout);
public Task<IRequest> RunAndWaitForRequestAsync(Func<Task> action, Func<IRequest, bool> urlOrPredicate, PageRunAndWaitForRequestOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Request, action, e => urlOrPredicate(e), options?.Timeout);
public Task<IResponse> RunAndWaitForResponseAsync(Func<Task> action, string urlOrPredicate, PageRunAndWaitForResponseOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Response, action, e => Context.UrlMatches(e.Url, urlOrPredicate), options?.Timeout);
public Task<IResponse> RunAndWaitForResponseAsync(Func<Task> action, Regex urlOrPredicate, PageRunAndWaitForResponseOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Response, action, e => urlOrPredicate.IsMatch(e.Url), options?.Timeout);
public Task<IResponse> RunAndWaitForResponseAsync(Func<Task> action, Func<IResponse, bool> urlOrPredicate, PageRunAndWaitForResponseOptions options = default)
=> InnerWaitForEventAsync(PageEvent.Response, action, e => urlOrPredicate(e), options?.Timeout);
public Task<IJSHandle> WaitForFunctionAsync(string expression, object arg = default, PageWaitForFunctionOptions options = default)
=> MainFrame.WaitForFunctionAsync(expression, arg, new() { PollingInterval = options?.PollingInterval, Timeout = options?.Timeout });
public async Task<T> InnerWaitForEventAsync<T>(PlaywrightEvent<T> pageEvent, Func<Task> action = default, Func<T, bool> predicate = default, float? timeout = default)
{
if (pageEvent == null)
{
throw new ArgumentException("Page event is required", nameof(pageEvent));
}
timeout ??= _defaultTimeout;
using var waiter = new Waiter(this, $"page.WaitForEventAsync(\"{typeof(T)}\")");
waiter.RejectOnTimeout(Convert.ToInt32(timeout), $"Timeout {timeout}ms exceeded while waiting for event \"{pageEvent.Name}\"");
if (pageEvent.Name != PageEvent.Crash.Name)
{
waiter.RejectOnEvent<IPage>(this, PageEvent.Crash.Name, new("Page crashed"));
}
if (pageEvent.Name != PageEvent.Close.Name)
{
waiter.RejectOnEvent<IPage>(this, PageEvent.Close.Name, new("Page closed"));
}
var result = waiter.WaitForEventAsync(this, pageEvent.Name, predicate);
if (action != null)
{
await WrapApiBoundaryAsync(() => Task.WhenAll(result, action())).ConfigureAwait(false);
}
return await result.ConfigureAwait(false);
}
public async Task CloseAsync(PageCloseOptions options = default)
{
try
{
await _channel.CloseAsync(options?.RunBeforeUnload ?? false).ConfigureAwait(false);
if (OwnedContext != null)
{
await OwnedContext.CloseAsync().ConfigureAwait(false);
}
}
catch (Exception e) when (DriverMessages.IsSafeCloseError(e))
{
// Swallow exception
}
}
public Task<T> EvaluateAsync<T>(string expression, object arg) => MainFrame.EvaluateAsync<T>(expression, arg);
public Task<JsonElement?> EvalOnSelectorAsync(string selector, string expression, object arg) => MainFrame.EvalOnSelectorAsync(selector, expression, arg);
public Task<T> EvalOnSelectorAsync<T>(string selector, string expression, object arg = null, PageEvalOnSelectorOptions options = null)
=> MainFrame.EvalOnSelectorAsync<T>(selector, expression, arg, new() { Strict = options?.Strict });
public ILocator Locator(string selector, PageLocatorOptions options = default)
=> MainFrame.Locator(selector, new() { HasTextString = options?.HasTextString, HasTextRegex = options?.HasTextRegex, Has = options?.Has });
public Task<IElementHandle> QuerySelectorAsync(string selector, PageQuerySelectorOptions options = null)
=> MainFrame.QuerySelectorAsync(selector, new() { Strict = options?.Strict });
public Task<T> EvalOnSelectorAsync<T>(string selector, string expression, object arg) => MainFrame.EvalOnSelectorAsync<T>(selector, expression, arg);
public Task<JsonElement?> EvalOnSelectorAllAsync(string selector, string expression, object arg) => MainFrame.EvalOnSelectorAllAsync(selector, expression, arg);
public Task<T> EvalOnSelectorAllAsync<T>(string selector, string expression, object arg) => MainFrame.EvalOnSelectorAllAsync<T>(selector, expression, arg);
public Task FillAsync(string selector, string value, PageFillOptions options = default)
=> MainFrame.FillAsync(selector, value, new() { NoWaitAfter = options?.NoWaitAfter, Timeout = options?.Timeout, Force = options?.Force, Strict = options?.Strict });
public Task SetInputFilesAsync(string selector, string files, PageSetInputFilesOptions options = default)
=> MainFrame.SetInputFilesAsync(selector, files, Map(options));
public Task SetInputFilesAsync(string selector, IEnumerable<string> files, PageSetInputFilesOptions options = default)
=> MainFrame.SetInputFilesAsync(selector, files, Map(options));
public Task SetInputFilesAsync(string selector, FilePayload files, PageSetInputFilesOptions options = default)
=> MainFrame.SetInputFilesAsync(selector, files, Map(options));
public Task SetInputFilesAsync(string selector, IEnumerable<FilePayload> files, PageSetInputFilesOptions options = default)
=> MainFrame.SetInputFilesAsync(selector, files, Map(options));
public Task TypeAsync(string selector, string text, PageTypeOptions options = default)
=> MainFrame.TypeAsync(selector, text, new()
{
Delay = options?.Delay,
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task FocusAsync(string selector, PageFocusOptions options = default)
=> MainFrame.FocusAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task HoverAsync(string selector, PageHoverOptions options = default)
=> MainFrame.HoverAsync(
selector,
new()
{
Position = options?.Position,
Modifiers = options?.Modifiers,
Force = options?.Force,
Timeout = options?.Timeout,
Trial = options?.Trial,
Strict = options?.Strict,
});
public Task PressAsync(string selector, string key, PagePressOptions options = default)
=> MainFrame.PressAsync(selector, key, new()
{
Delay = options?.Delay,
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, string values, PageSelectOptionOptions options = default)
=> SelectOptionAsync(selector, new[] { values }, options);
public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IEnumerable<string> values, PageSelectOptionOptions options = default)
=> SelectOptionAsync(selector, values.Select(x => new SelectOptionValue() { Value = x }), options);
public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IElementHandle values, PageSelectOptionOptions options = default)
=> SelectOptionAsync(selector, new[] { values }, options);
public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IEnumerable<IElementHandle> values, PageSelectOptionOptions options = default)
=> MainFrame.SelectOptionAsync(selector, values, new()
{
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Force = options?.Force,
Strict = options?.Strict,
});
public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, SelectOptionValue values, PageSelectOptionOptions options = default)
=> SelectOptionAsync(selector, new[] { values }, options);
public Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IEnumerable<SelectOptionValue> values, PageSelectOptionOptions options = default)
=> MainFrame.SelectOptionAsync(selector, values, new()
{
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Force = options?.Force,
Strict = options?.Strict,
});
public Task WaitForTimeoutAsync(float timeout) => MainFrame.WaitForTimeoutAsync(timeout);
public Task<IElementHandle> WaitForSelectorAsync(string selector, PageWaitForSelectorOptions options = default)
=> MainFrame.WaitForSelectorAsync(selector, new()
{
State = options?.State,
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<JsonElement?> EvaluateAsync(string expression, object arg) => MainFrame.EvaluateAsync(expression, arg);
public async Task<byte[]> ScreenshotAsync(PageScreenshotOptions options = default)
{
options ??= new PageScreenshotOptions();
if (options.Type == null && !string.IsNullOrEmpty(options.Path))
{
options.Type = ElementHandle.DetermineScreenshotType(options.Path);
}
byte[] result = await _channel.ScreenshotAsync(
path: options.Path,
fullPage: options.FullPage,
clip: options.Clip,
omitBackground: options.OmitBackground,
type: options.Type,
quality: options.Quality,
mask: options.Mask,
animations: options.Animations,
caret: options.Caret,
scale: options.Scale,
timeout: options.Timeout).ConfigureAwait(false);
if (!string.IsNullOrEmpty(options.Path))
{
Directory.CreateDirectory(new FileInfo(options.Path).Directory.FullName);
File.WriteAllBytes(options.Path, result);
}
return result;
}
public Task SetContentAsync(string html, PageSetContentOptions options = default)
=> MainFrame.SetContentAsync(html, new() { WaitUntil = options?.WaitUntil, Timeout = options?.Timeout });
public Task<string> ContentAsync() => MainFrame.ContentAsync();
public Task SetExtraHTTPHeadersAsync(IEnumerable<KeyValuePair<string, string>> headers)
=> _channel.SetExtraHTTPHeadersAsync(headers);
public Task<IElementHandle> QuerySelectorAsync(string selector) => MainFrame.QuerySelectorAsync(selector);
public Task<IReadOnlyList<IElementHandle>> QuerySelectorAllAsync(string selector)
=> MainFrame.QuerySelectorAllAsync(selector);
public Task<IJSHandle> EvaluateHandleAsync(string expression, object arg) => MainFrame.EvaluateHandleAsync(expression, arg);
public Task<IElementHandle> AddScriptTagAsync(PageAddScriptTagOptions options = default)
=> MainFrame.AddScriptTagAsync(new()
{
Url = options?.Url,
Path = options?.Path,
Content = options?.Content,
Type = options?.Type,
});
public Task<IElementHandle> AddStyleTagAsync(PageAddStyleTagOptions options = default)
=> MainFrame.AddStyleTagAsync(new()
{
Url = options?.Url,
Path = options?.Path,
Content = options?.Content,
});
public Task ClickAsync(string selector, PageClickOptions options = default)
=> MainFrame.ClickAsync(
selector,
new()
{
Button = options?.Button,
ClickCount = options?.ClickCount,
Delay = options?.Delay,
Position = options?.Position,
Modifiers = options?.Modifiers,
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Trial = options?.Trial,
Strict = options?.Strict,
});
public Task DblClickAsync(string selector, PageDblClickOptions options = default)
=> MainFrame.DblClickAsync(selector, new()
{
Delay = options?.Delay,
Button = options?.Button,
Position = options?.Position,
Modifiers = options?.Modifiers,
Timeout = options?.Timeout,
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Trial = options?.Trial,
Strict = options?.Strict,
});
public async Task<IResponse> GoBackAsync(PageGoBackOptions options = default)
=> (await _channel.GoBackAsync(options?.Timeout, options?.WaitUntil).ConfigureAwait(false))?.Object;
public async Task<IResponse> GoForwardAsync(PageGoForwardOptions options = default)
=> (await _channel.GoForwardAsync(options?.Timeout, options?.WaitUntil).ConfigureAwait(false))?.Object;
public async Task<IResponse> ReloadAsync(PageReloadOptions options = default)
=> (await _channel.ReloadAsync(options?.Timeout, options?.WaitUntil).ConfigureAwait(false))?.Object;
public Task ExposeBindingAsync(string name, Action callback, PageExposeBindingOptions options = default)
=> InnerExposeBindingAsync(name, (Delegate)callback, options?.Handle ?? false);
public Task ExposeBindingAsync(string name, Action<BindingSource> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback);
public Task ExposeBindingAsync<T>(string name, Action<BindingSource, T> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback);
public Task ExposeBindingAsync<TResult>(string name, Func<BindingSource, TResult> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback);
public Task ExposeBindingAsync<TResult>(string name, Func<BindingSource, IJSHandle, TResult> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback, true);
public Task ExposeBindingAsync<T, TResult>(string name, Func<BindingSource, T, TResult> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback);
public Task ExposeBindingAsync<T1, T2, TResult>(string name, Func<BindingSource, T1, T2, TResult> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback);
public Task ExposeBindingAsync<T1, T2, T3, TResult>(string name, Func<BindingSource, T1, T2, T3, TResult> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback);
public Task ExposeBindingAsync<T1, T2, T3, T4, TResult>(string name, Func<BindingSource, T1, T2, T3, T4, TResult> callback)
=> InnerExposeBindingAsync(name, (Delegate)callback);
public Task ExposeFunctionAsync(string name, Action callback)
=> ExposeBindingAsync(name, (BindingSource _) => callback());
public Task ExposeFunctionAsync<T>(string name, Action<T> callback)
=> ExposeBindingAsync(name, (BindingSource _, T t) => callback(t));
public Task ExposeFunctionAsync<TResult>(string name, Func<TResult> callback)
=> ExposeBindingAsync(name, (BindingSource _) => callback());
public Task ExposeFunctionAsync<T, TResult>(string name, Func<T, TResult> callback)
=> ExposeBindingAsync(name, (BindingSource _, T t) => callback(t));
public Task ExposeFunctionAsync<T1, T2, TResult>(string name, Func<T1, T2, TResult> callback)
=> ExposeBindingAsync(name, (BindingSource _, T1 t1, T2 t2) => callback(t1, t2));
public Task ExposeFunctionAsync<T1, T2, T3, TResult>(string name, Func<T1, T2, T3, TResult> callback)
=> ExposeBindingAsync(name, (BindingSource _, T1 t1, T2 t2, T3 t3) => callback(t1, t2, t3));
public Task ExposeFunctionAsync<T1, T2, T3, T4, TResult>(string name, Func<T1, T2, T3, T4, TResult> callback)
=> ExposeBindingAsync(name, (BindingSource _, T1 t1, T2 t2, T3 t3, T4 t4) => callback(t1, t2, t3, t4));
public async Task<byte[]> PdfAsync(PagePdfOptions options = default)
{
if (!Context.IsChromium)
{
throw new NotSupportedException("This browser doesn't support this action.");
}
byte[] result = await _channel.PdfAsync(
scale: options?.Scale,
displayHeaderFooter: options?.DisplayHeaderFooter,
headerTemplate: options?.HeaderTemplate,
footerTemplate: options?.FooterTemplate,
printBackground: options?.PrintBackground,
landscape: options?.Landscape,
pageRanges: options?.PageRanges,
format: options?.Format,
width: options?.Width,
height: options?.Height,
margin: options?.Margin,
preferCSSPageSize: options?.PreferCSSPageSize).ConfigureAwait(false);
if (!string.IsNullOrEmpty(options?.Path))
{
Directory.CreateDirectory(new FileInfo(options.Path).Directory.FullName);
File.WriteAllBytes(options.Path, result);
}
return result;
}
public Task AddInitScriptAsync(string script, string scriptPath)
=> _channel.AddInitScriptAsync(ScriptsHelper.EvaluationScript(script, scriptPath));
public Task RouteAsync(string url, Action<IRoute> handler, PageRouteOptions options = null)
=> RouteAsync(new Regex(Context.CombineUrlWithBase(url).GlobToRegex()), null, handler, options);
public Task RouteAsync(Regex url, Action<IRoute> handler, PageRouteOptions options = null)
=> RouteAsync(url, null, handler, options);
public Task RouteAsync(Func<string, bool> url, Action<IRoute> handler, PageRouteOptions options = null)
=> RouteAsync(null, url, handler, options);
public Task UnrouteAsync(string urlString, Action<IRoute> handler)
=> UnrouteAsync(new Regex(Context.CombineUrlWithBase(urlString).GlobToRegex()), null, handler);
public Task UnrouteAsync(Regex urlString, Action<IRoute> handler)
=> UnrouteAsync(urlString, null, handler);
public Task UnrouteAsync(Func<string, bool> urlFunc, Action<IRoute> handler)
=> UnrouteAsync(null, urlFunc, handler);
public Task WaitForLoadStateAsync(LoadState? state = default, PageWaitForLoadStateOptions options = default)
=> MainFrame.WaitForLoadStateAsync(state, new() { Timeout = options?.Timeout });
public Task SetViewportSizeAsync(int width, int height)
{
ViewportSize = new() { Width = width, Height = height };
return _channel.SetViewportSizeAsync(ViewportSize);
}
public Task SetCheckedAsync(string selector, bool checkedState, PageSetCheckedOptions options = null)
=> checkedState ?
MainFrame.CheckAsync(selector, new()
{
Position = options?.Position,
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Strict = options?.Strict,
Timeout = options?.Timeout,
Trial = options?.Trial,
})
: MainFrame.UncheckAsync(selector, new()
{
Position = options?.Position,
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Trial = options?.Trial,
Strict = options?.Strict,
});
public Task CheckAsync(string selector, PageCheckOptions options = default)
=> MainFrame.CheckAsync(selector, new()
{
Position = options?.Position,
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Strict = options?.Strict,
Timeout = options?.Timeout,
Trial = options?.Trial,
});
public Task UncheckAsync(string selector, PageUncheckOptions options = default)
=> MainFrame.UncheckAsync(selector, new()
{
Position = options?.Position,
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Trial = options?.Trial,
Strict = options?.Strict,
});
public Task DispatchEventAsync(string selector, string type, object eventInit = default, PageDispatchEventOptions options = default)
=> MainFrame.DispatchEventAsync(selector, type, eventInit, new() { Timeout = options?.Timeout, Strict = options?.Strict });
public Task<string> GetAttributeAsync(string selector, string name, PageGetAttributeOptions options = default)
=> MainFrame.GetAttributeAsync(selector, name, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<string> InnerHTMLAsync(string selector, PageInnerHTMLOptions options = default)
=> MainFrame.InnerHTMLAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<string> InnerTextAsync(string selector, PageInnerTextOptions options = default)
=> MainFrame.InnerTextAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<string> TextContentAsync(string selector, PageTextContentOptions options = default)
=> MainFrame.TextContentAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task TapAsync(string selector, PageTapOptions options = default)
=> MainFrame.TapAsync(
selector,
new()
{
Modifiers = options?.Modifiers,
Position = options?.Position,
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Trial = options?.Trial,
Strict = options?.Strict,
});
public Task<bool> IsCheckedAsync(string selector, PageIsCheckedOptions options = default)
=> MainFrame.IsCheckedAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<bool> IsDisabledAsync(string selector, PageIsDisabledOptions options = default)
=> MainFrame.IsDisabledAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<bool> IsEditableAsync(string selector, PageIsEditableOptions options = default)
=> MainFrame.IsEditableAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<bool> IsEnabledAsync(string selector, PageIsEnabledOptions options = default)
=> MainFrame.IsEnabledAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
#pragma warning disable CS0612 // Type or member is obsolete
public Task<bool> IsHiddenAsync(string selector, PageIsHiddenOptions options = default)
=> MainFrame.IsHiddenAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task<bool> IsVisibleAsync(string selector, PageIsVisibleOptions options = default)
=> MainFrame.IsVisibleAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
#pragma warning restore CS0612 // Type or member is obsolete
public Task PauseAsync() => Context.Channel.PauseAsync();
public void SetDefaultNavigationTimeout(float timeout) => DefaultNavigationTimeout = timeout;
public void SetDefaultTimeout(float timeout) => DefaultTimeout = timeout;
public Task<string> InputValueAsync(string selector, PageInputValueOptions options = null)
=> MainFrame.InputValueAsync(selector, new()
{
Timeout = options?.Timeout,
Strict = options?.Strict,
});
public Task DragAndDropAsync(string source, string target, PageDragAndDropOptions options = null)
=> MainFrame.DragAndDropAsync(source, target, new()
{
Force = options?.Force,
NoWaitAfter = options?.NoWaitAfter,
Timeout = options?.Timeout,
Trial = options?.Trial,
Strict = options?.Strict,
});
internal void NotifyPopup(Page page) => Popup?.Invoke(this, page);
internal void OnFrameNavigated(Frame frame)
=> FrameNavigated?.Invoke(this, frame);
internal void FireRequest(IRequest request) => Request?.Invoke(this, request);
internal void FireRequestFailed(IRequest request) => RequestFailed?.Invoke(this, request);
internal void FireRequestFinished(IRequest request) => RequestFinished?.Invoke(this, request);
internal void FireResponse(IResponse response) => Response?.Invoke(this, response);
private Task RouteAsync(Regex urlRegex, Func<string, bool> urlFunc, Action<IRoute> handler, PageRouteOptions options)
=> RouteAsync(new()
{
Regex = urlRegex,
Function = urlFunc,
Handler = handler,
Times = options?.Times,
});
private Task RouteAsync(RouteSetting setting)
{
_routes.Insert(0, setting);
if (_routes.Count == 1)
{
return _channel.SetNetworkInterceptionEnabledAsync(true);
}
return Task.CompletedTask;
}
private Task UnrouteAsync(Regex urlRegex, Func<string, bool> urlFunc, Action<IRoute> handler = null)
=> UnrouteAsync(new()
{
Function = urlFunc,
Regex = urlRegex,
Handler = handler,
});
private Task UnrouteAsync(RouteSetting setting)
{
var newRoutesList = new List<RouteSetting>();
newRoutesList.AddRange(_routes.Where(r =>
(setting.Regex != null && !(r.Regex == setting.Regex || (r.Regex.ToString() == setting.Regex.ToString() && r.Regex.Options == setting.Regex.Options))) ||
(setting.Function != null && r.Function != setting.Function) ||
(setting.Handler != null && r.Handler != setting.Handler)));
_routes = newRoutesList;
if (_routes.Count == 0)
{
return DisableInterceptionAsync();
}
return Task.CompletedTask;
}
internal void OnClose()
{
IsClosed = true;
Context?.PagesList.Remove(this);
RejectPendingOperations(false);
Close?.Invoke(this, this);
}
private void Channel_Crashed(object sender, EventArgs e)
{
RejectPendingOperations(true);
Crash?.Invoke(this, this);
}
private void Channel_BindingCall(object sender, BindingCallEventArgs e)
{
if (Bindings.TryGetValue(e.BindingCall.Name, out var binding))
{
_ = e.BindingCall.CallAsync(binding);
}
}
private void OnRoute(Route route, IRequest request)
{
foreach (var routeHandler in _routes.ToList())
{
if ((routeHandler.Regex?.IsMatch(request.Url) == true) ||
(routeHandler.Function?.Invoke(request.Url) == true))
{
try
{
routeHandler.Handle(route);
}
finally
{
if (!routeHandler.IsActive())
{
_routes.Remove(routeHandler);
if (_routes.Count == 0)
{
DisableInterceptionAsync().ConfigureAwait(false);
}
}
}
return;
}
}
Context.OnRoute(route, request);
}
internal async Task DisableInterceptionAsync()
{
await Channel.SetNetworkInterceptionEnabledAsync(false).ConfigureAwait(false);
}
private void Channel_FrameDetached(object sender, IFrame args)
{
var frame = (Frame)args;
_frames.Remove(frame);
frame.IsDetached = true;
frame.ParentFrame?.ChildFramesList?.Remove(frame);
FrameDetached?.Invoke(this, args);
}
private void Channel_FrameAttached(object sender, IFrame args)
{
var frame = (Frame)args;
frame.Page = this;
_frames.Add(frame);
frame.ParentFrame?.ChildFramesList?.Add(frame);
FrameAttached?.Invoke(this, args);
}
private void RejectPendingOperations(bool isCrash)
{
foreach (var (_, waitTcs) in _waitForCancellationTcs.Where(e => e.PageEvent != (isCrash ? PageEvent.Crash : PageEvent.Close)))
{
waitTcs.TrySetException(new PlaywrightException(isCrash ? "Page crashed" : "Page closed"));
}
_waitForCancellationTcs.Clear();
}
private Task InnerExposeBindingAsync(string name, Delegate callback, bool handle = false)
{
if (Bindings.ContainsKey(name))
{
throw new PlaywrightException($"Function \"{name}\" has been already registered");
}
Bindings.Add(name, callback);
return _channel.ExposeBindingAsync(name, handle);
}
private Video ForceVideo() => _video ??= new(this, _channel.Connection);
private FrameSetInputFilesOptions Map(PageSetInputFilesOptions options)
{
if (options == null)
{
return null;
}
return new()
{
NoWaitAfter = options.NoWaitAfter,
Timeout = options.Timeout,
Strict = options.Strict,
};
}
}
}
/*
* MIT License
*
* Copyright (c) Microsoft Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Runtime.Serialization;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
#nullable enable
namespace Microsoft.Playwright
{
/// <summary>
/// <para>
/// Page provides methods to interact with a single tab in a <see cref="IBrowser"/>,
/// or an <a href="https://developer.chrome.com/extensions/background_pages">extension
/// background page</a> in Chromium. One <see cref="IBrowser"/> instance might have
/// multiple <see cref="IPage"/> instances.
/// </para>
/// <para>This example creates a page, navigates it to a URL, and then saves a screenshot:</para>
/// <code>
/// using Microsoft.Playwright;<br/>
/// using System.Threading.Tasks;<br/>
/// <br/>
/// class PageExamples<br/>
/// {<br/>
/// public static async Task Run()<br/>
/// {<br/>
/// using var playwright = await Playwright.CreateAsync();<br/>
/// await using var browser = await playwright.Webkit.LaunchAsync();<br/>
/// var page = await browser.NewPageAsync();<br/>
/// await page.GotoAsync("https://www.theverge.com");<br/>
/// await page.ScreenshotAsync(new PageScreenshotOptions { Path = "theverge.png" });<br/>
/// }<br/>
/// }
/// </code>
/// <para>
/// The Page class emits various events (described below) which can be handled using
/// any of Node's native <a href="https://nodejs.org/api/events.html#events_class_eventemitter"><c>EventEmitter</c></a>
/// methods, such as <c>on</c>, <c>once</c> or <c>removeListener</c>.
/// </para>
/// <para>This example logs a message for a single page <c>load</c> event:</para>
/// <code>page.Load += (_, _) => Console.WriteLine("Page loaded!");</code>
/// <para>To unsubscribe from events use the <c>removeListener</c> method:</para>
/// <code>
/// void PageLoadHandler(object _, IPage p) {<br/>
/// Console.WriteLine("Page loaded!");<br/>
/// };<br/>
/// <br/>
/// page.Load += PageLoadHandler;<br/>
/// // Do some work...<br/>
/// page.Load -= PageLoadHandler;
/// </code>
/// </summary>
public partial interface IPage
{
/// <summary><para>Emitted when the page closes.</para></summary>
event EventHandler<IPage> Close;
/// <summary>
/// <para>
/// Emitted when JavaScript within the page calls one of console API methods, e.g. <c>console.log</c>
/// or <c>console.dir</c>. Also emitted if the page throws an error or a warning.
/// </para>
/// <para>The arguments passed into <c>console.log</c> appear as arguments on the event handler.</para>
/// <para>An example of handling <c>console</c> event:</para>
/// <code>
/// page.Console += async (_, msg) =><br/>
/// {<br/>
/// foreach (var arg in msg.Args)<br/>
/// Console.WriteLine(await arg.JsonValueAsync<object>());<br/>
/// };<br/>
/// <br/>
/// await page.EvaluateAsync("console.log('hello', 5, { foo: 'bar' })");
/// </code>
/// </summary>
event EventHandler<IConsoleMessage> Console;
/// <summary>
/// <para>
/// Emitted when the page crashes. Browser pages might crash if they try to allocate
/// too much memory. When the page crashes, ongoing and subsequent operations will throw.
/// </para>
/// <para>The most common way to deal with crashes is to catch an exception:</para>
/// <code>
/// try {<br/>
/// // Crash might happen during a click.<br/>
/// await page.ClickAsync("button");<br/>
/// // Or while waiting for an event.<br/>
/// await page.WaitForPopup();<br/>
/// } catch (PlaywrightException e) {<br/>
/// // When the page crashes, exception message contains "crash".<br/>
/// }
/// </code>
/// </summary>
event EventHandler<IPage> Crash;
/// <summary>
/// <para>
/// Emitted when a JavaScript dialog appears, such as <c>alert</c>, <c>prompt</c>, <c>confirm</c>
/// or <c>beforeunload</c>. Listener **must** either <see cref="IDialog.AcceptAsync"/>
/// or <see cref="IDialog.DismissAsync"/> the dialog - otherwise the page will <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking">freeze</a>
/// waiting for the dialog, and actions like click will never finish.
/// </para>
/// <code>
/// page.RequestFailed += (_, request) =><br/>
/// {<br/>
/// Console.WriteLine(request.Url + " " + request.Failure);<br/>
/// };
/// </code>
/// </summary>
/// <remarks>
/// <para>
/// When no <see cref="IPage.Dialog"/> listeners are present, all dialogs are automatically
/// dismissed.
/// </para>
/// </remarks>
event EventHandler<IDialog> Dialog;
/// <summary>
/// <para>
/// Emitted when the JavaScript <a href="https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded"><c>DOMContentLoaded</c></a>
/// event is dispatched.
/// </para>
/// </summary>
event EventHandler<IPage> DOMContentLoaded;
/// <summary>
/// <para>
/// Emitted when attachment download started. User can access basic file operations
/// on downloaded content via the passed <see cref="IDownload"/> instance.
/// </para>
/// </summary>
event EventHandler<IDownload> Download;
/// <summary>
/// <para>
/// Emitted when a file chooser is supposed to appear, such as after clicking the <c><input
/// type=file></c>. Playwright can respond to it via setting the input files using
/// <see cref="IFileChooser.SetFilesAsync"/> that can be uploaded after that.
/// </para>
/// <code>
/// page.FileChooser += (_, fileChooser) =><br/>
/// {<br/>
/// fileChooser.SetFilesAsync(@"C:\temp\myfile.pdf");<br/>
/// };
/// </code>
/// </summary>
event EventHandler<IFileChooser> FileChooser;
/// <summary><para>Emitted when a frame is attached.</para></summary>
event EventHandler<IFrame> FrameAttached;
/// <summary><para>Emitted when a frame is detached.</para></summary>
event EventHandler<IFrame> FrameDetached;
/// <summary><para>Emitted when a frame is navigated to a new url.</para></summary>
event EventHandler<IFrame> FrameNavigated;
/// <summary>
/// <para>
/// Emitted when the JavaScript <a href="https://developer.mozilla.org/en-US/docs/Web/Events/load"><c>load</c></a>
/// event is dispatched.
/// </para>
/// </summary>
event EventHandler<IPage> Load;
/// <summary>
/// <para>Emitted when an uncaught exception happens within the page.</para>
/// <code>
/// // Log all uncaught errors to the terminal<br/>
/// page.PageError += (_, exception) =><br/>
/// {<br/>
/// Console.WriteLine("Uncaught exception: " + exception);<br/>
/// };
/// </code>
/// </summary>
event EventHandler<string> PageError;
/// <summary>
/// <para>
/// Emitted when the page opens a new tab or window. This event is emitted in addition
/// to the <see cref="IBrowserContext.Page"/>, but only for popups relevant to this
/// page.
/// </para>
/// <para>
/// The earliest moment that page is available is when it has navigated to the initial
/// url. For example, when opening a popup with <c>window.open('http://example.com')</c>,
/// this event will fire when the network request to "http://example.com" is done and
/// its response has started loading in the popup.
/// </para>
/// <code>
/// var popup = await page.RunAndWaitForPopupAsync(async () =><br/>
/// {<br/>
/// await page.EvaluateAsync("() => window.open('https://microsoft.com')");<br/>
/// });<br/>
/// Console.WriteLine(await popup.EvaluateAsync<string>("location.href"));
/// </code>
/// </summary>
/// <remarks>
/// <para>
/// Use <see cref="IPage.WaitForLoadStateAsync"/> to wait until the page gets to a particular
/// state (you should not need it in most cases).
/// </para>
/// </remarks>
event EventHandler<IPage> Popup;
/// <summary>
/// <para>
/// Emitted when a page issues a request. The <see cref="request"/> object is read-only.
/// In order to intercept and mutate requests, see <see cref="IPage.RouteAsync"/> or
/// <see cref="IBrowserContext.RouteAsync"/>.
/// </para>
/// </summary>
event EventHandler<IRequest> Request;
/// <summary><para>Emitted when a request fails, for example by timing out.</para></summary>
/// <remarks>
/// <para>
/// HTTP Error responses, such as 404 or 503, are still successful responses from HTTP
/// standpoint, so request will complete with <see cref="IPage.RequestFinished"/> event
/// and not with <see cref="IPage.RequestFailed"/>. A request will only be considered
/// failed when the client cannot get an HTTP response from the server, e.g. due to
/// network error net::ERR_FAILED.
/// </para>
/// </remarks>
event EventHandler<IRequest> RequestFailed;
/// <summary>
/// <para>
/// Emitted when a request finishes successfully after downloading the response body.
/// For a successful response, the sequence of events is <c>request</c>, <c>response</c>
/// and <c>requestfinished</c>.
/// </para>
/// </summary>
event EventHandler<IRequest> RequestFinished;
/// <summary>
/// <para>
/// Emitted when <see cref="response"/> status and headers are received for a request.
/// For a successful response, the sequence of events is <c>request</c>, <c>response</c>
/// and <c>requestfinished</c>.
/// </para>
/// </summary>
event EventHandler<IResponse> Response;
/// <summary><para>Emitted when <see cref="IWebSocket"/> request is sent.</para></summary>
event EventHandler<IWebSocket> WebSocket;
/// <summary>
/// <para>
/// Emitted when a dedicated <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API">WebWorker</a>
/// is spawned by the page.
/// </para>
/// </summary>
event EventHandler<IWorker> Worker;
public IAccessibility Accessibility { get; }
/// <summary>
/// <para>Adds a script which would be evaluated in one of the following scenarios:</para>
/// <list type="bullet">
/// <item><description>Whenever the page is navigated.</description></item>
/// <item><description>
/// Whenever the child frame is attached or navigated. In this case, the script is evaluated
/// in the context of the newly attached frame.
/// </description></item>
/// </list>
/// <para>
/// The script is evaluated after the document was created but before any of its scripts
/// were run. This is useful to amend the JavaScript environment, e.g. to seed <c>Math.random</c>.
/// </para>
/// <para>An example of overriding <c>Math.random</c> before the page loads:</para>
/// <code>await page.AddInitScriptAsync(new PageAddInitScriptOption { ScriptPath = "./preload.js" });</code>
/// </summary>
/// <remarks>
/// <para>
/// The order of evaluation of multiple scripts installed via <see cref="IBrowserContext.AddInitScriptAsync"/>
/// and <see cref="IPage.AddInitScriptAsync"/> is not defined.
/// </para>
/// </remarks>
/// <param name="script">Script to be evaluated in all pages in the browser context.</param>
/// <param name="scriptPath">Instead of specifying <paramref name="script"/>, gives the file name to load from.</param>
Task AddInitScriptAsync(string? script = default, string? scriptPath = default);
/// <summary>
/// <para>
/// Adds a <c><script></c> tag into the page with the desired url or content.
/// Returns the added tag when the script's onload fires or when the script content
/// was injected into frame.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.AddScriptTagAsync"/>.</para>
/// </summary>
/// <param name="options">Call options</param>
Task<IElementHandle> AddScriptTagAsync(PageAddScriptTagOptions? options = default);
/// <summary>
/// <para>
/// Adds a <c><link rel="stylesheet"></c> tag into the page with the desired url
/// or a <c><style type="text/css"></c> tag with the content. Returns the added
/// tag when the stylesheet's onload fires or when the CSS content was injected into
/// frame.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.AddStyleTagAsync"/>.</para>
/// </summary>
/// <param name="options">Call options</param>
Task<IElementHandle> AddStyleTagAsync(PageAddStyleTagOptions? options = default);
/// <summary><para>Brings page to front (activates tab).</para></summary>
Task BringToFrontAsync();
/// <summary>
/// <para>
/// This method checks an element matching <paramref name="selector"/> by performing
/// the following steps:
/// </para>
/// <list type="ordinal">
/// <item><description>
/// Find an element matching <paramref name="selector"/>. If there is none, wait until
/// a matching element is attached to the DOM.
/// </description></item>
/// <item><description>
/// Ensure that matched element is a checkbox or a radio input. If not, this method
/// throws. If the element is already checked, this method returns immediately.
/// </description></item>
/// <item><description>
/// Wait for <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a>
/// checks on the matched element, unless <paramref name="force"/> option is set. If
/// the element is detached during the checks, the whole action is retried.
/// </description></item>
/// <item><description>Scroll the element into view if needed.</description></item>
/// <item><description>Use <see cref="IPage.Mouse"/> to click in the center of the element.</description></item>
/// <item><description>
/// Wait for initiated navigations to either succeed or fail, unless <paramref name="noWaitAfter"/>
/// option is set.
/// </description></item>
/// <item><description>Ensure that the element is now checked. If not, this method throws.</description></item>
/// </list>
/// <para>
/// When all steps combined have not finished during the specified <paramref name="timeout"/>,
/// this method throws a <see cref="TimeoutException"/>. Passing zero timeout disables
/// this.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.CheckAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task CheckAsync(string selector, PageCheckOptions? options = default);
/// <summary>
/// <para>
/// This method clicks an element matching <paramref name="selector"/> by performing
/// the following steps:
/// </para>
/// <list type="ordinal">
/// <item><description>
/// Find an element matching <paramref name="selector"/>. If there is none, wait until
/// a matching element is attached to the DOM.
/// </description></item>
/// <item><description>
/// Wait for <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a>
/// checks on the matched element, unless <paramref name="force"/> option is set. If
/// the element is detached during the checks, the whole action is retried.
/// </description></item>
/// <item><description>Scroll the element into view if needed.</description></item>
/// <item><description>
/// Use <see cref="IPage.Mouse"/> to click in the center of the element, or the specified
/// <paramref name="position"/>.
/// </description></item>
/// <item><description>
/// Wait for initiated navigations to either succeed or fail, unless <paramref name="noWaitAfter"/>
/// option is set.
/// </description></item>
/// </list>
/// <para>
/// When all steps combined have not finished during the specified <paramref name="timeout"/>,
/// this method throws a <see cref="TimeoutException"/>. Passing zero timeout disables
/// this.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.ClickAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task ClickAsync(string selector, PageClickOptions? options = default);
/// <summary>
/// <para>
/// If <paramref name="runBeforeUnload"/> is <c>false</c>, does not run any unload handlers
/// and waits for the page to be closed. If <paramref name="runBeforeUnload"/> is <c>true</c>
/// the method will run unload handlers, but will **not** wait for the page to close.
/// </para>
/// <para>By default, <c>page.close()</c> **does not** run <c>beforeunload</c> handlers.</para>
/// </summary>
/// <remarks>
/// <para>
/// if <paramref name="runBeforeUnload"/> is passed as true, a <c>beforeunload</c> dialog
/// might be summoned and should be handled manually via <see cref="IPage.Dialog"/>
/// event.
/// </para>
/// </remarks>
/// <param name="options">Call options</param>
Task CloseAsync(PageCloseOptions? options = default);
/// <summary><para>Gets the full HTML contents of the page, including the doctype.</para></summary>
Task<string> ContentAsync();
/// <summary><para>Get the browser context that the page belongs to.</para></summary>
IBrowserContext Context { get; }
/// <summary>
/// <para>
/// This method double clicks an element matching <paramref name="selector"/> by performing
/// the following steps:
/// </para>
/// <list type="ordinal">
/// <item><description>
/// Find an element matching <paramref name="selector"/>. If there is none, wait until
/// a matching element is attached to the DOM.
/// </description></item>
/// <item><description>
/// Wait for <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a>
/// checks on the matched element, unless <paramref name="force"/> option is set. If
/// the element is detached during the checks, the whole action is retried.
/// </description></item>
/// <item><description>Scroll the element into view if needed.</description></item>
/// <item><description>
/// Use <see cref="IPage.Mouse"/> to double click in the center of the element, or the
/// specified <paramref name="position"/>.
/// </description></item>
/// <item><description>
/// Wait for initiated navigations to either succeed or fail, unless <paramref name="noWaitAfter"/>
/// option is set. Note that if the first click of the <c>dblclick()</c> triggers a
/// navigation event, this method will throw.
/// </description></item>
/// </list>
/// <para>
/// When all steps combined have not finished during the specified <paramref name="timeout"/>,
/// this method throws a <see cref="TimeoutException"/>. Passing zero timeout disables
/// this.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.DblClickAsync"/>.</para>
/// </summary>
/// <remarks>
/// <para>
/// <c>page.dblclick()</c> dispatches two <c>click</c> events and a single <c>dblclick</c>
/// event.
/// </para>
/// </remarks>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task DblClickAsync(string selector, PageDblClickOptions? options = default);
/// <summary>
/// <para>
/// The snippet below dispatches the <c>click</c> event on the element. Regardless of
/// the visibility state of the element, <c>click</c> is dispatched. This is equivalent
/// to calling <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click">element.click()</a>.
/// </para>
/// <code>await page.DispatchEventAsync("button#submit", "click");</code>
/// <para>
/// Under the hood, it creates an instance of an event based on the given <paramref
/// name="type"/>, initializes it with <paramref name="eventInit"/> properties and dispatches
/// it on the element. Events are <c>composed</c>, <c>cancelable</c> and bubble by default.
/// </para>
/// <para>
/// Since <paramref name="eventInit"/> is event-specific, please refer to the events
/// documentation for the lists of initial properties:
/// </para>
/// <list type="bullet">
/// <item><description><a href="https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent">DragEvent</a></description></item>
/// <item><description><a href="https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent">FocusEvent</a></description></item>
/// <item><description><a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent">KeyboardEvent</a></description></item>
/// <item><description><a href="https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent">MouseEvent</a></description></item>
/// <item><description><a href="https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent">PointerEvent</a></description></item>
/// <item><description><a href="https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent">TouchEvent</a></description></item>
/// <item><description><a href="https://developer.mozilla.org/en-US/docs/Web/API/Event/Event">Event</a></description></item>
/// </list>
/// <para>
/// You can also specify <c>JSHandle</c> as the property value if you want live objects
/// to be passed into the event:
/// </para>
/// <code>
/// var dataTransfer = await page.EvaluateHandleAsync("() => new DataTransfer()");<br/>
/// await page.DispatchEventAsync("#source", "dragstart", new { dataTransfer });
/// </code>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="type">DOM event type: <c>"click"</c>, <c>"dragstart"</c>, etc.</param>
/// <param name="eventInit">Optional event-specific initialization properties.</param>
/// <param name="options">Call options</param>
Task DispatchEventAsync(string selector, string type, object? eventInit = default, PageDispatchEventOptions? options = default);
/// <param name="source">
/// </param>
/// <param name="target">
/// </param>
/// <param name="options">Call options</param>
Task DragAndDropAsync(string source, string target, PageDragAndDropOptions? options = default);
/// <summary>
/// <para>
/// This method changes the <c>CSS media type</c> through the <c>media</c> argument,
/// and/or the <c>'prefers-colors-scheme'</c> media feature, using the <c>colorScheme</c>
/// argument.
/// </para>
/// <code>
/// await page.EvaluateAsync("() => matchMedia('screen').matches");<br/>
/// // â true<br/>
/// await page.EvaluateAsync("() => matchMedia('print').matches");<br/>
/// // â false<br/>
/// <br/>
/// await page.EmulateMediaAsync(new PageEmulateMediaOptions { Media = Media.Print });<br/>
/// await page.EvaluateAsync("() => matchMedia('screen').matches");<br/>
/// // â false<br/>
/// await page.EvaluateAsync("() => matchMedia('print').matches");<br/>
/// // â true<br/>
/// <br/>
/// await page.EmulateMediaAsync(new PageEmulateMediaOptions { Media = Media.Screen });<br/>
/// await page.EvaluateAsync("() => matchMedia('screen').matches");<br/>
/// // â true<br/>
/// await page.EvaluateAsync("() => matchMedia('print').matches");<br/>
/// // â false
/// </code>
/// <code>
/// await page.EmulateMediaAsync(new PageEmulateMediaOptions { ColorScheme = ColorScheme.Dark });<br/>
/// await page.EvaluateAsync("matchMedia('(prefers-color-scheme: dark)').matches");<br/>
/// // â true<br/>
/// await page.EvaluateAsync("matchMedia('(prefers-color-scheme: light)').matches");<br/>
/// // â false<br/>
/// await page.EvaluateAsync("matchMedia('(prefers-color-scheme: no-preference)').matches");<br/>
/// // â false
/// </code>
/// </summary>
/// <param name="options">Call options</param>
Task EmulateMediaAsync(PageEmulateMediaOptions? options = default);
/// <summary>
/// <para>
/// The method finds an element matching the specified selector within the page and
/// passes it as a first argument to <paramref name="expression"/>. If no elements match
/// the selector, the method throws an error. Returns the value of <paramref name="expression"/>.
/// </para>
/// <para>
/// If <paramref name="expression"/> returns a <see cref="Task"/>, then <see cref="IPage.EvalOnSelectorAsync"/>
/// would wait for the promise to resolve and return its value.
/// </para>
/// <para>Examples:</para>
/// <code>
/// var searchValue = await page.EvalOnSelectorAsync<string>("#search", "el => el.value");<br/>
/// var preloadHref = await page.EvalOnSelectorAsync<string>("link[rel=preload]", "el => el.href");<br/>
/// var html = await page.EvalOnSelectorAsync(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello");
/// </code>
/// <para>Shortcut for main frame's <see cref="IFrame.EvalOnSelectorAsync"/>.</para>
/// </summary>
/// <remarks>
/// <para>
/// This method does not wait for the element to pass actionability checks and therefore
/// can lead to the flaky tests. Use <see cref="ILocator.EvaluateAsync"/>, other <see
/// cref="ILocator"/> helper methods or web-first assertions instead.
/// </para>
/// </remarks>
/// <param name="selector">
/// A selector to query for. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="expression">
/// JavaScript expression to be evaluated in the browser context. If it looks like a
/// function declaration, it is interpreted as a function. Otherwise, evaluated as an
/// expression.
/// </param>
/// <param name="arg">Optional argument to pass to <paramref name="expression"/>.</param>
/// <param name="options">Call options</param>
Task<T> EvalOnSelectorAsync<T>(string selector, string expression, object? arg = default, PageEvalOnSelectorOptions? options = default);
/// <summary>
/// <para>
/// The method finds all elements matching the specified selector within the page and
/// passes an array of matched elements as a first argument to <paramref name="expression"/>.
/// Returns the result of <paramref name="expression"/> invocation.
/// </para>
/// <para>
/// If <paramref name="expression"/> returns a <see cref="Task"/>, then <see cref="IPage.EvalOnSelectorAllAsync"/>
/// would wait for the promise to resolve and return its value.
/// </para>
/// <para>Examples:</para>
/// <code>var divsCount = await page.EvalOnSelectorAllAsync<bool>("div", "(divs, min) => divs.length >= min", 10);</code>
/// </summary>
/// <remarks>
/// <para>
/// In most cases, <see cref="ILocator.EvaluateAllAsync"/>, other <see cref="ILocator"/>
/// helper methods and web-first assertions do a better job.
/// </para>
/// </remarks>
/// <param name="selector">
/// A selector to query for. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="expression">
/// JavaScript expression to be evaluated in the browser context. If it looks like a
/// function declaration, it is interpreted as a function. Otherwise, evaluated as an
/// expression.
/// </param>
/// <param name="arg">Optional argument to pass to <paramref name="expression"/>.</param>
Task<T> EvalOnSelectorAllAsync<T>(string selector, string expression, object? arg = default);
/// <summary>
/// <para>Returns the value of the <paramref name="expression"/> invocation.</para>
/// <para>
/// If the function passed to the <see cref="IPage.EvaluateAsync"/> returns a <see cref="Task"/>,
/// then <see cref="IPage.EvaluateAsync"/> would wait for the promise to resolve and
/// return its value.
/// </para>
/// <para>
/// If the function passed to the <see cref="IPage.EvaluateAsync"/> returns a non-<see
/// cref="Serializable"/> value, then <see cref="IPage.EvaluateAsync"/> resolves to
/// <c>undefined</c>. Playwright also supports transferring some additional values that
/// are not serializable by <c>JSON</c>: <c>-0</c>, <c>NaN</c>, <c>Infinity</c>, <c>-Infinity</c>.
/// </para>
/// <para>Passing argument to <paramref name="expression"/>:</para>
/// <code>
/// var result = await page.EvaluateAsync<int>("([x, y]) => Promise.resolve(x * y)", new[] { 7, 8 });<br/>
/// Console.WriteLine(result);
/// </code>
/// <para>A string can also be passed in instead of a function:</para>
/// <code>Console.WriteLine(await page.EvaluateAsync<int>("1 + 2")); // prints "3"</code>
/// <para>
/// <see cref="IElementHandle"/> instances can be passed as an argument to the <see
/// cref="IPage.EvaluateAsync"/>:
/// </para>
/// <code>
/// var bodyHandle = await page.EvaluateAsync("document.body");<br/>
/// var html = await page.EvaluateAsync<string>("([body, suffix]) => body.innerHTML + suffix", new object [] { bodyHandle, "hello" });<br/>
/// await bodyHandle.DisposeAsync();
/// </code>
/// <para>Shortcut for main frame's <see cref="IFrame.EvaluateAsync"/>.</para>
/// </summary>
/// <param name="expression">
/// JavaScript expression to be evaluated in the browser context. If it looks like a
/// function declaration, it is interpreted as a function. Otherwise, evaluated as an
/// expression.
/// </param>
/// <param name="arg">Optional argument to pass to <paramref name="expression"/>.</param>
Task<T> EvaluateAsync<T>(string expression, object? arg = default);
/// <summary>
/// <para>Returns the value of the <paramref name="expression"/> invocation as a <see cref="IJSHandle"/>.</para>
/// <para>
/// The only difference between <see cref="IPage.EvaluateAsync"/> and <see cref="IPage.EvaluateHandleAsync"/>
/// is that <see cref="IPage.EvaluateHandleAsync"/> returns <see cref="IJSHandle"/>.
/// </para>
/// <para>
/// If the function passed to the <see cref="IPage.EvaluateHandleAsync"/> returns a
/// <see cref="Task"/>, then <see cref="IPage.EvaluateHandleAsync"/> would wait for
/// the promise to resolve and return its value.
/// </para>
/// <code>
/// // Handle for the window object.<br/>
/// var aWindowHandle = await page.EvaluateHandleAsync("() => Promise.resolve(window)");
/// </code>
/// <para>A string can also be passed in instead of a function:</para>
/// <code>var docHandle = await page.EvaluateHandleAsync("document"); // Handle for the `document`</code>
/// <para><see cref="IJSHandle"/> instances can be passed as an argument to the <see cref="IPage.EvaluateHandleAsync"/>:</para>
/// <code>
/// var handle = await page.EvaluateHandleAsync("() => document.body");<br/>
/// var resultHandle = await page.EvaluateHandleAsync("([body, suffix]) => body.innerHTML + suffix", new object[] { handle, "hello" });<br/>
/// Console.WriteLine(await resultHandle.JsonValueAsync<string>());<br/>
/// await resultHandle.DisposeAsync();
/// </code>
/// </summary>
/// <param name="expression">
/// JavaScript expression to be evaluated in the browser context. If it looks like a
/// function declaration, it is interpreted as a function. Otherwise, evaluated as an
/// expression.
/// </param>
/// <param name="arg">Optional argument to pass to <paramref name="expression"/>.</param>
Task<IJSHandle> EvaluateHandleAsync(string expression, object? arg = default);
/// <summary>
/// <para>
/// The method adds a function called <paramref name="name"/> on the <c>window</c> object
/// of every frame in this page. When called, the function executes <paramref name="callback"/>
/// and returns a <see cref="Task"/> which resolves to the return value of <paramref
/// name="callback"/>. If the <paramref name="callback"/> returns a <see cref="Promise"/>,
/// it will be awaited.
/// </para>
/// <para>
/// The first argument of the <paramref name="callback"/> function contains information
/// about the caller: <c>{ browserContext: BrowserContext, page: Page, frame: Frame
/// }</c>.
/// </para>
/// <para>See <see cref="IBrowserContext.ExposeBindingAsync"/> for the context-wide version.</para>
/// <para>An example of exposing page URL to all frames in a page:</para>
/// <code>
/// using Microsoft.Playwright;<br/>
/// using System.Threading.Tasks;<br/>
/// <br/>
/// class PageExamples<br/>
/// {<br/>
/// public static async Task Main()<br/>
/// {<br/>
/// using var playwright = await Playwright.CreateAsync();<br/>
/// await using var browser = await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions<br/>
/// {<br/>
/// Headless: false<br/>
/// });<br/>
/// var page = await browser.NewPageAsync();<br/>
/// <br/>
/// await page.ExposeBindingAsync("pageUrl", (source) => source.Page.Url);<br/>
/// await page.SetContentAsync("<script>\n" +<br/>
/// " async function onClick() {\n" +<br/>
/// " document.querySelector('div').textContent = await window.pageURL();\n" +<br/>
/// " }\n" +<br/>
/// "</script>\n" +<br/>
/// "<button onclick=\"onClick()\">Click me</button>\n" +<br/>
/// "<div></div>");<br/>
/// <br/>
/// await page.ClickAsync("button");<br/>
/// }<br/>
/// }
/// </code>
/// <para>An example of passing an element handle:</para>
/// <code>
/// var result = new TaskCompletionSource<string>();<br/>
/// await page.ExposeBindingAsync("clicked", async (BindingSource _, IJSHandle t) =><br/>
/// {<br/>
/// return result.TrySetResult(await t.AsElement().TextContentAsync());<br/>
/// });<br/>
/// <br/>
/// await page.SetContentAsync("<script>\n" +<br/>
/// " document.addEventListener('click', event => window.clicked(event.target));\n" +<br/>
/// "</script>\n" +<br/>
/// "<div>Click me</div>\n" +<br/>
/// "<div>Or click me</div>\n");<br/>
/// <br/>
/// await page.ClickAsync("div");<br/>
/// Console.WriteLine(await result.Task);
/// </code>
/// </summary>
/// <remarks><para>Functions installed via <see cref="IPage.ExposeBindingAsync"/> survive navigations.</para></remarks>
/// <param name="name">Name of the function on the window object.</param>
/// <param name="callback">Callback function that will be called in the Playwright's context.</param>
/// <param name="options">Call options</param>
Task ExposeBindingAsync(string name, Action callback, PageExposeBindingOptions? options = default);
/// <summary>
/// <para>
/// The method adds a function called <paramref name="name"/> on the <c>window</c> object
/// of every frame in the page. When called, the function executes <paramref name="callback"/>
/// and returns a <see cref="Task"/> which resolves to the return value of <paramref
/// name="callback"/>.
/// </para>
/// <para>If the <paramref name="callback"/> returns a <see cref="Task"/>, it will be awaited.</para>
/// <para>See <see cref="IBrowserContext.ExposeFunctionAsync"/> for context-wide exposed function.</para>
/// <para>An example of adding a <c>sha256</c> function to the page:</para>
/// <code>
/// using Microsoft.Playwright;<br/>
/// using System;<br/>
/// using System.Security.Cryptography;<br/>
/// using System.Threading.Tasks;<br/>
/// <br/>
/// class PageExamples<br/>
/// {<br/>
/// public static async Task Main()<br/>
/// {<br/>
/// using var playwright = await Playwright.CreateAsync();<br/>
/// await using var browser = await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions<br/>
/// {<br/>
/// Headless: false<br/>
/// });<br/>
/// var page = await browser.NewPageAsync();<br/>
/// <br/>
/// await page.ExposeFunctionAsync("sha256", (string input) =><br/>
/// {<br/>
/// return Convert.ToBase64String(<br/>
/// SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(input)));<br/>
/// });<br/>
/// <br/>
/// await page.SetContentAsync("<script>\n" +<br/>
/// " async function onClick() {\n" +<br/>
/// " document.querySelector('div').textContent = await window.sha256('PLAYWRIGHT');\n" +<br/>
/// " }\n" +<br/>
/// "</script>\n" +<br/>
/// "<button onclick=\"onClick()\">Click me</button>\n" +<br/>
/// "<div></div>");<br/>
/// <br/>
/// await page.ClickAsync("button");<br/>
/// Console.WriteLine(await page.TextContentAsync("div"));<br/>
/// }<br/>
/// }
/// </code>
/// </summary>
/// <remarks><para>Functions installed via <see cref="IPage.ExposeFunctionAsync"/> survive navigations.</para></remarks>
/// <param name="name">Name of the function on the window object</param>
/// <param name="callback">Callback function which will be called in Playwright's context.</param>
Task ExposeFunctionAsync(string name, Action callback);
/// <summary>
/// <para>
/// This method waits for an element matching <paramref name="selector"/>, waits for
/// <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a> checks,
/// focuses the element, fills it and triggers an <c>input</c> event after filling.
/// Note that you can pass an empty string to clear the input field.
/// </para>
/// <para>
/// If the target element is not an <c><input></c>, <c><textarea></c> or
/// <c>[contenteditable]</c> element, this method throws an error. However, if the element
/// is inside the <c><label></c> element that has an associated <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control">control</a>,
/// the control will be filled instead.
/// </para>
/// <para>To send fine-grained keyboard events, use <see cref="IPage.TypeAsync"/>.</para>
/// <para>Shortcut for main frame's <see cref="IFrame.FillAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="value">
/// Value to fill for the <c><input></c>, <c><textarea></c> or <c>[contenteditable]</c>
/// element.
/// </param>
/// <param name="options">Call options</param>
Task FillAsync(string selector, string value, PageFillOptions? options = default);
/// <summary>
/// <para>
/// This method fetches an element with <paramref name="selector"/> and focuses it.
/// If there's no element matching <paramref name="selector"/>, the method waits until
/// a matching element appears in the DOM.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.FocusAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task FocusAsync(string selector, PageFocusOptions? options = default);
/// <summary>
/// <para>
/// Returns frame matching the specified criteria. Either <c>name</c> or <c>url</c>
/// must be specified.
/// </para>
/// <code>var frame = page.Frame("frame-name");</code>
/// <code>var frame = page.FrameByUrl(".*domain.*");</code>
/// </summary>
/// <param name="name">Frame name specified in the <c>iframe</c>'s <c>name</c> attribute.</param>
IFrame? Frame(string name);
/// <summary><para>Returns frame with matching URL.</para></summary>
/// <param name="url">
/// A glob pattern, regex pattern or predicate receiving frame's <c>url</c> as a <see
/// cref="URL"/> object.
/// </param>
IFrame? FrameByUrl(string url);
/// <summary><para>Returns frame with matching URL.</para></summary>
/// <param name="url">
/// A glob pattern, regex pattern or predicate receiving frame's <c>url</c> as a <see
/// cref="URL"/> object.
/// </param>
IFrame? FrameByUrl(Regex url);
/// <summary><para>Returns frame with matching URL.</para></summary>
/// <param name="url">
/// A glob pattern, regex pattern or predicate receiving frame's <c>url</c> as a <see
/// cref="URL"/> object.
/// </param>
IFrame? FrameByUrl(Func<string, bool> url);
/// <summary>
/// <para>
/// When working with iframes, you can create a frame locator that will enter the iframe
/// and allow selecting elements in that iframe. Following snippet locates element with
/// text "Submit" in the iframe with id <c>my-frame</c>, like <c><iframe id="my-frame"></c>:
/// </para>
/// <code>
/// var locator = page.FrameLocator("#my-iframe").Locator("text=Submit");<br/>
/// await locator.ClickAsync();
/// </code>
/// </summary>
/// <param name="selector">
/// A selector to use when resolving DOM element. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
IFrameLocator FrameLocator(string selector);
/// <summary><para>An array of all frames attached to the page.</para></summary>
IReadOnlyList<IFrame> Frames { get; }
/// <summary><para>Returns element attribute value.</para></summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="name">Attribute name to get the value for.</param>
/// <param name="options">Call options</param>
Task<string?> GetAttributeAsync(string selector, string name, PageGetAttributeOptions? options = default);
/// <summary>
/// <para>
/// Returns the main resource response. In case of multiple redirects, the navigation
/// will resolve with the response of the last redirect. If can not go back, returns
/// <c>null</c>.
/// </para>
/// <para>Navigate to the previous page in history.</para>
/// </summary>
/// <param name="options">Call options</param>
Task<IResponse?> GoBackAsync(PageGoBackOptions? options = default);
/// <summary>
/// <para>
/// Returns the main resource response. In case of multiple redirects, the navigation
/// will resolve with the response of the last redirect. If can not go forward, returns
/// <c>null</c>.
/// </para>
/// <para>Navigate to the next page in history.</para>
/// </summary>
/// <param name="options">Call options</param>
Task<IResponse?> GoForwardAsync(PageGoForwardOptions? options = default);
/// <summary>
/// <para>
/// Returns the main resource response. In case of multiple redirects, the navigation
/// will resolve with the response of the last redirect.
/// </para>
/// <para>The method will throw an error if:</para>
/// <list type="bullet">
/// <item><description>there's an SSL error (e.g. in case of self-signed certificates).</description></item>
/// <item><description>target URL is invalid.</description></item>
/// <item><description>the <paramref name="timeout"/> is exceeded during navigation.</description></item>
/// <item><description>the remote server does not respond or is unreachable.</description></item>
/// <item><description>the main resource failed to load.</description></item>
/// </list>
/// <para>
/// The method will not throw an error when any valid HTTP status code is returned by
/// the remote server, including 404 "Not Found" and 500 "Internal Server Error". The
/// status code for such responses can be retrieved by calling <see cref="IResponse.Status"/>.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.GotoAsync"/></para>
/// </summary>
/// <remarks>
/// <para>
/// The method either throws an error or returns a main resource response. The only
/// exceptions are navigation to <c>about:blank</c> or navigation to the same URL with
/// a different hash, which would succeed and return <c>null</c>.
/// </para>
/// <para>
/// Headless mode doesn't support navigation to a PDF document. See the <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=761295">upstream
/// issue</a>.
/// </para>
/// </remarks>
/// <param name="url">
/// URL to navigate page to. The url should include scheme, e.g. <c>https://</c>. When
/// a <paramref name="baseURL"/> via the context options was provided and the passed
/// URL is a path, it gets merged via the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL"><c>new
/// URL()</c></a> constructor.
/// </param>
/// <param name="options">Call options</param>
Task<IResponse?> GotoAsync(string url, PageGotoOptions? options = default);
/// <summary>
/// <para>
/// This method hovers over an element matching <paramref name="selector"/> by performing
/// the following steps:
/// </para>
/// <list type="ordinal">
/// <item><description>
/// Find an element matching <paramref name="selector"/>. If there is none, wait until
/// a matching element is attached to the DOM.
/// </description></item>
/// <item><description>
/// Wait for <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a>
/// checks on the matched element, unless <paramref name="force"/> option is set. If
/// the element is detached during the checks, the whole action is retried.
/// </description></item>
/// <item><description>Scroll the element into view if needed.</description></item>
/// <item><description>
/// Use <see cref="IPage.Mouse"/> to hover over the center of the element, or the specified
/// <paramref name="position"/>.
/// </description></item>
/// <item><description>
/// Wait for initiated navigations to either succeed or fail, unless <c>noWaitAfter</c>
/// option is set.
/// </description></item>
/// </list>
/// <para>
/// When all steps combined have not finished during the specified <paramref name="timeout"/>,
/// this method throws a <see cref="TimeoutException"/>. Passing zero timeout disables
/// this.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.HoverAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task HoverAsync(string selector, PageHoverOptions? options = default);
/// <summary><para>Returns <c>element.innerHTML</c>.</para></summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<string> InnerHTMLAsync(string selector, PageInnerHTMLOptions? options = default);
/// <summary><para>Returns <c>element.innerText</c>.</para></summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<string> InnerTextAsync(string selector, PageInnerTextOptions? options = default);
/// <summary>
/// <para>
/// Returns <c>input.value</c> for the selected <c><input></c> or <c><textarea></c>
/// or <c><select></c> element. Throws for non-input elements.
/// </para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<string> InputValueAsync(string selector, PageInputValueOptions? options = default);
/// <summary>
/// <para>
/// Returns whether the element is checked. Throws if the element is not a checkbox
/// or radio input.
/// </para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<bool> IsCheckedAsync(string selector, PageIsCheckedOptions? options = default);
/// <summary><para>Indicates that the page has been closed.</para></summary>
bool IsClosed { get; }
/// <summary><para>Returns whether the element is disabled, the opposite of <a href="https://playwright.dev/dotnet/docs/actionability#enabled">enabled</a>.</para></summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<bool> IsDisabledAsync(string selector, PageIsDisabledOptions? options = default);
/// <summary><para>Returns whether the element is <a href="https://playwright.dev/dotnet/docs/actionability#editable">editable</a>.</para></summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<bool> IsEditableAsync(string selector, PageIsEditableOptions? options = default);
/// <summary><para>Returns whether the element is <a href="https://playwright.dev/dotnet/docs/actionability#enabled">enabled</a>.</para></summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<bool> IsEnabledAsync(string selector, PageIsEnabledOptions? options = default);
/// <summary>
/// <para>
/// Returns whether the element is hidden, the opposite of <a href="https://playwright.dev/dotnet/docs/actionability#visible">visible</a>.
/// <paramref name="selector"/> that does not match any elements is considered hidden.
/// </para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<bool> IsHiddenAsync(string selector, PageIsHiddenOptions? options = default);
/// <summary>
/// <para>
/// Returns whether the element is <a href="https://playwright.dev/dotnet/docs/actionability#visible">visible</a>.
/// <paramref name="selector"/> that does not match any elements is considered not visible.
/// </para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<bool> IsVisibleAsync(string selector, PageIsVisibleOptions? options = default);
public IKeyboard Keyboard { get; }
/// <summary>
/// <para>
/// The method returns an element locator that can be used to perform actions on the
/// page. Locator is resolved to the element immediately before performing an action,
/// so a series of actions on the same locator can in fact be performed on different
/// DOM elements. That would happen if the DOM structure between those actions has changed.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.Locator"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to use when resolving DOM element. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
ILocator Locator(string selector, PageLocatorOptions? options = default);
/// <summary>
/// <para>
/// The page's main frame. Page is guaranteed to have a main frame which persists during
/// navigations.
/// </para>
/// </summary>
IFrame MainFrame { get; }
public IMouse Mouse { get; }
/// <summary>
/// <para>
/// Returns the opener for popup pages and <c>null</c> for others. If the opener has
/// been closed already the returns <c>null</c>.
/// </para>
/// </summary>
Task<IPage?> OpenerAsync();
/// <summary>
/// <para>
/// Pauses script execution. Playwright will stop executing the script and wait for
/// the user to either press 'Resume' button in the page overlay or to call <c>playwright.resume()</c>
/// in the DevTools console.
/// </para>
/// <para>
/// User can inspect selectors or perform manual steps while paused. Resume will continue
/// running the original script from the place it was paused.
/// </para>
/// </summary>
/// <remarks>
/// <para>
/// This method requires Playwright to be started in a headed mode, with a falsy <paramref
/// name="headless"/> value in the <see cref="IBrowserType.LaunchAsync"/>.
/// </para>
/// </remarks>
Task PauseAsync();
/// <summary>
/// <para>Returns the PDF buffer.</para>
/// <para>
/// <c>page.pdf()</c> generates a pdf of the page with <c>print</c> css media. To generate
/// a pdf with <c>screen</c> media, call <see cref="IPage.EmulateMediaAsync"/> before
/// calling <c>page.pdf()</c>:
/// </para>
/// <code>
/// // Generates a PDF with 'screen' media type<br/>
/// await page.EmulateMediaAsync(new PageEmulateMediaOptions { Media = Media.Screen });<br/>
/// await page.PdfAsync(new PagePdfOptions { Path = "page.pdf" });
/// </code>
/// <para>
/// The <paramref name="width"/>, <paramref name="height"/>, and <paramref name="margin"/>
/// options accept values labeled with units. Unlabeled values are treated as pixels.
/// </para>
/// <para>A few examples:</para>
/// <list type="bullet">
/// <item><description><c>page.pdf({width: 100})</c> - prints with width set to 100 pixels</description></item>
/// <item><description><c>page.pdf({width: '100px'})</c> - prints with width set to 100 pixels</description></item>
/// <item><description><c>page.pdf({width: '10cm'})</c> - prints with width set to 10 centimeters.</description></item>
/// </list>
/// <para>All possible units are:</para>
/// <list type="bullet">
/// <item><description><c>px</c> - pixel</description></item>
/// <item><description><c>in</c> - inch</description></item>
/// <item><description><c>cm</c> - centimeter</description></item>
/// <item><description><c>mm</c> - millimeter</description></item>
/// </list>
/// <para>The <paramref name="format"/> options are:</para>
/// <list type="bullet">
/// <item><description><c>Letter</c>: 8.5in x 11in</description></item>
/// <item><description><c>Legal</c>: 8.5in x 14in</description></item>
/// <item><description><c>Tabloid</c>: 11in x 17in</description></item>
/// <item><description><c>Ledger</c>: 17in x 11in</description></item>
/// <item><description><c>A0</c>: 33.1in x 46.8in</description></item>
/// <item><description><c>A1</c>: 23.4in x 33.1in</description></item>
/// <item><description><c>A2</c>: 16.54in x 23.4in</description></item>
/// <item><description><c>A3</c>: 11.7in x 16.54in</description></item>
/// <item><description><c>A4</c>: 8.27in x 11.7in</description></item>
/// <item><description><c>A5</c>: 5.83in x 8.27in</description></item>
/// <item><description><c>A6</c>: 4.13in x 5.83in</description></item>
/// </list>
/// </summary>
/// <remarks>
/// <para>Generating a pdf is currently only supported in Chromium headless.</para>
/// <para>
/// By default, <c>page.pdf()</c> generates a pdf with modified colors for printing.
/// Use the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust"><c>-webkit-print-color-adjust</c></a>
/// property to force rendering of exact colors.
/// </para>
/// <para>
/// <paramref name="headerTemplate"/> and <paramref name="footerTemplate"/> markup have
/// the following limitations: > 1. Script tags inside templates are not evaluated.
/// > 2. Page styles are not visible inside templates.
/// </para>
/// </remarks>
/// <param name="options">Call options</param>
Task<byte[]> PdfAsync(PagePdfOptions? options = default);
/// <summary>
/// <para>Focuses the element, and then uses <see cref="IKeyboard.DownAsync"/> and <see cref="IKeyboard.UpAsync"/>.</para>
/// <para>
/// <paramref name="key"/> can specify the intended <a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key">keyboardEvent.key</a>
/// value or a single character to generate the text for. A superset of the <paramref
/// name="key"/> values can be found <a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values">here</a>.
/// Examples of the keys are:
/// </para>
/// <para>
/// <c>F1</c> - <c>F12</c>, <c>Digit0</c>- <c>Digit9</c>, <c>KeyA</c>- <c>KeyZ</c>,
/// <c>Backquote</c>, <c>Minus</c>, <c>Equal</c>, <c>Backslash</c>, <c>Backspace</c>,
/// <c>Tab</c>, <c>Delete</c>, <c>Escape</c>, <c>ArrowDown</c>, <c>End</c>, <c>Enter</c>,
/// <c>Home</c>, <c>Insert</c>, <c>PageDown</c>, <c>PageUp</c>, <c>ArrowRight</c>, <c>ArrowUp</c>,
/// etc.
/// </para>
/// <para>
/// Following modification shortcuts are also supported: <c>Shift</c>, <c>Control</c>,
/// <c>Alt</c>, <c>Meta</c>, <c>ShiftLeft</c>.
/// </para>
/// <para>
/// Holding down <c>Shift</c> will type the text that corresponds to the <paramref name="key"/>
/// in the upper case.
/// </para>
/// <para>
/// If <paramref name="key"/> is a single character, it is case-sensitive, so the values
/// <c>a</c> and <c>A</c> will generate different respective texts.
/// </para>
/// <para>
/// Shortcuts such as <c>key: "Control+o"</c> or <c>key: "Control+Shift+T"</c> are supported
/// as well. When specified with the modifier, modifier is pressed and being held while
/// the subsequent key is being pressed.
/// </para>
/// <code>
/// var page = await browser.NewPageAsync();<br/>
/// await page.GotoAsync("https://keycode.info");<br/>
/// await page.PressAsync("body", "A");<br/>
/// await page.ScreenshotAsync(new PageScreenshotOptions { Path = "A.png" });<br/>
/// await page.PressAsync("body", "ArrowLeft");<br/>
/// await page.ScreenshotAsync(new PageScreenshotOptions { Path = "ArrowLeft.png" });<br/>
/// await page.PressAsync("body", "Shift+O");<br/>
/// await page.ScreenshotAsync(new PageScreenshotOptions { Path = "O.png" });
/// </code>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="key">
/// Name of the key to press or a character to generate, such as <c>ArrowLeft</c> or
/// <c>a</c>.
/// </param>
/// <param name="options">Call options</param>
Task PressAsync(string selector, string key, PagePressOptions? options = default);
/// <summary>
/// <para>
/// The method finds an element matching the specified selector within the page. If
/// no elements match the selector, the return value resolves to <c>null</c>. To wait
/// for an element on the page, use <see cref="ILocator.WaitForAsync"/>.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.QuerySelectorAsync"/>.</para>
/// </summary>
/// <remarks>
/// <para>
/// The use of <see cref="IElementHandle"/> is discouraged, use <see cref="ILocator"/>
/// objects and web-first assertions instead.
/// </para>
/// </remarks>
/// <param name="selector">
/// A selector to query for. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="options">Call options</param>
Task<IElementHandle?> QuerySelectorAsync(string selector, PageQuerySelectorOptions? options = default);
/// <summary>
/// <para>
/// The method finds all elements matching the specified selector within the page. If
/// no elements match the selector, the return value resolves to <c>[]</c>.
/// </para>
/// <para>Shortcut for main frame's <see cref="IFrame.QuerySelectorAllAsync"/>.</para>
/// </summary>
/// <remarks>
/// <para>
/// The use of <see cref="IElementHandle"/> is discouraged, use <see cref="ILocator"/>
/// objects and web-first assertions instead.
/// </para>
/// </remarks>
/// <param name="selector">
/// A selector to query for. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
Task<IReadOnlyList<IElementHandle>> QuerySelectorAllAsync(string selector);
/// <summary>
/// <para>
/// This method reloads the current page, in the same way as if the user had triggered
/// a browser refresh. Returns the main resource response. In case of multiple redirects,
/// the navigation will resolve with the response of the last redirect.
/// </para>
/// </summary>
/// <param name="options">Call options</param>
Task<IResponse?> ReloadAsync(PageReloadOptions? options = default);
/// <summary>
/// <para>Routing provides the capability to modify network requests that are made by a page.</para>
/// <para>
/// Once routing is enabled, every request matching the url pattern will stall unless
/// it's continued, fulfilled or aborted.
/// </para>
/// <para>An example of a naive handler that aborts all image requests:</para>
/// <code>
/// var page = await browser.NewPageAsync();<br/>
/// await page.RouteAsync("**/*.{png,jpg,jpeg}", async r => await r.AbortAsync());<br/>
/// await page.GotoAsync("https://www.microsoft.com");
/// </code>
/// <para>or the same snippet using a regex pattern instead:</para>
/// <code>
/// var page = await browser.NewPageAsync();<br/>
/// await page.RouteAsync(new Regex("(\\.png$)|(\\.jpg$)"), async r => await r.AbortAsync());<br/>
/// await page.GotoAsync("https://www.microsoft.com");
/// </code>
/// <para>
/// It is possible to examine the request to decide the route action. For example, mocking
/// all requests that contain some post data, and leaving all other requests as is:
/// </para>
/// <code>
/// await page.RouteAsync("/api/**", async r =><br/>
/// {<br/>
/// if (r.Request.PostData.Contains("my-string"))<br/>
/// await r.FulfillAsync(new RouteFulfillOptions { Body = "mocked-data" });<br/>
/// else<br/>
/// await r.ContinueAsync();<br/>
/// });
/// </code>
/// <para>
/// Page routes take precedence over browser context routes (set up with <see cref="IBrowserContext.RouteAsync"/>)
/// when request matches both handlers.
/// </para>
/// <para>To remove a route with its handler you can use <see cref="IPage.UnrouteAsync"/>.</para>
/// </summary>
/// <remarks>
/// <para>The handler will only be called for the first url if the response is a redirect.</para>
/// <para>
/// <see cref="IPage.RouteAsync"/> will not intercept requests intercepted by Service
/// Worker. See <a href="https://github.com/microsoft/playwright/issues/1090">this</a>
/// issue. We recommend disabling Service Workers when using request interception. Via
/// <c>await context.addInitScript(() => delete window.navigator.serviceWorker);</c>
/// </para>
/// <para>Enabling routing disables http cache.</para>
/// </remarks>
/// <param name="url">
/// A glob pattern, regex pattern or predicate receiving <see cref="URL"/> to match
/// while routing. When a <paramref name="baseURL"/> via the context options was provided
/// and the passed URL is a path, it gets merged via the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL"><c>new
/// URL()</c></a> constructor.
/// </param>
/// <param name="handler">handler function to route the request.</param>
/// <param name="options">Call options</param>
Task RouteAsync(string url, Action<IRoute> handler, PageRouteOptions? options = default);
/// <summary>
/// <para>Routing provides the capability to modify network requests that are made by a page.</para>
/// <para>
/// Once routing is enabled, every request matching the url pattern will stall unless
/// it's continued, fulfilled or aborted.
/// </para>
/// <para>An example of a naive handler that aborts all image requests:</para>
/// <code>
/// var page = await browser.NewPageAsync();<br/>
/// await page.RouteAsync("**/*.{png,jpg,jpeg}", async r => await r.AbortAsync());<br/>
/// await page.GotoAsync("https://www.microsoft.com");
/// </code>
/// <para>or the same snippet using a regex pattern instead:</para>
/// <code>
/// var page = await browser.NewPageAsync();<br/>
/// await page.RouteAsync(new Regex("(\\.png$)|(\\.jpg$)"), async r => await r.AbortAsync());<br/>
/// await page.GotoAsync("https://www.microsoft.com");
/// </code>
/// <para>
/// It is possible to examine the request to decide the route action. For example, mocking
/// all requests that contain some post data, and leaving all other requests as is:
/// </para>
/// <code>
/// await page.RouteAsync("/api/**", async r =><br/>
/// {<br/>
/// if (r.Request.PostData.Contains("my-string"))<br/>
/// await r.FulfillAsync(new RouteFulfillOptions { Body = "mocked-data" });<br/>
/// else<br/>
/// await r.ContinueAsync();<br/>
/// });
/// </code>
/// <para>
/// Page routes take precedence over browser context routes (set up with <see cref="IBrowserContext.RouteAsync"/>)
/// when request matches both handlers.
/// </para>
/// <para>To remove a route with its handler you can use <see cref="IPage.UnrouteAsync"/>.</para>
/// </summary>
/// <remarks>
/// <para>The handler will only be called for the first url if the response is a redirect.</para>
/// <para>
/// <see cref="IPage.RouteAsync"/> will not intercept requests intercepted by Service
/// Worker. See <a href="https://github.com/microsoft/playwright/issues/1090">this</a>
/// issue. We recommend disabling Service Workers when using request interception. Via
/// <c>await context.addInitScript(() => delete window.navigator.serviceWorker);</c>
/// </para>
/// <para>Enabling routing disables http cache.</para>
/// </remarks>
/// <param name="url">
/// A glob pattern, regex pattern or predicate receiving <see cref="URL"/> to match
/// while routing. When a <paramref name="baseURL"/> via the context options was provided
/// and the passed URL is a path, it gets merged via the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL"><c>new
/// URL()</c></a> constructor.
/// </param>
/// <param name="handler">handler function to route the request.</param>
/// <param name="options">Call options</param>
Task RouteAsync(Regex url, Action<IRoute> handler, PageRouteOptions? options = default);
/// <summary>
/// <para>Routing provides the capability to modify network requests that are made by a page.</para>
/// <para>
/// Once routing is enabled, every request matching the url pattern will stall unless
/// it's continued, fulfilled or aborted.
/// </para>
/// <para>An example of a naive handler that aborts all image requests:</para>
/// <code>
/// var page = await browser.NewPageAsync();<br/>
/// await page.RouteAsync("**/*.{png,jpg,jpeg}", async r => await r.AbortAsync());<br/>
/// await page.GotoAsync("https://www.microsoft.com");
/// </code>
/// <para>or the same snippet using a regex pattern instead:</para>
/// <code>
/// var page = await browser.NewPageAsync();<br/>
/// await page.RouteAsync(new Regex("(\\.png$)|(\\.jpg$)"), async r => await r.AbortAsync());<br/>
/// await page.GotoAsync("https://www.microsoft.com");
/// </code>
/// <para>
/// It is possible to examine the request to decide the route action. For example, mocking
/// all requests that contain some post data, and leaving all other requests as is:
/// </para>
/// <code>
/// await page.RouteAsync("/api/**", async r =><br/>
/// {<br/>
/// if (r.Request.PostData.Contains("my-string"))<br/>
/// await r.FulfillAsync(new RouteFulfillOptions { Body = "mocked-data" });<br/>
/// else<br/>
/// await r.ContinueAsync();<br/>
/// });
/// </code>
/// <para>
/// Page routes take precedence over browser context routes (set up with <see cref="IBrowserContext.RouteAsync"/>)
/// when request matches both handlers.
/// </para>
/// <para>To remove a route with its handler you can use <see cref="IPage.UnrouteAsync"/>.</para>
/// </summary>
/// <remarks>
/// <para>The handler will only be called for the first url if the response is a redirect.</para>
/// <para>
/// <see cref="IPage.RouteAsync"/> will not intercept requests intercepted by Service
/// Worker. See <a href="https://github.com/microsoft/playwright/issues/1090">this</a>
/// issue. We recommend disabling Service Workers when using request interception. Via
/// <c>await context.addInitScript(() => delete window.navigator.serviceWorker);</c>
/// </para>
/// <para>Enabling routing disables http cache.</para>
/// </remarks>
/// <param name="url">
/// A glob pattern, regex pattern or predicate receiving <see cref="URL"/> to match
/// while routing. When a <paramref name="baseURL"/> via the context options was provided
/// and the passed URL is a path, it gets merged via the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL"><c>new
/// URL()</c></a> constructor.
/// </param>
/// <param name="handler">handler function to route the request.</param>
/// <param name="options">Call options</param>
Task RouteAsync(Func<string, bool> url, Action<IRoute> handler, PageRouteOptions? options = default);
/// <summary><para>Returns the buffer with the captured screenshot.</para></summary>
/// <param name="options">Call options</param>
Task<byte[]> ScreenshotAsync(PageScreenshotOptions? options = default);
/// <summary>
/// <para>
/// This method waits for an element matching <paramref name="selector"/>, waits for
/// <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a> checks,
/// waits until all specified options are present in the <c><select></c> element
/// and selects these options.
/// </para>
/// <para>
/// If the target element is not a <c><select></c> element, this method throws
/// an error. However, if the element is inside the <c><label></c> element that
/// has an associated <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control">control</a>,
/// the control will be used instead.
/// </para>
/// <para>Returns the array of option values that have been successfully selected.</para>
/// <para>
/// Triggers a <c>change</c> and <c>input</c> event once all the provided options have
/// been selected.
/// </para>
/// <code>
/// // single selection matching the value<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "blue" });<br/>
/// // single selection matching both the value and the label<br/>
/// await page.SelectOptionAsync("select#colors", new[] { new SelectOptionValue() { Label = "blue" } });<br/>
/// // multiple<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "red", "green", "blue" });
/// </code>
/// <para>Shortcut for main frame's <see cref="IFrame.SelectOptionAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="values">
/// Options to select. If the <c><select></c> has the <c>multiple</c> attribute,
/// all matching options are selected, otherwise only the first option matching one
/// of the passed options is selected. String values are equivalent to <c>{value:'string'}</c>.
/// Option is considered matching if all specified properties match.
/// </param>
/// <param name="options">Call options</param>
Task<IReadOnlyList<string>> SelectOptionAsync(string selector, string values, PageSelectOptionOptions? options = default);
/// <summary>
/// <para>
/// This method waits for an element matching <paramref name="selector"/>, waits for
/// <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a> checks,
/// waits until all specified options are present in the <c><select></c> element
/// and selects these options.
/// </para>
/// <para>
/// If the target element is not a <c><select></c> element, this method throws
/// an error. However, if the element is inside the <c><label></c> element that
/// has an associated <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control">control</a>,
/// the control will be used instead.
/// </para>
/// <para>Returns the array of option values that have been successfully selected.</para>
/// <para>
/// Triggers a <c>change</c> and <c>input</c> event once all the provided options have
/// been selected.
/// </para>
/// <code>
/// // single selection matching the value<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "blue" });<br/>
/// // single selection matching both the value and the label<br/>
/// await page.SelectOptionAsync("select#colors", new[] { new SelectOptionValue() { Label = "blue" } });<br/>
/// // multiple<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "red", "green", "blue" });
/// </code>
/// <para>Shortcut for main frame's <see cref="IFrame.SelectOptionAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="values">
/// Options to select. If the <c><select></c> has the <c>multiple</c> attribute,
/// all matching options are selected, otherwise only the first option matching one
/// of the passed options is selected. String values are equivalent to <c>{value:'string'}</c>.
/// Option is considered matching if all specified properties match.
/// </param>
/// <param name="options">Call options</param>
Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IElementHandle values, PageSelectOptionOptions? options = default);
/// <summary>
/// <para>
/// This method waits for an element matching <paramref name="selector"/>, waits for
/// <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a> checks,
/// waits until all specified options are present in the <c><select></c> element
/// and selects these options.
/// </para>
/// <para>
/// If the target element is not a <c><select></c> element, this method throws
/// an error. However, if the element is inside the <c><label></c> element that
/// has an associated <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control">control</a>,
/// the control will be used instead.
/// </para>
/// <para>Returns the array of option values that have been successfully selected.</para>
/// <para>
/// Triggers a <c>change</c> and <c>input</c> event once all the provided options have
/// been selected.
/// </para>
/// <code>
/// // single selection matching the value<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "blue" });<br/>
/// // single selection matching both the value and the label<br/>
/// await page.SelectOptionAsync("select#colors", new[] { new SelectOptionValue() { Label = "blue" } });<br/>
/// // multiple<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "red", "green", "blue" });
/// </code>
/// <para>Shortcut for main frame's <see cref="IFrame.SelectOptionAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="values">
/// Options to select. If the <c><select></c> has the <c>multiple</c> attribute,
/// all matching options are selected, otherwise only the first option matching one
/// of the passed options is selected. String values are equivalent to <c>{value:'string'}</c>.
/// Option is considered matching if all specified properties match.
/// </param>
/// <param name="options">Call options</param>
Task<IReadOnlyList<string>> SelectOptionAsync(string selector, IEnumerable<string> values, PageSelectOptionOptions? options = default);
/// <summary>
/// <para>
/// This method waits for an element matching <paramref name="selector"/>, waits for
/// <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a> checks,
/// waits until all specified options are present in the <c><select></c> element
/// and selects these options.
/// </para>
/// <para>
/// If the target element is not a <c><select></c> element, this method throws
/// an error. However, if the element is inside the <c><label></c> element that
/// has an associated <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control">control</a>,
/// the control will be used instead.
/// </para>
/// <para>Returns the array of option values that have been successfully selected.</para>
/// <para>
/// Triggers a <c>change</c> and <c>input</c> event once all the provided options have
/// been selected.
/// </para>
/// <code>
/// // single selection matching the value<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "blue" });<br/>
/// // single selection matching both the value and the label<br/>
/// await page.SelectOptionAsync("select#colors", new[] { new SelectOptionValue() { Label = "blue" } });<br/>
/// // multiple<br/>
/// await page.SelectOptionAsync("select#colors", new[] { "red", "green", "blue" });
/// </code>
/// <para>Shortcut for main frame's <see cref="IFrame.SelectOptionAsync"/>.</para>
/// </summary>
/// <param name="selector">
/// A selector to search for an element. If there are multiple elements satisfying the
/// selector, the first will be used. See <a href="https://playwright.dev/dotnet/docs/selectors">working
/// with selectors</a> for more details.
/// </param>
/// <param name="values">
/// Options to select. If the <c><select></c> has the <c>multiple</c> attribute,
/// all matching options are selected, otherwise only the first option matching one
/// of the passed options is selected. String values are equivalent to <c>{value:'string'}</c>.
/// Option is considered matching if all specified properties match.
/// </param>
/// <param name="options">Call options</param>
Task<IReadOnlyList<string>> SelectOptionAsync(string selector, SelectOptionValue values, PageSelectOptionOptions? options = default);
/// <summary>
/// <para>
/// This method waits for an element matching <paramref name="selector"/>, waits for
/// <a href="https://playwright.dev/dotnet/docs/actionability">actionability</a> checks,
/// waits until all specified options are present in the <c><select></c> element
/// and selects these options.