Skip to content

Commit f68098d

Browse files
Meir017kblok
authored andcommitted
Implemented input tests (#180)
1 parent a818f43 commit f68098d

21 files changed

+2821
-205
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
contents of the file

lib/PuppeteerSharp.Tests/Input/InputTests.cs

Lines changed: 555 additions & 0 deletions
Large diffs are not rendered by default.

lib/PuppeteerSharp/ElementHandle.cs

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using System;
2-
using System.Collections.Generic;
1+
using PuppeteerSharp.Input;
2+
using System.IO;
33
using System.Linq;
44
using System.Threading.Tasks;
55

@@ -17,15 +17,98 @@ public ElementHandle(ExecutionContext context, Session client, object remoteObje
1717

1818
public override ElementHandle AsElement() => this;
1919

20-
public async Task ClickAsync(Dictionary<string, object> options = null)
20+
/// <summary>
21+
/// Scrolls element into view if needed, and then uses <see cref="Page.Mouse"/> to hover over the center of the element.
22+
/// </summary>
23+
/// <returns>Task which resolves when the element is successfully hovered</returns>
24+
public async Task HoverAsync()
2125
{
2226
var (x, y) = await VisibleCenterAsync();
23-
await _page.Mouse.Click(x, y, options ?? new Dictionary<string, object>());
27+
await _page.Mouse.MoveAsync(x, y);
2428
}
2529

26-
internal Task TapAsync()
30+
/// <summary>
31+
/// Scrolls element into view if needed, and then uses <see cref="Page.Mouse"/> to click in the center of the element.
32+
/// </summary>
33+
/// <param name="options">click options</param>
34+
/// <exception cref="PuppeteerException">if the element is detached from DOM</exception>
35+
/// <returns>Task which resolves when the element is successfully clicked</returns>
36+
public async Task ClickAsync(ClickOptions options = null)
2737
{
28-
throw new NotImplementedException();
38+
var (x, y) = await VisibleCenterAsync();
39+
await _page.Mouse.ClickAsync(x, y, options);
40+
}
41+
42+
/// <summary>
43+
/// Uploads files
44+
/// </summary>
45+
/// <param name="filePaths">Sets the value of the file input these paths. paths are resolved using <see cref="Path.GetFullPath(string)"/></param>
46+
/// <remarks>This method expects <c>elementHandle</c> to point to an <c>input element</c> <see cref="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"/> </remarks>
47+
/// <returns>Task</returns>
48+
public async Task UploadFileAsync(params string[] filePaths)
49+
{
50+
var files = filePaths.Select(Path.GetFullPath).ToArray();
51+
var objectId = RemoteObject.objectId.ToString();
52+
await _client.SendAsync("DOM.setFileInputFiles", new { objectId, files });
53+
}
54+
55+
/// <summary>
56+
/// Scrolls element into view if needed, and then uses <see cref="Touchscreen.TapAsync(decimal, decimal)"/> to tap in the center of the element.
57+
/// </summary>
58+
/// <exception cref="PuppeteerException">if the element is detached from DOM</exception>
59+
/// <returns>Task which resolves when the element is successfully tapped</returns>
60+
public async Task TapAsync()
61+
{
62+
var (x, y) = await VisibleCenterAsync();
63+
await _page.Touchscreen.TapAsync(x, y);
64+
}
65+
66+
/// <summary>
67+
/// Calls <c>focus</c> <see cref="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus"/> on the element.
68+
/// </summary>
69+
/// <returns>Task</returns>
70+
public Task FocusAsync() => ExecutionContext.EvaluateFunctionAsync("element => element.focus()", this);
71+
72+
/// <summary>
73+
/// Focuses the element, and sends a <c>keydown</c>, <c>keypress</c>/<c>input</c>, and <c>keyup</c> event for each character in the text.
74+
/// </summary>
75+
/// <param name="text">A text to type into a focused element</param>
76+
/// <param name="options">type options</param>
77+
/// <remarks>
78+
/// To press a special key, like <c>Control</c> or <c>ArrowDown</c> use <see cref="ElementHandle.PressAsync(string, PressOptions)"/>
79+
/// </remarks>
80+
/// <example>
81+
/// <code>
82+
/// elementHandle.TypeAsync("#mytextarea", "Hello"); // Types instantly
83+
/// elementHandle.TypeAsync("#mytextarea", "World", new TypeOptions { Delay = 100 }); // Types slower, like a user
84+
/// </code>
85+
/// An example of typing into a text field and then submitting the form:
86+
/// <code>
87+
/// var elementHandle = await page.GetElementAsync("input");
88+
/// await elementHandle.TypeAsync("some text");
89+
/// await elementHandle.PressAsync("Enter");
90+
/// </code>
91+
/// </example>
92+
/// <returns>Task</returns>
93+
public async Task TypeAsync(string text, TypeOptions options = null)
94+
{
95+
await FocusAsync();
96+
await _page.Keyboard.TypeAsync(text, options);
97+
}
98+
99+
/// <summary>
100+
/// Focuses the element, and then uses <see cref="Keyboard.DownAsync(string, DownOptions)"/> and <see cref="Keyboard.UpAsync(string)"/>.
101+
/// </summary>
102+
/// <param name="key">Name of key to press, such as <c>ArrowLeft</c>. See <see cref="KeyDefinitions"/> for a list of all key names.</param>
103+
/// <param name="options">press options</param>
104+
/// <remarks>
105+
/// 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 be generated. The <see cref="DownOptions.Text"/> option can be specified to force an input event to be generated.
106+
/// </remarks>
107+
/// <returns></returns>
108+
public async Task PressAsync(string key, PressOptions options = null)
109+
{
110+
await FocusAsync();
111+
await _page.Keyboard.PressAsync(key, options);
29112
}
30113

31114
internal async Task<ElementHandle> GetElementAsync(string selector)
@@ -40,15 +123,10 @@ internal async Task<ElementHandle> GetElementAsync(string selector)
40123
return element;
41124
}
42125

43-
await handle.Dispose();
126+
await handle.DisposeAsync();
44127
return null;
45128
}
46129

47-
internal Task DisposeAsync()
48-
{
49-
throw new NotImplementedException();
50-
}
51-
52130
private async Task<(decimal x, decimal y)> VisibleCenterAsync()
53131
{
54132
await ScrollIntoViewIfNeededAsync();

lib/PuppeteerSharp/ExecutionContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private async Task<T> EvaluateAsync<T>(Task<JSHandle> handleEvaluator)
120120
var result = await handle.JsonValue<T>()
121121
.ContinueWith(jsonTask => jsonTask.Exception != null ? default(T) : jsonTask.Result);
122122

123-
await handle.Dispose();
123+
await handle.DisposeAsync();
124124
return result;
125125
}
126126

lib/PuppeteerSharp/Frame.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ internal void SetDefaultContext(ExecutionContext context)
261261
}
262262
else
263263
{
264+
_documentCompletionSource = null;
264265
ContextResolveTaskWrapper = new TaskCompletionSource<ExecutionContext>();
265266
}
266267
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace PuppeteerSharp.Input
2+
{
3+
/// <summary>
4+
/// Options to use when clicking
5+
/// </summary>
6+
public class ClickOptions
7+
{
8+
/// <summary>
9+
/// Time to wait between <c>mousedown</c> and <c>mouseup</c> in milliseconds. Defaults to 0
10+
/// </summary>
11+
public int Delay { get; set; } = 0;
12+
13+
/// <summary>
14+
/// Defaults to 1. See https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail
15+
/// </summary>
16+
public int ClickCount { get; set; } = 1;
17+
18+
/// <summary>
19+
/// The button to use for the click. Defaults to <see cref="MouseButton.Left"/>
20+
/// </summary>
21+
public MouseButton Button { get; set; } = MouseButton.Left;
22+
}
23+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace PuppeteerSharp.Input
2+
{
3+
/// <summary>
4+
/// options to use with <see cref="Keyboard.DownAsync(string, DownOptions)"/>
5+
/// </summary>
6+
public class DownOptions
7+
{
8+
/// <summary>
9+
/// If specified, generates an input event with this text
10+
/// </summary>
11+
public string Text { get; set; }
12+
}
13+
}

lib/PuppeteerSharp/Input/Key.cs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
namespace PuppeteerSharp.Input
2+
{
3+
public class Key
4+
{
5+
public string Value { get; }
6+
private Key(string value) => Value = value;
7+
8+
public static readonly Key Cancel = new Key("Cancel");
9+
public static readonly Key Help = new Key("Help");
10+
public static readonly Key Backspace = new Key("Backspace");
11+
public static readonly Key Tab = new Key("Tab");
12+
public static readonly Key Clear = new Key("Clear");
13+
public static readonly Key Enter = new Key("Enter");
14+
public static readonly Key Shift = new Key("Shift");
15+
public static readonly Key Control = new Key("Control");
16+
public static readonly Key Alt = new Key("Alt");
17+
public static readonly Key Pause = new Key("Pause");
18+
public static readonly Key CapsLock = new Key("CapsLock");
19+
public static readonly Key Escape = new Key("Escape");
20+
public static readonly Key Convert = new Key("Convert");
21+
public static readonly Key NonConvert = new Key("NonConvert");
22+
public static readonly Key Accept = new Key("Accept");
23+
public static readonly Key ModeChange = new Key("ModeChange");
24+
public static readonly Key PageUp = new Key("PageUp");
25+
public static readonly Key PageDown = new Key("PageDown");
26+
public static readonly Key End = new Key("End");
27+
public static readonly Key Home = new Key("Home");
28+
public static readonly Key ArrowLeft = new Key("ArrowLeft");
29+
public static readonly Key ArrowUp = new Key("ArrowUp");
30+
public static readonly Key ArrowRight = new Key("ArrowRight");
31+
public static readonly Key ArrowDown = new Key("ArrowDown");
32+
public static readonly Key Select = new Key("Select");
33+
public static readonly Key Print = new Key("Print");
34+
public static readonly Key Execute = new Key("Execute");
35+
public static readonly Key PrintScreen = new Key("PrintScreen");
36+
public static readonly Key Insert = new Key("Insert");
37+
public static readonly Key Delete = new Key("Delete");
38+
public static readonly Key CloseParentheses = new Key(")");
39+
public static readonly Key ExclamationMark = new Key("!");
40+
public static readonly Key AtSign = new Key("@");
41+
public static readonly Key NumberSign = new Key("#");
42+
public static readonly Key DollarSign = new Key("$");
43+
public static readonly Key Percent = new Key("%");
44+
public static readonly Key Caret = new Key("^");
45+
public static readonly Key Ampersand = new Key("&");
46+
public static readonly Key Asterisk = new Key("*");
47+
public static readonly Key OpenParentheses = new Key("(");
48+
public static readonly Key Meta = new Key("Meta");
49+
public static readonly Key ContextMenu = new Key("ContextMenu");
50+
public static readonly Key F1 = new Key("F1");
51+
public static readonly Key F2 = new Key("F2");
52+
public static readonly Key F3 = new Key("F3");
53+
public static readonly Key F4 = new Key("F4");
54+
public static readonly Key F5 = new Key("F5");
55+
public static readonly Key F6 = new Key("F6");
56+
public static readonly Key F7 = new Key("F7");
57+
public static readonly Key F8 = new Key("F8");
58+
public static readonly Key F9 = new Key("F9");
59+
public static readonly Key F10 = new Key("F10");
60+
public static readonly Key F11 = new Key("F11");
61+
public static readonly Key F12 = new Key("F12");
62+
public static readonly Key F13 = new Key("F13");
63+
public static readonly Key F14 = new Key("F14");
64+
public static readonly Key F15 = new Key("F15");
65+
public static readonly Key F16 = new Key("F16");
66+
public static readonly Key F17 = new Key("F17");
67+
public static readonly Key F18 = new Key("F18");
68+
public static readonly Key F19 = new Key("F19");
69+
public static readonly Key F20 = new Key("F20");
70+
public static readonly Key F21 = new Key("F21");
71+
public static readonly Key F22 = new Key("F22");
72+
public static readonly Key F23 = new Key("F23");
73+
public static readonly Key F24 = new Key("F24");
74+
public static readonly Key NumLock = new Key("NumLock");
75+
public static readonly Key ScrollLock = new Key("ScrollLock");
76+
public static readonly Key AudioVolumeMute = new Key("AudioVolumeMute");
77+
public static readonly Key AudioVolumeDown = new Key("AudioVolumeDown");
78+
public static readonly Key AudioVolumeUp = new Key("AudioVolumeUp");
79+
public static readonly Key MediaTrackNext = new Key("MediaTrackNext");
80+
public static readonly Key MediaTrackPrevious = new Key("MediaTrackPrevious");
81+
public static readonly Key MediaStop = new Key("MediaStop");
82+
public static readonly Key MediaPlayPause = new Key("MediaPlayPause");
83+
public static readonly Key Semicolon = new Key(";");
84+
public static readonly Key Comma = new Key(",");
85+
public static readonly Key EqualsSign = new Key("=");
86+
public static readonly Key PlusSign = new Key("+");
87+
public static readonly Key LesserThan = new Key("<");
88+
public static readonly Key MinusSign = new Key("-");
89+
public static readonly Key Underscore = new Key("_");
90+
public static readonly Key Period = new Key(".");
91+
public static readonly Key GreaterThan = new Key(">");
92+
public static readonly Key Slash = new Key("/");
93+
public static readonly Key QuestionMark = new Key("?");
94+
public static readonly Key Backquote = new Key("`");
95+
public static readonly Key Tilde = new Key("~");
96+
public static readonly Key OpenSquareBrackets = new Key("[");
97+
public static readonly Key OpenBrackets = new Key("{");
98+
public static readonly Key Pipe = new Key("|");
99+
public static readonly Key CloseSquareBrackets = new Key("]");
100+
public static readonly Key CloseBrackets = new Key("}");
101+
public static readonly Key Backslash = new Key("\\");
102+
public static readonly Key AltGraph = new Key("AltGraph");
103+
public static readonly Key Attn = new Key("Attn");
104+
public static readonly Key CrSel = new Key("CrSel");
105+
public static readonly Key ExSel = new Key("ExSel");
106+
public static readonly Key EraseEof = new Key("EraseEof");
107+
public static readonly Key Play = new Key("Play");
108+
public static readonly Key ZoomOut = new Key("ZoomOut");
109+
110+
public override string ToString() => Value;
111+
public static implicit operator string(Key key) => key.Value;
112+
}
113+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace PuppeteerSharp.Input
2+
{
3+
internal class KeyDefinition
4+
{
5+
internal int KeyCode { get; set; }
6+
internal int? ShiftKeyCode { get; set; }
7+
internal string Key { get; set; }
8+
internal string ShiftKey { get; set; }
9+
internal string Code { get; set; }
10+
internal string Text { get; set; }
11+
internal string ShiftText { get; set; }
12+
internal int Location { get; set; }
13+
}
14+
}

0 commit comments

Comments
 (0)