diff --git a/src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs b/src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs index 1b326af871ea..a64004713330 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/CircuitGracefulTerminationTests.cs @@ -63,8 +63,8 @@ public async Task ReloadingThePage_GracefullyDisconnects_TheCurrentCircuit() await Task.WhenAny(Task.Delay(10000), GracefulDisconnectCompletionSource.Task); // Assert - Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); - Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages.ToArray()); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages.ToArray()); } [Fact] @@ -76,8 +76,8 @@ public async Task ClosingTheBrowserWindow_GracefullyDisconnects_TheCurrentCircui // Assert Assert.True(GracefulDisconnectCompletionSource.Task.IsCompletedSuccessfully); - Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); - Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages.ToArray()); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages.ToArray()); } [Fact] @@ -90,8 +90,8 @@ public async Task ClosingTheBrowserWindow_GracefullyDisconnects_WhenNavigatingAw // Assert Assert.Equal(GracefulDisconnectCompletionSource.Task, task); - Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); - Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages.ToArray()); + Assert.Contains((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages.ToArray()); } [Fact] @@ -103,8 +103,8 @@ public async Task NavigatingToProtocolLink_DoesNotGracefullyDisconnect_TheCurren await Task.WhenAny(Task.Delay(10000), GracefulDisconnectCompletionSource.Task); // Assert - Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); - Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages.ToArray()); + Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages.ToArray()); } [Fact] @@ -116,8 +116,8 @@ public async Task DownloadAction_DoesNotGracefullyDisconnect_TheCurrentCircuit() await Task.WhenAny(Task.Delay(10000), GracefulDisconnectCompletionSource.Task); // Assert - Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); - Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages.ToArray()); + Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages.ToArray()); } [Fact] @@ -129,8 +129,8 @@ public async Task DownloadHref_DoesNotGracefullyDisconnect_TheCurrentCircuit() await Task.WhenAny(Task.Delay(10000), GracefulDisconnectCompletionSource.Task); // Assert - Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages); - Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages); + Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitTerminatedGracefully"), Messages.ToArray()); + Assert.DoesNotContain((Extensions.Logging.LogLevel.Debug, "CircuitDisconnectedPermanently"), Messages.ToArray()); } private void Log(WriteContext wc) diff --git a/src/Components/test/E2ETest/Tests/ComponentRenderingTestBase.cs b/src/Components/test/E2ETest/Tests/ComponentRenderingTestBase.cs index 6bd25034562a..5963d5a1c5be 100644 --- a/src/Components/test/E2ETest/Tests/ComponentRenderingTestBase.cs +++ b/src/Components/test/E2ETest/Tests/ComponentRenderingTestBase.cs @@ -485,7 +485,7 @@ public void CanFocusDuringOnAfterRenderAsyncWithFocusInEvent(string triggerButto Browser.Equal("focus-input-onafterrender", () => Browser.SwitchTo().ActiveElement().GetAttribute("id")); // As well as actually focusing and triggering the onfocusin event, we should not be seeing any errors - var log = Browser.Manage().Logs.GetLog(LogType.Browser); + var log = Browser.Manage().Logs.GetLog(LogType.Browser).ToArray(); Assert.DoesNotContain(log, entry => entry.Level == LogLevel.Severe); } diff --git a/src/Components/test/E2ETest/Tests/FormsTest.cs b/src/Components/test/E2ETest/Tests/FormsTest.cs index c95813707567..d06ff812ed6c 100644 --- a/src/Components/test/E2ETest/Tests/FormsTest.cs +++ b/src/Components/test/E2ETest/Tests/FormsTest.cs @@ -212,7 +212,7 @@ public void InputDateInteractsWithEditContext_NonNullableDateTime() Browser.Equal("modified valid", () => renewalDateInput.GetAttribute("class")); // Can become invalid - ApplyInvalidInputDateValue(".renewal-date input", "11111-11-11"); + renewalDateInput.SendKeys("11-11-11111\t"); Browser.Equal("modified invalid", () => renewalDateInput.GetAttribute("class")); Browser.Equal(new[] { "The RenewalDate field must be a date." }, messagesAccessor); @@ -236,11 +236,11 @@ public void InputDateInteractsWithEditContext_NullableDateTimeOffset() // Validates on edit Browser.Equal("valid", () => expiryDateInput.GetAttribute("class")); - expiryDateInput.SendKeys("01/01/2000\t"); + expiryDateInput.SendKeys("01-01-2000\t"); Browser.Equal("modified valid", () => expiryDateInput.GetAttribute("class")); // Can become invalid - ApplyInvalidInputDateValue(".expiry-date input", "11111-11-11"); + expiryDateInput.SendKeys("11-11-11111\t"); Browser.Equal("modified invalid", () => expiryDateInput.GetAttribute("class")); Browser.Equal(new[] { "The OptionalExpiryDate field must be a date." }, messagesAccessor); @@ -264,21 +264,14 @@ public void InputDateInteractsWithEditContext_TimeInput() Browser.Equal("modified valid", () => departureTimeInput.GetAttribute("class")); // Can become invalid - ApplyInvalidInputDateValue(".departure-time input", "01:234:56"); + // Stricly speaking the following is equivalent to the empty state, because that's how incomplete input is represented + // We don't know of any way to produce a different (non-empty-equivalent) state using UI gestures, so there's nothing else to test + departureTimeInput.SendKeys($"20{Keys.Backspace}\t"); Browser.Equal("modified invalid", () => departureTimeInput.GetAttribute("class")); Browser.Equal(new[] { "The DepartureTime field must be a time." }, messagesAccessor); - - // Empty is invalid, because it's not nullable - departureTimeInput.SendKeys($"{Keys.Backspace}\t{Keys.Backspace}\t{Keys.Backspace}\t"); - Browser.Equal("modified invalid", () => departureTimeInput.GetAttribute("class")); - Browser.Equal(new[] { "The DepartureTime field must be a time." }, messagesAccessor); - - departureTimeInput.SendKeys("07201\t"); - Browser.Equal("modified valid", () => departureTimeInput.GetAttribute("class")); - Browser.Empty(messagesAccessor); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/aspnetcore/issues/35498")] public void InputDateInteractsWithEditContext_MonthInput() { var appElement = MountTypicalValidationComponent(); @@ -287,11 +280,11 @@ public void InputDateInteractsWithEditContext_MonthInput() // Validates on edit Browser.Equal("valid", () => visitMonthInput.GetAttribute("class")); - visitMonthInput.SendKeys("03\t2005\t"); + visitMonthInput.SendKeys($"03{Keys.ArrowRight}2005\t"); Browser.Equal("modified valid", () => visitMonthInput.GetAttribute("class")); // Can become invalid - ApplyInvalidInputDateValue(".visit-month input", "05/1992"); + visitMonthInput.SendKeys($"11{Keys.ArrowRight}11111\t"); Browser.Equal("modified invalid", () => visitMonthInput.GetAttribute("class")); Browser.Equal(new[] { "The VisitMonth field must be a year and month." }, messagesAccessor); @@ -300,12 +293,13 @@ public void InputDateInteractsWithEditContext_MonthInput() Browser.Equal("modified invalid", () => visitMonthInput.GetAttribute("class")); Browser.Equal(new[] { "The VisitMonth field must be a year and month." }, messagesAccessor); - visitMonthInput.SendKeys("05\t2007\t"); + visitMonthInput.Clear(); + visitMonthInput.SendKeys($"05{Keys.ArrowRight}2007\t"); Browser.Equal("modified valid", () => visitMonthInput.GetAttribute("class")); Browser.Empty(messagesAccessor); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/aspnetcore/issues/35498")] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/34884")] public void InputDateInteractsWithEditContext_DateTimeLocalInput() { @@ -319,7 +313,7 @@ public void InputDateInteractsWithEditContext_DateTimeLocalInput() Browser.Equal("modified valid", () => appointmentInput.GetAttribute("class")); // Can become invalid - ApplyInvalidInputDateValue(".appointment-date-time input", "1234/567/89 33:44 FM"); + appointmentInput.SendKeys($"11{Keys.ArrowRight}11{Keys.ArrowRight}11111{Keys.ArrowRight}\t"); Browser.Equal("modified invalid", () => appointmentInput.GetAttribute("class")); Browser.Equal(new[] { "The AppointmentDateAndTime field must be a date and time." }, messagesAccessor); @@ -862,21 +856,6 @@ private Func CreateValidationMessagesAccessor(IWebElement appElement) .ToArray(); } - private void ApplyInvalidInputDateValue(string cssSelector, string invalidValue) - { - // It's very difficult to enter an invalid value into an , because - // most combinations of keystrokes get normalized to something valid. Additionally, - // using Selenium's SendKeys interacts unpredictably with this normalization logic, - // most likely based on timings. As a workaround, use JS to apply the values. This - // should only be used when strictly necessary, as it doesn't represent actual user - // interaction as authentically as SendKeys in other cases. - var javascript = (IJavaScriptExecutor)Browser; - javascript.ExecuteScript( - $"document.querySelector('{cssSelector}').value = {JsonSerializer.Serialize(invalidValue, TestJsonSerializerOptionsProvider.Options)}"); - javascript.ExecuteScript( - $"document.querySelector('{cssSelector}').dispatchEvent(new KeyboardEvent('change'))"); - } - private void EnsureAttributeRendering(IWebElement element, string attributeName, bool shouldBeRendered = true) { Browser.Equal(shouldBeRendered, () => element.GetAttribute(attributeName) != null); diff --git a/src/Components/test/testassets/BasicTestApp/ElementFocusComponent.razor b/src/Components/test/testassets/BasicTestApp/ElementFocusComponent.razor index 3998dc897af7..97c246887303 100644 --- a/src/Components/test/testassets/BasicTestApp/ElementFocusComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/ElementFocusComponent.razor @@ -30,15 +30,18 @@ { Task.Run(async () => { - await Task.Yield(); - performFocusDuringOnAfterRender = true; - _ = InvokeAsync(StateHasChanged); + await Task.Delay(500); + _ = InvokeAsync(() => + { + performFocusDuringOnAfterRender = true; + StateHasChanged(); + }); }); } private async Task FocusDuringOnAfterRenderViaAwait() { - await Task.Yield(); + await Task.Delay(500); performFocusDuringOnAfterRender = true; }