diff --git a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs index bbeb1ad4d9bb..3de7fdc739b6 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs @@ -83,18 +83,28 @@ public void NavigatesWithoutInteractivityByRequestRedirection(bool controlFlowBy [Theory] [InlineData(true)] [InlineData(false)] - public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(bool streaming) + public void ProgrammaticNavigationToNotExistingPath_ReExecutesTo404(bool streaming) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); string streamingPath = streaming ? "-streaming" : ""; Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}?navigate-programmatically=true"); AssertReExecutionPageRendered(); } + [Fact] + public void ProgrammaticNavigationToNotExistingPath_AfterAsyncOperation_ReExecutesTo404() + { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); + Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr?doAsync=true&navigate-programmatically=true"); + AssertReExecutionPageRendered(); + } + [Theory] [InlineData(true)] [InlineData(false)] - public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming) + public void LinkNavigationToNotExistingPath_ReExecutesTo404(bool streaming) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); string streamingPath = streaming ? "-streaming" : ""; Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}"); Browser.Click(By.Id("link-to-not-existing-page")); @@ -104,8 +114,9 @@ public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming) [Theory] [InlineData(true)] [InlineData(false)] - public void BrowserNavigationToNotExistingPathReExecutesTo404(bool streaming) + public void BrowserNavigationToNotExistingPath_ReExecutesTo404(bool streaming) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true); // 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 diff --git a/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs index f3b70bc87509..4d9830c09033 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs @@ -32,9 +32,13 @@ public override async Task InitializeAsync() Browser.Equal("Redirections", () => _originalH1Element.Text); } - [Fact] - public void RedirectStreamingGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.LinkText("Streaming GET with internal redirection")).Click(); AssertElementRemoved(_originalH1Element); Browser.Equal("Scroll to hash", () => Browser.Exists(By.TagName("h1")).Text); @@ -47,16 +51,23 @@ public void RedirectStreamingGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.LinkText("Streaming GET with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectStreamingPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.CssSelector("#form-streaming-internal button")).Click(); AssertElementRemoved(_originalH1Element); Browser.Equal("Scroll to hash", () => Browser.Exists(By.TagName("h1")).Text); @@ -69,16 +80,23 @@ public void RedirectStreamingPostToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingPostToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingPostToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.CssSelector("#form-streaming-external button")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // Note that for enhanced nav we can't preserve the hash part of the URL, as it // gets discarded when the browser follows a 'fetch' redirection. This is not solvable // unless we are willing to make the server return extra information so that the @@ -95,16 +113,23 @@ public void RedirectEnhancedGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectEnhancedGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.LinkText("Enhanced GET with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.CssSelector("#form-enhanced-internal button")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -116,16 +141,23 @@ public void RedirectEnhancedPostToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectEnhancedPostToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedPostToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); Browser.Exists(By.CssSelector("#form-enhanced-external button")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectStreamingEnhancedGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.LinkText("Streaming enhanced GET with internal redirection")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -137,16 +169,25 @@ public void RedirectStreamingEnhancedGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingEnhancedGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.LinkText("Streaming enhanced GET with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } + - [Fact] - public void RedirectStreamingEnhancedPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.CssSelector("#form-streaming-enhanced-internal button")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -158,16 +199,24 @@ public void RedirectStreamingEnhancedPostToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectStreamingEnhancedPostToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectStreamingEnhancedPostToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.CssSelector("#form-streaming-enhanced-external button")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedNonBlazorGetToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedNonBlazorGetToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.LinkText("Enhanced GET to non-Blazor endpoint with internal redirection")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -179,16 +228,24 @@ public void RedirectEnhancedNonBlazorGetToInternal() Assert.EndsWith("/subdir/redirect", Browser.Url); } - [Fact] - public void RedirectEnhancedNonBlazorGetToExternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedNonBlazorGetToExternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + Browser.Exists(By.LinkText("Enhanced GET to non-Blazor endpoint with external redirection")).Click(); Browser.Contains("microsoft.com", () => Browser.Url); } - [Fact] - public void RedirectEnhancedNonBlazorPostToInternal() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedNonBlazorPostToInternal(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // See above for why enhanced nav doesn't support preserving the hash Browser.Exists(By.CssSelector("#form-nonblazor-enhanced-internal button")).Click(); Browser.Equal("Scroll to hash", () => _originalH1Element.Text); @@ -205,9 +262,13 @@ public void RedirectEnhancedNonBlazorPostToInternal() // response to something like a 200 that the 'fetch' is allowed to read (embedding the // destination URL). - [Fact] - public void RedirectEnhancedGetToInternalWithErrorBoundary() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void RedirectEnhancedGetToInternalWithErrorBoundary(bool disableThrowNavigationException) { + AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException); + // This test verifies that redirection works even if an ErrorBoundary wraps // a component throwing a NavigationException. diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor index 74374799ce04..f9d0b9da9b5a 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor @@ -2,4 +2,4 @@ @page "/reexecution/redirection-not-found-ssr-streaming" @attribute [StreamRendering(true)] - + diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor index 80a579a2e456..d64425d233d9 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor @@ -2,4 +2,9 @@ @page "/reexecution/redirection-not-found-ssr" @attribute [StreamRendering(false)] - \ No newline at end of file + + +@code{ + [SupplyParameterFromQuery(Name = "doAsync")] + public bool DoAsync { get; set; } = false; +} diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor index 68df9c6e0c8c..46d8496af1cb 100644 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor @@ -16,7 +16,7 @@ public bool? NavigateProgrammatically { get; set; } [Parameter] - public bool StartStreaming { get; set; } = false; + public bool DoAsyncOperationBeforeRedirection { get; set; } = false; [Parameter] public bool WaitForInteractivity { get; set; } = false; @@ -25,7 +25,7 @@ protected override async Task OnInitializedAsync() { - if (StartStreaming) + if (DoAsyncOperationBeforeRedirection) { await Task.Yield(); }