Skip to content

Commit 133b116

Browse files
authored
Use a controlled external origin in redirection tests (#68782)
1 parent d013315 commit 133b116

8 files changed

Lines changed: 81 additions & 21 deletions

File tree

src/Components/test/E2ETest/ServerRenderingTests/RedirectionTest.cs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,24 @@
1212

1313
namespace Microsoft.AspNetCore.Components.E2ETests.ServerRenderingTests;
1414

15-
public class RedirectionTest : ServerTestBase<BasicTestAppServerSiteFixture<RazorComponentEndpointsStartup<App>>>
15+
public class RedirectionTest :
16+
ServerTestBase<BasicTestAppServerSiteFixture<RazorComponentEndpointsStartup<App>>>,
17+
IClassFixture<BasicTestAppServerSiteFixture<ExternalNavigationStartup>>
1618
{
19+
private readonly Uri _externalNavigationTargetUri;
20+
private readonly Uri _externalNavigationTargetUriWithQuery;
1721
private IWebElement _originalH1Element;
1822

1923
public RedirectionTest(
2024
BrowserFixture browserFixture,
2125
BasicTestAppServerSiteFixture<RazorComponentEndpointsStartup<App>> serverFixture,
26+
BasicTestAppServerSiteFixture<ExternalNavigationStartup> externalNavigationFixture,
2227
ITestOutputHelper output)
2328
: base(browserFixture, serverFixture, output)
2429
{
30+
_externalNavigationTargetUri = new Uri(externalNavigationFixture.RootUri, "/external-navigation-target");
31+
_externalNavigationTargetUriWithQuery = new Uri($"{_externalNavigationTargetUri}?foo=🙂");
32+
serverFixture.AdditionalArguments.Add($"--ExternalNavigationTargetUri={_externalNavigationTargetUri.AbsoluteUri}");
2533
}
2634

2735
public override async Task InitializeAsync()
@@ -55,12 +63,11 @@ public void RedirectStreamingGetToInternal(bool disableThrowNavigationException)
5563
[Theory]
5664
[InlineData(true)]
5765
[InlineData(false)]
58-
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/66969")]
5966
public void RedirectStreamingGetToExternal(bool disableThrowNavigationException)
6067
{
6168
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException);
6269
Browser.Exists(By.LinkText("Streaming GET with external redirection")).Click();
63-
Browser.Contains("microsoft.com", () => Browser.Url);
70+
AssertExternalNavigationCompleted();
6471
}
6572

6673
[Theory]
@@ -85,12 +92,11 @@ public void RedirectStreamingPostToInternal(bool disableThrowNavigationException
8592
[Theory]
8693
[InlineData(true)]
8794
[InlineData(false)]
88-
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/67342")]
8995
public void RedirectStreamingPostToExternal(bool disableThrowNavigationException)
9096
{
9197
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException);
9298
Browser.Exists(By.CssSelector("#form-streaming-external button")).Click();
93-
Browser.Contains("microsoft.com", () => Browser.Url);
99+
AssertExternalNavigationCompleted();
94100
}
95101

96102
[Theory]
@@ -119,12 +125,11 @@ public void RedirectEnhancedGetToInternal(bool disableThrowNavigationException)
119125
[Theory]
120126
[InlineData(true)]
121127
[InlineData(false)]
122-
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/67738")]
123128
public void RedirectEnhancedGetToExternal(bool disableThrowNavigationException)
124129
{
125130
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException);
126131
Browser.Exists(By.LinkText("Enhanced GET with external redirection")).Click();
127-
Browser.Contains("microsoft.com", () => Browser.Url);
132+
AssertExternalNavigationCompleted();
128133
}
129134

130135
[Theory]
@@ -148,12 +153,11 @@ public void RedirectEnhancedPostToInternal(bool disableThrowNavigationException)
148153
[Theory]
149154
[InlineData(true)]
150155
[InlineData(false)]
151-
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/67444")]
152156
public void RedirectEnhancedPostToExternal(bool disableThrowNavigationException)
153157
{
154158
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException);
155159
Browser.Exists(By.CssSelector("#form-enhanced-external button")).Click();
156-
Browser.Contains("microsoft.com", () => Browser.Url);
160+
AssertExternalNavigationCompleted();
157161
}
158162

159163
[Theory]
@@ -177,13 +181,12 @@ public void RedirectStreamingEnhancedGetToInternal(bool disableThrowNavigationEx
177181
[Theory]
178182
[InlineData(true)]
179183
[InlineData(false)]
180-
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/66969")]
181184
public void RedirectStreamingEnhancedGetToExternal(bool disableThrowNavigationException)
182185
{
183186
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException);
184187

185188
Browser.Exists(By.LinkText("Streaming enhanced GET with external redirection")).Click();
186-
Browser.Contains("microsoft.com", () => Browser.Url);
189+
AssertExternalNavigationCompleted();
187190
}
188191

189192
[Theory]
@@ -207,13 +210,12 @@ public void RedirectStreamingEnhancedPostToInternal(bool disableThrowNavigationE
207210
[Theory]
208211
[InlineData(true)]
209212
[InlineData(false)]
210-
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/66869")]
211213
public void RedirectStreamingEnhancedPostToExternal(bool disableThrowNavigationException)
212214
{
213215
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException);
214216

215217
Browser.Exists(By.CssSelector("#form-streaming-enhanced-external button")).Click();
216-
Browser.Contains("microsoft.com", () => Browser.Url);
218+
AssertExternalNavigationCompleted();
217219
}
218220

219221
[Theory]
@@ -238,13 +240,12 @@ public void RedirectEnhancedNonBlazorGetToInternal(bool disableThrowNavigationEx
238240
[Theory]
239241
[InlineData(true)]
240242
[InlineData(false)]
241-
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/67342")]
242243
public void RedirectEnhancedNonBlazorGetToExternal(bool disableThrowNavigationException)
243244
{
244245
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", disableThrowNavigationException);
245246

246247
Browser.Exists(By.LinkText("Enhanced GET to non-Blazor endpoint with external redirection")).Click();
247-
Browser.Contains("microsoft.com", () => Browser.Url);
248+
AssertExternalNavigationCompleted(hasQuery: false);
248249
}
249250

250251
[Theory]
@@ -322,4 +323,11 @@ private void AssertElementRemoved(IWebElement element)
322323
return false;
323324
});
324325
}
326+
327+
private void AssertExternalNavigationCompleted(bool hasQuery = true)
328+
{
329+
var expectedUri = hasQuery ? _externalNavigationTargetUriWithQuery : _externalNavigationTargetUri;
330+
Browser.Equal(expectedUri, () => new Uri(Browser.Url));
331+
Browser.Exists(By.Id("external-navigation-target"));
332+
}
325333
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace TestServer;
5+
6+
public class ExternalNavigationStartup
7+
{
8+
public void Configure(IApplicationBuilder app)
9+
{
10+
app.Run(async context =>
11+
{
12+
context.Response.ContentType = "text/html";
13+
await context.Response.WriteAsync(
14+
"""
15+
<!DOCTYPE html>
16+
<html>
17+
<body>
18+
<h1 id="external-navigation-target">External navigation target</h1>
19+
</body>
20+
</html>
21+
""");
22+
});
23+
}
24+
}

src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Components.TestServer.RazorComponents;
99
using Components.TestServer.RazorComponents.Pages.Forms;
1010
using Components.TestServer.RazorComponents.Pages.PersistentState;
11+
using Components.TestServer.RazorComponents.Pages.Redirections;
1112
using Components.TestServer.Services;
1213
using Microsoft.AspNetCore.Builder;
1314
using Microsoft.AspNetCore.Components;
@@ -53,6 +54,7 @@ public void ConfigureServices(IServiceCollection services)
5354
}
5455
services.AddSingleton<IStringLocalizerFactory>(
5556
new TestStringLocalizerFactory(ClientValidationLocalizationData.Translations));
57+
services.AddSingleton<ExternalNavigationTarget>();
5658
services.AddValidation(options =>
5759
options.Resolvers.Add(new BasicTestApp.FormsTest.AsyncValidationResolver()));
5860

@@ -396,10 +398,13 @@ private static void MapEnhancedNavigationEndpoints(IEndpointRouteBuilder endpoin
396398

397399
endpoints.Map("/test-formaction", () => "Formaction url");
398400

399-
static Task PerformRedirection(HttpRequest request, HttpResponse response)
401+
static Task PerformRedirection(
402+
HttpRequest request,
403+
HttpResponse response,
404+
ExternalNavigationTarget externalNavigationTarget)
400405
{
401406
response.Redirect(request.Query["external"] == "true"
402-
? "https://microsoft.com"
407+
? externalNavigationTarget.Uri.AbsoluteUri
403408
: $"{request.PathBase}/nav/scroll-to-hash#some-content");
404409
return Task.CompletedTask;
405410
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.AspNetCore.WebUtilities;
5+
6+
namespace Components.TestServer.RazorComponents.Pages.Redirections;
7+
8+
internal sealed class ExternalNavigationTarget
9+
{
10+
public ExternalNavigationTarget(IConfiguration configuration)
11+
{
12+
Uri = new Uri(configuration["ExternalNavigationTargetUri"] ?? "https://microsoft.com");
13+
UriWithQuery = QueryHelpers.AddQueryString(Uri.AbsoluteUri, "foo", "🙂");
14+
}
15+
16+
public Uri Uri { get; }
17+
18+
public string UriWithQuery { get; }
19+
}

src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/Redirections/RedirectGet.razor

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@page "/redirect/get"
22
@inject NavigationManager Nav
3+
@inject ExternalNavigationTarget ExternalNavigationTarget
34

45
<h1>Nonstreaming GET</h1>
56

@@ -10,6 +11,6 @@
1011
protected override async Task OnInitializedAsync()
1112
{
1213
await Task.Delay(500);
13-
Nav.NavigateTo(External ? "https://microsoft.com?foo=🙂" : "nav/scroll-to-hash?foo=🙂#some-content");
14+
Nav.NavigateTo(External ? ExternalNavigationTarget.UriWithQuery : "nav/scroll-to-hash?foo=🙂#some-content");
1415
}
1516
}

src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/Redirections/RedirectPost.razor

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@page "/redirect/post"
22
@inject NavigationManager Nav
3+
@inject ExternalNavigationTarget ExternalNavigationTarget
34
@using Microsoft.AspNetCore.Components.Forms
45

56
<h1>Nonstreaming POST</h1>
@@ -12,6 +13,6 @@
1213
private async Task DoRedirectionAsync()
1314
{
1415
await Task.Delay(500);
15-
Nav.NavigateTo(External ? "https://microsoft.com?foo=🙂" : "nav/scroll-to-hash?foo=🙂#some-content");
16+
Nav.NavigateTo(External ? ExternalNavigationTarget.UriWithQuery : "nav/scroll-to-hash?foo=🙂#some-content");
1617
}
1718
}

src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/Redirections/RedirectStreamingGet.razor

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@page "/redirect/streaming/get"
22
@attribute [StreamRendering]
33
@inject NavigationManager Nav
4+
@inject ExternalNavigationTarget ExternalNavigationTarget
45

56
<h1>Streaming GET</h1>
67

@@ -11,6 +12,6 @@
1112
protected override async Task OnInitializedAsync()
1213
{
1314
await Task.Delay(500);
14-
Nav.NavigateTo(External ? "https://microsoft.com?foo=🙂" : "nav/scroll-to-hash?foo=🙂#some-content");
15+
Nav.NavigateTo(External ? ExternalNavigationTarget.UriWithQuery : "nav/scroll-to-hash?foo=🙂#some-content");
1516
}
1617
}

src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/Redirections/RedirectStreamingPost.razor

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@page "/redirect/streaming/post"
22
@attribute [StreamRendering]
33
@inject NavigationManager Nav
4+
@inject ExternalNavigationTarget ExternalNavigationTarget
45
@using Microsoft.AspNetCore.Components.Forms
56

67
<h1>Streaming POST</h1>
@@ -13,6 +14,6 @@
1314
private async Task DoRedirectionAsync()
1415
{
1516
await Task.Delay(500);
16-
Nav.NavigateTo(External ? "https://microsoft.com?foo=🙂" : "nav/scroll-to-hash?foo=🙂#some-content");
17+
Nav.NavigateTo(External ? ExternalNavigationTarget.UriWithQuery : "nav/scroll-to-hash?foo=🙂#some-content");
1718
}
1819
}

0 commit comments

Comments
 (0)