Skip to content

Commit a5ae465

Browse files
authored
Improve FrameWaitForXPathTests tests (#2235)
1 parent 6ecce37 commit a5ae465

File tree

3 files changed

+53
-32
lines changed

3 files changed

+53
-32
lines changed

lib/PuppeteerSharp.Tests/ConnectionTransportInterceptor.cs renamed to lib/PuppeteerSharp.Tests/PollerInterceptor.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
namespace PuppeteerSharp.Tests
66
{
7-
public sealed class ConnectionTransportInterceptor : IConnectionTransport
7+
public sealed class PollerInterceptor : IConnectionTransport
88
{
99
private readonly IConnectionTransport _connectionTransport;
1010

11-
public ConnectionTransportInterceptor(IConnectionTransport connectionTransport)
11+
public PollerInterceptor(IConnectionTransport connectionTransport)
1212
{
1313
_connectionTransport = connectionTransport;
1414
}
@@ -39,5 +39,22 @@ public event EventHandler<MessageReceivedEventArgs> MessageReceived
3939
public void Dispose() => _connectionTransport.Dispose();
4040

4141
public void StopReading() => _connectionTransport.StopReading();
42+
43+
public Task<bool> WaitForStartPollingAsync()
44+
{
45+
var startedPolling = new TaskCompletionSource<bool>();
46+
47+
// Wait for function will release the execution faster than in node.
48+
// We intercept the poller.start() call to prevent tests from continuing before the polling has started.
49+
MessageSent += (_, message) =>
50+
{
51+
if (message.Contains("poller => poller.start()"))
52+
{
53+
startedPolling.SetResult(true);
54+
}
55+
};
56+
57+
return startedPolling.Task;
58+
}
4259
}
4360
}

lib/PuppeteerSharp.Tests/WaitTaskTests/FrameWaitForFunctionTests.cs

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace PuppeteerSharp.Tests.WaitTaskTests
1111
[Collection(TestConstants.TestFixtureCollectionName)]
1212
public sealed class FrameWaitForFunctionTests : PuppeteerPageBaseTest, IDisposable
1313
{
14-
private ConnectionTransportInterceptor _connectionTransportInterceptor;
14+
private PollerInterceptor _pollerInterceptor;
1515

1616
public FrameWaitForFunctionTests(ITestOutputHelper output) : base(output)
1717
{
@@ -25,14 +25,14 @@ public FrameWaitForFunctionTests(ITestOutputHelper output) : base(output)
2525
// due to differences between node.js's task scheduler and .net's.
2626
DefaultOptions.TransportFactory = async (url, options, cancellationToken) =>
2727
{
28-
_connectionTransportInterceptor = new ConnectionTransportInterceptor(await WebSocketTransport.DefaultTransportFactory(url, options, cancellationToken));
29-
return _connectionTransportInterceptor;
28+
_pollerInterceptor = new PollerInterceptor(await WebSocketTransport.DefaultTransportFactory(url, options, cancellationToken));
29+
return _pollerInterceptor;
3030
};
3131
}
3232

3333
public void Dispose()
3434
{
35-
_connectionTransportInterceptor.Dispose();
35+
_pollerInterceptor.Dispose();
3636
}
3737

3838
[PuppeteerTest("waittask.spec.ts", "Frame.waitForFunction", "should work when resolved right before execution context disposal")]
@@ -54,7 +54,7 @@ public async Task ShouldPollOnInterval()
5454
{
5555
var startTime = DateTime.UtcNow;
5656
var polling = 100;
57-
var startedPolling = WaitForStartPollingAsync();
57+
var startedPolling = _pollerInterceptor.WaitForStartPollingAsync();
5858
var watchdog = Page.WaitForFunctionAsync("() => window.__FOO === 'hit'", new WaitForFunctionOptions { PollingInterval = polling });
5959
await startedPolling;
6060
await Page.EvaluateFunctionAsync("() => setTimeout(window.__FOO = 'hit', 50)");
@@ -69,7 +69,7 @@ public async Task ShouldPollOnIntervalAsync()
6969
{
7070
var startTime = DateTime.UtcNow;
7171
var polling = 1000;
72-
var startedPolling = WaitForStartPollingAsync();
72+
var startedPolling = _pollerInterceptor.WaitForStartPollingAsync();
7373
var watchdog = Page.WaitForFunctionAsync("async () => window.__FOO === 'hit'", new WaitForFunctionOptions { PollingInterval = polling });
7474
await startedPolling;
7575
await Page.EvaluateFunctionAsync("async () => setTimeout(window.__FOO = 'hit', 50)");
@@ -82,7 +82,7 @@ public async Task ShouldPollOnIntervalAsync()
8282
public async Task ShouldPollOnMutation()
8383
{
8484
var success = false;
85-
var startedPolling = WaitForStartPollingAsync();
85+
var startedPolling = _pollerInterceptor.WaitForStartPollingAsync();
8686
var watchdog = Page.WaitForFunctionAsync("() => window.__FOO === 'hit'",
8787
new WaitForFunctionOptions { Polling = WaitForFunctionPollingOption.Mutation })
8888
.ContinueWith(_ => success = true);
@@ -98,7 +98,7 @@ public async Task ShouldPollOnMutation()
9898
public async Task ShouldPollOnMutationAsync()
9999
{
100100
var success = false;
101-
var startedPolling = WaitForStartPollingAsync();
101+
var startedPolling = _pollerInterceptor.WaitForStartPollingAsync();
102102
var watchdog = Page.WaitForFunctionAsync("async () => window.__FOO === 'hit'",
103103
new WaitForFunctionOptions { Polling = WaitForFunctionPollingOption.Mutation })
104104
.ContinueWith(_ => success = true);
@@ -239,22 +239,5 @@ public async Task ShouldSurviveNavigations()
239239
await Page.EvaluateFunctionAsync("() => window.__done = true");
240240
await watchdog;
241241
}
242-
243-
private Task<bool> WaitForStartPollingAsync()
244-
{
245-
TaskCompletionSource<bool> startedPolling = new TaskCompletionSource<bool>();
246-
247-
// Wait for function will release the execution faster than in node.
248-
// We intercept the poller.start() call to prevent tests from continuing before the polling has started.
249-
_connectionTransportInterceptor.MessageSent += (_, message) =>
250-
{
251-
if (message.Contains("poller => poller.start()"))
252-
{
253-
startedPolling.SetResult(true);
254-
}
255-
};
256-
257-
return startedPolling.Task;
258-
}
259242
}
260243
}

lib/PuppeteerSharp.Tests/WaitTaskTests/FrameWaitForXPathTests.cs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,36 @@
77
using PuppeteerSharp.Helpers;
88
using PuppeteerSharp.Xunit;
99
using PuppeteerSharp.Tests.Attributes;
10+
using PuppeteerSharp.Transport;
1011

1112
namespace PuppeteerSharp.Tests.WaitTaskTests
1213
{
1314
[Collection(TestConstants.TestFixtureCollectionName)]
14-
public class FrameWaitForXPathTests : PuppeteerPageBaseTest
15+
public sealed class FrameWaitForXPathTests : PuppeteerPageBaseTest, IDisposable
1516
{
16-
const string addElement = "tag => document.body.appendChild(document.createElement(tag))";
17+
const string AddElement = "tag => document.body.appendChild(document.createElement(tag))";
18+
private PollerInterceptor _pollerInterceptor;
1719

1820
public FrameWaitForXPathTests(ITestOutputHelper output) : base(output)
1921
{
22+
DefaultOptions = TestConstants.DefaultBrowserOptions();
23+
24+
// Set up a custom TransportFactory to intercept sent messages
25+
// Some of the tests require making assertions after a WaitForFunction has
26+
// started, but before it has resolved. We detect that reliably by
27+
// listening to the message that is sent to start polling.
28+
// This might not be an issue in upstream puppeteer.js, or may be highly unlikely,
29+
// due to differences between node.js's task scheduler and .net's.
30+
DefaultOptions.TransportFactory = async (url, options, cancellationToken) =>
31+
{
32+
_pollerInterceptor = new PollerInterceptor(await WebSocketTransport.DefaultTransportFactory(url, options, cancellationToken));
33+
return _pollerInterceptor;
34+
};
35+
}
36+
37+
public void Dispose()
38+
{
39+
_pollerInterceptor.Dispose();
2040
}
2141

2242
[PuppeteerTest("waittask.spec.ts", "Frame.waitForXPath", "should support some fancy xpath")]
@@ -37,8 +57,8 @@ public async Task ShouldRunInSpecifiedFrame()
3757
var frame1 = Page.Frames.First(f => f.Name == "frame1");
3858
var frame2 = Page.Frames.First(f => f.Name == "frame2");
3959
var waitForXPathPromise = frame2.WaitForXPathAsync("//div");
40-
await frame1.EvaluateFunctionAsync(addElement, "div");
41-
await frame2.EvaluateFunctionAsync(addElement, "div");
60+
await frame1.EvaluateFunctionAsync(AddElement, "div");
61+
await frame2.EvaluateFunctionAsync(AddElement, "div");
4262
var eHandle = await waitForXPathPromise;
4363
Assert.Equal(frame2, eHandle.ExecutionContext.Frame);
4464
}
@@ -60,10 +80,11 @@ public async Task ShouldThrowWhenFrameIsDetached()
6080
public async Task HiddenShouldWaitForDisplayNone()
6181
{
6282
var divHidden = false;
83+
var startedPolling = _pollerInterceptor.WaitForStartPollingAsync();
6384
await Page.SetContentAsync("<div style='display: block;'></div>");
6485
var waitForXPath = Page.WaitForXPathAsync("//div", new WaitForSelectorOptions { Hidden = true })
6586
.ContinueWith(_ => divHidden = true);
66-
await Page.WaitForXPathAsync("//div"); // do a round trip
87+
await startedPolling;
6788
Assert.False(divHidden);
6889
await Page.EvaluateExpressionAsync("document.querySelector('div').style.setProperty('display', 'none')");
6990
Assert.True(await waitForXPath.WithTimeout());

0 commit comments

Comments
 (0)