Skip to content
Merged
8 changes: 6 additions & 2 deletions src/Components/Web.JS/src/Boot.Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ import { DotNet } from '@microsoft/dotnet-js-interop';
import { InitialRootComponentsList } from './Services/InitialRootComponentsList';
import { JSEventRegistry } from './Services/JSEventRegistry';

type BlazorServerStartOptions = Partial<CircuitStartOptions> & { circuit?: Partial<CircuitStartOptions> };

let started = false;

function boot(userOptions?: Partial<CircuitStartOptions>): Promise<void> {
function boot(userOptions?: BlazorServerStartOptions): Promise<void> {
if (started) {
throw new Error('Blazor has already started.');
}
started = true;

const configuredOptions = resolveOptions(userOptions);
// Accept the `circuit` property from the blazor.web.js options format
const normalizedOptions = userOptions?.circuit ?? userOptions;
const configuredOptions = resolveOptions(normalizedOptions);
setCircuitOptions(Promise.resolve(configuredOptions || {}));

JSEventRegistry.create(Blazor);
Expand Down
8 changes: 6 additions & 2 deletions src/Components/Web.JS/src/Boot.WebAssembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ import { InitialRootComponentsList } from './Services/InitialRootComponentsList'
import { JSEventRegistry } from './Services/JSEventRegistry';
import { printErr } from './Platform/Mono/MonoPlatform';

type BlazorWebAssemblyStartOptions = Partial<WebAssemblyStartOptions> & { webAssembly?: Partial<WebAssemblyStartOptions> };

let started = false;

async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
async function boot(options?: BlazorWebAssemblyStartOptions): Promise<void> {
if (started) {
throw new Error('Blazor has already started.');
}
started = true;

setWebAssemblyOptions(Promise.resolve(options || {}));
// Accept the `webAssembly` property from the blazor.web.js options format
const normalizedOptions = options?.webAssembly ?? options ?? {};
setWebAssemblyOptions(Promise.resolve(normalizedOptions));

JSEventRegistry.create(Blazor);
const webAssemblyComponents = discoverComponents(document, 'webassembly') as WebAssemblyComponentDescriptor[];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting;
using OpenQA.Selenium;
using TestServer;
using Xunit.Abstractions;

namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests;

/// <summary>
/// Tests that the blazor.web.js options format (with nested <c>circuit:</c> property)
/// is accepted by blazor.server.js.
/// </summary>
public class ServerNestedOptionsTest : ServerTestBase<BasicTestAppServerSiteFixture<ServerStartup>>
{
public ServerNestedOptionsTest(
BrowserFixture browserFixture,
BasicTestAppServerSiteFixture<ServerStartup> serverFixture,
ITestOutputHelper output)
: base(browserFixture, serverFixture, output)
{
}

protected override void InitializeAsyncCore()
{
// Navigate to the page that uses the nested circuit options format
Navigate($"{ServerPathBase}/nestedCircuitOptions");
}

[Fact]
public void NestedCircuitOptionsAreAccepted()
{
// Verify the page loads and the counter component works,
// which confirms the circuit options were processed correctly
var appElement = Browser.MountTestComponent<CounterComponent>();
var countDisplayElement = appElement.FindElement(By.TagName("p"));
Browser.Equal("Current count: 0", () => countDisplayElement.Text);

// Clicking button increments count
appElement.FindElement(By.TagName("button")).Click();
Browser.Equal("Current count: 1", () => countDisplayElement.Text);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting;
using OpenQA.Selenium;
using Xunit.Abstractions;

namespace Microsoft.AspNetCore.Components.E2ETest.Tests;

/// <summary>
/// Tests that the blazor.web.js options format (with nested <c>webAssembly:</c> property)
/// is accepted by blazor.webassembly.js.
/// </summary>
public class WebAssemblyNestedOptionsTest : ServerTestBase<BlazorWasmTestAppFixture<BasicTestApp.Program>>
{
public WebAssemblyNestedOptionsTest(
BrowserFixture browserFixture,
BlazorWasmTestAppFixture<Program> serverFixture,
ITestOutputHelper output)
: base(browserFixture, serverFixture, output)
{
_serverFixture.PathBase = "/subdir";
}

protected override void InitializeAsyncCore()
{
base.InitializeAsyncCore();

// Navigate to the page that uses the nested webAssembly options format
Navigate($"{ServerPathBase}/nestedWebAssemblyOptions.html");
Browser.MountTestComponent<ConfigureRuntime>();
}

[Fact]
public void NestedWebAssemblyOptionsAreAccepted()
{
// Verify that the configureRuntime option inside the nested webAssembly property works
var element = Browser.Exists(By.Id("environment"));
Browser.Equal("true", () => element.Text);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title>Basic test app - Nested WebAssembly Options</title>
<base href="/subdir/" />
<link href="style.css" rel="stylesheet" />
<link rel="icon" href="data:,">

<!-- Used by ExternalContentPackage -->
<link href="_content/TestContentPackage/styles.css" rel="stylesheet" />

<!-- App bundle that contains a reference to the scoped css bundle created by TestContentPackage -->
<link href="BasicTestApp.styles.css" rel="stylesheet" />
</head>

<body>
<root>Loading...</root>

<!-- Explicit display:none required so StartupErrorNotificationTest can observe it change -->
<div id="blazor-error-ui" style="display: none;">
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>

<!-- Used for specific test cases -->
<script src="js/circuitContextTest.js"></script>
<script src="js/jsinteroptests.js"></script>
<script src="js/renderattributestest.js"></script>
<script src="js/webComponentPerformingJsInterop.js"></script>
<script src="js/customLinkElement.js"></script>
<script src="js/jsRootComponentInitializers.js"></script>
<script src="js/customElementTests.js"></script>

<script>
// Used by ElementRefComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}

function navigationManagerNavigate() {
Blazor.navigateTo('/subdir/some-path');
}

function getCurrentUrl() {
return location.href;
}

function getRuntimeBuildConfiguration() {
return Blazor.runtime.runtimeBuildInfo.buildConfiguration;
}
</script>
<script src="_framework/blazor.webassembly.js" autostart="false"></script>

<script>
(function () {
if (location.hash.indexOf('initializer') !== -1) {
const element = document.createElement('div');
element.id = 'initializers-content';
document.body.append(element);
}

// Use the blazor.web.js options format with nested webAssembly property
Blazor.start({
webAssembly: {
configureRuntime: dotnet => {
dotnet.withEnvironmentVariable("CONFIGURE_RUNTIME", "true");
}
}
});
})();
</script>

<!-- Used by ExternalContentPackage -->
<script src="_content/TestContentPackage/prompt.js"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@page "/nestedCircuitOptions"
@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Basic test app - Nested Circuit Options</title>
<base href="~/" />
<link href="style.css" rel="stylesheet" />
<link rel="icon" href="data:,">

<!-- Used by ExternalContentPackage -->
<link href="_content/TestContentPackage/styles.css" rel="stylesheet" />
<link href="Components.TestServer.styles.css" rel="stylesheet" />
<component type="typeof(Microsoft.AspNetCore.Components.Web.HeadOutlet)" render-mode="Server" />
</head>
<body>
<root><component type="typeof(BasicTestApp.Index)" render-mode="Server" /></root>

<!-- Used for specific test cases -->
<script src="js/circuitContextTest.js"></script>
<script src="js/jsinteroptests.js"></script>
<script src="js/renderattributestest.js"></script>
<script src="js/webComponentPerformingJsInterop.js"></script>
<script src="js/customLinkElement.js"></script>
<script src="js/jsRootComponentInitializers.js"></script>

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>

<script>
// Used by ElementRefComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}

function navigationManagerNavigate() {
Blazor.navigateTo('/subdir/some-path');
}
</script>

<script>
if (location.hash.indexOf('initializer') !== -1) {
const element = document.createElement('div');
element.id = 'initializers-content';
document.body.append(element);
}
</script>

<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
// Use the blazor.web.js options format with nested circuit property
Blazor.start({
circuit: {
reconnectionOptions: {
// It's easier to test the reconnection logic if we wait a bit
// before attempting to reconnect
retryIntervalMilliseconds: Array.prototype.at.bind([5000, 5000, 5000, 10000, 30000]),
},
},
});
</script>
<script src="js/jsRootComponentInitializers.js"></script>

<!-- Used by ExternalContentPackage -->
<script src="_content/TestContentPackage/prompt.js"></script>
<script>
console.log('Blazor server-side with nested circuit options');
</script>
</body>
</html>
Loading