Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
using Microsoft.Extensions.DependencyInjection;
using PhotinoNET;

namespace Microsoft.AspNetCore.Components.WebViewE2E.Test;

public class BasicBlazorHybridTest
public class BasicTest : IExecutionMode
{
private string _latestControlDivValue;
const int MaxWaitTimes = 60;
const int WaitTimeInMS = 250;

public void Run()
{
// Note: This test produces *a lot* of debug output to aid when debugging failures. The only output
// that is necessary for the functioning of this test is the "Test passed" at the end of this method.

Console.WriteLine($"Current directory: {Environment.CurrentDirectory}");
Console.WriteLine($"Current assembly: {typeof(Program).Assembly.Location}");
var thisProgramDir = Path.GetDirectoryName(typeof(Program).Assembly.Location);
Console.WriteLine($"Current assembly: {typeof(BasicTest).Assembly.Location}");
var thisProgramDir = Path.GetDirectoryName(typeof(BasicTest).Assembly.Location);

// Add correct runtime sub-folder to PATH to ensure native files are discovered (this is supposed to happen automatically, but somehow it doesn't...)
var newNativePath = Path.Combine(thisProgramDir, "runtimes", RuntimeInformation.RuntimeIdentifier, "native");
Expand Down Expand Up @@ -66,7 +66,7 @@ public void Run()
};

Console.WriteLine($"Setting up root components...");
mainWindow.RootComponents.Add<Pages.TestPage>("root");
mainWindow.RootComponents.Add<PhotinoTestApp.Pages.TestPage>("root");

Console.WriteLine($"Running window...");

Expand All @@ -82,6 +82,10 @@ public void Run()
{
isWebViewReady = true;
}
else if (msg.StartsWith("wvt:ConsoleLog:", StringComparison.Ordinal))
{
Console.WriteLine($"[WebView JS] {msg.Substring("wvt:ConsoleLog:".Length)}");
}
else if (msg.StartsWith(NewControlDivValueMessage, StringComparison.Ordinal))
{
_latestControlDivValue = msg.Substring(NewControlDivValueMessage.Length + 1);
Expand All @@ -100,7 +104,7 @@ public void Run()

// 1. Wait for WebView ready
Console.WriteLine($"Waiting for WebView ready...");
var isWebViewReadyRetriesLeft = 20;
var isWebViewReadyRetriesLeft = 40;
while (!isWebViewReady)
{
Console.WriteLine($"WebView not ready yet, waiting 1sec...");
Expand Down Expand Up @@ -161,10 +165,7 @@ public void Run()
Console.WriteLine($"Test passed? {testPassed}");
}

const int MaxWaitTimes = 30;
const int WaitTimeInMS = 250;

public async Task<bool> WaitForControlDiv(PhotinoWindow photinoWindow, string controlValueToWaitFor)
private async Task<bool> WaitForControlDiv(PhotinoWindow photinoWindow, string controlValueToWaitFor)
{

for (var i = 0; i < MaxWaitTimes; i++)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

public interface IExecutionMode
{
void Run();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net.Http;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebView.Photino;
using Microsoft.Extensions.DependencyInjection;

public class LaunchSample : IExecutionMode
{
public void Run()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddBlazorWebView();
serviceCollection.AddSingleton<HttpClient>();

var mainWindow = new BlazorWindow(
title: "Hello, world!",
hostPage: "wwwroot/webviewhost.html",
services: serviceCollection.BuildServiceProvider(),
pathBase: "/subdir"); // The content in BasicTestApp assumes this

AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
Console.Write(
"Fatal exception" + Environment.NewLine +
error.ExceptionObject.ToString() + Environment.NewLine);
};

mainWindow.RootComponents.Add<BasicTestApp.Index>("root");
mainWindow.RootComponents.RegisterForJavaScript<BasicTestApp.DynamicallyAddedRootComponent>("my-dynamic-root-component");
mainWindow.RootComponents.RegisterForJavaScript<BasicTestApp.JavaScriptRootComponentParameterTypes>(
"component-with-many-parameters",
javaScriptInitializer: "myJsRootComponentInitializers.testInitializer");

mainWindow.Run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<OutputType>Exe</OutputType>
<IsShippingPackage>false</IsShippingPackage>
<SignAssembly>false</SignAssembly>
<_WebViewAssetsBasePath>..\..\..\..\..\Web.JS\dist\Release\</_WebViewAssetsBasePath>
<_WebViewAssetsBasePath>..\..\..\..\..\Web.JS\dist\$(Configuration)\</_WebViewAssetsBasePath>
<_BlazorModulesFilePath>..\..\..\..\WebView\src\blazor.modules.json</_BlazorModulesFilePath>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net.Http;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebView.Photino;
using Microsoft.Extensions.DependencyInjection;

namespace PhotinoTestApp;

class Program
{
[STAThread]
static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddBlazorWebView();
serviceCollection.AddSingleton<HttpClient>();

var mainWindow = new BlazorWindow(
title: "Hello, world!",
hostPage: "wwwroot/webviewhost.html",
services: serviceCollection.BuildServiceProvider(),
pathBase: "/subdir"); // The content in BasicTestApp assumes this

AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
if (args.Length < 1)
{
Console.Write(
"Fatal exception" + Environment.NewLine +
error.ExceptionObject.ToString() + Environment.NewLine);
};

mainWindow.RootComponents.Add<BasicTestApp.Index>("root");
mainWindow.RootComponents.RegisterForJavaScript<BasicTestApp.DynamicallyAddedRootComponent>("my-dynamic-root-component");
mainWindow.RootComponents.RegisterForJavaScript<BasicTestApp.JavaScriptRootComponentParameterTypes>(
"component-with-many-parameters",
javaScriptInitializer: "myJsRootComponentInitializers.testInitializer");

mainWindow.Run();
var sample = new LaunchSample();
sample.Run();
return;
}
var testScenario = args[0];
if (testScenario == "--basic-test")
{
var basic = new BasicTest();
basic.Run();
}
else
{
throw new ArgumentException($"Scenario {testScenario} is unknown.", nameof(args));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@
</script>
</body>

</html>
</html>
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>
<!-- Suppress CS8002 because Photino assemblies are not signed -->
<NoWarn>@(NoWarn);CS8002</NoWarn>
<!-- See code comment in Program.cs/Main in this project regarding this -->
<StartupObject>Microsoft.AspNetCore.Components.WebViewE2E.Test.Program</StartupObject>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Samples\PhotinoPlatform\src\Microsoft.AspNetCore.Components.WebView.Photino.csproj" />
<!-- Add project reference to ensure PhotinoTestApp is built and copied to our output directory -->
<ProjectReference Include="..\..\Samples\PhotinoPlatform\testassets\PhotinoTestApp\PhotinoTestApp.csproj" />
</ItemGroup>

<ItemGroup>
<Content Update="wwwroot\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\Samples\PhotinoPlatform\testassets\PhotinoTestApp\wwwroot\**" CopyToOutputDirectory="PreserveNewest" LinkBase="wwwroot/" />
</ItemGroup>

</Project>
30 changes: 0 additions & 30 deletions src/Components/WebView/test/E2ETest/Program.cs

This file was deleted.

56 changes: 42 additions & 14 deletions src/Components/WebView/test/E2ETest/WebViewManagerE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Diagnostics;
using Microsoft.AspNetCore.InternalTesting;
using Xunit.Abstractions;

namespace Microsoft.AspNetCore.Components.WebViewE2E.Test;

Expand All @@ -18,32 +19,59 @@ public class WebViewManagerE2ETests
[ConditionalFact]
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX,
SkipReason = "On Helix/Ubuntu the native Photino assemblies can't be found, and on macOS it can't detect when the WebView is ready")]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/50802")]
public async Task CanLaunchPhotinoWebViewAndClickButton()
{
var photinoTestProgramExePath = typeof(WebViewManagerE2ETests).Assembly.Location;
// With the project reference, PhotinoTestApp.dll should be copied to the same directory as this test assembly
var testAssemblyDirectory = Path.GetDirectoryName(typeof(WebViewManagerE2ETests).Assembly.Location)!;
var photinoTestAppPath = Path.Combine(testAssemblyDirectory, "PhotinoTestApp.dll");

// This test launches this very test assembly as an executable so that the Photino UI window
// can launch and be automated. See the comment in Program.Main() for more info.
if (!File.Exists(photinoTestAppPath))
{
throw new FileNotFoundException($"Could not find PhotinoTestApp.dll at: {photinoTestAppPath}. " +
"Ensure the PhotinoTestApp project reference is properly configured.");
}

// This test launches the PhotinoTestApp sample as an executable so that the Photino UI window
// can launch and be automated.
var photinoProcess = new Process()
{
StartInfo = new ProcessStartInfo
{
WorkingDirectory = Path.GetDirectoryName(photinoTestProgramExePath),
FileName = "dotnet",
Arguments = $"\"{photinoTestProgramExePath}\"",
RedirectStandardOutput = true,
},
StartInfo = new ProcessStartInfo
{
WorkingDirectory = Path.GetDirectoryName(photinoTestAppPath),
FileName = "dotnet",
Arguments = $"\"{photinoTestAppPath}\" --basic-test",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
},
};

photinoProcess.Start();

var testProgramOutput = photinoProcess.StandardOutput.ReadToEnd();
var testProgramError = photinoProcess.StandardError.ReadToEnd();

await photinoProcess.WaitForExitAsync().TimeoutAfter(TimeSpan.FromSeconds(30));

// The test app reports its own results by calling Console.WriteLine(), so here we only need to verify that
// the test internally believes it passed (and we trust it!).
Assert.Contains($"Test passed? {true}", testProgramOutput);
// Use Assert.True with a custom message to include the full output in the failure message
var expectedMessage = $"Test passed? {true}";
var testPassed = testProgramOutput.Contains(expectedMessage);

if (!testPassed)
{
var errorInfo = $"Process exit code: {photinoProcess.ExitCode}\n" +
$"Working directory: {photinoProcess.StartInfo.WorkingDirectory}\n" +
$"Command: {photinoProcess.StartInfo.FileName} {photinoProcess.StartInfo.Arguments}\n" +
$"PhotinoTestApp path: {photinoTestAppPath}\n\n" +
$"=== Full Standard Output ===\n{testProgramOutput}\n" +
$"=== End of Standard Output ===\n";

if (!string.IsNullOrEmpty(testProgramError))
{
errorInfo += $"\n=== Standard Error ===\n{testProgramError}\n=== End of Standard Error ===";
}

Assert.True(testPassed, $"Expected to find '{expectedMessage}' in PhotinoTestApp output.\n\n{errorInfo}");
}
}
}
7 changes: 0 additions & 7 deletions src/Components/WebView/test/E2ETest/_Imports.razor

This file was deleted.

23 changes: 0 additions & 23 deletions src/Components/WebView/test/E2ETest/wwwroot/css/app.css

This file was deleted.

Loading