Skip to content

Commit

Permalink
Test - Mouse/Keyboard Add WaitForRenderIdle
Browse files Browse the repository at this point in the history
Need to wait for the browser to finish rendering before executing
our mouse/keyboard tests. They will fail otherwise.

Resolves #8
  • Loading branch information
amaitland committed Mar 21, 2022
1 parent 107e4a5 commit 1a85dcc
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 19 deletions.
63 changes: 48 additions & 15 deletions lib/PuppeteerSharp.Tests/KeyboardTests/KeyboardTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ public KeyboardTests(ITestOutputHelper output) : base(output, initialUrl: TestCo
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should type into a textarea")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldTypeIntoTheTextarea()
{
const string expected = "Type in this text!";

await ChromiumWebBrowser.WaitForRenderIdle();

var textarea = await DevToolsContext.QuerySelectorAsync("textarea");

await textarea.TypeAsync(expected);
Expand All @@ -32,9 +34,11 @@ public async Task ShouldTypeIntoTheTextarea()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should move with the arrow keys")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldMoveWithTheArrowKeys()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.TypeAsync("textarea", "Hello World!");
Assert.Equal("Hello World!", await DevToolsContext.EvaluateExpressionAsync<string>("document.querySelector('textarea').value"));
for (var i = 0; i < "World!".Length; i++)
Expand All @@ -56,9 +60,11 @@ public async Task ShouldMoveWithTheArrowKeys()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should send a character with ElementHandle.press")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldSendACharacterWithElementHandlePress()
{
await ChromiumWebBrowser.WaitForRenderIdle();

var textarea = await DevToolsContext.QuerySelectorAsync("textarea");
await textarea.PressAsync("a");
Assert.Equal("a", await DevToolsContext.EvaluateExpressionAsync<string>("document.querySelector('textarea').value"));
Expand All @@ -70,9 +76,11 @@ public async Task ShouldSendACharacterWithElementHandlePress()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "ElementHandle.press should support |text| option")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ElementHandlePressShouldSupportTextOption()
{
await ChromiumWebBrowser.WaitForRenderIdle();

var textarea = await DevToolsContext.QuerySelectorAsync("textarea");
await textarea.PressAsync("a", new PressOptions { Text = "ё" });
Assert.Equal("ё", await DevToolsContext.EvaluateExpressionAsync<string>("document.querySelector('textarea').value"));
Expand All @@ -82,6 +90,8 @@ public async Task ElementHandlePressShouldSupportTextOption()
[PuppeteerFact]
public async Task ShouldSendACharacterWithSendCharacter()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.FocusAsync("textarea");
await DevToolsContext.Keyboard.SendCharacterAsync("");
Assert.Equal("", await DevToolsContext.EvaluateExpressionAsync<string>("document.querySelector('textarea').value"));
Expand All @@ -91,10 +101,12 @@ public async Task ShouldSendACharacterWithSendCharacter()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should report shiftKey")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldReportShiftKey()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html");
await ChromiumWebBrowser.WaitForRenderIdle();

var keyboard = DevToolsContext.Keyboard;
var codeForKey = new Dictionary<string, int> { ["Shift"] = 16, ["Alt"] = 18, ["Control"] = 17 };
foreach (var modifier in codeForKey)
Expand All @@ -120,10 +132,12 @@ public async Task ShouldReportShiftKey()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should report multiple modifiers")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldReportMultipleModifiers()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html");
await ChromiumWebBrowser.WaitForRenderIdle();

var keyboard = DevToolsContext.Keyboard;
await keyboard.DownAsync("Control");
Assert.Equal("Keydown: Control ControlLeft 17 [Control]", await DevToolsContext.EvaluateExpressionAsync<string>("getResult()"));
Expand All @@ -140,10 +154,11 @@ public async Task ShouldReportMultipleModifiers()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should send proper codes while typing")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldSendProperCodesWhileTyping()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html");
await ChromiumWebBrowser.WaitForRenderIdle();

var element = await DevToolsContext.QuerySelectorAsync("textarea");

Expand All @@ -167,10 +182,12 @@ public async Task ShouldSendProperCodesWhileTyping()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should send proper codes while typing with shift")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldSendProperCodesWhileTypingWithShift()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html");
await ChromiumWebBrowser.WaitForRenderIdle();

var keyboard = DevToolsContext.Keyboard;
await keyboard.DownAsync("Shift");
await DevToolsContext.Keyboard.TypeAsync("~");
Expand All @@ -183,9 +200,11 @@ public async Task ShouldSendProperCodesWhileTypingWithShift()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should not type canceled events")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldNotTypeCanceledEvents()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.FocusAsync("textarea");
await DevToolsContext.EvaluateExpressionAsync(@"{
window.addEventListener('keydown', event => {
Expand All @@ -202,9 +221,11 @@ public async Task ShouldNotTypeCanceledEvents()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should specify repeat property")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldSpecifyRepeatProperty()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.FocusAsync("textarea");
await DevToolsContext.EvaluateExpressionAsync("document.querySelector('textarea').addEventListener('keydown', e => window.lastEvent = e, true)");
await DevToolsContext.Keyboard.DownAsync("a");
Expand All @@ -223,11 +244,13 @@ public async Task ShouldSpecifyRepeatProperty()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should type all kinds of characters")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldTypeAllKindsOfCharacters()
{
const string expected = "This text goes onto two lines.\nThis character is 嗨.";

await ChromiumWebBrowser.WaitForRenderIdle();

var textarea = await DevToolsContext.QuerySelectorAsync("textarea");

await textarea.FocusAsync();
Expand All @@ -240,9 +263,11 @@ public async Task ShouldTypeAllKindsOfCharacters()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should specify location")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldSpecifyLocation()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.EvaluateExpressionAsync(@"{
window.addEventListener('keydown', event => window.keyLocation = event.location, true);
}");
Expand Down Expand Up @@ -277,6 +302,8 @@ public async Task ShouldSpecifyLocation()
[PuppeteerFact]
public async Task ShouldThrowOnUnknownKeys()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await Assert.ThrowsAsync<KeyNotFoundException>(() => DevToolsContext.Keyboard.PressAsync("NotARealKey"));

await Assert.ThrowsAsync<KeyNotFoundException>(() => DevToolsContext.Keyboard.PressAsync("ё"));
Expand All @@ -285,11 +312,13 @@ public async Task ShouldThrowOnUnknownKeys()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should type emoji")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldTypeEmoji()
{
const string expected = "👹 Tokyo street Japan \uD83C\uDDEF\uD83C\uDDF5";

await ChromiumWebBrowser.WaitForRenderIdle();

var textArea = await DevToolsContext.QuerySelectorAsync("textarea");

await textArea.TypeAsync(expected);
Expand All @@ -300,12 +329,14 @@ public async Task ShouldTypeEmoji()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should type emoji into an iframe")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldTypeEmojiIntoAniframe()
{
const string expected = "👹 Tokyo street Japan \uD83C\uDDEF\uD83C\uDDF5";

await DevToolsContext.GoToAsync(TestConstants.EmptyPage);
await ChromiumWebBrowser.WaitForRenderIdle();

await FrameUtils.AttachFrameAsync(DevToolsContext, "emoji-test", TestConstants.ServerUrl + "/input/textarea.html");

var frame = DevToolsContext.FirstChildFrame();
Expand All @@ -318,9 +349,11 @@ public async Task ShouldTypeEmojiIntoAniframe()
}

[PuppeteerTest("keyboard.spec.ts", "Keyboard", "should press the metaKey")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldPressTheMetaKey()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.EvaluateFunctionAsync(@"() =>
{
window.result = null;
Expand Down
24 changes: 20 additions & 4 deletions lib/PuppeteerSharp.Tests/MouseTests/MouseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ public MouseTests(ITestOutputHelper output) : base(output)
}

[PuppeteerTest("mouse.spec.ts", "Mouse", "should click the document")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldClickTheDocument()
{
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.EvaluateFunctionAsync(@"() => {
globalThis.clickPromise = new Promise((resolve) => {
document.addEventListener('click', (event) => {
Expand All @@ -57,10 +59,12 @@ public async Task ShouldClickTheDocument()
}

[PuppeteerTest("mouse.spec.ts", "Mouse", "should resize the textarea")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldResizeTheTextarea()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html");
await ChromiumWebBrowser.WaitForRenderIdle();

var dimensions = await DevToolsContext.EvaluateFunctionAsync<Dimensions>(Dimensions);
var mouse = DevToolsContext.Mouse;
await mouse.MoveAsync(dimensions.X + dimensions.Width - 4, dimensions.Y + dimensions.Height - 4);
Expand All @@ -73,10 +77,12 @@ public async Task ShouldResizeTheTextarea()
}

[PuppeteerTest("mouse.spec.ts", "Mouse", "should select the text with mouse")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldSelectTheTextWithMouse()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html");
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.FocusAsync("textarea");
const string expectedText = "This is the text that we are going to try to select. Let's see how it goes.";
await DevToolsContext.Keyboard.TypeAsync(expectedText);
Expand All @@ -98,6 +104,8 @@ public async Task ShouldSelectTheTextWithMouse()
public async Task ShouldTriggerHoverState()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html");
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.HoverAsync("#button-6");
Assert.Equal("button-6", await DevToolsContext.EvaluateExpressionAsync<string>("document.querySelector('button:hover').id"));
await DevToolsContext.HoverAsync("#button-2");
Expand All @@ -111,6 +119,8 @@ public async Task ShouldTriggerHoverState()
public async Task ShouldTriggerHoverStateWithRemovedWindowNode()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html");
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.EvaluateExpressionAsync("delete window.Node");
await DevToolsContext.HoverAsync("#button-6");
Assert.Equal("button-6", await DevToolsContext.EvaluateExpressionAsync("document.querySelector('button:hover').id"));
Expand All @@ -121,6 +131,8 @@ public async Task ShouldTriggerHoverStateWithRemovedWindowNode()
public async Task ShouldSetModifierKeysOnClick()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html");
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.EvaluateExpressionAsync("document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true)");
var modifiers = new Dictionary<string, string> { ["Shift"] = "shiftKey", ["Control"] = "ctrlKey", ["Alt"] = "altKey", ["Meta"] = "metaKey" };
foreach (var modifier in modifiers)
Expand Down Expand Up @@ -149,6 +161,8 @@ public async Task ShouldSetModifierKeysOnClick()
public async Task ShouldSendMouseWheelEvents()
{
await DevToolsContext.GoToAsync(TestConstants.ServerUrl + "/input/wheel.html");
await ChromiumWebBrowser.WaitForRenderIdle();

var elem = await DevToolsContext.QuerySelectorAsync("div");
var boundingBoxBefore = await elem.BoundingBoxAsync();
Assert.Equal(115, boundingBoxBefore.Width);
Expand Down Expand Up @@ -187,7 +201,7 @@ public async Task ShouldTweenMouseMovement()
}

[PuppeteerTest("mouse.spec.ts", "Mouse", "should work with mobile viewports and cross process navigations")]
[PuppeteerFact(Skip = "Issue https://github.com/cefsharp/Puppeteer/issues/8")]
[PuppeteerFact]
public async Task ShouldWorkWithMobileViewportsAndCrossProcessNavigations()
{
await DevToolsContext.GoToAsync(TestConstants.EmptyPage);
Expand All @@ -198,6 +212,8 @@ public async Task ShouldWorkWithMobileViewportsAndCrossProcessNavigations()
IsMobile = true
});
await DevToolsContext.GoToAsync(TestConstants.CrossProcessUrl + "/mobile.html");
await ChromiumWebBrowser.WaitForRenderIdle();

await DevToolsContext.EvaluateFunctionAsync(@"() => {
document.addEventListener('click', event => {
window.result = { x: event.clientX, y: event.clientY };
Expand Down
44 changes: 44 additions & 0 deletions lib/PuppeteerSharp.Tests/WebBrowserExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Threading.Tasks;
using System.Timers;
using CefSharp.OffScreen;

namespace PuppeteerSharp.Tests
{
public static class WebBrowserExtensions
{
public static Task WaitForRenderIdle(this ChromiumWebBrowser chromiumWebBrowser, int idleTime = 500)
{
var renderIdleTcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);

var idleTimer = new Timer
{
Interval = idleTime
};

EventHandler<OnPaintEventArgs> handler = null;

idleTimer.Elapsed += (sender, args) =>
{
chromiumWebBrowser.Paint -= handler;
idleTimer.Stop();
idleTimer.Dispose();
renderIdleTcs.TrySetResult(true);
};

handler = (s, args) =>
{
idleTimer.Stop();
idleTimer.Start();
};

idleTimer.Start();

chromiumWebBrowser.Paint += handler;

return renderIdleTcs.Task;
}
}
}

0 comments on commit 1a85dcc

Please sign in to comment.