Skip to content

Commit

Permalink
[BREAKING] Remove XPathAsync and WaitForXPathAsync (#2597)
Browse files Browse the repository at this point in the history
* Remove XPathAsync and WaitForXPathAsync

* Docs changes

* fix a test

* Code factor

---------

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
kblok and actions-user authored Apr 11, 2024
1 parent eddc391 commit 975c86d
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 347 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
using System;
using System.Threading.Tasks;
using NUnit.Framework;
using PuppeteerSharp.Nunit;

namespace PuppeteerSharp.Tests.ElementHandleTests
namespace PuppeteerSharp.Tests.QuerySelectorTests
{
public class ElementHandleQuerySelectorTests : PuppeteerPageBaseTest
{
public ElementHandleQuerySelectorTests() : base()
{
}

[Test, Retry(2), PuppeteerTest("queryselector.spec", "ElementHandle.$", "should query existing element")]
public async Task ShouldQueryExistingElement()
{
Expand All @@ -31,5 +26,26 @@ public async Task ShouldReturnNullForNonExistingElement()
var second = await html.QuerySelectorAsync(".third");
Assert.Null(second);
}

[Test, Retry(2), PuppeteerTest("queryselector.spec", "ElementHandle.$$ xpath", "should query existing element")]
public async Task XPathShouldQueryExistingElement()
{
await Page.GoToAsync(TestConstants.ServerUrl + "/playground.html");
await Page.SetContentAsync("<html><body><div class=\"second\"><div class=\"inner\">A</div></div></body></html>");
var html = await Page.QuerySelectorAsync("html");
var second = await html.QuerySelectorAllAsync("xpath/./body/div[contains(@class, 'second')]");
var inner = await second[0].QuerySelectorAllAsync("xpath/./div[contains(@class, 'inner')]");
var content = await Page.EvaluateFunctionAsync<string>("e => e.textContent", inner[0]);
Assert.AreEqual("A", content);
}

[Test, Retry(2), PuppeteerTest("queryselector.spec", "ElementHandle.$$ xpath", "should return null for non-existing element")]
public async Task XPathShouldReturnNullForNonExistingElement()
{
await Page.SetContentAsync("<html><body><div class=\"second\"><div class=\"inner\">B</div></div></body></html>");
var html = await Page.QuerySelectorAsync("html");
var second = await html.QuerySelectorAllAsync("xpath/div[contains(@class, 'third')]");
Assert.IsEmpty(second);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ namespace PuppeteerSharp.Tests.QuerySelectorTests
{
public class PageQuerySelectorTests : PuppeteerPageBaseTest
{
public PageQuerySelectorTests() : base()
{
}

[Test, Retry(2), PuppeteerTest("queryselector.spec", "Page.$", "should query existing element")]
public async Task ShouldQueryExistingElement()
{
Expand All @@ -24,5 +20,29 @@ public async Task ShouldReturnNullForNonExistingElement()
var element = await Page.QuerySelectorAsync("non-existing-element");
Assert.Null(element);
}

[Test, Retry(2), PuppeteerTest("queryselector.spec", "querySelector Page.$$ xpath", "should query existing element")]
public async Task XPathShouldQueryExistingElement()
{
await Page.SetContentAsync("<section>test</section>");
var elements = await Page.QuerySelectorAllAsync("xpath/html/body/section");
Assert.NotNull(elements[0]);
Assert.That(elements, Has.Exactly(1).Items);
}

[Test, Retry(2), PuppeteerTest("queryselector.spec", "querySelector Page.$$ xpath", "should return empty array for non-existing element")]
public async Task ShouldReturnEmptyArrayForNonExistingElement()
{
var elements = await Page.QuerySelectorAllAsync("xpath/html/body/non-existing-element");
Assert.IsEmpty(elements);
}

[Test, Retry(2), PuppeteerTest("queryselector.spec", "querySelector Page.$$ xpath", "should return multiple elements")]
public async Task XpathShouldReturnMultipleElements()
{
await Page.SetContentAsync("<div></div><div></div>");
var elements = await Page.QuerySelectorAllAsync("xpath/html/body/div");
Assert.AreEqual(2, elements.Length);
}
}
}
39 changes: 0 additions & 39 deletions lib/PuppeteerSharp.Tests/QuerySelectorTests/PageXPathTests.cs

This file was deleted.

112 changes: 110 additions & 2 deletions lib/PuppeteerSharp.Tests/WaitTaskTests/FrameWaitForSelectorTests.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using PuppeteerSharp.Helpers;
using PuppeteerSharp.Nunit;
using PuppeteerSharp.Transport;

namespace PuppeteerSharp.Tests.WaitTaskTests
{
public class FrameWaitForSelectorTests : PuppeteerPageBaseTest
{
private const string AddElement = "tag => document.body.appendChild(document.createElement(tag))";
private PollerInterceptor _pollerInterceptor;

public FrameWaitForSelectorTests()
{
DefaultOptions = TestConstants.DefaultBrowserOptions();

// Set up a custom TransportFactory to intercept sent messages
// Some of the tests require making assertions after a WaitForFunction has
// started, but before it has resolved. We detect that reliably by
// listening to the message that is sent to start polling.
// This might not be an issue in upstream puppeteer.js, or may be highly unlikely,
// due to differences between node.js's task scheduler and .net's.
DefaultOptions.TransportFactory = async (url, options, cancellationToken) =>
{
_pollerInterceptor = new PollerInterceptor(await WebSocketTransport.DefaultTransportFactory(url, options, cancellationToken));
return _pollerInterceptor;
};
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_pollerInterceptor.Dispose();
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector", "should immediately resolve promise if node exists")]
public async Task ShouldImmediatelyResolveTaskIfNodeExists()
Expand Down Expand Up @@ -222,7 +247,7 @@ public async Task ShouldReturnNullIfWaitingToHideNonExistingElement()
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector", "should respect timeout")]
public void ShouldRespectTimeout()
public void XpathShouldRespectTimeout()
{
var exception = Assert.ThrowsAsync<WaitTaskTimeoutException>(async ()
=> await Page.WaitForSelectorAsync("div", new WaitForSelectorOptions { Timeout = 10 }));
Expand Down Expand Up @@ -266,5 +291,88 @@ public void ShouldHaveCorrectStackTraceForTimeout()
=> await Page.WaitForSelectorAsync(".zombo", new WaitForSelectorOptions { Timeout = 10 }));
StringAssert.Contains("WaitForSelectorTests", exception.StackTrace);
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "should support some fancy xpath")]
public async Task ShouldSupportSomeFancyXpath()
{
await Page.SetContentAsync("<p>red herring</p><p>hello world </p>");
var waitForXPath = Page.WaitForSelectorAsync("xpath/.//p[normalize-space(.)=\"hello world\"]");
Assert.AreEqual("hello world ", await Page.EvaluateFunctionAsync<string>("x => x.textContent", await waitForXPath));
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "should run in specified frame")]
public async Task XpathShouldRunInSpecifiedFrame()
{
await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage);
await FrameUtils.AttachFrameAsync(Page, "frame2", TestConstants.EmptyPage);
var frame1 = Page.Frames.First(f => f.Name == "frame1");
var frame2 = Page.Frames.First(f => f.Name == "frame2");
var waitForXPathPromise = frame2.WaitForSelectorAsync("xpath/.//div");
await frame1.EvaluateFunctionAsync(AddElement, "div");
await frame2.EvaluateFunctionAsync(AddElement, "div");
var eHandle = await waitForXPathPromise;
Assert.AreEqual(frame2, eHandle.Frame);
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "should throw when frame is detached")]
public async Task XpathShouldThrowWhenFrameIsDetached()
{
await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage);
var frame = Page.FirstChildFrame();
var waitPromise = frame.WaitForSelectorAsync("xpath/.//*[@class=\"box\"]");
await FrameUtils.DetachFrameAsync(Page, "frame1");
var exception = Assert.ThrowsAsync<WaitTaskTimeoutException>(() => waitPromise);
StringAssert.Contains("waitForFunction failed: frame got detached.", exception.Message);
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "hidden should wait for display: none")]
public async Task HiddenShouldWaitForDisplayNone()
{
var divHidden = false;
var startedPolling = _pollerInterceptor.WaitForStartPollingAsync();
await Page.SetContentAsync("<div style='display: block;'></div>");
var waitForXPath = Page.WaitForSelectorAsync("xpath/.//div", new WaitForSelectorOptions { Hidden = true })
.ContinueWith(_ => divHidden = true);
await startedPolling;
Assert.False(divHidden);
await Page.EvaluateExpressionAsync("document.querySelector('div').style.setProperty('display', 'none')");
Assert.True(await waitForXPath.WithTimeout());
Assert.True(divHidden);
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "should return the element handle")]
public async Task XpathShouldReturnTheElementHandle()
{
var waitForXPath = Page.WaitForSelectorAsync("xpath/.//*[@class=\"zombo\"]");
await Page.SetContentAsync("<div class='zombo'>anything</div>");
Assert.AreEqual("anything", await Page.EvaluateFunctionAsync<string>("x => x.textContent", await waitForXPath));
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "should allow you to select a text node")]
public async Task ShouldAllowYouToSelectATextNode()
{
await Page.SetContentAsync("<div>some text</div>");
var text = await Page.WaitForSelectorAsync("xpath/.//div/text()");
Assert.AreEqual(3 /* Node.TEXT_NODE */, await (await text.GetPropertyAsync("nodeType")).JsonValueAsync<int>());
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "should allow you to select an element with single slash")]
public async Task ShouldAllowYouToSelectAnElementWithSingleSlash()
{
await Page.SetContentAsync("<div>some text</div>");
var waitForXPath = Page.WaitForSelectorAsync("xpath/html/body/div");
Assert.AreEqual("some text", await Page.EvaluateFunctionAsync<string>("x => x.textContent", await waitForXPath));
}

[Test, Retry(2), PuppeteerTest("waittask.spec", "waittask specs Frame.waitForSelector xpath", "should respect timeout")]
public void ShouldRespectTimeout()
{
const int timeout = 10;

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

StringAssert.Contains($"Waiting failed: {timeout}ms exceeded", exception.Message);
}
}
}
Loading

0 comments on commit 975c86d

Please sign in to comment.