Skip to content

Commit

Permalink
Waittask refactor (#2190)
Browse files Browse the repository at this point in the history
* Waittask refactor

* remove typescript code

* Fix some javascript calls

* Some improvements

* cr

* Fix some tests

* passing tests

* WaitTask Refactor - Fix Evaluation failed: TypeError: fun is not a function (#2192)

* Fix Evaluation failed: TypeError: fun is not a function

- The whitespace is causing the new Function() call to fail.

* Alternate fix

* Fix ShouldRespectTimeout test

* Fix failing test

---------

Co-authored-by: Alex Maitland <amaitland@users.noreply.github.com>
  • Loading branch information
kblok and amaitland committed Apr 26, 2023
1 parent 28f0354 commit f24c854
Show file tree
Hide file tree
Showing 13 changed files with 580 additions and 252 deletions.
8 changes: 5 additions & 3 deletions lib/PuppeteerSharp.Tests/TestConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ public static class TestConstants
" http://localhost:<PORT>/frames/frame.html (aframe)"
};

public static LaunchOptions DefaultBrowserOptions() => new LaunchOptions
public static LaunchOptions DefaultBrowserOptions() => new()
{
SlowMo = Convert.ToInt32(Environment.GetEnvironmentVariable("SLOW_MO")),
Headless = Convert.ToBoolean(Environment.GetEnvironmentVariable("HEADLESS") ?? "true"),
Headless = Convert.ToBoolean(
Environment.GetEnvironmentVariable("HEADLESS") ??
(System.Diagnostics.Debugger.IsAttached ? "false" : "true")),
Product = IsChrome ? Product.Chrome : Product.Firefox,
EnqueueAsyncMessages = Convert.ToBoolean(Environment.GetEnvironmentVariable("ENQUEUE_ASYNC_MESSAGES") ?? "false"),
Timeout = 0,
Expand All @@ -55,7 +57,7 @@ public static class TestConstants
#endif
};

public static LaunchOptions BrowserWithExtensionOptions() => new LaunchOptions
public static LaunchOptions BrowserWithExtensionOptions() => new()
{
Headless = false,
Args = new[]
Expand Down
25 changes: 12 additions & 13 deletions lib/PuppeteerSharp.Tests/WaitTaskTests/FrameWaitForFunctionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,29 @@ public async Task ShouldWorkWhenResolvedRightBeforeExecutionContextDisposal()
[PuppeteerFact]
public async Task ShouldPollOnInterval()
{
var success = false;
var startTime = DateTime.UtcNow;
var polling = 100;
var watchdog = Page.WaitForFunctionAsync("() => window.__FOO === 'hit'", new WaitForFunctionOptions { PollingInterval = polling })
.ContinueWith(_ => success = true);
await Page.EvaluateExpressionAsync("window.__FOO = 'hit'");
Assert.False(success);
var watchdog = Page.WaitForFunctionAsync("() => window.__FOO === 'hit'", new WaitForFunctionOptions { PollingInterval = polling });
// Wait for function will release the execution faster than in node.
// We add some CDP action to wait for the task to start the polling
await Page.EvaluateExpressionAsync("document.body.appendChild(document.createElement('div'))");
await Page.EvaluateFunctionAsync("() => setTimeout(window.__FOO = 'hit', 50)");
await watchdog;

Assert.True((DateTime.UtcNow - startTime).TotalMilliseconds > polling / 2);
}

[PuppeteerTest("waittask.spec.ts", "Frame.waitForFunction", "should poll on interval async")]
[PuppeteerFact]
public async Task ShouldPollOnIntervalAsync()
{
var success = false;
var startTime = DateTime.UtcNow;
var polling = 100;
var watchdog = Page.WaitForFunctionAsync("async () => window.__FOO === 'hit'", new WaitForFunctionOptions { PollingInterval = polling })
.ContinueWith(_ => success = true);
await Page.EvaluateFunctionAsync("async () => window.__FOO = 'hit'");
Assert.False(success);
var polling = 1000;
var watchdog = Page.WaitForFunctionAsync("async () => window.__FOO === 'hit'", new WaitForFunctionOptions { PollingInterval = polling });
// Wait for function will release the execution faster than in node.
// We add some CDP action to wait for the task to start the polling
await Page.EvaluateExpressionAsync("document.body.appendChild(document.createElement('div'))");
await Page.EvaluateFunctionAsync("async () => setTimeout(window.__FOO = 'hit', 50)");
await watchdog;
Assert.True((DateTime.UtcNow - startTime).TotalMilliseconds > polling / 2);
}
Expand Down Expand Up @@ -162,7 +161,7 @@ public async Task ShouldRespectTimeout()
var exception = await Assert.ThrowsAsync<WaitTaskTimeoutException>(()
=> Page.WaitForExpressionAsync("false", new WaitForFunctionOptions { Timeout = 10 }));

Assert.Contains("waiting for function failed: timeout", exception.Message);
Assert.Contains("Waiting failed: 10ms exceeded", exception.Message);
}

[PuppeteerTest("waittask.spec.ts", "Frame.waitForFunction", "should respect default timeout")]
Expand All @@ -173,7 +172,7 @@ public async Task ShouldRespectDefaultTimeout()
var exception = await Assert.ThrowsAsync<WaitTaskTimeoutException>(()
=> Page.WaitForExpressionAsync("false"));

Assert.Contains("waiting for function failed: timeout", exception.Message);
Assert.Contains("Waiting failed: 1ms exceeded", exception.Message);
}

[PuppeteerTest("waittask.spec.ts", "Frame.waitForFunction", "should disable timeout when its set to 0")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public async Task ShouldThrowWhenFrameIsDetached()
var frame = Page.FirstChildFrame();
var waitTask = frame.WaitForSelectorAsync(".box");
await FrameUtils.DetachFrameAsync(Page, "frame1");
var waitException = await Assert.ThrowsAsync<Exception>(() => waitTask);
var waitException = await Assert.ThrowsAsync<WaitTaskTimeoutException>(() => waitTask);

Assert.NotNull(waitException);
Assert.Contains("waitForFunction failed: frame got detached.", waitException.Message);
Expand Down Expand Up @@ -206,7 +206,7 @@ public async Task ShouldRespectTimeout()
var exception = await Assert.ThrowsAsync<WaitTaskTimeoutException>(async ()
=> await Page.WaitForSelectorAsync("div", new WaitForSelectorOptions { Timeout = 10 }));

Assert.Contains("waiting for selector 'div' failed: timeout", exception.Message);
Assert.Contains("Waiting for selector `div` failed: Waiting failed: 10ms exceeded", exception.Message);
}

[PuppeteerTest("waittask.spec.ts", "Frame.waitForSelector", "should have an error message specifically for awaiting an element to be hidden")]
Expand All @@ -217,7 +217,7 @@ public async Task ShouldHaveAnErrorMessageSpecificallyForAwaitingAnElementToBeHi
var exception = await Assert.ThrowsAsync<WaitTaskTimeoutException>(async ()
=> await Page.WaitForSelectorAsync("div", new WaitForSelectorOptions { Hidden = true, Timeout = 10 }));

Assert.Contains("waiting for selector 'div' to be hidden failed: timeout", exception.Message);
Assert.Contains("Waiting for selector `div` failed: Waiting failed: 10ms exceeded", exception.Message);
}

[PuppeteerTest("waittask.spec.ts", "Frame.waitForSelector", "should respond to node attribute mutation")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ public async Task ShouldAllowYouToSelectAnElementWithSingleSlash()
[PuppeteerFact]
public async Task ShouldRespectTimeout()
{
const int timeout = 10;

var exception = await Assert.ThrowsAsync<WaitTaskTimeoutException>(()
=> Page.WaitForXPathAsync("//div", new WaitForSelectorOptions { Timeout = 10 }));
=> Page.WaitForXPathAsync("//div", new WaitForSelectorOptions { Timeout = timeout }));

Assert.Contains("waiting for XPath '//div' failed: timeout", exception.Message);
Assert.Contains($"Waiting failed: {timeout}ms exceeded", exception.Message);
}
}
}
2 changes: 1 addition & 1 deletion lib/PuppeteerSharp.Tests/WaitTaskTests/PageWaitForTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task ShouldWaitForAnXpath()
public async Task ShouldNotAllowYouToSelectAnElementWithSingleSlashXpath()
{
await Page.SetContentAsync("<div>some text</div>");
var exception = await Assert.ThrowsAsync<EvaluationFailedException>(() =>
var exception = await Assert.ThrowsAsync<WaitTaskTimeoutException>(() =>
Page.WaitForSelectorAsync("/html/body/div"));
Assert.NotNull(exception);
}
Expand Down
1 change: 1 addition & 0 deletions lib/PuppeteerSharp/AriaQueryHandlerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ async Task<IElementHandle> WaitFor(IElementHandle root, string selector, WaitFor

return await frame.PuppeteerWorld.WaitForSelectorInPageAsync(
@"(_, selector) => globalThis.ariaQuerySelector(selector)",
element,
selector,
options,
new[] { binding }).ConfigureAwait(false);
Expand Down
4 changes: 2 additions & 2 deletions lib/PuppeteerSharp/CustomQueriesManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ private static InternalQueryHandler MakeQueryHandler(CustomQueryHandler handler)
internalHandler.WaitFor = async (IElementHandle root, string selector, WaitForSelectorOptions options) =>
{
var frame = (root as ElementHandle).Frame;
var element = await frame.PuppeteerWorld.AdoptHandleAsync(root).ConfigureAwait(false);
var element = await frame.PuppeteerWorld.AdoptHandleAsync(root).ConfigureAwait(false) as IElementHandle;
return await frame.PuppeteerWorld.WaitForSelectorInPageAsync(handler.QueryOne, selector, options).ConfigureAwait(false);
return await frame.PuppeteerWorld.WaitForSelectorInPageAsync(handler.QueryOne, element, selector, options).ConfigureAwait(false);
};
}

Expand Down
Loading

0 comments on commit f24c854

Please sign in to comment.