diff --git a/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithNoBackForwardCacheTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithNoBackForwardCacheTest.cs new file mode 100644 index 000000000000..3efc991508a7 --- /dev/null +++ b/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithNoBackForwardCacheTest.cs @@ -0,0 +1,89 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.ObjectModel; +using System.Net.Http; +using System.Text; +using Components.TestServer.RazorComponents; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.InternalTesting; +using OpenQA.Selenium; +using TestServer; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETests.ServerRenderingTests.FormHandlingTests; + +public class FormWithNoBackForwardCacheTest : ServerTestBase>> +{ + public FormWithNoBackForwardCacheTest( + BrowserFixture browserFixture, + BasicTestAppServerSiteFixture> serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + } + + public override Task InitializeAsync() + { + return InitializeAsync(BrowserFixture.StreamingBackForwardCacheContext); + } + + private void SuppressEnhancedNavigation(bool shouldSuppress) + => EnhancedNavigationTestUtil.SuppressEnhancedNavigation(this, shouldSuppress); + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CanUseFormWithMethodGet(bool suppressEnhancedNavigation) + { + SuppressEnhancedNavigation(suppressEnhancedNavigation); + Navigate($"{ServerPathBase}/forms/method-get"); + Browser.Equal("Form with method=get", () => Browser.FindElement(By.TagName("h2")).Text); + + // Validate initial state + var stringInput = Browser.FindElement(By.Id("mystring")); + var boolInput = Browser.FindElement(By.Id("mybool")); + Browser.Equal("Initial value", () => stringInput.GetDomProperty("value")); + Browser.Equal("False", () => boolInput.GetDomProperty("checked")); + + // Edit and submit the form; check it worked + stringInput.Clear(); + stringInput.SendKeys("Edited value"); + boolInput.Click(); + Browser.FindElement(By.Id("submit-get-form")).Click(); + AssertUiState("Edited value", true); + Browser.Contains($"MyString=Edited+value", () => Browser.Url); + Browser.Contains($"MyBool=True", () => Browser.Url); + + // Check 'back' correctly gets us to the previous state + Browser.Navigate().Back(); + AssertUiState("Initial value", false); + Browser.False(() => Browser.Url.Contains("MyString")); + Browser.False(() => Browser.Url.Contains("MyBool")); + + // Check 'forward' correctly recreates the edited state + Browser.Navigate().Forward(); + AssertUiState("Edited value", true); + Browser.Contains($"MyString=Edited+value", () => Browser.Url); + Browser.Contains($"MyBool=True", () => Browser.Url); + + void AssertUiState(string expectedStringValue, bool expectedBoolValue) + { + Browser.Equal(expectedStringValue, () => Browser.FindElement(By.Id("mystring-value")).Text); + Browser.Equal(expectedBoolValue.ToString(), () => Browser.FindElement(By.Id("mybool-value")).Text); + + // If we're not suppressing, we'll keep referencing the same elements to show they were preserved + if (suppressEnhancedNavigation) + { + stringInput = Browser.FindElement(By.Id("mystring")); + boolInput = Browser.FindElement(By.Id("mybool")); + } + + Browser.Equal(expectedStringValue, () => stringInput.GetDomProperty("value")); + Browser.Equal(expectedBoolValue.ToString(), () => boolInput.GetDomProperty("checked")); + } + } +} + diff --git a/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs index d6dc438db468..7de639439dee 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs @@ -1369,59 +1369,6 @@ public void CanBindToFormWithFiles() Assert.Equal("Total: 7", Browser.Exists(By.Id("form-collection")).Text); } - [Theory] - // [InlineData(true)] QuarantinedTest: https://github.com/dotnet/aspnetcore/issues/61882 - [InlineData(false)] - public void CanUseFormWithMethodGet(bool suppressEnhancedNavigation) - { - SuppressEnhancedNavigation(suppressEnhancedNavigation); - GoTo("forms/method-get"); - Browser.Equal("Form with method=get", () => Browser.FindElement(By.TagName("h2")).Text); - - // Validate initial state - var stringInput = Browser.FindElement(By.Id("mystring")); - var boolInput = Browser.FindElement(By.Id("mybool")); - Browser.Equal("Initial value", () => stringInput.GetDomProperty("value")); - Browser.Equal("False", () => boolInput.GetDomProperty("checked")); - - // Edit and submit the form; check it worked - stringInput.Clear(); - stringInput.SendKeys("Edited value"); - boolInput.Click(); - Browser.FindElement(By.Id("submit-get-form")).Click(); - AssertUiState("Edited value", true); - Browser.Contains($"MyString=Edited+value", () => Browser.Url); - Browser.Contains($"MyBool=True", () => Browser.Url); - - // Check 'back' correctly gets us to the previous state - Browser.Navigate().Back(); - AssertUiState("Initial value", false); - Browser.False(() => Browser.Url.Contains("MyString")); - Browser.False(() => Browser.Url.Contains("MyBool")); - - // Check 'forward' correctly recreates the edited state - Browser.Navigate().Forward(); - AssertUiState("Edited value", true); - Browser.Contains($"MyString=Edited+value", () => Browser.Url); - Browser.Contains($"MyBool=True", () => Browser.Url); - - void AssertUiState(string expectedStringValue, bool expectedBoolValue) - { - Browser.Equal(expectedStringValue, () => Browser.FindElement(By.Id("mystring-value")).Text); - Browser.Equal(expectedBoolValue.ToString(), () => Browser.FindElement(By.Id("mybool-value")).Text); - - // If we're not suppressing, we'll keep referencing the same elements to show they were preserved - if (suppressEnhancedNavigation) - { - stringInput = Browser.FindElement(By.Id("mystring")); - boolInput = Browser.FindElement(By.Id("mybool")); - } - - Browser.Equal(expectedStringValue, () => stringInput.GetDomProperty("value")); - Browser.Equal(expectedBoolValue.ToString(), () => boolInput.GetDomProperty("checked")); - } - } - [Fact] public void RadioButtonGetsResetAfterSubmittingEnhancedForm() { diff --git a/src/Shared/E2ETesting/BrowserFixture.cs b/src/Shared/E2ETesting/BrowserFixture.cs index e046634232b3..861281ad1cd2 100644 --- a/src/Shared/E2ETesting/BrowserFixture.cs +++ b/src/Shared/E2ETesting/BrowserFixture.cs @@ -15,6 +15,7 @@ public class BrowserFixture : IAsyncLifetime { public static string StreamingContext { get; } = "streaming"; public static string RoutingTestContext { get; } = "routing"; + public static string StreamingBackForwardCacheContext { get; } = "streaming.backforwardcache"; private readonly ConcurrentDictionary _browsers = new(); @@ -142,12 +143,19 @@ private async Task DeleteBrowserUserProfileDirectoriesAsync() opts.UseWebSocketUrl = true; } - if (context?.StartsWith(StreamingContext, StringComparison.Ordinal) == true) + if (context?.StartsWith(StreamingContext, StringComparison.Ordinal) == true || context?.StartsWith(StreamingBackForwardCacheContext, StringComparison.Ordinal) == true) { // Tells Selenium not to wait until the page navigation has completed before continuing with the tests opts.PageLoadStrategy = PageLoadStrategy.None; } + if (context?.StartsWith(StreamingBackForwardCacheContext, StringComparison.Ordinal) == true) + { + // Tells Selenium to disable the back/forward cache, which is enabled by default in Chrome. + // This is needed for tests that rely on the browser's back/forward navigation. + opts.AddArgument("--disable-back-forward-cache"); + } + // Force language to english for tests opts.AddUserProfilePreference("intl.accept_languages", "en");