Skip to content

Account for Layout ordering in Blazor #15001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 15, 2019
Merged
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 @@ -3,7 +3,7 @@
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
"Microsoft": "Debug"
}
}
}
2 changes: 1 addition & 1 deletion src/Components/Web.JS/dist/Release/blazor.server.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function discoverComponents(document: Document): ComponentDescriptor[] {
discoveredComponents.push(entry);
}

return discoveredComponents;
return discoveredComponents.sort((a, b) => a.sequence - b.sequence);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
{
public class MultipleComponentsTest : ServerTestBase<BasicTestAppServerSiteFixture<PrerenderedStartup>>
public class MultipleComponentsTest : ServerTestBase<BasicTestAppServerSiteFixture<MultipleComponents>>
{
private const string MarkerPattern = ".*?<!--Blazor:(.*?)-->.*?";

public MultipleComponentsTest(
BrowserFixture browserFixture,
BasicTestAppServerSiteFixture<PrerenderedStartup> serverFixture,
BasicTestAppServerSiteFixture<MultipleComponents> serverFixture,
ITestOutputHelper output)
: base(browserFixture, serverFixture, output)
{
Expand All @@ -46,7 +46,7 @@ public override async Task InitializeAsync()
[Fact]
public void DoesNotStartMultipleConnections()
{
Navigate("/prerendered/multiple-components");
Navigate("/multiple-components");

BeginInteractivity();
Browser.Exists(By.CssSelector("h3.interactive"));
Expand All @@ -60,17 +60,18 @@ public void DoesNotStartMultipleConnections()
});
}


[Fact]
public void CanRenderMultipleRootComponents()
{
Navigate("/prerendered/multiple-components");
Navigate("/multiple-components");

var greets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray();

Assert.Equal(5, greets.Length); // 1 statically rendered + 3 prerendered + 1 server prerendered
Assert.Equal(7, greets.Length); // 1 statically rendered + 5 prerendered + 1 server prerendered
Assert.DoesNotContain("Hello Red fish", greets);
Assert.Single(greets, "Hello John");
Assert.Single(greets, "Hello Abraham");
Assert.Equal(2, greets.Where(g => g == "Hello Blue fish").Count());
Assert.Equal(3, greets.Where(g => string.Equals("Hello", g)).Count()); // 3 server prerendered without parameters
var content = Browser.FindElement(By.Id("test-container")).GetAttribute("innerHTML");
var markers = ReadMarkers(content);
Expand All @@ -86,7 +87,11 @@ public void CanRenderMultipleRootComponents()
false,
true,
false,
true
true,
false,
true,
false,
true,
};
Assert.Equal(expectedComponentSequence, componentSequence);

Expand All @@ -96,6 +101,8 @@ public void CanRenderMultipleRootComponents()
Browser.Exists(By.CssSelector("h3.interactive"));
var updatedGreets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray();
Assert.Equal(7, updatedGreets.Where(g => string.Equals("Hello Alfred", g)).Count());
Assert.Equal(2, updatedGreets.Where(g => g == "Hello Red fish").Count());
Assert.Equal(2, updatedGreets.Where(g => g == "Hello Blue fish").Count());
Assert.Single(updatedGreets.Where(g => string.Equals("Hello Albert", g)));
Assert.Single(updatedGreets.Where(g => string.Equals("Hello Abraham", g)));
}
Expand Down
51 changes: 51 additions & 0 deletions src/Components/test/testassets/TestServer/MultipleComponents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace TestServer
{
public class MultipleComponents
{
public MultipleComponents(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddServerSideBlazor();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.Map("/multiple-components", app =>
{
app.UseStaticFiles();

app.UseAuthentication();

app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapFallbackToPage("/MultipleComponents");
endpoints.MapBlazorHub();
});
});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,59 +1,29 @@
@page "/multiple-components"
@using BasicTestApp.MultipleComponents;
<!DOCTYPE html>
<html>
<head>
<title>Multiple component entry points</title>
<base href="~/" />
@* This page is used to validate the ability to render multiple root components in a blazor server-side application.
*@
</head>
<body>
<div id="test-container">
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.ServerPrerendered))
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server))
<component type="typeof(GreeterComponent)" render-mode="Static" param-name='"John"' />
<component type="typeof(GreeterComponent)" render-mode="Server"/>
<div id="container">
<p>Some content before</p>
<component type="typeof(GreeterComponent)" render-mode="Server"/>
<p>Some content between</p>
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered"/>
<p>Some content after</p>
<div id="nested-an-extra-level">
<p>Some content before</p>
<component type="typeof(GreeterComponent)" render-mode="Server"/>
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered"/>
<p>Some content after</p>
</div>
</div>
<div id="container">
<component type="typeof(GreeterComponent)" render-mode="Server" param-name='"Albert"' />
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" param-name='"Abraham"' />
</div>
</div>

@*
So that E2E tests can make assertions about both the prerendered and
interactive states, we only load the .js file when told to.
*@
<hr />

<button id="load-boot-script" onclick="start()">Load boot script</button>
@{
Layout = "./MultipleComponentsLayout.cshtml";
}

<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
// Used by InteropOnInitializationComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}

function start() {
Blazor.start({
logLevel: 1 // LogLevel.Debug
});
}
</script>
</body>
</html>
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.ServerPrerendered))
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server))
<component type="typeof(GreeterComponent)" render-mode="Static" param-name='"John"' />
<component type="typeof(GreeterComponent)" render-mode="Server" />
<div id="container">
<p>Some content before</p>
<component type="typeof(GreeterComponent)" render-mode="Server" />
<p>Some content between</p>
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" />
<p>Some content after</p>
<div id="nested-an-extra-level">
<p>Some content before</p>
<component type="typeof(GreeterComponent)" render-mode="Server" />
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" />
<p>Some content after</p>
</div>
</div>
<div id="container">
<component type="typeof(GreeterComponent)" render-mode="Server" param-name='"Albert"' />
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" param-name='"Abraham"' />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
@using BasicTestApp.MultipleComponents;

<!DOCTYPE html>
<html>
<head>
<title>Multiple component entry points</title>
<base href="~/" />
@* This page is used to validate the ability to render multiple root components in a blazor server-side application.
*@
</head>
<body>
<div id="test-container">
<component type="typeof(GreeterComponent)" render-mode="Server" param-name='"Red fish"' />
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" param-name='"Blue fish"' />
@RenderBody()
<component type="typeof(GreeterComponent)" render-mode="Server" param-name='"Red fish"' />
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" param-name='"Blue fish"' />
</div>

@*
So that E2E tests can make assertions about both the prerendered and
interactive states, we only load the .js file when told to.
*@
<hr />

<button id="load-boot-script" onclick="start()">Load boot script</button>

<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
// Used by InteropOnInitializationComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}

function start() {
Blazor.start({
logLevel: 1 // LogLevel.Debug
});
}
</script>
</body>
</html>
6 changes: 1 addition & 5 deletions src/Components/test/testassets/TestServer/Program.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
Expand All @@ -28,6 +23,7 @@ public static void Main(string[] args)
["Server authentication"] = (BuildWebHost<ServerAuthenticationStartup>(CreateAdditionalArgs(args)), "/subdir"),
["CORS (WASM)"] = (BuildWebHost<CorsStartup>(CreateAdditionalArgs(args)), "/subdir"),
["Prerendering (Server-side)"] = (BuildWebHost<PrerenderedStartup>(CreateAdditionalArgs(args)), "/prerendered"),
["Multiple components (Server-side)"] = (BuildWebHost<MultipleComponents>(CreateAdditionalArgs(args)), "/multiple-components"),
["Globalization + Localization (Server-side)"] = (BuildWebHost<InternationalizationStartup>(CreateAdditionalArgs(args)), "/subdir"),
["Server-side blazor"] = (BuildWebHost<ServerStartup>(CreateAdditionalArgs(args)), "/subdir"),
["Hosted client-side blazor"] = (BuildWebHost<ClientStartup>(CreateAdditionalArgs(args)), "/subdir"),
Expand Down