Родитель
4278532046
Коммит
a7b7e075af
|
@ -0,0 +1,25 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Modifiers for <see cref="ClickOptions.Modifiers"/>
|
||||
/// </summary>
|
||||
public enum ClickModifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Alt key
|
||||
/// </summary>
|
||||
Alt,
|
||||
/// <summary>
|
||||
/// Control key
|
||||
/// </summary>
|
||||
Control,
|
||||
/// <summary>
|
||||
/// Meta key
|
||||
/// </summary>
|
||||
Meta,
|
||||
/// <summary>
|
||||
/// Shift Key
|
||||
/// </summary>
|
||||
Shift
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using System.Drawing;
|
||||
|
||||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Options to use when clicking
|
||||
/// </summary>
|
||||
public class ClickOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Time to wait between <c>mousedown</c> and <c>mouseup</c> in milliseconds. Defaults to 0
|
||||
/// </summary>
|
||||
public int Delay { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to 1. See https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail
|
||||
/// </summary>
|
||||
public int ClickCount { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The button to use for the click. Defaults to <see cref="MouseButton.Left"/>
|
||||
/// </summary>
|
||||
public MouseButton Button { get; set; } = MouseButton.Left;
|
||||
|
||||
/// <summary>
|
||||
/// Wait for element to become visible (visible), hidden (hidden), present in dom (any) or do not wait at all (nowait). Defaults to visible.
|
||||
/// </summary>
|
||||
public WaitForOptions WaitFor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A point to click relative to the top-left corner of element padding box. If not specified, clicks to some visible point of the element.
|
||||
/// </summary>
|
||||
public Point RelativePoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Modifier keys to press. Ensures that only these modifiers are pressed during the click, and then restores current modifiers back. If not specified, currently pressed modifiers are used.
|
||||
/// </summary>
|
||||
public ClickModifier[] Modifiers { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
|
||||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IPage.Console"/> data.
|
||||
/// </summary>
|
||||
public class ConsoleEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the message.
|
||||
/// </summary>
|
||||
/// <value>The message.</value>
|
||||
public ConsoleMessage Message { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConsoleEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">Message.</param>
|
||||
public ConsoleEventArgs(ConsoleMessage message) => Message = message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// ConsoleMessage is part of <see cref="ConsoleEventArgs"/> used by <see cref="IPage.Console"/>
|
||||
/// </summary>
|
||||
public class ConsoleMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the ConsoleMessage type.
|
||||
/// </summary>
|
||||
/// <value>ConsoleMessageType.</value>
|
||||
public ConsoleType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the console text.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
public string Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments.
|
||||
/// </summary>
|
||||
/// <value>The arguments.</value>
|
||||
public IList<IJSHandle> Args { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the location.
|
||||
/// </summary>
|
||||
public ConsoleMessageLocation Location { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConsoleMessage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="type">Type.</param>
|
||||
/// <param name="text">Text.</param>
|
||||
/// <param name="args">Arguments.</param>
|
||||
/// <param name="location">Message location</param>
|
||||
public ConsoleMessage(ConsoleType type, string text, IList<IJSHandle> args, ConsoleMessageLocation location = null)
|
||||
{
|
||||
Type = type;
|
||||
Text = text;
|
||||
Args = args;
|
||||
Location = location;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Console message location.
|
||||
/// </summary>
|
||||
public class ConsoleMessageLocation : IEquatable<ConsoleMessageLocation>
|
||||
{
|
||||
/// <summary>
|
||||
/// URL of the resource if known.
|
||||
/// </summary>
|
||||
public string URL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 0-based line number in the resource if known.
|
||||
/// </summary>
|
||||
public int? LineNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 0-based column number in the resource if known.
|
||||
/// </summary>
|
||||
public int? ColumnNumber { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(ConsoleMessageLocation other)
|
||||
=> (URL, LineNumber, ColumnNumber) == (other?.URL, other?.LineNumber, other?.ColumnNumber);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj) => Equals(obj as ConsoleMessageLocation);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
=> 412870874 +
|
||||
EqualityComparer<string>.Default.GetHashCode(URL) +
|
||||
EqualityComparer<int?>.Default.GetHashCode(LineNumber) +
|
||||
EqualityComparer<int?>.Default.GetHashCode(ColumnNumber);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator ==(ConsoleMessageLocation location1, ConsoleMessageLocation location2)
|
||||
=> EqualityComparer<ConsoleMessageLocation>.Default.Equals(location1, location2);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator !=(ConsoleMessageLocation location1, ConsoleMessageLocation location2)
|
||||
=> !(location1 == location2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Console type used on <see cref="ConsoleMessage"/>.
|
||||
/// </summary>
|
||||
public enum ConsoleType
|
||||
{
|
||||
/// <summary>
|
||||
/// Log.
|
||||
/// </summary>
|
||||
Log,
|
||||
/// <summary>
|
||||
/// Debug.
|
||||
/// </summary>
|
||||
Debug,
|
||||
/// <summary>
|
||||
/// Info.
|
||||
/// </summary>
|
||||
Info,
|
||||
/// <summary>
|
||||
/// Error.
|
||||
/// </summary>
|
||||
Error,
|
||||
/// <summary>
|
||||
/// Warning.
|
||||
/// </summary>
|
||||
Warning,
|
||||
/// <summary>
|
||||
/// Dir.
|
||||
/// </summary>
|
||||
Dir,
|
||||
/// <summary>
|
||||
/// Dirxml.
|
||||
/// </summary>
|
||||
Dirxml,
|
||||
/// <summary>
|
||||
/// Table.
|
||||
/// </summary>
|
||||
Table,
|
||||
/// <summary>
|
||||
/// Trace.
|
||||
/// </summary>
|
||||
Trace,
|
||||
/// <summary>
|
||||
/// Clear.
|
||||
/// </summary>
|
||||
Clear,
|
||||
/// <summary>
|
||||
/// StartGroup.
|
||||
/// </summary>
|
||||
StartGroup,
|
||||
/// <summary>
|
||||
/// StartGroupCollapsed.
|
||||
/// </summary>
|
||||
StartGroupCollapsed,
|
||||
/// <summary>
|
||||
/// EndGroup.
|
||||
/// </summary>
|
||||
EndGroup,
|
||||
/// <summary>
|
||||
/// Assert.
|
||||
/// </summary>
|
||||
Assert,
|
||||
/// <summary>
|
||||
/// Profile.
|
||||
/// </summary>
|
||||
Profile,
|
||||
/// <summary>
|
||||
/// ProfileEnd.
|
||||
/// </summary>
|
||||
ProfileEnd,
|
||||
/// <summary>
|
||||
/// Count.
|
||||
/// </summary>
|
||||
Count,
|
||||
/// <summary>
|
||||
/// TimeEnd.
|
||||
/// </summary>
|
||||
TimeEnd,
|
||||
/// <summary>
|
||||
/// Verbose.
|
||||
/// </summary>
|
||||
Verbose,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for <see cref="IKeyboard.DownAsync(string, DownOptions)"/>
|
||||
/// </summary>
|
||||
public class DownOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// If specified, generates an input event with this text
|
||||
/// </summary>
|
||||
public string Text { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Threading.Tasks;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PlaywrightSharp
|
||||
{
|
||||
|
@ -21,5 +22,24 @@ namespace PlaywrightSharp
|
|||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> that completes when the frame is resolved, yielding element's parent <see cref="IFrame" /></returns>
|
||||
Task<IFrame> ContentFrameAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Scrolls element into view if needed, and then uses <see cref="IPage.Mouse"/> to click in the center of the element.
|
||||
/// </summary>
|
||||
/// <param name="options">click options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the element is successfully clicked</returns>
|
||||
Task ClickAsync(ClickOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Executes a function in browser context, passing the current <see cref="IElementHandle"/> as the first argument.
|
||||
/// </summary>
|
||||
/// <param name="script">Script to be evaluated in browser context</param>
|
||||
/// <param name="args">Arguments to pass to script</param>
|
||||
/// <remarks>
|
||||
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
|
||||
/// <see cref="IJSHandle"/> instances can be passed as arguments
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="Task"/> that completes when the script is executed, yieling the return value of that script</returns>
|
||||
Task<JsonElement?> EvaluateAsync(string script, params object[] args);
|
||||
}
|
||||
}
|
|
@ -57,6 +57,11 @@ namespace PlaywrightSharp
|
|||
/// </summary>
|
||||
string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent <see cref="IFrame"/>, if any. Detached frames and main frames return <c>null</c>
|
||||
/// </summary>
|
||||
IFrame ParentFrame { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the HTML markup to the frame
|
||||
/// </summary>
|
||||
|
@ -100,5 +105,54 @@ namespace PlaywrightSharp
|
|||
/// <seealso cref="IPage.EvaluateAsync(string, object[])"/>
|
||||
/// <returns>Task that completes when the script finishes or the promise is resolved, yielding the result of the script as an row Json element.</returns>
|
||||
Task<JsonElement?> EvaluateAsync(string script, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// <![CDATA[
|
||||
/// This method focuses the element and triggers an input event after filling. If there's no text <input>, <textarea> or [contenteditable] element matching selector, the method throws an error.
|
||||
/// ]]>
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector to query page for.</param>
|
||||
/// <param name="text"><![CDATA[Value to fill for the <input>, <textarea> or [contenteditable] element]]></param>
|
||||
/// <param name="options">Optional waiting parameters</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the fill message is confirmed by the browser.</returns>
|
||||
Task FillAsync(string selector, string text, WaitForSelectorOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Waits for a selector to be added to the DOM
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector of an element to wait for</param>
|
||||
/// <param name="options">Optional waiting parameters</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when element specified by selector string is added to DOM, yielding the <see cref="IElementHandle"/> to wait for.
|
||||
/// Resolves to `null` if waiting for `hidden: true` and selector is not found in DOM.</returns>
|
||||
Task<IElementHandle> WaitForSelectorAsync(string selector, WaitForSelectorOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Queries frame for the selector. If there's no such element within the frame, the method will resolve to <c>null</c>.
|
||||
/// </summary>
|
||||
/// <param name="selector">Selector to query frame for</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the selector is found (or failed), yielding the <see cref="IElementHandle"/> pointing to the frame element</returns>
|
||||
/// <seealso cref="IPage.QuerySelectorAsync(string)"/>
|
||||
Task<IElementHandle> QuerySelectorAsync(string selector);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an element with <paramref name="selector"/>, scrolls it into view if needed, and then uses <see cref="IPage.Mouse"/> to click in the center of the element.
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked.</param>
|
||||
/// <param name="options">click options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the element matching <paramref name="selector"/> is successfully clicked</returns>
|
||||
Task ClickAsync(string selector, ClickOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// This method runs document.querySelector within the page and passes it as the first argument to pageFunction.
|
||||
/// If there's no element matching selector, the method throws an error.
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector to query page for</param>
|
||||
/// <param name="script">Script to be evaluated in browser context</param>
|
||||
/// <param name="args">Arguments to pass to script</param>
|
||||
/// <remarks>
|
||||
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="Task"/> that completes when the script finishes or the promise is resolved, yielding the result of the script</returns>
|
||||
Task QuerySelectorEvaluateAsync(string selector, string script, params object[] args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Keyboard provides an api for managing a virtual keyboard.
|
||||
/// </summary>
|
||||
public interface IKeyboard
|
||||
{
|
||||
/// <summary>
|
||||
/// <![CDATA[
|
||||
/// Dispatches a <c>keydown</c> event
|
||||
/// ]]>
|
||||
/// </summary>
|
||||
/// <param name="key">Name of key to press, such as <c>ArrowLeft</c>.</param>
|
||||
/// <param name="options">down options</param>
|
||||
/// <remarks>
|
||||
/// If <c>key</c> is a single character and no modifier keys besides <c>Shift</c> are being held down, a <c>keypress</c>/<c>input</c> event will also generated. The <c>text</c> option can be specified to force an input event to be generated.
|
||||
/// If <c>key</c> is a modifier key, <c>Shift</c>, <c>Meta</c>, <c>Control</c>, or <c>Alt</c>, subsequent key presses will be sent with that modifier active. To release the modifier key, use <see cref="UpAsync(string)"/>
|
||||
/// After the key is pressed once, subsequent calls to <see cref="DownAsync(string, DownOptions)"/> will have <see href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat">repeat</see> set to <c>true</c>. To release the key, use <see cref="UpAsync(string)"/>
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="Task"/> that completes when the message is confirmed by the browser</returns>
|
||||
Task DownAsync(string key, DownOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches a <c>keyup</c> event.
|
||||
/// </summary>
|
||||
/// <param name="key">Name of key to release, such as `ArrowLeft`.</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the message is confirmed by the browser</returns>
|
||||
Task UpAsync(string key);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods to interact with the mouse
|
||||
/// </summary>
|
||||
public interface IMouse
|
||||
{
|
||||
/// <summary>
|
||||
/// Dispatches a <c>mousemove</c> event.
|
||||
/// </summary>
|
||||
/// <param name="x">X coordinate</param>
|
||||
/// <param name="y">Y coordinate</param>
|
||||
/// <param name="options">Extra options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the message is confirmed by the browser.</returns>
|
||||
Task MoveAsync(decimal x, decimal y, MoveOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for <see cref="MoveAsync(decimal, decimal, MoveOptions)"/>, <see cref="DownAsync(ClickOptions)"/> and <see cref="UpAsync(ClickOptions)"/>
|
||||
/// </summary>
|
||||
/// <param name="x">X coordinate</param>
|
||||
/// <param name="y">Y coordinate</param>
|
||||
/// <param name="options">Extra options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the message is confirmed by the browser.</returns>
|
||||
Task ClickAsync(decimal x, decimal y, ClickOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches a <c>mousedown</c> event.
|
||||
/// </summary>
|
||||
/// <param name="options">Extra options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the message is confirmed by the browser.</returns>
|
||||
Task DownAsync(ClickOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches a <c>mouseup</c> event.
|
||||
/// </summary>
|
||||
/// <param name="options">Extra options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the message is confirmed by the browser.</returns>
|
||||
Task UpAsync(ClickOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches a <c>wheel</c> event.
|
||||
/// </summary>
|
||||
/// <param name="deltaX">delta X</param>
|
||||
/// <param name="deltaY">delta Y</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the message is confirmed by the browser.</returns>
|
||||
Task WheelAsync(decimal deltaX, decimal deltaY);
|
||||
}
|
||||
}
|
|
@ -106,11 +106,57 @@ namespace PlaywrightSharp
|
|||
/// </summary>
|
||||
IAccessibility Accessibility { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets this page's mouse
|
||||
/// </summary>
|
||||
IMouse Mouse { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for MainFrame.Url
|
||||
/// </summary>
|
||||
string Url { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all frames attached to the page.
|
||||
/// </summary>
|
||||
IFrame[] Frames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets this page's keyboard
|
||||
/// </summary>
|
||||
IKeyboard Keyboard { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Raised 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.
|
||||
/// The arguments passed into <c>console.log</c> appear as arguments on the event handler.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// An example of handling <see cref="Console"/> event:
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// page.Console += (sender, e) =>
|
||||
/// {
|
||||
/// for (var i = 0; i < e.Message.Args.Count; ++i)
|
||||
/// {
|
||||
/// System.Console.WriteLine($"{i}: {e.Message.Args[i]}");
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
/// </code>
|
||||
/// </example>
|
||||
event EventHandler<ConsoleEventArgs> Console;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a JavaScript dialog appears, such as <c>alert</c>, <c>prompt</c>, <c>confirm</c> or <c>beforeunload</c>. PlaywrightSharp can respond to the dialog via <see cref="Dialog"/>'s <see cref="IDialog.AcceptAsync(string)"/> or <see cref="IDialog.DismissAsync"/> methods.
|
||||
/// </summary>
|
||||
event EventHandler<DialogEventArgs> Dialog;
|
||||
|
||||
/// <summary>
|
||||
/// Closes the page.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> that completes when the close process finishes.</returns>
|
||||
Task CloseAsync(PageCloseOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Executes a script in browser context
|
||||
/// </summary>
|
||||
|
@ -120,7 +166,7 @@ namespace PlaywrightSharp
|
|||
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
|
||||
/// </remarks>
|
||||
/// <seealso cref="IFrame.EvaluateAsync{T}(string, object[])"/>
|
||||
/// <returns>Task that completes when the script finishes or the promise is resolved, yielding the result of the script</returns>
|
||||
/// <returns>A <see cref="Task"/> that completes when the script finishes or the promise is resolved, yielding the result of the script</returns>
|
||||
Task<T> EvaluateAsync<T>(string script, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
|
@ -133,9 +179,30 @@ namespace PlaywrightSharp
|
|||
/// <remarks>
|
||||
/// If the script, returns a Promise, then the method would wait for the promise to resolve and return its value.
|
||||
/// </remarks>
|
||||
/// <returns>Task that completes when the script finishes or the promise is resolved, yielding the result of the script</returns>
|
||||
/// <returns>A <see cref="Task"/> that completes when the script finishes or the promise is resolved, yielding the result of the script</returns>
|
||||
Task QuerySelectorEvaluateAsync(string selector, string script, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// <![CDATA[
|
||||
/// This method focuses the element and triggers an input event after filling. If there's no text <input>, <textarea> or [contenteditable] element matching selector, the method throws an error.
|
||||
/// ]]>
|
||||
/// Shortcut for MainFrame.FillAsync.
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector to query page for.</param>
|
||||
/// <param name="text"><![CDATA[Value to fill for the <input>, <textarea> or [contenteditable] element]]></param>
|
||||
/// <param name="options">Optional waiting parameters</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the fill message is confirmed by the browser.</returns>
|
||||
Task FillAsync(string selector, string text, WaitForSelectorOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Waits for a selector to be added to the DOM
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector of an element to wait for</param>
|
||||
/// <param name="options">Optional waiting parameters</param>
|
||||
/// <returns>A task that completes when element specified by selector string is added to DOM, yielding the <see cref="IElementHandle"/> to wait for.
|
||||
/// Resolves to `null` if waiting for `hidden: true` and selector is not found in DOM.</returns>
|
||||
public Task<IElementHandle> WaitForSelectorAsync(string selector, WaitForSelectorOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Executes a script in browser context
|
||||
/// </summary>
|
||||
|
@ -274,5 +341,44 @@ namespace PlaywrightSharp
|
|||
/// </remarks>
|
||||
/// <returns>A <see cref="Task"/> that completes when the tag is added, yielding the added tag when the script's onload fires or when the script content was injected into frame</returns>
|
||||
Task<IElementHandle> AddScriptTagAsync(AddTagOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an element with <paramref name="selector"/>, scrolls it into view if needed, and then uses <see cref="Mouse"/> to click in the center of the element.
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked.</param>
|
||||
/// <param name="options">click options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the element matching <paramref name="selector"/> is successfully clicked</returns>
|
||||
Task ClickAsync(string selector, ClickOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an element with <paramref name="selector"/>, scrolls it into view if needed, and then uses <see cref="Mouse"/> to triple click in the center of the element.
|
||||
/// </summary>
|
||||
/// <param name="selector">A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked.</param>
|
||||
/// <param name="options">click options</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the element matching <paramref name="selector"/> is successfully triple clicked</returns>
|
||||
Task TripleClickAsync(string selector, ClickOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the viewport.
|
||||
/// In the case of multiple pages in a single browser, each page can have its own viewport size.
|
||||
/// <see cref="SetViewportAsync(Viewport)"/> will resize the page. A lot of websites don't expect phones to change size, so you should set the viewport before navigating to the page.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
///<![CDATA[
|
||||
/// using(var page = await context.NewPageAsync())
|
||||
/// {
|
||||
/// await page.SetViewPortAsync(new Viewport
|
||||
/// {
|
||||
/// Width = 640,
|
||||
/// Height = 480,
|
||||
/// DeviceScaleFactor = 1
|
||||
/// });
|
||||
/// await page.GoToAsync('https://www.example.com');
|
||||
/// }
|
||||
/// ]]>
|
||||
/// </example>
|
||||
/// <param name="viewport">Viewport</param>
|
||||
/// <returns>A<see cref="Task"/> that copletes when the message is confirmed by the browser</returns>
|
||||
Task SetViewportAsync(Viewport viewport);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of button click to use with <see cref="IPage.ClickAsync(string, ClickOptions)"/>
|
||||
/// </summary>
|
||||
public enum MouseButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Non specified
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// The left mouse button
|
||||
/// </summary>
|
||||
Left,
|
||||
|
||||
/// <summary>
|
||||
/// The right mouse button
|
||||
/// </summary>
|
||||
Right,
|
||||
|
||||
/// <summary>
|
||||
/// The middle mouse button
|
||||
/// </summary>
|
||||
Middle
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for <see cref="IMouse.MoveAsync(decimal, decimal, MoveOptions)"/>
|
||||
/// </summary>
|
||||
public class MoveOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends intermediate <c>mousemove</c> events. Defaults to 1
|
||||
/// </summary>
|
||||
public int Steps { get; set; } = 1;
|
||||
}
|
||||
}
|
|
@ -24,4 +24,4 @@
|
|||
/// <value>The referer.</value>
|
||||
public string Referer { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for <see cref="IPage.CloseAsync(PageCloseOptions)"/>.
|
||||
/// </summary>
|
||||
public class PageCloseOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Defaults to <c>false</c>. Whether to run the beforeunload page handlers.
|
||||
/// </summary>
|
||||
/// <see href="https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload"/>
|
||||
public bool RunBeforeUnload { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for <see cref="ClickOptions.WaitFor"/>
|
||||
/// </summary>
|
||||
public enum WaitForOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait for visible
|
||||
/// </summary>
|
||||
Visible,
|
||||
/// <summary>
|
||||
/// Wait for hidden
|
||||
/// </summary>
|
||||
Hidden,
|
||||
/// <summary>
|
||||
/// Wait for any
|
||||
/// </summary>
|
||||
Any,
|
||||
/// <summary>
|
||||
/// No wait
|
||||
/// </summary>
|
||||
NoWait
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Optional waiting parameters.
|
||||
/// </summary>
|
||||
/// <seealso cref="IPage.WaitForSelectorAsync(string, WaitForSelectorOptions)"/>
|
||||
/// <seealso cref="IFrame.WaitForSelectorAsync(string, WaitForSelectorOptions)"/>
|
||||
public class WaitForSelectorOptions
|
||||
{
|
||||
}
|
||||
}
|
|
@ -25,4 +25,4 @@
|
|||
/// </summary>
|
||||
Networkidle2
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ namespace PlaywrightSharp.Tests.BaseTests
|
|||
}
|
||||
}
|
||||
|
||||
internal Task<IBrowserContext> NewContextAsync(BrowserContextOptions options) => Browser.NewContextAsync(options);
|
||||
internal Task<IBrowserContext> NewContextAsync(BrowserContextOptions options = null) => Browser.NewContextAsync(options);
|
||||
|
||||
internal async Task<IPage> NewPageAsync(BrowserContextOptions options = null)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,599 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using PlaywrightSharp.Tests.Attributes;
|
||||
using PlaywrightSharp.Tests.BaseTests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace PlaywrightSharp.Tests.Page
|
||||
{
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
public class ClickTests : PlaywrightSharpPageBaseTest
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ClickTests(ITestOutputHelper output) : base(output)
|
||||
{
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButton()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click svg</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickSvg()
|
||||
{
|
||||
await Page.SetContentAsync($@"
|
||||
<svg height=""100"" width=""100"">
|
||||
<circle onclick=""javascript:window.__CLICKED=42"" cx=""50"" cy=""50"" r=""40"" stroke=""black"" stroke-width=""3"" fill=""red""/>
|
||||
</svg>
|
||||
");
|
||||
await Page.ClickAsync("circle");
|
||||
Assert.Equal(42, await Page.EvaluateAsync<int>("() => window.__CLICKED"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click svg</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButtonIfWindowNodeIsRemoved()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.EvaluateAsync("delete window.Node");
|
||||
await Page.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click on a span with an inline element inside</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickOnASpanWithAnInlineElementInside()
|
||||
{
|
||||
await Page.SetContentAsync($@"
|
||||
<style>
|
||||
span::before {{
|
||||
content: 'q';
|
||||
}}
|
||||
</style>
|
||||
<span onclick='javascript:window.CLICKED=42'></span>
|
||||
");
|
||||
await Page.ClickAsync("span");
|
||||
Assert.Equal(42, await Page.EvaluateAsync<int>("() => window.CLICKED"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should not throw UnhandledPromiseRejection when page closes</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldGracefullyFailWhenPageCloses()
|
||||
{
|
||||
var context = await NewContextAsync();
|
||||
var newPage = await context.NewPageAsync();
|
||||
await Assert.ThrowsAsync<TargetClosedException>(() => Task.WhenAll(
|
||||
newPage.CloseAsync(),
|
||||
newPage.Mouse.ClickAsync(1, 2)
|
||||
));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button after navigation </playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButtonAfterNavigation()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.ClickAsync("button");
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button after a cross origin navigation </playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButtonAfterACrossOriginNavigation()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.ClickAsync("button");
|
||||
await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/input/button.html");
|
||||
await Page.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click with disabled javascript</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickWithDisabledJavascript()
|
||||
{
|
||||
var page = await NewPageAsync(new BrowserContextOptions { JavaScriptEnabled = false });
|
||||
await page.GoToAsync(TestConstants.ServerUrl + "/wrappedlink.html");
|
||||
await Task.WhenAll(
|
||||
page.ClickAsync("a"),
|
||||
page.WaitForNavigationAsync()
|
||||
);
|
||||
Assert.Equal(TestConstants.ServerUrl + "/wrappedlink.html#clicked", Page.Url);
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click when one of inline box children is outside of viewport</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickWhenOneOfInlineBoxChildrenIsOutsideOfViewport()
|
||||
{
|
||||
await Page.SetContentAsync($@"
|
||||
<style>
|
||||
i {{
|
||||
position: absolute;
|
||||
top: -1000px;
|
||||
}}
|
||||
</style>
|
||||
<span onclick='javascript:window.CLICKED = 42;'><i>woof</i><b>doggo</b></span>
|
||||
");
|
||||
|
||||
await Page.ClickAsync("span");
|
||||
Assert.Equal(42, await Page.EvaluateAsync<int>("() => window.CLICKED"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should select the text by triple clicking</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldSelectTheTextByTripleClicking()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html");
|
||||
const string text = "This is the text that we are going to try to select. Let's see how it goes.";
|
||||
await Page.FillAsync("textarea", text);
|
||||
await Page.TripleClickAsync("textarea");
|
||||
|
||||
Assert.Equal(text, await Page.EvaluateAsync<string>("window.getSelection().toString()"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click offscreen buttons</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickOffscreenButtons()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/offscreenbuttons.html");
|
||||
var messages = new List<string>();
|
||||
Page.Console += (sender, e) => messages.Add(e.Message.Text);
|
||||
|
||||
for (int i = 0; i < 11; ++i)
|
||||
{
|
||||
// We might've scrolled to click a button - reset to (0, 0).
|
||||
await Page.EvaluateAsync("() => window.scrollTo(0, 0)");
|
||||
await Page.ClickAsync($"#btn{i}");
|
||||
}
|
||||
Assert.Equal(new List<string>
|
||||
{
|
||||
"button #0 clicked",
|
||||
"button #1 clicked",
|
||||
"button #2 clicked",
|
||||
"button #3 clicked",
|
||||
"button #4 clicked",
|
||||
"button #5 clicked",
|
||||
"button #6 clicked",
|
||||
"button #7 clicked",
|
||||
"button #8 clicked",
|
||||
"button #9 clicked",
|
||||
"button #10 clicked"
|
||||
}, messages);
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should waitFor visible when already visible</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldWaitForVisibleWhenAlreadyVisible()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should waitFor hidden when already hidden</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldWaitForHiddenWhenAlreadyHidden()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.QuerySelectorEvaluateAsync("button", "b => b.style.display = 'none'");
|
||||
|
||||
var exception = await Assert.ThrowsAsync<PlaywrightSharpException>(()
|
||||
=> Page.ClickAsync("button", new ClickOptions { WaitFor = WaitForOptions.Hidden }));
|
||||
|
||||
Assert.Equal("Node is either not visible or not an HTMLElement", exception.Message);
|
||||
Assert.Equal("Was not clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should waitFor hidden</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldWaitForHidden()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
var clickTask = Page.ClickAsync("button", new ClickOptions { WaitFor = WaitForOptions.Hidden });
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
await Page.EvaluateAsync("1");
|
||||
}
|
||||
Assert.False(clickTask.IsCompleted);
|
||||
|
||||
await Page.QuerySelectorEvaluateAsync("button", "b => b.style.display = 'none'");
|
||||
|
||||
var exception = await Assert.ThrowsAsync<PlaywrightSharpException>(() => clickTask);
|
||||
|
||||
Assert.Equal("Node is either not visible or not an HTMLElement", exception.Message);
|
||||
Assert.Equal("Was not clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should waitFor visible</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldWaitForVisible()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.QuerySelectorEvaluateAsync("button", "b => b.style.display = 'none'");
|
||||
|
||||
var clickTask = Page.ClickAsync("button");
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
await Page.EvaluateAsync("1");
|
||||
}
|
||||
Assert.False(clickTask.IsCompleted);
|
||||
|
||||
await Page.QuerySelectorEvaluateAsync("button", "b => b.style.display = 'block'");
|
||||
|
||||
Assert.True(clickTask.IsCompleted);
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click wrapped links</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickWrappedLinks()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/wrappedlink.html");
|
||||
await Page.ClickAsync("a");
|
||||
Assert.True(await Page.EvaluateAsync<bool>("window.__clicked"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click on checkbox input and toggle</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickOnCheckboxInputAndToggle()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/checkbox.html");
|
||||
Assert.Null(await Page.EvaluateAsync("result.check"));
|
||||
await Page.ClickAsync("input#agree");
|
||||
Assert.True(await Page.EvaluateAsync<bool>("result.check"));
|
||||
Assert.Equal(new[] {
|
||||
"mouseover",
|
||||
"mouseenter",
|
||||
"mousemove",
|
||||
"mousedown",
|
||||
"mouseup",
|
||||
"click",
|
||||
"input",
|
||||
"change"
|
||||
}, await Page.EvaluateAsync<string[]>("result.events"));
|
||||
await Page.ClickAsync("input#agree");
|
||||
Assert.False(await Page.EvaluateAsync<bool>("result.check"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click on checkbox label and toggle</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickOnCheckboxLabelAndToggle()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/checkbox.html");
|
||||
Assert.Null(await Page.EvaluateAsync("result.check"));
|
||||
await Page.ClickAsync("label[for=\"agree\"]");
|
||||
Assert.True(await Page.EvaluateAsync<bool>("result.check"));
|
||||
Assert.Equal(new[] {
|
||||
"click",
|
||||
"input",
|
||||
"change"
|
||||
}, await Page.EvaluateAsync<string[]>("result.events"));
|
||||
await Page.ClickAsync("label[for=\"agree\"]");
|
||||
Assert.False(await Page.EvaluateAsync<bool>("result.check"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should fail to click a missing button</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldFailToClickAMissingButton()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
var exception = await Assert.ThrowsAsync<SelectorException>(()
|
||||
=> Page.ClickAsync("button.does-not-exist"));
|
||||
Assert.Equal("No node found for selector: button.does-not-exist", exception.Message);
|
||||
Assert.Equal("button.does-not-exist", exception.Selector);
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should not hang with touch-enabled viewports</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldNotHangWithTouchEnabledViewports()
|
||||
{
|
||||
await Page.SetViewportAsync(TestConstants.IPhone.ViewPort);
|
||||
await Page.Mouse.DownAsync();
|
||||
await Page.Mouse.MoveAsync(100, 10);
|
||||
await Page.Mouse.UpAsync();
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should scroll and click the button</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldScrollAndClickTheButton()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html");
|
||||
await Page.ClickAsync("#button-5");
|
||||
Assert.Equal("clicked", await Page.EvaluateAsync<string>("document.querySelector(\"#button-5\").textContent"));
|
||||
await Page.ClickAsync("#button-80");
|
||||
Assert.Equal("clicked", await Page.EvaluateAsync<string>("document.querySelector(\"#button-80\").textContent"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should double click the button</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldDoubleClickTheButton()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.EvaluateAsync(@"{
|
||||
window.double = false;
|
||||
const button = document.querySelector('button');
|
||||
button.addEventListener('dblclick', event => {
|
||||
window.double = true;
|
||||
});
|
||||
}");
|
||||
var button = await Page.QuerySelectorAsync("button");
|
||||
await button.ClickAsync(new ClickOptions { ClickCount = 2 });
|
||||
Assert.True(await Page.EvaluateAsync<bool>("double"));
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click a partially obscured button</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickAPartiallyObscuredButton()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.EvaluateAsync(@"{
|
||||
const button = document.querySelector('button');
|
||||
button.textContent = 'Some really long text that will go offscreen';
|
||||
|
||||
button.style.position = 'absolute';
|
||||
button.style.left = '368px';
|
||||
}");
|
||||
await Page.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click a rotated button</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickARotatedButton()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/rotatedButton.html");
|
||||
await Page.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should fire contextmenu event on right click</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldFireContextmenuEventOnRightClick()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html");
|
||||
await Page.ClickAsync("#button-8", new ClickOptions { Button = MouseButton.Right });
|
||||
Assert.Equal("context menu", await Page.EvaluateAsync<string>("document.querySelector('#button-8').textContent"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click links which cause navigation</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickLinksWhichCauseNavigation()
|
||||
{
|
||||
await Page.SetContentAsync($"<a href=\"{TestConstants.EmptyPage}\">empty.html</a>");
|
||||
// This await should not hang.
|
||||
await Page.ClickAsync("a");
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button inside an iframe</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButtonInsideAnIframe()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.EmptyPage);
|
||||
await Page.SetContentAsync("<div style=\"width:100px;height:100px\">spacer</div>");
|
||||
await FrameUtils.AttachFrameAsync(Page, "button-test", TestConstants.ServerUrl + "/input/button.html");
|
||||
var frame = Page.FirstChildFrame();
|
||||
var button = await frame.QuerySelectorAsync("button");
|
||||
await button.ClickAsync();
|
||||
Assert.Equal("Clicked", await frame.EvaluateAsync<string>("window.result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button with fixed position inside an iframe</playwright-it>
|
||||
[Fact(Skip = "See test in playwright")]
|
||||
public async Task ShouldClickTheButtonWithFixedPositionInsideAnIframe()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.EmptyPage);
|
||||
await Page.SetViewportAsync(new Viewport
|
||||
{
|
||||
Width = 500,
|
||||
Height = 500
|
||||
});
|
||||
await Page.SetContentAsync("<div style=\"width:100px;height:2000px\">spacer</div>");
|
||||
await FrameUtils.AttachFrameAsync(Page, "button-test", TestConstants.ServerUrl + "/input/button.html");
|
||||
var frame = Page.FirstChildFrame();
|
||||
await frame.QuerySelectorEvaluateAsync("button", "button => button.style.setProperty('position', 'fixed')");
|
||||
await frame.ClickAsync("button");
|
||||
Assert.Equal("Clicked", await frame.EvaluateAsync<string>("window.result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button with deviceScaleFactor set</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButtonWithDeviceScaleFactorSet()
|
||||
{
|
||||
await Page.SetViewportAsync(new Viewport { Width = 400, Height = 400, DeviceScaleFactor = 5 });
|
||||
Assert.Equal(5, await Page.EvaluateAsync<int>("window.devicePixelRatio"));
|
||||
await Page.SetContentAsync("<div style=\"width:100px;height:100px\">spacer</div>");
|
||||
await FrameUtils.AttachFrameAsync(Page, "button-test", TestConstants.ServerUrl + "/input/button.html");
|
||||
var frame = Page.FirstChildFrame();
|
||||
var button = await frame.QuerySelectorAsync("button");
|
||||
await button.ClickAsync();
|
||||
Assert.Equal("Clicked", await frame.EvaluateAsync<string>("window.result"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button with px border with relative point</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButtonWithPxBorderWithRelativePoint()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.QuerySelectorEvaluateAsync("button", "button => button.style.borderWidth = '8px'");
|
||||
await Page.ClickAsync("button", new ClickOptions { RelativePoint = new Point { X = 20, Y = 10 } });
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("window.result"));
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
Assert.Equal(TestConstants.IsWebKit ? 20 + 8 : 20, await Page.EvaluateAsync<int>("offsetX"));
|
||||
Assert.Equal(TestConstants.IsWebKit ? 10 + 8 : 10, await Page.EvaluateAsync<int>("offsetY"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click the button with em border with relative point</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickTheButtonWithEmBorderWithRelativePoint()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.QuerySelectorEvaluateAsync("button", "button => button.style.borderWidth = '2em'");
|
||||
await Page.QuerySelectorEvaluateAsync("button", "button => button.style.fontSize = '12px'");
|
||||
await Page.ClickAsync("button", new ClickOptions { RelativePoint = new Point { X = 20, Y = 10 } });
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("window.result"));
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
Assert.Equal(TestConstants.IsWebKit ? 12 * 2 + 20 : 20, await Page.EvaluateAsync<int>("offsetX"));
|
||||
Assert.Equal(TestConstants.IsWebKit ? 12 * 2 + 20 : 10, await Page.EvaluateAsync<int>("offsetY"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click a very large button with relative point</playwright-it>
|
||||
[Fact]
|
||||
public async Task ShouldClickAVeryLargeButtonWithRelativePoint()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.QuerySelectorEvaluateAsync("button", "button => button.style.borderWidth = '8px'");
|
||||
await Page.QuerySelectorEvaluateAsync("button", "button.style.height = button.style.width = '2000px'");
|
||||
await Page.ClickAsync("button", new ClickOptions { RelativePoint = new Point { X = 1900, Y = 1910 } });
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("window.result"));
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
Assert.Equal(TestConstants.IsWebKit ? 1900 + 8 : 1900, await Page.EvaluateAsync<int>("offsetX"));
|
||||
Assert.Equal(TestConstants.IsWebKit ? 1910 + 8 : 1910, await Page.EvaluateAsync<int>("offsetY"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click a button in scrolling container with relative point</playwright-it>
|
||||
[Fact(Skip = "Skipped in Playwright")]
|
||||
public async Task ShouldClickAButtonInScrollingContainerWithRelativePoint()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.QuerySelectorEvaluateAsync("button", @"button => {
|
||||
const container = document.createElement('div');
|
||||
container.style.overflow = 'auto';
|
||||
container.style.width = '200px';
|
||||
container.style.height = '200px';
|
||||
button.parentElement.insertBefore(container, button);
|
||||
container.appendChild(button);
|
||||
button.style.height = '2000px';
|
||||
button.style.width = '2000px';
|
||||
}");
|
||||
|
||||
await Page.ClickAsync("button", new ClickOptions { RelativePoint = new Point { X = 1900, Y = 1910 } });
|
||||
Assert.Equal("Clicked", await Page.EvaluateAsync<string>("window.result"));
|
||||
// Safari reports border-relative offsetX/offsetY.
|
||||
Assert.Equal(1900, await Page.EvaluateAsync<int>("offsetX"));
|
||||
Assert.Equal(1910, await Page.EvaluateAsync<int>("offsetY"));
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should update modifiers correctly</playwright-it>
|
||||
[SkipBrowserAndPlayformFact(skipWebkit: true)]
|
||||
public async Task ShouldUpdateModifiersCorrectly()
|
||||
{
|
||||
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
|
||||
await Page.ClickAsync("button", new ClickOptions { Modifiers = new[] { ClickModifier.Shift } });
|
||||
Assert.True(await Page.EvaluateAsync<bool>("shiftKey"));
|
||||
await Page.ClickAsync("button", new ClickOptions { Modifiers = new ClickModifier[] { } });
|
||||
Assert.False(await Page.EvaluateAsync<bool>("shiftKey"));
|
||||
|
||||
await Page.Keyboard.DownAsync("Shift");
|
||||
|
||||
await Page.ClickAsync("button", new ClickOptions { Modifiers = new ClickModifier[] { } });
|
||||
Assert.False(await Page.EvaluateAsync<bool>("shiftKey"));
|
||||
|
||||
await Page.ClickAsync("button");
|
||||
Assert.True(await Page.EvaluateAsync<bool>("shiftKey"));
|
||||
|
||||
await Page.Keyboard.UpAsync("Shift");
|
||||
|
||||
await Page.ClickAsync("button");
|
||||
Assert.False(await Page.EvaluateAsync<bool>("shiftKey"));
|
||||
|
||||
}
|
||||
|
||||
///<playwright-file>click.spec.js</playwright-file>
|
||||
///<playwright-describe>Page.click</playwright-describe>
|
||||
///<playwright-it>should click an offscreen element when scroll-behavior is smooth</playwright-it>
|
||||
[SkipBrowserAndPlayformFact(skipChromium: true)]
|
||||
public async Task ShouldClickAnOffscreenElementWhenScrollBehaviorIsSmooth()
|
||||
{
|
||||
await Page.SetContentAsync(@$"
|
||||
<div style=""border: 1px solid black; height: 500px; overflow: auto; width: 500px; scroll-behavior: smooth"">
|
||||
<button style=""margin-top: 2000px"" onClick=""window.clicked = true"" >hi</button>
|
||||
</div>");
|
||||
|
||||
await Page.ClickAsync("button");
|
||||
Assert.True(await Page.EvaluateAsync<bool>("window.clicked"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PlaywrightSharp.Tests
|
||||
{
|
||||
internal static class PageExtensions
|
||||
{
|
||||
public static IFrame FirstChildFrame(this IPage page) => page.Frames.FirstOrDefault(f => f.ParentFrame == page.MainFrame);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception thrown when an element selector returns null.
|
||||
/// </summary>
|
||||
public class SelectorException : PlaywrightSharpException
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the selector.
|
||||
/// </summary>
|
||||
/// <value>The selector.</value>
|
||||
public string Selector { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SelectorException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">Message.</param>
|
||||
public SelectorException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SelectorException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">Message.</param>
|
||||
/// <param name="selector">Selector.</param>
|
||||
public SelectorException(string message, string selector) : base(message)
|
||||
{
|
||||
Selector = selector;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
namespace PlaywrightSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception thrown by a connection when it detects that the target was closed.
|
||||
/// </summary>
|
||||
public class TargetClosedException : PlaywrightSharpException
|
||||
{
|
||||
/// <summary>
|
||||
/// Close Reason.
|
||||
/// </summary>
|
||||
/// <value>The close reason.</value>
|
||||
public string CloseReason { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TargetClosedException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">Message.</param>
|
||||
/// <param name="closeReason">Close reason.</param>
|
||||
public TargetClosedException(string message, string closeReason) : base($"{message} ({closeReason})")
|
||||
=> CloseReason = closeReason;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче