Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5fff491
Add re-exec tests for SSR + move NotFound sources into one directory.
ilonatommy May 21, 2025
66cc974
Per-component interactivity: test navigation to non-existing page.
ilonatommy May 21, 2025
8907524
Add streaming SSR tests.
ilonatommy May 21, 2025
3b89c4b
Clean up tests and make them work.
ilonatommy May 21, 2025
217e8dd
Fix interactivity tests.
ilonatommy May 21, 2025
6e3eb98
Remove routing sandwitch.
ilonatommy May 22, 2025
e89fe2d
Trigger streaming.
ilonatommy May 22, 2025
e4b89c1
Templates use reexecution.
ilonatommy May 22, 2025
0f52575
Merge branch 'main' into not-found-works-after-navigation
ilonatommy May 23, 2025
fe7074f
Fix templates and layout.
ilonatommy May 28, 2025
1c2dcae
Fix namespace.
ilonatommy May 28, 2025
9f6df01
Make sure that interactive tests work only when interactivity is on.
ilonatommy May 28, 2025
b69773a
Fix: link has to have ID to check if layout is rendered.
ilonatommy May 28, 2025
6b439b5
Merge branch 'main' into not-found-works-after-navigation
ilonatommy May 28, 2025
f1bbf65
Fix: Wrong placing of NotFoundPage parameter.
ilonatommy May 28, 2025
a10a0fb
Whitespace
ilonatommy May 28, 2025
561c04c
Empty templates should not contain `NotFound.razor`.
ilonatommy May 29, 2025
8d96617
Move layout import for -ai Auto from server to client project.
ilonatommy May 29, 2025
90f6f0f
Feedback: use `RouteView`.
ilonatommy May 29, 2025
bdc5050
Feedback: explicit layout passing is not necessary when rendering wit…
ilonatommy May 29, 2025
05169c9
Fix misscommit.
ilonatommy May 29, 2025
1e207c2
Add error pages middlewarefor reexecution + use status code pages on …
ilonatommy May 30, 2025
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 @@ -1411,4 +1411,41 @@ public void NavigatesWithInteractivityByRequestRedirection(bool controlFlowByExc
Browser.Click(By.Id("redirectButton"));
Browser.Equal("Routing test cases", () => Browser.Exists(By.Id("test-info")).Text);
}

[Theory]
// prerendering (SSR) is tested in NoInteractivityTest
[InlineData("ServerNonPrerendered")]
[InlineData("WebAssemblyNonPrerendered")]
public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(string renderMode)
{
Navigate($"{ServerPathBase}/reexecution/redirection-not-found?renderMode={renderMode}&navigate-programmatically=true");
Assert404ReExecuted();
}

[Theory]
// prerendering (SSR) is tested in NoInteractivityTest
[InlineData("ServerNonPrerendered")]
[InlineData("WebAssemblyNonPrerendered")]
public void LinkNavigationToNotExistingPathReExecutesTo404(string renderMode)
{
Navigate($"{ServerPathBase}/reexecution/redirection-not-found?renderMode={renderMode}");
Browser.Click(By.Id("link-to-not-existing-page"));
Assert404ReExecuted();
}

[Theory]
// prerendering (SSR) is tested in NoInteractivityTest
[InlineData("ServerNonPrerendered")]
[InlineData("WebAssemblyNonPrerendered")]
public void BrowserNavigationToNotExistingPathReExecutesTo404(string renderMode)
{
// non-existing path has to have re-execution middleware set up
// so it has to have "reexecution" prefix. Otherwise middleware mapping
// will not be activated, see configuration in Startup
Navigate($"{ServerPathBase}/reexecution/not-existing-page?renderMode={renderMode}");
Assert404ReExecuted();
}

private void Assert404ReExecuted() =>
Browser.Equal("Welcome On Page Re-executed After Not Found Event", () => Browser.Exists(By.Id("test-info")).Text);
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,43 @@ public void CanRenderNotFoundPageAfterStreamingStarted()
Browser.Equal("Default Not Found Page", () => Browser.Title);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(bool streaming)
{
string streamingPath = streaming ? "-streaming" : "";
Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}?navigate-programmatically=true");
Assert404ReExecuted();
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming)
{
string streamingPath = streaming ? "-streaming" : "";
Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}");
Browser.Click(By.Id("link-to-not-existing-page"));
Assert404ReExecuted();
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void BrowserNavigationToNotExistingPathReExecutesTo404(bool streaming)
{
// non-existing path has to have re-execution middleware set up
// so it has to have "reexecution" prefix. Otherwise middleware mapping
// will not be activated, see configuration in Startup
string streamingPath = streaming ? "-streaming" : "";
Navigate($"{ServerPathBase}/reexecution/not-existing-page-ssr{streamingPath}");
Assert404ReExecuted();
}

private void Assert404ReExecuted() =>
Browser.Equal("Welcome On Page Re-executed After Not Found Event", () => Browser.Exists(By.Id("test-info")).Text);

[Theory]
[InlineData(true)]
[InlineData(false)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,37 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

app.Map("/subdir", app =>
{
if (!env.IsDevelopment())
app.Map("/reexecution", reexecutionApp =>
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
}

app.UseStaticFiles();
app.UseRouting();
RazorComponentEndpointsStartup<TRootComponent>.UseFakeAuthState(app);
app.UseAntiforgery();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorComponents<TRootComponent>();
reexecutionApp.UseStaticFiles();
reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true);
reexecutionApp.UseRouting();
RazorComponentEndpointsStartup<TRootComponent>.UseFakeAuthState(reexecutionApp);
reexecutionApp.UseAntiforgery();
reexecutionApp.UseEndpoints(endpoints =>
{
endpoints.MapRazorComponents<TRootComponent>();
});
});

ConfigureSubdirPipeline(app, env);
});
}

private void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env)
{
if (!env.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
}

app.UseStaticFiles();
app.UseRouting();
RazorComponentEndpointsStartup<TRootComponent>.UseFakeAuthState(app);
app.UseAntiforgery();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorComponents<TRootComponent>();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,17 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.Map("/reexecution", reexecutionApp =>
{
reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true);

reexecutionApp.UseRouting();

reexecutionApp.UseAntiforgery();
reexecutionApp.UseEndpoints(endpoints =>
{
endpoints.MapRazorComponents<TRootComponent>();
});
ConfigureEndpoints(reexecutionApp, env);
});

ConfigureSubdirPipeline(app, env);
});
}

protected virtual void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env)
private void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env)
{
WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app);

Expand All @@ -106,11 +103,15 @@ protected virtual void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHost
{
if (ctx.Request.Query.ContainsKey("add-csp"))
{
ctx.Response.Headers.Add("Content-Security-Policy", "script-src 'self' 'unsafe-inline'");
ctx.Response.Headers.Add("Content-Security-Policy", "script-src 'self' 'unsafe-inline'");
}
return nxt();
});
ConfigureEndpoints(app, env);
}

private void ConfigureEndpoints(IApplicationBuilder app, IWebHostEnvironment env)
{
_ = app.UseEndpoints(endpoints =>
{
var contentRootStaticAssetsPath = Path.Combine(env.ContentRootPath, "Components.TestServer.staticwebassets.endpoints.json");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@page "/redirection-not-found-ssr-streaming"
@page "/reexecution/redirection-not-found-ssr-streaming"
@attribute [StreamRendering(true)]

<Components.WasmMinimal.Pages.NotFound.RedirectionNotFoundComponent StartStreaming="true" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@page "/redirection-not-found-ssr"
@page "/reexecution/redirection-not-found-ssr"
@attribute [StreamRendering(false)]

<Components.WasmMinimal.Pages.NotFound.RedirectionNotFoundComponent />
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@page "/redirection-not-found"
@page "/reexecution/redirection-not-found"

<RedirectionNotFoundComponent @rendermode="@RenderModeHelper.GetRenderMode(_renderMode)" />

@code{
[Parameter, SupplyParameterFromQuery(Name = "renderMode")]
public string? RenderModeStr { get; set; }

private RenderModeId _renderMode;

protected override void OnInitialized()
{
if (!string.IsNullOrEmpty(RenderModeStr))
{
_renderMode = RenderModeHelper.ParseRenderMode(RenderModeStr);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

@inject NavigationManager NavigationManager

<h1>Original page</h1>

<p id="test-info">Any content</p>
<a id="link-to-not-existing-page" href="@_nonExistingPath">
Go to not-existing-page
</a>

@code{
[Parameter]
[SupplyParameterFromQuery(Name = "navigate-programmatically")]
public bool? NavigateProgrammatically { get; set; }

[Parameter]
public bool StartStreaming { get; set; } = false;

private string _nonExistingPath = string.Empty;

protected override async Task OnInitializedAsync()
{
if (StartStreaming)
{
await Task.Yield();
}
_nonExistingPath = $"{NavigationManager.BaseUri}reexecution/not-existing-page";
if (NavigateProgrammatically == true)
{
NavigationManager.NavigateTo(_nonExistingPath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace TestServer;

public static class RenderModeHelper
{
public static IComponentRenderMode GetRenderMode(RenderModeId renderMode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,12 @@ public static void Main(string[] args)
#endif
}

app.UseStatusCodePagesWithReExecute("/not-found", createScopeForErrors: true);

#if (HasHttpsProfile)
app.UseHttpsRedirection();

#endif
#endif
app.UseAntiforgery();

app.MapStaticAssets();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
app.UseHsts();
#endif
}
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForErrors: true);

#if (HasHttpsProfile)
app.UseHttpsRedirection();
Expand Down
Loading