Skip to content

Commit 9444c9c

Browse files
kblokMeir017
authored andcommitted
Intersect content quads with viewport (#1099)
* Intersect content quads with viewport * Improve error handling * ops
1 parent 66056c8 commit 9444c9c

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

lib/PuppeteerSharp.Tests/InputTests/ClickTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,23 @@ await Task.WhenAll(
6868
Assert.Equal(TestConstants.ServerUrl + "/wrappedlink.html#clicked", Page.Url);
6969
}
7070

71+
[Fact]
72+
public async Task ShouldClickWhenOneOfInlineBoxChildrenIsOutsideOfViewport()
73+
{
74+
await Page.SetContentAsync($@"
75+
<style>
76+
i {{
77+
position: absolute;
78+
top: -1000px;
79+
}}
80+
</style>
81+
<span onclick='javascript:window.CLICKED = 42;'><i>woof</i><b>doggo</b></span>
82+
");
83+
84+
await Page.ClickAsync("span");
85+
Assert.Equal(42, await Page.EvaluateFunctionAsync<int>("() => window.CLICKED"));
86+
}
87+
7188
[Fact]
7289
public async Task ShouldSelectTheTextByTripleClicking()
7390
{

lib/PuppeteerSharp/ElementHandle.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using PuppeteerSharp.Input;
66
using PuppeteerSharp.Messaging;
77
using System;
8+
using System.Collections.Generic;
89
using System.IO;
910
using System.Linq;
1011
using System.Threading.Tasks;
@@ -426,16 +427,20 @@ public Task<bool> IsIntersectingViewportAsync()
426427
{
427428
GetContentQuadsResponse result = null;
428429

430+
var contentQuadsTask = Client.SendAsync<GetContentQuadsResponse>("DOM.getContentQuads", new DomGetContentQuadsRequest
431+
{
432+
ObjectId = RemoteObject.ObjectId
433+
});
434+
var layoutTask = Client.SendAsync<PageGetLayoutMetricsResponse>("Page.getLayoutMetrics");
435+
429436
try
430437
{
431-
result = await Client.SendAsync<GetContentQuadsResponse>("DOM.getContentQuads", new DomGetContentQuadsRequest
432-
{
433-
ObjectId = RemoteObject.ObjectId
434-
}).ConfigureAwait(false);
438+
await Task.WhenAll(contentQuadsTask, layoutTask).ConfigureAwait(false);
439+
result = contentQuadsTask.Result;
435440
}
436441
catch (Exception ex)
437442
{
438-
_logger.LogError(ex.Message);
443+
_logger.LogError(ex, "Unable to get content quads");
439444
}
440445

441446
if (result == null || result.Quads.Length == 0)
@@ -444,7 +449,11 @@ public Task<bool> IsIntersectingViewportAsync()
444449
}
445450

446451
// Filter out quads that have too small area to click into.
447-
var quads = result.Quads.Select(FromProtocolQuad).Where(q => ComputeQuadArea(q) > 1);
452+
var quads = result.Quads
453+
.Select(FromProtocolQuad)
454+
.Select(q => IntersectQuadWithViewport(q, layoutTask.Result))
455+
.Where(q => ComputeQuadArea(q.ToArray()) > 1);
456+
448457
if (!quads.Any())
449458
{
450459
throw new PuppeteerException("Node is either not visible or not an HTMLElement");
@@ -466,6 +475,13 @@ public Task<bool> IsIntersectingViewportAsync()
466475
);
467476
}
468477

478+
private IEnumerable<BoxModelPoint> IntersectQuadWithViewport(IEnumerable<BoxModelPoint> quad, PageGetLayoutMetricsResponse viewport)
479+
=> quad.Select(point => new BoxModelPoint
480+
{
481+
X = Math.Min(Math.Max(point.X, 0), viewport.ContentSize.Width),
482+
Y = Math.Min(Math.Max(point.Y, 0), viewport.ContentSize.Height),
483+
});
484+
469485
private async Task ScrollIntoViewIfNeededAsync()
470486
{
471487
var errorMessage = await ExecutionContext.EvaluateFunctionAsync<string>(@"async(element, pageJavascriptEnabled) => {

0 commit comments

Comments
 (0)