Attempt to read the logs from the browser (#26289)
* Attempt to read the logs from the browser Seleniunm currently does not return log messages (See https://github.com/SeleniumHQ/selenium/issues/8229). This making figuring out blazor WASM test failures a lot harder. This change adds some JS to the test apps to read the console output. * WIP
This commit is contained in:
parent
90f4cdad9e
commit
0e5d7ef1d4
|
|
@ -6,6 +6,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<app>Loading...</app>
|
<app>Loading...</app>
|
||||||
|
<script src="seleniumworkaround.js"></script>
|
||||||
<script src="customJsFileForTests.js"></script>
|
<script src="customJsFileForTests.js"></script>
|
||||||
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
|
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
(function () {
|
||||||
|
// Note: there are multiple copies of this file throughout the repo. If you're editing it, please look for
|
||||||
|
// other seleniumworkaround.js files and keep them all in sync.
|
||||||
|
const logs = [];
|
||||||
|
|
||||||
|
const defaultLog = console.log;
|
||||||
|
console.log = function () {
|
||||||
|
defaultLog.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultError = console.error;
|
||||||
|
console.error = function () {
|
||||||
|
defaultError.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultWarn = console.warn;
|
||||||
|
console.warn = function () {
|
||||||
|
defaultWarn.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
window.getBrowserLogs = () => logs;
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
<a href="" class="reload">Reload</a>
|
<a href="" class="reload">Reload</a>
|
||||||
<a class="dismiss">🗙</a>
|
<a class="dismiss">🗙</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="seleniumworkaround.js"></script>
|
||||||
<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
|
<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
<script src="_framework/blazor.webassembly.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
(function () {
|
||||||
|
// Note: there are multiple copies of this file throughout the repo. If you're editing it, please look for
|
||||||
|
// other seleniumworkaround.js files and keep them all in sync.
|
||||||
|
const logs = [];
|
||||||
|
|
||||||
|
const defaultLog = console.log;
|
||||||
|
console.log = function () {
|
||||||
|
defaultLog.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultError = console.error;
|
||||||
|
console.error = function () {
|
||||||
|
defaultError.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultWarn = console.warn;
|
||||||
|
console.warn = function () {
|
||||||
|
defaultWarn.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
window.getBrowserLogs = () => logs;
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
@ -62,8 +62,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
||||||
((IJavaScriptExecutor)Browser).ExecuteScript("Blazor._internal.forceCloseConnection()");
|
((IJavaScriptExecutor)Browser).ExecuteScript("Blazor._internal.forceCloseConnection()");
|
||||||
|
|
||||||
// Wait until the reconnection dialog has been shown but is now hidden
|
// Wait until the reconnection dialog has been shown but is now hidden
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(10))
|
var reconnectModel = Browser.Exists(By.Id("components-reconnect-modal"));
|
||||||
.Until(driver => driver.FindElement(By.Id("components-reconnect-modal"))?.GetCssValue("display") == "none");
|
Browser.Equal("none", () => reconnectModel.GetCssValue("display"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
||||||
var interopButton = Browser.FindElement(By.Id("btn-interop"));
|
var interopButton = Browser.FindElement(By.Id("btn-interop"));
|
||||||
interopButton.Click();
|
interopButton.Click();
|
||||||
|
|
||||||
var wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(10))
|
Browser.Exists(By.Id("done-with-interop"));
|
||||||
.Until(d => d.FindElement(By.Id("done-with-interop")));
|
|
||||||
|
|
||||||
foreach (var expectedValue in expectedValues)
|
foreach (var expectedValue in expectedValues)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,11 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using BasicTestApp;
|
|
||||||
using BasicTestApp.HttpClientTest;
|
using BasicTestApp.HttpClientTest;
|
||||||
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
|
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
|
||||||
using Microsoft.AspNetCore.E2ETesting;
|
using Microsoft.AspNetCore.E2ETesting;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using OpenQA.Selenium;
|
using OpenQA.Selenium;
|
||||||
using OpenQA.Selenium.Support.UI;
|
|
||||||
using TestServer;
|
using TestServer;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
|
@ -61,9 +59,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
_appElement.FindElement(By.Id("send-request")).Click();
|
_appElement.FindElement(By.Id("send-request")).Click();
|
||||||
|
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
_responseStatus = Browser.Exists(By.Id("response-status"));
|
||||||
driver => driver.FindElement(By.Id("response-status")) != null);
|
|
||||||
_responseStatus = _appElement.FindElement(By.Id("response-status"));
|
|
||||||
_responseStatusText = _appElement.FindElement(By.Id("response-status-text"));
|
_responseStatusText = _appElement.FindElement(By.Id("response-status-text"));
|
||||||
_testOutcome = _appElement.FindElement(By.Id("test-outcome"));
|
_testOutcome = _appElement.FindElement(By.Id("test-outcome"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,8 +148,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
private void WaitUntilLoaded()
|
private void WaitUntilLoaded()
|
||||||
{
|
{
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
var element = Browser.Exists(By.TagName("h1"));
|
||||||
driver => driver.FindElement(By.TagName("h1")).Text == "Hello, world!");
|
Browser.Equal("Hello, world!", () => element.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,10 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void WaitUntilLoaded()
|
private void WaitUntilLoaded()
|
||||||
{
|
{
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
var app = Browser.Exists(By.TagName("app"));
|
||||||
driver => driver.FindElement(By.TagName("app")).Text != "Loading...");
|
Browser.NotEqual("Loading...", () => app.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
private void WaitUntilLoaded()
|
private void WaitUntilLoaded()
|
||||||
{
|
{
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
var app = Browser.Exists(By.TagName("app"));
|
||||||
driver => driver.FindElement(By.TagName("app")).Text != "Loading...");
|
Browser.NotEqual("Loading...", () => app.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
string WaitAndGetResponseText()
|
string WaitAndGetResponseText()
|
||||||
{
|
{
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
return Browser.Exists(By.Id("response-text")).Text;
|
||||||
driver => driver.FindElement(By.Id("response-text")) != null);
|
|
||||||
return app.FindElement(By.Id("response-text")).Text;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,9 +148,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
_appElement.FindElement(By.Id("send-request")).Click();
|
_appElement.FindElement(By.Id("send-request")).Click();
|
||||||
|
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
_responseStatus = Browser.Exists(By.Id("response-status"));
|
||||||
driver => driver.FindElement(By.Id("response-status")) != null);
|
|
||||||
_responseStatus = _appElement.FindElement(By.Id("response-status"));
|
|
||||||
_responseBody = _appElement.FindElement(By.Id("response-body"));
|
_responseBody = _appElement.FindElement(By.Id("response-body"));
|
||||||
_responseHeaders = _appElement.FindElement(By.Id("response-headers"));
|
_responseHeaders = _appElement.FindElement(By.Id("response-headers"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,8 +135,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
var interopButton = Browser.FindElement(By.Id("btn-interop"));
|
var interopButton = Browser.FindElement(By.Id("btn-interop"));
|
||||||
interopButton.Click();
|
interopButton.Click();
|
||||||
|
|
||||||
var wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(10))
|
Browser.Exists(By.Id("done-with-interop"));
|
||||||
.Until(d => d.FindElement(By.Id("done-with-interop")));
|
|
||||||
|
|
||||||
foreach (var expectedValue in expectedValues)
|
foreach (var expectedValue in expectedValues)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -546,10 +546,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
SetUrlViaPushState("/LongPage1");
|
SetUrlViaPushState("/LongPage1");
|
||||||
|
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(2)).Until(
|
Browser.Exists(By.Id("loading-banner"));
|
||||||
driver => driver.FindElement(By.Id("loading-banner")) != null);
|
|
||||||
|
|
||||||
Assert.True(app.FindElement(By.Id("loading-banner")) != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
// Wait until loaded
|
// Wait until loaded
|
||||||
var tableSelector = By.CssSelector("table.table");
|
var tableSelector = By.CssSelector("table.table");
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(10)).Until(
|
Browser.Exists(tableSelector);
|
||||||
driver => driver.FindElement(tableSelector) != null);
|
|
||||||
|
|
||||||
// Check the table is displayed correctly
|
// Check the table is displayed correctly
|
||||||
var rows = Browser.FindElements(By.CssSelector("table.table tbody tr"));
|
var rows = Browser.FindElements(By.CssSelector("table.table tbody tr"));
|
||||||
|
|
@ -111,8 +110,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
|
|
||||||
private void WaitUntilLoaded()
|
private void WaitUntilLoaded()
|
||||||
{
|
{
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
var app = Browser.Exists(By.TagName("app"));
|
||||||
driver => driver.FindElement(By.TagName("app")).Text != "Loading...");
|
Browser.NotEqual("Loading...", () => app.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
|
||||||
|
|
@ -66,13 +66,10 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
{
|
{
|
||||||
// Navigate to a page with lazy loaded assemblies for the first time
|
// Navigate to a page with lazy loaded assemblies for the first time
|
||||||
SetUrlViaPushState("/WithLazyAssembly");
|
SetUrlViaPushState("/WithLazyAssembly");
|
||||||
var app = Browser.MountTestComponent<TestRouterWithLazyAssembly>();
|
Browser.MountTestComponent<TestRouterWithLazyAssembly>();
|
||||||
|
|
||||||
// Wait for the page to finish loading
|
// Wait for the page to finish loading
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(2)).Until(
|
var button = Browser.Exists(By.Id("use-package-button"));
|
||||||
driver => driver.FindElement(By.Id("use-package-button")) != null);
|
|
||||||
|
|
||||||
var button = app.FindElement(By.Id("use-package-button"));
|
|
||||||
|
|
||||||
// We should have requested the DLL
|
// We should have requested the DLL
|
||||||
Assert.True(HasLoadedAssembly("Newtonsoft.Json.dll"));
|
Assert.True(HasLoadedAssembly("Newtonsoft.Json.dll"));
|
||||||
|
|
@ -98,8 +95,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
SetUrlViaPushState("/WithLazyLoadedRoutes");
|
SetUrlViaPushState("/WithLazyLoadedRoutes");
|
||||||
|
|
||||||
// Wait for the page to finish loading
|
// Wait for the page to finish loading
|
||||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(2)).Until(
|
Browser.Exists(By.Id("lazy-load-msg"));
|
||||||
driver => driver.FindElement(By.Id("lazy-load-msg")) != null);
|
|
||||||
|
|
||||||
// Now the assembly has been loaded
|
// Now the assembly has been loaded
|
||||||
Assert.True(HasLoadedAssembly("LazyTestContentPackage.dll"));
|
Assert.True(HasLoadedAssembly("LazyTestContentPackage.dll"));
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Used for specific test cases -->
|
<!-- Used for specific test cases -->
|
||||||
|
<script src="js/seleniumworkaround.js"></script>
|
||||||
<script src="js/jsinteroptests.js"></script>
|
<script src="js/jsinteroptests.js"></script>
|
||||||
<script src="js/renderattributestest.js"></script>
|
<script src="js/renderattributestest.js"></script>
|
||||||
<script src="js/webComponentPerformingJsInterop.js"></script>
|
<script src="js/webComponentPerformingJsInterop.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
(function () {
|
||||||
|
// Note: there are multiple copies of this file throughout the repo. If you're editing it, please look for
|
||||||
|
// other seleniumworkaround.js files and keep them all in sync.
|
||||||
|
const logs = [];
|
||||||
|
|
||||||
|
const defaultLog = console.log;
|
||||||
|
console.log = function () {
|
||||||
|
defaultLog.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultError = console.error;
|
||||||
|
console.error = function () {
|
||||||
|
defaultError.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultWarn = console.warn;
|
||||||
|
console.warn = function () {
|
||||||
|
defaultWarn.apply(console, arguments);
|
||||||
|
logs.push(Array.from(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
window.getBrowserLogs = () => logs;
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
@ -14,12 +14,12 @@ namespace OpenQA.Selenium
|
||||||
// case.
|
// case.
|
||||||
public class BrowserAssertFailedException : XunitException
|
public class BrowserAssertFailedException : XunitException
|
||||||
{
|
{
|
||||||
public BrowserAssertFailedException(IReadOnlyList<LogEntry> logs, Exception innerException, string screenShotPath, string innerHTML)
|
public BrowserAssertFailedException(IReadOnlyCollection<string> logs, Exception innerException, string screenShotPath, string innerHTML)
|
||||||
: base(BuildMessage(innerException, logs, screenShotPath, innerHTML), innerException)
|
: base(BuildMessage(innerException, logs, screenShotPath, innerHTML), innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildMessage(Exception exception, IReadOnlyList<LogEntry> logs, string screenShotPath, string innerHTML)
|
private static string BuildMessage(Exception exception, IReadOnlyCollection<string> logs, string screenShotPath, string innerHTML)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
builder.AppendLine(exception.ToString());
|
builder.AppendLine(exception.ToString());
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,11 @@ using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using OpenQA.Selenium;
|
using OpenQA.Selenium;
|
||||||
|
using OpenQA.Selenium.DevTools.Page;
|
||||||
|
using OpenQA.Selenium.Interactions;
|
||||||
using OpenQA.Selenium.Support.UI;
|
using OpenQA.Selenium.Support.UI;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -117,7 +120,17 @@ namespace Microsoft.AspNetCore.E2ETesting
|
||||||
|
|
||||||
var fileId = $"{Guid.NewGuid():N}.png";
|
var fileId = $"{Guid.NewGuid():N}.png";
|
||||||
var screenShotPath = Path.Combine(Path.GetFullPath(E2ETestOptions.Instance.ScreenShotsPath), fileId);
|
var screenShotPath = Path.Combine(Path.GetFullPath(E2ETestOptions.Instance.ScreenShotsPath), fileId);
|
||||||
var errors = driver.GetBrowserLogs(LogLevel.All);
|
var errors = driver.GetBrowserLogs(LogLevel.All).Select(c => c.ToString()).ToList();
|
||||||
|
if (errors.Count == 0)
|
||||||
|
{
|
||||||
|
// Workaround for selenium bug https://github.com/SeleniumHQ/selenium/issues/8229. Getting log does
|
||||||
|
// not work. However some of our test apps provide a mechnanism to read the logs. Try that.
|
||||||
|
|
||||||
|
var logs = (IReadOnlyCollection<object>)((IJavaScriptExecutor)driver).ExecuteScript(
|
||||||
|
"return window.getBrowserLogs && window.getBrowserLogs() || []");
|
||||||
|
|
||||||
|
errors = logs.Select(l => l.ToString()).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
TakeScreenShot(driver, screenShotPath);
|
TakeScreenShot(driver, screenShotPath);
|
||||||
var exceptionInfo = lastException != null ? ExceptionDispatchInfo.Capture(lastException) :
|
var exceptionInfo = lastException != null ? ExceptionDispatchInfo.Capture(lastException) :
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue