2018-09-10 02:41:13 +02:00
|
|
|
// Copyright © 2017 The CefSharp Authors. All rights reserved.
|
2017-10-24 12:21:04 +10:00
|
|
|
//
|
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
using System;
|
2022-05-30 19:11:17 +10:00
|
|
|
using System.Reflection;
|
2017-10-24 12:21:04 +10:00
|
|
|
using System.Threading.Tasks;
|
2022-01-27 15:58:00 +10:00
|
|
|
using CefSharp.OffScreen;
|
2023-02-15 13:45:07 +10:00
|
|
|
using Xunit;
|
2017-10-24 12:21:04 +10:00
|
|
|
|
|
|
|
|
namespace CefSharp.Test
|
|
|
|
|
{
|
2018-09-10 02:41:13 +02:00
|
|
|
public static class WebBrowserTestExtensions
|
|
|
|
|
{
|
2023-02-15 13:45:07 +10:00
|
|
|
public static async Task<T> EvaluateScriptAndAssertAsync<T>(this IChromiumWebBrowserBase browser, string script)
|
|
|
|
|
{
|
|
|
|
|
var response = await browser.EvaluateScriptAsync(script).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
Assert.True(response.Success, response.Message);
|
|
|
|
|
|
|
|
|
|
return (T)response.Result;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-30 19:11:17 +10:00
|
|
|
public static int PaintEventHandlerCount(this CefSharp.Wpf.ChromiumWebBrowser browser)
|
|
|
|
|
{
|
|
|
|
|
var field = typeof(CefSharp.Wpf.ChromiumWebBrowser).GetField("Paint", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
|
|
|
|
|
|
|
if(field == null)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Unable to obtain Paint event handler");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var handler = field.GetValue(browser) as Delegate;
|
|
|
|
|
|
|
|
|
|
if (handler == null)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var subscribers = handler.GetInvocationList();
|
|
|
|
|
|
|
|
|
|
return subscribers.Length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int PaintEventHandlerCount(this ChromiumWebBrowser browser)
|
|
|
|
|
{
|
|
|
|
|
var field = typeof(ChromiumWebBrowser).GetField("Paint", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
|
|
|
|
|
|
|
if (field == null)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Unable to obtain Paint event handler");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var handler = field.GetValue(browser) as Delegate;
|
|
|
|
|
|
|
|
|
|
if (handler == null)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var subscribers = handler.GetInvocationList();
|
|
|
|
|
|
|
|
|
|
return subscribers.Length;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 09:32:32 +10:00
|
|
|
public static Task<LoadUrlAsyncResponse> LoadRequestAsync(this IWebBrowser browser, IRequest request)
|
2021-01-15 13:39:34 +10:00
|
|
|
{
|
|
|
|
|
if(request == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("request");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//If using .Net 4.6 then use TaskCreationOptions.RunContinuationsAsynchronously
|
|
|
|
|
//and switch to tcs.TrySetResult below - no need for the custom extension method
|
2021-06-05 09:32:32 +10:00
|
|
|
var tcs = new TaskCompletionSource<LoadUrlAsyncResponse>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
|
|
|
|
|
|
|
|
EventHandler<LoadErrorEventArgs> loadErrorHandler = null;
|
|
|
|
|
EventHandler<LoadingStateChangedEventArgs> loadingStateChangeHandler = null;
|
2021-01-15 13:39:34 +10:00
|
|
|
|
2021-06-05 09:32:32 +10:00
|
|
|
loadErrorHandler = (sender, args) =>
|
|
|
|
|
{
|
|
|
|
|
//Ignore Aborted
|
|
|
|
|
//Currently invalid SSL certificates which aren't explicitly allowed
|
|
|
|
|
//end up with CefErrorCode.Aborted, I've created the following PR
|
|
|
|
|
//in the hopes of getting this fixed.
|
|
|
|
|
//https://bitbucket.org/chromiumembedded/cef/pull-requests/373
|
|
|
|
|
if (args.ErrorCode == CefErrorCode.Aborted)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//If LoadError was called then we'll remove both our handlers
|
|
|
|
|
//as we won't need to capture LoadingStateChanged, we know there
|
|
|
|
|
//was an error
|
|
|
|
|
browser.LoadError -= loadErrorHandler;
|
|
|
|
|
browser.LoadingStateChanged -= loadingStateChangeHandler;
|
|
|
|
|
|
|
|
|
|
tcs.TrySetResult(new LoadUrlAsyncResponse(args.ErrorCode, -1));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
loadingStateChangeHandler = (sender, args) =>
|
2021-01-15 13:39:34 +10:00
|
|
|
{
|
|
|
|
|
//Wait for while page to finish loading not just the first frame
|
|
|
|
|
if (!args.IsLoading)
|
|
|
|
|
{
|
2021-06-05 09:32:32 +10:00
|
|
|
var host = args.Browser.GetHost();
|
|
|
|
|
|
|
|
|
|
var navEntry = host?.GetVisibleNavigationEntry();
|
|
|
|
|
|
|
|
|
|
int statusCode = navEntry?.HttpStatusCode ?? -1;
|
|
|
|
|
|
|
|
|
|
//By default 0 is some sort of error, we map that to -1
|
|
|
|
|
//so that it's clearer that something failed.
|
|
|
|
|
if (statusCode == 0)
|
|
|
|
|
{
|
|
|
|
|
statusCode = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
browser.LoadingStateChanged -= loadingStateChangeHandler;
|
2021-01-15 13:39:34 +10:00
|
|
|
//This is required when using a standard TaskCompletionSource
|
|
|
|
|
//Extension method found in the CefSharp.Internals namespace
|
2021-06-05 09:32:32 +10:00
|
|
|
tcs.TrySetResult(new LoadUrlAsyncResponse(CefErrorCode.None, statusCode));
|
2021-01-15 13:39:34 +10:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2021-06-05 09:32:32 +10:00
|
|
|
browser.LoadingStateChanged += loadingStateChangeHandler;
|
2021-01-15 13:39:34 +10:00
|
|
|
|
|
|
|
|
browser.GetMainFrame().LoadRequest(request);
|
|
|
|
|
|
|
|
|
|
return tcs.Task;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-27 15:58:00 +10:00
|
|
|
public static Task<QUnitTestResult> CreateBrowserAndWaitForQUnitTestExeuctionToComplete(this ChromiumWebBrowser browser)
|
2020-05-19 21:55:16 +10:00
|
|
|
{
|
|
|
|
|
//If using .Net 4.6 then use TaskCreationOptions.RunContinuationsAsynchronously
|
|
|
|
|
//and switch to tcs.TrySetResult below - no need for the custom extension method
|
2021-10-14 13:00:08 +10:00
|
|
|
var tcs = new TaskCompletionSource<QUnitTestResult>(TaskCreationOptions.RunContinuationsAsynchronously);
|
2020-05-19 21:55:16 +10:00
|
|
|
|
|
|
|
|
EventHandler<JavascriptMessageReceivedEventArgs> handler = null;
|
|
|
|
|
handler = (sender, args) =>
|
|
|
|
|
{
|
|
|
|
|
dynamic msg = args.Message;
|
|
|
|
|
//Wait for while page to finish loading not just the first frame
|
|
|
|
|
if (msg.Type == "QUnitExecutionComplete")
|
|
|
|
|
{
|
2021-10-21 13:36:50 +10:00
|
|
|
browser.JavascriptMessageReceived -= handler;
|
|
|
|
|
|
2020-05-19 21:55:16 +10:00
|
|
|
var details = msg.Details;
|
|
|
|
|
var total = (int)details.total;
|
|
|
|
|
var passed = (int)details.passed;
|
|
|
|
|
|
2021-10-14 19:37:15 +10:00
|
|
|
tcs.TrySetResult(new QUnitTestResult { Passed = passed, Total = total });
|
2020-05-19 21:55:16 +10:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
browser.JavascriptMessageReceived += handler;
|
|
|
|
|
|
2022-01-27 15:58:00 +10:00
|
|
|
browser.CreateBrowser();
|
|
|
|
|
|
2020-05-19 21:55:16 +10:00
|
|
|
return tcs.Task;
|
|
|
|
|
}
|
2018-09-10 02:41:13 +02:00
|
|
|
}
|
2017-10-24 12:21:04 +10:00
|
|
|
}
|