From 6eede7b109c1428e2c492998fa0534cfc748d3cb Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 15 Dec 2017 10:57:44 +0000 Subject: [PATCH] Low-level MonoSanity tests for invoking JS from .NET code --- samples/MonoSanity/wwwroot/index.html | 34 ++++++++++++++++--- samples/MonoSanityClient/Examples.cs | 12 +++++++ .../MonoSanityClient/WebAssembly.Runtime.cs | 15 ++++++++ .../Tests/MonoSanityTest.cs | 23 ++++++++++++- 4 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 samples/MonoSanityClient/WebAssembly.Runtime.cs diff --git a/samples/MonoSanity/wwwroot/index.html b/samples/MonoSanity/wwwroot/index.html index 52ee7448df..003d37c2fa 100644 --- a/samples/MonoSanity/wwwroot/index.html +++ b/samples/MonoSanity/wwwroot/index.html @@ -28,7 +28,7 @@
- Trigger exception + Trigger .NET exception
@@ -36,6 +36,15 @@
+
+ Call JS from .NET +
+ + +
+
+
+

Loading...

@@ -54,7 +63,7 @@ var b = parseInt(el('addNumberB').value); var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'AddNumbers', [a, b]); el('addNumbersResult').value = result; - } + }; el('repeatString').onsubmit = function (evt) { evt.preventDefault(); @@ -62,7 +71,7 @@ var count = parseInt(el('repeatStringCount').value); var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'RepeatString', [str, count]); el('repeatStringResult').value = result; - } + }; el('triggerException').onsubmit = function (evt) { evt.preventDefault(); @@ -73,11 +82,28 @@ } catch (ex) { 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) { 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.'); + } diff --git a/samples/MonoSanityClient/Examples.cs b/samples/MonoSanityClient/Examples.cs index 24be61d54e..a9d99b9d02 100644 --- a/samples/MonoSanityClient/Examples.cs +++ b/samples/MonoSanityClient/Examples.cs @@ -3,6 +3,7 @@ using System; using System.Text; +using WebAssembly; namespace MonoSanityClient { @@ -27,5 +28,16 @@ namespace MonoSanityClient { 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}"; + } } } diff --git a/samples/MonoSanityClient/WebAssembly.Runtime.cs b/samples/MonoSanityClient/WebAssembly.Runtime.cs new file mode 100644 index 0000000000..bc461b992b --- /dev/null +++ b/samples/MonoSanityClient/WebAssembly.Runtime.cs @@ -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); + } +} diff --git a/test/Microsoft.Blazor.E2ETest/Tests/MonoSanityTest.cs b/test/Microsoft.Blazor.E2ETest/Tests/MonoSanityTest.cs index 49d2a04e0b..f3b47d231f 100644 --- a/test/Microsoft.Blazor.E2ETest/Tests/MonoSanityTest.cs +++ b/test/Microsoft.Blazor.E2ETest/Tests/MonoSanityTest.cs @@ -4,6 +4,7 @@ using Microsoft.Blazor.E2ETest.Infrastructure; using Microsoft.Blazor.E2ETest.Infrastructure.ServerFixtures; using OpenQA.Selenium; +using System; using Xunit; namespace Microsoft.Blazor.E2ETest.Tests @@ -48,7 +49,7 @@ namespace Microsoft.Blazor.E2ETest.Tests } [Fact] - public void CanTriggerException() + public void CanReceiveDotNetExceptionInJavaScript() { Navigate("/", noReload: true); @@ -58,6 +59,26 @@ namespace Microsoft.Blazor.E2ETest.Tests 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) { var element = webDriver.FindElement(By.Id(elementId));