Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -480,13 +480,6 @@
"expectations": ["SKIP"],
"comment": "Firefox does not support --remote-debugging-pipe argument"
},
{
"testIdPattern": "[frame.spec] Frame specs Frame.prototype.frameElement should handle shadow roots",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"],
"comment": "https://github.com/w3c/webdriver-bidi/issues/794"
},
{
"testIdPattern": "[idle_override.spec] *",
"platforms": ["darwin", "linux", "win32"],
Expand Down
54 changes: 53 additions & 1 deletion lib/PuppeteerSharp.Tests/FrameTests/FrameElementTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using PuppeteerSharp.Nunit;
Expand All @@ -6,6 +7,39 @@ namespace PuppeteerSharp.Tests.FrameTests
{
public class FrameElementTests : PuppeteerPageBaseTest
{
[Test, PuppeteerTest("frame.spec", "Frame specs Frame.prototype.frameElement", "should work")]
public async Task ShouldWork()
{
await FrameUtils.AttachFrameAsync(Page, "theFrameId", TestConstants.EmptyPage);
await Page.EvaluateFunctionAsync(@"(url) => {
const frame = document.createElement('iframe');
frame.name = 'theFrameName';
frame.src = url;
document.body.appendChild(frame);
return new Promise(x => frame.onload = x);
}", TestConstants.EmptyPage);

await using var mainFrameElement = await Page.MainFrame.FrameElementAsync();
Assert.That(mainFrameElement, Is.Null);

var childFrames = Page.Frames.Where(f => f != Page.MainFrame).ToArray();
Assert.That(childFrames, Has.Length.EqualTo(2));

await using var frame1 = await childFrames[0].FrameElementAsync();
Assert.That(frame1, Is.Not.Null);

await using var frame2 = await childFrames[1].FrameElementAsync();
Assert.That(frame2, Is.Not.Null);

var name1 = await frame1.EvaluateFunctionAsync<string>("frame => frame.id");
var name2 = await frame2.EvaluateFunctionAsync<string>("frame => frame.name");

// The order of child frames may vary, so check both possibilities
Assert.That(
new[] { name1, name2 },
Is.EquivalentTo(new[] { "theFrameId", "theFrameName" }));
}

[Test, PuppeteerTest("frame.spec", "Frame specs Frame.prototype.frameElement", "should handle shadow roots")]
public async Task ShouldHandleShadowRoots()
{
Expand All @@ -22,12 +56,30 @@ await Page.SetContentAsync(@"
// Wait for the iframe to load inside shadow DOM
await Page.WaitForFrameAsync(f => f != Page.MainFrame);
Assert.That(Page.Frames, Has.Length.EqualTo(2));
var frame = Page.Frames[1];
var frame = Page.MainFrame.ChildFrames.First();
await using var frameElement = await frame.FrameElementAsync();
Assert.That(frameElement, Is.Not.Null);
Assert.That(
await frameElement.EvaluateFunctionAsync<string>("el => el.tagName.toLocaleLowerCase()"),
Is.EqualTo("iframe"));
}

[Test, PuppeteerTest("frame.spec", "Frame specs Frame.prototype.frameElement", "should return ElementHandle in the correct world")]
public async Task ShouldReturnElementHandleInTheCorrectWorld()
{
await FrameUtils.AttachFrameAsync(Page, "theFrameId", TestConstants.EmptyPage);
await Page.EvaluateFunctionAsync(@"() => {
globalThis.isMainWorld = true;
}");

Assert.That(Page.Frames, Has.Length.EqualTo(2));

var childFrame = Page.MainFrame.ChildFrames.First();
await using var frameElement = await childFrame.FrameElementAsync();
Assert.That(frameElement, Is.Not.Null);

var isMainWorld = await frameElement.EvaluateFunctionAsync<bool>("() => globalThis.isMainWorld");
Assert.That(isMainWorld, Is.True);
}
}
}
21 changes: 21 additions & 0 deletions lib/PuppeteerSharp/Bidi/BidiFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,27 @@ void OnHistoryUpdated(object sender, EventArgs args)
}
}

/// <inheritdoc />
public override async Task<ElementHandle> FrameElementAsync()
{
var parentFrame = ParentFrame as BidiFrame;
if (parentFrame == null)
{
return null;
}

var nodes = await parentFrame.BrowsingContext.LocateNodesAsync(
new WebDriverBiDi.BrowsingContext.ContextLocator(Id)).ConfigureAwait(false);

var node = nodes.FirstOrDefault();
if (node == null)
{
return null;
}

return BidiElementHandle.From(node, (BidiRealm)parentFrame.MainRealm) as ElementHandle;
}

internal static BidiFrame From(BidiPage parentPage, BidiFrame parentFrame, BrowsingContext browsingContext)
{
parentFrame = new BidiFrame(parentPage, parentFrame, browsingContext);
Expand Down
2 changes: 1 addition & 1 deletion lib/PuppeteerSharp/Bidi/Core/BrowsingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ internal async Task SetFilesAsync(WebDriverBiDi.Script.SharedReference element,
await Session.Driver.Input.SetFilesAsync(parameters).ConfigureAwait(false);
}

internal async Task<IList<RemoteValue>> LocateNodesAsync(Locator locator, SharedReference[] startNodes)
internal async Task<IList<RemoteValue>> LocateNodesAsync(Locator locator, SharedReference[] startNodes = null)
{
var parameters = new LocateNodesCommandParameters(Id, locator);
if (startNodes?.Length > 0)
Expand Down
Loading