Skip to content

Commit 8f25083

Browse files
authored
WaitForSelectorOptions and WaitForFunctionOptions add new TimeoutReturnsNull (#63)
- Instead of throwing exception on timeout, the task will return null Co-authored-by: amaitland <[email protected]>
1 parent eea37d9 commit 8f25083

File tree

5 files changed

+39
-3
lines changed

5 files changed

+39
-3
lines changed

lib/PuppeteerSharp.Tests/WaitTaskTests/FrameWaitForSelectorTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ public async Task ShouldRespectTimeout()
208208
Assert.Equal("waiting for function failed: timeout 10 ms exceeded", exception.Message);
209209
}
210210

211+
[PuppeteerTest("waittask.spec.ts", "Frame.waitForSelector", "should respect timeout")]
212+
[PuppeteerFact]
213+
public async Task ShouldRespectTimeoutReturnNull()
214+
{
215+
var result = await DevToolsContext.WaitForExpressionAsync("false", new WaitForFunctionOptions { Timeout = 10, TimeoutReturnsNull = true });
216+
217+
Assert.Null(result);
218+
}
219+
211220
[PuppeteerTest("waittask.spec.ts", "Frame.waitForSelector", "should have an error message specifically for awaiting an element to be hidden")]
212221
[PuppeteerFact]
213222
public async Task ShouldHaveAnErrorMessageSpecificallyForAwaitingAnElementToBeHidden()

lib/PuppeteerSharp/DOMWorld.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ internal async Task<JSHandle> WaitForFunctionAsync(string script, WaitForFunctio
364364
options.Polling,
365365
options.PollingInterval,
366366
options.Timeout ?? _timeoutSettings.Timeout,
367+
options.TimeoutReturnsNull,
367368
args);
368369

369370
return await waitTask
@@ -380,7 +381,8 @@ internal async Task<JSHandle> WaitForExpressionAsync(string script, WaitForFunct
380381
"function",
381382
options.Polling,
382383
options.PollingInterval,
383-
options.Timeout ?? _timeoutSettings.Timeout);
384+
options.Timeout ?? _timeoutSettings.Timeout,
385+
options.TimeoutReturnsNull);
384386

385387
return await waitTask
386388
.Task
@@ -437,6 +439,7 @@ function hasVisibleBoundingBox() {
437439
polling,
438440
null,
439441
timeout,
442+
options.TimeoutReturnsNull,
440443
new object[] { selectorOrXPath, isXPath, options.Visible, options.Hidden });
441444

442445
var handle = await waitTask.Task.ConfigureAwait(false);

lib/PuppeteerSharp/WaitForFunctionOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ public class WaitForFunctionOptions
1414
/// </summary>
1515
public int? Timeout { get; set; }
1616

17+
/// <summary>
18+
/// If set to <see langword="true" />, the method will return <see langword="null"/> if the timeout is reached.
19+
/// The default (<see langword="false" />) will throw a <see cref="WaitTaskTimeoutException"/> if the timeout is reached."/>
20+
/// </summary>
21+
public bool TimeoutReturnsNull { get; set; } = false;
22+
1723
/// <summary>
1824
/// An interval at which the <c>pageFunction</c> is executed. defaults to <see cref="WaitForFunctionPollingOption.Raf"/>
1925
/// </summary>

lib/PuppeteerSharp/WaitForSelectorOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ public class WaitForSelectorOptions
1414
/// </summary>
1515
public int? Timeout { get; set; }
1616

17+
/// <summary>
18+
/// If set to <see langword="true" />, the method will return <see langword="null"/> if the timeout is reached.
19+
/// The default (<see langword="false" />) will throw a <see cref="WaitTaskTimeoutException"/> if the timeout is reached."/>
20+
/// </summary>
21+
public bool TimeoutReturnsNull { get; set; } = false;
22+
1723
/// <summary>
1824
/// Wait for element to be present in DOM and to be visible.
1925
/// </summary>

lib/PuppeteerSharp/WaitTask.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ internal class WaitTask : IDisposable
1414
private readonly int _timeout;
1515
private readonly object[] _args;
1616
private readonly string _title;
17+
private readonly bool _timeoutReturnsNull;
1718
private readonly Task _timeoutTimer;
1819

1920
private readonly CancellationTokenSource _cts;
@@ -107,6 +108,7 @@ internal WaitTask(
107108
WaitForFunctionPollingOption polling,
108109
int? pollingInterval,
109110
int timeout,
111+
bool timeoutReturnsNull,
110112
object[] args = null)
111113
{
112114
if (string.IsNullOrEmpty(predicateBody))
@@ -125,6 +127,7 @@ internal WaitTask(
125127
_timeout = timeout;
126128
_args = args ?? Array.Empty<object>();
127129
_title = title;
130+
_timeoutReturnsNull = timeoutReturnsNull;
128131

129132
_cts = new CancellationTokenSource();
130133

@@ -136,7 +139,7 @@ internal WaitTask(
136139
{
137140
_timeoutTimer = System.Threading.Tasks.Task.Delay(timeout, _cts.Token)
138141
.ContinueWith(
139-
_ => Terminate(new WaitTaskTimeoutException(timeout, title)),
142+
_ => Terminate(_timeoutReturnsNull ? null : new WaitTaskTimeoutException(timeout, title)),
140143
TaskScheduler.Default);
141144
}
142145

@@ -212,7 +215,16 @@ await _world.EvaluateFunctionAsync<bool>("s => !s", success)
212215
internal void Terminate(Exception exception)
213216
{
214217
_terminated = true;
215-
_taskCompletion.TrySetException(exception);
218+
219+
if (exception == null)
220+
{
221+
_taskCompletion.TrySetResult(null);
222+
}
223+
else
224+
{
225+
_taskCompletion.TrySetException(exception);
226+
}
227+
216228
Cleanup();
217229
}
218230

0 commit comments

Comments
 (0)