Skip to content

Commit

Permalink
[BREAKING] Introduce Realm entity (#2356)
Browse files Browse the repository at this point in the history
* [BREAKING] Introduce Real entity

Worker was renamed to WebWorker.
IExecutionContext.QueryObjectsAsync was removed.

* fix build

* Remove outdated tests

* Update hover implementation

* fix build

* fix a build

* Fix function

* more progress

* Fix some builds

* Fix get property

* Fix cast

* Fix transfer handle

* Move isolation to the element handle

* Fix transfer

* fix array conversion

* Undo changes. Error will come

* Fix array translation

* More fixes

* Another change

* Undo some changes

* More validations

* Fix is hidden

* Validate execution context

* Increase timeout

* fix workers

* Revert "Increase timeout"

This reverts commit 9419592.

* fix firefox test
  • Loading branch information
kblok authored Nov 21, 2023
1 parent 4eb4b46 commit d5caa54
Show file tree
Hide file tree
Showing 39 changed files with 1,159 additions and 1,176 deletions.
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
using System;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Hosting.Server;
using PuppeteerSharp.Tests.Attributes;
using PuppeteerSharp.Nunit;
using SixLabors.ImageSharp;
using static System.Net.Mime.MediaTypeNames;
using NUnit.Framework;

namespace PuppeteerSharp.Tests.AriaQueryHandlerTests
{
public class WaitForSelectorAriaTests : PuppeteerPageBaseTest
{
public WaitForSelectorAriaTests(): base()
{
}

const string addElement = @"(tag) => document.body.appendChild(document.createElement(tag))";
private const string AddElement = @"(tag) => document.body.appendChild(document.createElement(tag))";

[PuppeteerTest("ariaqueryhandler.spec.ts", "waitForSelector (aria)", "should immediately resolve promise if node exists")]
[Skip(SkipAttribute.Targets.Firefox)]
public async Task ShouldImmediatelyResolvePromiseIfNodeExists()
{
await Page.GoToAsync(TestConstants.EmptyPage);
await Page.EvaluateFunctionAsync(addElement, "button");
await Page.EvaluateFunctionAsync(AddElement, "button");
await Page.WaitForSelectorAsync("aria/[role=\"button\"]");
}

Expand All @@ -50,10 +38,10 @@ await Page.EvaluateFunctionAsync(
public async Task ShouldPersistQueryHandlerBindingsAcrossReloads()
{
await Page.GoToAsync(TestConstants.EmptyPage);
await Page.EvaluateFunctionAsync(addElement, "button");
await Page.EvaluateFunctionAsync(AddElement, "button");
await Page.WaitForSelectorAsync("aria/[role=\"button\"]");
await Page.ReloadAsync();
await Page.EvaluateFunctionAsync(addElement, "button");
await Page.EvaluateFunctionAsync(AddElement, "button");
await Page.WaitForSelectorAsync("aria/[role=\"button\"]");
}

Expand All @@ -62,10 +50,10 @@ public async Task ShouldPersistQueryHandlerBindingsAcrossReloads()
public async Task ShouldPersistQueryHandlerBindingsAcrossNavigations()
{
await Page.GoToAsync("data:text/html,");
await Page.EvaluateFunctionAsync(addElement, "button");
await Page.EvaluateFunctionAsync(AddElement, "button");
await Page.WaitForSelectorAsync("aria/[role=\"button\"]");
await Page.GoToAsync("data:text/html,");
await Page.EvaluateFunctionAsync(addElement, "button");
await Page.EvaluateFunctionAsync(AddElement, "button");
await Page.WaitForSelectorAsync("aria/[role=\"button\"]");
}

Expand All @@ -75,7 +63,7 @@ public async Task ShouldWorkIndependentlyOfExposeFunction()
{
await Page.GoToAsync(TestConstants.EmptyPage);
await Page.ExposeFunctionAsync("ariaQuerySelector", new Func<int, int, int>((a, b) => a + b));
await Page.EvaluateFunctionAsync(addElement, "button");
await Page.EvaluateFunctionAsync(AddElement, "button");
await Page.WaitForSelectorAsync("aria/[role=\"button\"]");
var result = await Page.EvaluateExpressionAsync<int>("globalThis.ariaQuerySelector(2,8)");
Assert.AreEqual(10, result);
Expand All @@ -101,8 +89,8 @@ public async Task ShouldResolvePromiseWhenNodeIsAdded()
await Page.GoToAsync(TestConstants.EmptyPage);
var frame = Page.MainFrame;
var watchdog = frame.WaitForSelectorAsync("aria/[role=\"heading\"]");
await frame.EvaluateFunctionAsync(addElement, "br");
await frame.EvaluateFunctionAsync(addElement, "h1");
await frame.EvaluateFunctionAsync(AddElement, "br");
await frame.EvaluateFunctionAsync(AddElement, "h1");
var elementHandle = await watchdog;
var tagName = await (
await elementHandle.GetPropertyAsync("tagName")
Expand All @@ -112,11 +100,11 @@ await elementHandle.GetPropertyAsync("tagName")

[PuppeteerTest("ariaqueryhandler.spec.ts", "waitForSelector (aria)", "should work when node is added through innerHTML")]
[Skip(SkipAttribute.Targets.Firefox)]
public async Task ShouldWorkWhenNodeIsAddedThroughInnerHTML()
public async Task ShouldWorkWhenNodeIsAddedThroughInnerHtml()
{
await Page.GoToAsync(TestConstants.EmptyPage);
var watchdog = Page.WaitForSelectorAsync("aria/name");
await Page.EvaluateFunctionAsync(addElement, "span");
await Page.EvaluateFunctionAsync(AddElement, "span");
await Page.EvaluateFunctionAsync(@"() => {
return (document.querySelector('span').innerHTML =
'<h3><div aria-label=""name""></div></h3>');
Expand All @@ -132,10 +120,10 @@ public async Task PageWaitForSelectorIsShortcutForMainFrame()
await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage);
var otherFrame = Page.FirstChildFrame();
var watchdog = Page.WaitForSelectorAsync("aria/[role=\"button\"]");
await otherFrame.EvaluateFunctionAsync(addElement, "button");
await Page.EvaluateFunctionAsync(addElement, "button");
await otherFrame.EvaluateFunctionAsync(AddElement, "button");
await Page.EvaluateFunctionAsync(AddElement, "button");
var elementHandle = await watchdog;
Assert.AreSame(elementHandle.ExecutionContext.Frame, Page.MainFrame);
Assert.AreSame(elementHandle.Frame, Page.MainFrame);
}

[PuppeteerTest("ariaqueryhandler.spec.ts", "waitForSelector (aria)", "should run in specified frame")]
Expand All @@ -147,10 +135,10 @@ public async Task ShouldRunInSpecifiedFrame()
var frame1 = Page.Frames.First(frame => frame.Name == "frame1");
var frame2 = Page.Frames.First(frame => frame.Name == "frame2");
var waitForSelectorTask = frame2.WaitForSelectorAsync("aria/[role=\"button\"]");
await frame1.EvaluateFunctionAsync(addElement, "button");
await frame2.EvaluateFunctionAsync(addElement, "button");
await frame1.EvaluateFunctionAsync(AddElement, "button");
await frame2.EvaluateFunctionAsync(AddElement, "button");
var elementHandle = await waitForSelectorTask;
Assert.AreSame(elementHandle.ExecutionContext.Frame, frame2);
Assert.AreSame(elementHandle.Frame, frame2);
}
}
}
18 changes: 13 additions & 5 deletions lib/PuppeteerSharp.Tests/ElementHandleTests/ClickTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,23 @@ public async Task ShouldWorkForShadowDomV1()
Assert.True(await Page.EvaluateExpressionAsync<bool>("clicked"));
}

[PuppeteerTest("elementhandle.spec.ts", "ElementHandle.click", "should work for TextNodes")]
[PuppeteerTest("elementhandle.spec.ts", "ElementHandle.click", "should not work for TextNodes")]
[PuppeteerTimeout]
public async Task ShouldWorkForTextNodes()
public async Task ShouldNotWorkForTextNodes()
{
await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html");
var buttonTextNode = (IElementHandle)await Page.EvaluateExpressionHandleAsync(
"document.querySelector('button').firstChild");
var exception = Assert.ThrowsAsync<PuppeteerException>(async () => await buttonTextNode.ClickAsync());
Assert.AreEqual("Node is not of type HTMLElement", exception.Message);
var exception = Assert.ThrowsAsync<EvaluationFailedException>(async () => await buttonTextNode.ClickAsync());

if (TestConstants.IsChrome)
{
Assert.That(exception.Message, Does.Contain("is not of type 'Element'"));
}
else
{
Assert.That(exception.Message, Does.Contain("implement interface Element"));
}
}

[PuppeteerTest("elementhandle.spec.ts", "ElementHandle.click", "should throw for detached nodes")]
Expand All @@ -51,7 +59,7 @@ public async Task ShouldThrowForDetachedNodes()
var button = await Page.QuerySelectorAsync("button");
await Page.EvaluateFunctionAsync("button => button.remove()", button);
var exception = Assert.ThrowsAsync<PuppeteerException>(async () => await button.ClickAsync());
Assert.AreEqual("Node is detached from document", exception.Message);
Assert.AreEqual("Node is either not visible or not an HTMLElement", exception.Message);
}

[PuppeteerTest("elementhandle.spec.ts", "ElementHandle.click", "should throw for hidden nodes")]
Expand Down
17 changes: 0 additions & 17 deletions lib/PuppeteerSharp.Tests/EvaluationTests/PageEvaluateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,23 +298,6 @@ public async Task ShouldSimulateAUserGesture()
return document.execCommand('copy');
}"));

[PuppeteerTest("evaluation.spec.ts", "Page.evaluate", "should throw a nice error after a navigation")]
[Skip(SkipAttribute.Targets.Firefox)]
public async Task ShouldThrowANiceErrorAfterANavigation()
{
var executionContext = await Page.MainFrame.GetExecutionContextAsync();

await Task.WhenAll(
Page.WaitForNavigationAsync(),
executionContext.EvaluateFunctionAsync("() => window.location.reload()")
);
var ex = Assert.ThrowsAsync<EvaluationFailedException>(() =>
{
return executionContext.EvaluateFunctionAsync("() => null");
});
StringAssert.Contains("navigation", ex.Message);
}

[PuppeteerTest("evaluation.spec.ts", "Page.evaluate", "should not throw an error when evaluation does a navigation")]
[Skip(SkipAttribute.Targets.Firefox)]
public async Task ShouldNotThrowAnErrorWhenEvaluationDoesANavigation()
Expand Down
44 changes: 0 additions & 44 deletions lib/PuppeteerSharp.Tests/FrameTests/ExecutionContextTests.cs

This file was deleted.

94 changes: 42 additions & 52 deletions lib/PuppeteerSharp.Tests/HeadfulTests/HeadfulTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class HeadfulTests : PuppeteerBaseTest
{
private readonly LaunchOptions _forcedOopifOptions;

public HeadfulTests(): base()
public HeadfulTests()
{
_forcedOopifOptions = TestConstants.DefaultBrowserOptions();
_forcedOopifOptions.Headless = false;
Expand All @@ -29,9 +29,9 @@ public HeadfulTests(): base()
[Skip(SkipAttribute.Targets.Firefox)]
public async Task BackgroundPageTargetTypeShouldBeAvailable()
{
await using (var browserWithExtension = await Puppeteer.LaunchAsync(
await using var browserWithExtension = await Puppeteer.LaunchAsync(
TestConstants.BrowserWithExtensionOptions(),
TestConstants.LoggerFactory))
TestConstants.LoggerFactory);
await using (await browserWithExtension.NewPageAsync())
{
var backgroundPageTarget = await browserWithExtension.WaitForTargetAsync(t => t.Type == TargetType.BackgroundPage);
Expand All @@ -43,59 +43,51 @@ public async Task BackgroundPageTargetTypeShouldBeAvailable()
[Ignore("Marked as Fail/Pass upstream")]
public async Task TargetPageShouldReturnABackgroundPage()
{
await using (var browserWithExtension = await Puppeteer.LaunchAsync(
await using var browserWithExtension = await Puppeteer.LaunchAsync(
TestConstants.BrowserWithExtensionOptions(),
TestConstants.LoggerFactory))
{
var backgroundPageTarget = await browserWithExtension.WaitForTargetAsync(t => t.Type == TargetType.BackgroundPage);
await using (var page = await backgroundPageTarget.PageAsync())
{
Assert.AreEqual(6, await page.EvaluateFunctionAsync<int>("() => 2 * 3"));
Assert.AreEqual(42, await page.EvaluateFunctionAsync<int>("() => window.MAGIC"));
}
}
TestConstants.LoggerFactory);
var backgroundPageTarget = await browserWithExtension.WaitForTargetAsync(t => t.Type == TargetType.BackgroundPage);
await using var page = await backgroundPageTarget.PageAsync();
Assert.AreEqual(6, await page.EvaluateFunctionAsync<int>("() => 2 * 3"));
Assert.AreEqual(42, await page.EvaluateFunctionAsync<int>("() => window.MAGIC"));
}

[PuppeteerTest("headful.spec.ts", "HEADFUL", "should have default url when launching browser")]
[Skip(SkipAttribute.Targets.Firefox)]
public async Task ShouldHaveDefaultUrlWhenLaunchingBrowser()
{
await using (var browser = await Puppeteer.LaunchAsync(
await using var browser = await Puppeteer.LaunchAsync(
TestConstants.BrowserWithExtensionOptions(),
TestConstants.LoggerFactory))
{
var pages = (await browser.PagesAsync()).Select(page => page.Url).ToArray();
Assert.AreEqual(new[] { "about:blank" }, pages);
}
TestConstants.LoggerFactory);
var pages = (await browser.PagesAsync()).Select(page => page.Url).ToArray();
Assert.AreEqual(new[] { "about:blank" }, pages);
}

[PuppeteerTest("headful.spec.ts", "HEADFUL", "headless should be able to read cookies written by headful")]
[Ignore("Puppeteer ignores this in windows we do not have a platform filter yet")]
public async Task HeadlessShouldBeAbleToReadCookiesWrittenByHeadful()
{
using (var userDataDir = new TempDirectory())
using var userDataDir = new TempDirectory();
var launcher = new Launcher(TestConstants.LoggerFactory);
var options = TestConstants.DefaultBrowserOptions();
options.Args = options.Args.Concat(new[] { $"--user-data-dir=\"{userDataDir}\"" }).ToArray();
options.Headless = false;
await using (var browser = await launcher.LaunchAsync(options))
await using (var page = await browser.NewPageAsync())
{
var launcher = new Launcher(TestConstants.LoggerFactory);
var options = TestConstants.DefaultBrowserOptions();
options.Args = options.Args.Concat(new[] { $"--user-data-dir=\"{userDataDir}\"" }).ToArray();
options.Headless = false;
await using (var browser = await launcher.LaunchAsync(options))
await using (var page = await browser.NewPageAsync())
{
await page.GoToAsync(TestConstants.EmptyPage);
await page.EvaluateExpressionAsync(
"document.cookie = 'foo=true; expires=Fri, 31 Dec 9999 23:59:59 GMT'");
}
await page.GoToAsync(TestConstants.EmptyPage);
await page.EvaluateExpressionAsync(
"document.cookie = 'foo=true; expires=Fri, 31 Dec 9999 23:59:59 GMT'");
}

await TestUtils.WaitForCookieInChromiumFileAsync(userDataDir.Path, "foo");
await TestUtils.WaitForCookieInChromiumFileAsync(userDataDir.Path, "foo");

options.Headless = true;
await using (var browser2 = await Puppeteer.LaunchAsync(options, TestConstants.LoggerFactory))
{
var page2 = await browser2.NewPageAsync();
await page2.GoToAsync(TestConstants.EmptyPage);
Assert.AreEqual("foo=true", await page2.EvaluateExpressionAsync<string>("document.cookie"));
}
options.Headless = true;
await using (var browser2 = await Puppeteer.LaunchAsync(options, TestConstants.LoggerFactory))
{
var page2 = await browser2.NewPageAsync();
await page2.GoToAsync(TestConstants.EmptyPage);
Assert.AreEqual("foo=true", await page2.EvaluateExpressionAsync<string>("document.cookie"));
}
}

Expand All @@ -106,24 +98,22 @@ public async Task OOPIFShouldReportGoogleComFrame()
// https://google.com is isolated by default in Chromium embedder.
var headfulOptions = TestConstants.DefaultBrowserOptions();
headfulOptions.Headless = false;
await using (var browser = await Puppeteer.LaunchAsync(headfulOptions))
await using (var page = await browser.NewPageAsync())
{
await page.GoToAsync(TestConstants.EmptyPage);
await page.SetRequestInterceptionAsync(true);
page.Request += async (_, e) => await e.Request.RespondAsync(
new ResponseData { Body = "{ body: 'YO, GOOGLE.COM'}" });
await page.EvaluateFunctionHandleAsync(@"() => {
await using var browser = await Puppeteer.LaunchAsync(headfulOptions);
await using var page = await browser.NewPageAsync();
await page.GoToAsync(TestConstants.EmptyPage);
await page.SetRequestInterceptionAsync(true);
page.Request += async (_, e) => await e.Request.RespondAsync(
new ResponseData { Body = "{ body: 'YO, GOOGLE.COM'}" });
await page.EvaluateFunctionHandleAsync(@"() => {
const frame = document.createElement('iframe');
frame.setAttribute('src', 'https://google.com/');
document.body.appendChild(frame);
return new Promise(x => frame.onload = x);
}");
await page.WaitForSelectorAsync("iframe[src=\"https://google.com/\"]");
var urls = Array.ConvertAll(page.Frames, frame => frame.Url);
Array.Sort(urls);
Assert.AreEqual(new[] { TestConstants.EmptyPage, "https://google.com/" }, urls);
}
await page.WaitForSelectorAsync("iframe[src=\"https://google.com/\"]");
var urls = Array.ConvertAll(page.Frames, frame => frame.Url);
Array.Sort((Array)urls);
Assert.AreEqual(new[] { TestConstants.EmptyPage, "https://google.com/" }, urls);
}

[PuppeteerTest("headful.spec.ts", "HEADFUL", "OOPIF: should expose events within OOPIFs")]
Expand Down
Loading

0 comments on commit d5caa54

Please sign in to comment.