Low-level MonoSanity tests for invoking JS from .NET code

This commit is contained in:
Steve Sanderson 2017-12-15 10:57:44 +00:00
parent 4135f04901
commit 6eede7b109
4 changed files with 79 additions and 5 deletions

View File

@ -28,7 +28,7 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>Trigger exception</legend> <legend>Trigger .NET exception</legend>
<form id="triggerException"> <form id="triggerException">
<input id="triggerExceptionMessage" value="Your message here" /> <input id="triggerExceptionMessage" value="Your message here" />
<button type="submit" disabled>Go</button> <button type="submit" disabled>Go</button>
@ -36,6 +36,15 @@
</form> </form>
</fieldset> </fieldset>
<fieldset>
<legend>Call JS from .NET</legend>
<form id="callJs">
<input id="callJsEvalExpression" value="location.href" />
<button type="submit" disabled>Go</button>
<div><textarea rows="5" cols="80" readonly id="callJsResult"></textarea></div>
</form>
</fieldset>
<p id="loadingIndicator">Loading...</p> <p id="loadingIndicator">Loading...</p>
<script src="loader.js"></script> <script src="loader.js"></script>
@ -54,7 +63,7 @@
var b = parseInt(el('addNumberB').value); var b = parseInt(el('addNumberB').value);
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'AddNumbers', [a, b]); var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'AddNumbers', [a, b]);
el('addNumbersResult').value = result; el('addNumbersResult').value = result;
} };
el('repeatString').onsubmit = function (evt) { el('repeatString').onsubmit = function (evt) {
evt.preventDefault(); evt.preventDefault();
@ -62,7 +71,7 @@
var count = parseInt(el('repeatStringCount').value); var count = parseInt(el('repeatStringCount').value);
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'RepeatString', [str, count]); var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'RepeatString', [str, count]);
el('repeatStringResult').value = result; el('repeatStringResult').value = result;
} };
el('triggerException').onsubmit = function (evt) { el('triggerException').onsubmit = function (evt) {
evt.preventDefault(); evt.preventDefault();
@ -73,11 +82,28 @@
} catch (ex) { } catch (ex) {
el('triggerExceptionMessageStackTrace').value = ex.toString(); el('triggerExceptionMessageStackTrace').value = ex.toString();
} }
} };
el('callJs').onsubmit = function (evt) {
evt.preventDefault();
var expression = el('callJsEvalExpression').value;
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'EvaluateJavaScript', [expression]);
el('callJsResult').value = result;
};
function el(id) { function el(id) {
return document.getElementById(id); return document.getElementById(id);
} }
// Examples of functions we can invoke from .NET
function getUserAgentString() {
return navigator.userAgent;
}
function triggerJsException() {
throw new Error('This is a JavaScript exception.');
}
</script> </script>
</body> </body>
</html> </html>

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Text; using System.Text;
using WebAssembly;
namespace MonoSanityClient namespace MonoSanityClient
{ {
@ -27,5 +28,16 @@ namespace MonoSanityClient
{ {
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
public static string EvaluateJavaScript(string expression)
{
var result = Runtime.InvokeJS(expression, out var resultIsException);
if (resultIsException != 0)
{
return $".NET got exception: {result}";
}
return $".NET received: {result}";
}
} }
} }

View File

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Runtime.CompilerServices;
namespace WebAssembly
{
internal static class Runtime
{
// The exact namespace, type, and method name must match the corresponding entry in
// driver.c in the Mono distribution
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern string InvokeJS(string str, out int resultIsException);
}
}

View File

@ -4,6 +4,7 @@
using Microsoft.Blazor.E2ETest.Infrastructure; using Microsoft.Blazor.E2ETest.Infrastructure;
using Microsoft.Blazor.E2ETest.Infrastructure.ServerFixtures; using Microsoft.Blazor.E2ETest.Infrastructure.ServerFixtures;
using OpenQA.Selenium; using OpenQA.Selenium;
using System;
using Xunit; using Xunit;
namespace Microsoft.Blazor.E2ETest.Tests namespace Microsoft.Blazor.E2ETest.Tests
@ -48,7 +49,7 @@ namespace Microsoft.Blazor.E2ETest.Tests
} }
[Fact] [Fact]
public void CanTriggerException() public void CanReceiveDotNetExceptionInJavaScript()
{ {
Navigate("/", noReload: true); Navigate("/", noReload: true);
@ -58,6 +59,26 @@ namespace Microsoft.Blazor.E2ETest.Tests
Assert.Contains("Hello from test", GetValue(Browser, "triggerExceptionMessageStackTrace")); Assert.Contains("Hello from test", GetValue(Browser, "triggerExceptionMessageStackTrace"));
} }
[Fact]
public void CanCallJavaScriptFromDotNet()
{
Navigate("/", noReload: true);
SetValue(Browser, "callJsEvalExpression", "getUserAgentString()");
Browser.FindElement(By.CssSelector("#callJs button")).Click();
var result = GetValue(Browser, "callJsResult");
Assert.StartsWith(".NET received: Mozilla", result);
}
[Fact]
public void CanReceiveJavaScriptExceptionInDotNet()
{
Navigate("/", noReload: true);
SetValue(Browser, "callJsEvalExpression", "triggerJsException()");
Browser.FindElement(By.CssSelector("#callJs button")).Click();
var result = GetValue(Browser, "callJsResult");
Assert.StartsWith(".NET got exception: Error: This is a JavaScript exception.", result);
}
private static string GetValue(IWebDriver webDriver, string elementId) private static string GetValue(IWebDriver webDriver, string elementId)
{ {
var element = webDriver.FindElement(By.Id(elementId)); var element = webDriver.FindElement(By.Id(elementId));