// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Text.Json; using BasicTestApp; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.Testing; using Moq; using OpenQA.Selenium; using OpenQA.Selenium.Support.UI; using Xunit; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Components.E2ETest.Tests { public class BindTest : ServerTestBase> { public BindTest( BrowserFixture browserFixture, ToggleExecutionModeServerFixture serverFixture, ITestOutputHelper output) : base(browserFixture, serverFixture, output) { } protected override void InitializeAsyncCore() { // On WebAssembly, page reloads are expensive so skip if possible Navigate(ServerPathBase, noReload: _serverFixture.ExecutionMode == ExecutionMode.Client); Browser.MountTestComponent(); Browser.Exists(By.Id("bind-cases")); } [Fact] public void CanBindTextbox_InitiallyBlank() { var target = Browser.FindElement(By.Id("textbox-initially-blank")); var boundValue = Browser.FindElement(By.Id("textbox-initially-blank-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-initially-blank-mirror")); var setNullButton = Browser.FindElement(By.Id("textbox-initially-blank-setnull")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("Changed value"); Assert.Equal(string.Empty, boundValue.Text); // Doesn't update until change event Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal("Changed value", () => boundValue.Text); Assert.Equal("Changed value", mirrorValue.GetAttribute("value")); // Remove the value altogether setNullButton.Click(); Browser.Equal(string.Empty, () => target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextbox_InitiallyPopulated() { var target = Browser.FindElement(By.Id("textbox-initially-populated")); var boundValue = Browser.FindElement(By.Id("textbox-initially-populated-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-initially-populated-mirror")); var setNullButton = Browser.FindElement(By.Id("textbox-initially-populated-setnull")); Assert.Equal("Hello", target.GetAttribute("value")); Assert.Equal("Hello", boundValue.Text); Assert.Equal("Hello", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("Changed value\t"); Browser.Equal("Changed value", () => boundValue.Text); Assert.Equal("Changed value", mirrorValue.GetAttribute("value")); // Remove the value altogether setNullButton.Click(); Browser.Equal(string.Empty, () => target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextbox_WithBindSuffixInitiallyPopulated() { var target = Browser.FindElement(By.Id("bind-with-suffix-textbox-initially-populated")); var boundValue = Browser.FindElement(By.Id("bind-with-suffix-textbox-initially-populated-value")); var mirrorValue = Browser.FindElement(By.Id("bind-with-suffix-textbox-initially-populated-mirror")); var setNullButton = Browser.FindElement(By.Id("bind-with-suffix-textbox-initially-populated-setnull")); Assert.Equal("Hello", target.GetAttribute("value")); Assert.Equal("Hello", boundValue.Text); Assert.Equal("Hello", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("Changed value\t"); Browser.Equal("Changed value", () => boundValue.Text); Assert.Equal("Changed value", mirrorValue.GetAttribute("value")); // Remove the value altogether setNullButton.Click(); Browser.Equal(string.Empty, () => target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextArea_InitiallyBlank() { var target = Browser.FindElement(By.Id("textarea-initially-blank")); var boundValue = Browser.FindElement(By.Id("textarea-initially-blank-value")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); // Modify target; verify value is updated target.SendKeys("Changed value"); Assert.Equal(string.Empty, boundValue.Text); // Don't update as there's no change event fired yet. target.SendKeys("\t"); Browser.Equal("Changed value", () => boundValue.Text); } [Fact] public void CanBindTextArea_InitiallyPopulated() { var target = Browser.FindElement(By.Id("textarea-initially-populated")); var boundValue = Browser.FindElement(By.Id("textarea-initially-populated-value")); Assert.Equal("Hello", target.GetAttribute("value")); Assert.Equal("Hello", boundValue.Text); // Modify target; verify value is updated target.Clear(); target.SendKeys("Changed value\t"); Browser.Equal("Changed value", () => boundValue.Text); } [Fact] public void CanBindCheckbox_InitiallyNull() { var target = Browser.FindElement(By.Id("checkbox-initially-null")); var boundValue = Browser.FindElement(By.Id("checkbox-initially-null-value")); var invertButton = Browser.FindElement(By.Id("checkbox-initially-null-invert")); Assert.False(target.Selected); Assert.Equal(string.Empty, boundValue.Text); // Modify target; verify value is updated target.Click(); Browser.True(() => target.Selected); Browser.Equal("True", () => boundValue.Text); // Modify data; verify checkbox is updated invertButton.Click(); Browser.False(() => target.Selected); Browser.Equal("False", () => boundValue.Text); } [Fact] public void CanBindCheckbox_InitiallyUnchecked() { var target = Browser.FindElement(By.Id("checkbox-initially-unchecked")); var boundValue = Browser.FindElement(By.Id("checkbox-initially-unchecked-value")); var invertButton = Browser.FindElement(By.Id("checkbox-initially-unchecked-invert")); Assert.False(target.Selected); Assert.Equal("False", boundValue.Text); // Modify target; verify value is updated target.Click(); Browser.True(() => target.Selected); Browser.Equal("True", () => boundValue.Text); // Modify data; verify checkbox is updated invertButton.Click(); Browser.False(() => target.Selected); Browser.Equal("False", () => boundValue.Text); } [Fact] public void CanBindCheckbox_InitiallyChecked() { var target = Browser.FindElement(By.Id("checkbox-initially-checked")); var boundValue = Browser.FindElement(By.Id("checkbox-initially-checked-value")); var invertButton = Browser.FindElement(By.Id("checkbox-initially-checked-invert")); Assert.True(target.Selected); Assert.Equal("True", boundValue.Text); // Modify target; verify value is updated target.Click(); Browser.False(() => target.Selected); Browser.Equal("False", () => boundValue.Text); // Modify data; verify checkbox is updated invertButton.Click(); Browser.True(() => target.Selected); Browser.Equal("True", () => boundValue.Text); } [Fact] public void CanBindSelect() { var target = new SelectElement(Browser.FindElement(By.Id("select-box"))); var boundValue = Browser.FindElement(By.Id("select-box-value")); Assert.Equal("Second choice", target.SelectedOption.Text); Assert.Equal("Second", boundValue.Text); // Modify target; verify value is updated target.SelectByText("Third choice"); Browser.Equal("Third", () => boundValue.Text); // Also verify we can add and select new options atomically // Don't move this into a separate test, because then the previous assertions // would be dependent on test execution order (or would require a full page reload) Browser.FindElement(By.Id("select-box-add-option")).Click(); Browser.Equal("Fourth", () => boundValue.Text); Assert.Equal("Fourth choice", target.SelectedOption.Text); // verify that changing an option value and selected value at the same time works. Browser.FindElement(By.Id("change-variable-value")).Click(); Browser.Equal("Sixth", () => boundValue.Text); // Verify we can select options whose value is empty // https://github.com/dotnet/aspnetcore/issues/17735 target.SelectByText("Empty value"); Browser.Equal(string.Empty, () => boundValue.Text); Browser.Equal("Empty value", () => target.SelectedOption.Text); } [Fact] public void CanBindSelectToMarkup() { var target = new SelectElement(Browser.FindElement(By.Id("select-markup-box"))); var boundValue = Browser.FindElement(By.Id("select-markup-box-value")); Assert.Equal("Second choice", target.SelectedOption.Text); Assert.Equal("Second", boundValue.Text); // Modify target; verify value is updated target.SelectByText("Third choice"); Browser.Equal("Third", () => boundValue.Text); // Verify we can select options whose value is empty // https://github.com/dotnet/aspnetcore/issues/17735 target.SelectByText("Empty value"); Browser.Equal(string.Empty, () => boundValue.Text); Browser.Equal("Empty value", () => target.SelectedOption.Text); } [Fact] public void CanBindTextboxInt() { var target = Browser.FindElement(By.Id("textbox-int")); var boundValue = Browser.FindElement(By.Id("textbox-int-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-int-mirror")); Assert.Equal("-42", target.GetAttribute("value")); Assert.Equal("-42", boundValue.Text); Assert.Equal("-42", mirrorValue.GetAttribute("value")); // Clear target; value resets to zero target.Clear(); Browser.Equal("0", () => target.GetAttribute("value")); Assert.Equal("0", boundValue.Text); Assert.Equal("0", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // Leading zeros are not preserved target.SendKeys("42"); Browser.Equal("042", () => target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal("42", () => target.GetAttribute("value")); Assert.Equal("42", boundValue.Text); Assert.Equal("42", mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxNullableInt() { var target = Browser.FindElement(By.Id("textbox-nullable-int")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-int-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-int-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("-42\t"); Browser.Equal("-42", () => boundValue.Text); Assert.Equal("-42", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("42\t"); Browser.Equal("42", () => boundValue.Text); Assert.Equal("42", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxLong() { var target = Browser.FindElement(By.Id("textbox-long")); var boundValue = Browser.FindElement(By.Id("textbox-long-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-long-mirror")); Assert.Equal("3000000000", target.GetAttribute("value")); Assert.Equal("3000000000", boundValue.Text); Assert.Equal("3000000000", mirrorValue.GetAttribute("value")); // Clear target; value resets to zero target.Clear(); Browser.Equal("0", () => target.GetAttribute("value")); Assert.Equal("0", boundValue.Text); Assert.Equal("0", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Backspace); target.SendKeys("-3000000000\t"); Browser.Equal("-3000000000", () => target.GetAttribute("value")); Assert.Equal("-3000000000", boundValue.Text); Assert.Equal("-3000000000", mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxNullableLong() { var target = Browser.FindElement(By.Id("textbox-nullable-long")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-long-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-long-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("3000000000\t"); Browser.Equal("3000000000", () => boundValue.Text); Assert.Equal("3000000000", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("-3000000000\t"); Browser.Equal("-3000000000", () => boundValue.Text); Assert.Equal("-3000000000", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxShort() { var target = Browser.FindElement(By.Id("textbox-short")); var boundValue = Browser.FindElement(By.Id("textbox-short-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-short-mirror")); Assert.Equal("-42", target.GetAttribute("value")); Assert.Equal("-42", boundValue.Text); Assert.Equal("-42", mirrorValue.GetAttribute("value")); // Clear target; value resets to zero target.Clear(); Browser.Equal("0", () => target.GetAttribute("value")); Assert.Equal("0", boundValue.Text); Assert.Equal("0", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // Leading zeros are not preserved target.SendKeys("42"); Browser.Equal("042", () => target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal("42", () => target.GetAttribute("value")); Assert.Equal("42", boundValue.Text); Assert.Equal("42", mirrorValue.GetAttribute("value")); } [Fact] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23826")] public void CanBindTextboxNullableShort() { var target = Browser.FindElement(By.Id("textbox-nullable-short")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-short-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-short-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("-42\t"); Browser.Equal("-42", () => boundValue.Text); Assert.Equal("-42", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("42\t"); Browser.Equal("42", () => boundValue.Text); Assert.Equal("42", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxFloat() { var target = Browser.FindElement(By.Id("textbox-float")); var boundValue = Browser.FindElement(By.Id("textbox-float-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-float-mirror")); Assert.Equal("3.141", target.GetAttribute("value")); Assert.Equal("3.141", boundValue.Text); Assert.Equal("3.141", mirrorValue.GetAttribute("value")); // Clear target; value resets to zero target.Clear(); Browser.Equal("0", () => target.GetAttribute("value")); Assert.Equal("0", boundValue.Text); Assert.Equal("0", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Backspace); target.SendKeys("-3.141\t"); Browser.Equal("-3.141", () => target.GetAttribute("value")); Assert.Equal("-3.141", boundValue.Text); Assert.Equal("-3.141", mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxNullableFloat() { var target = Browser.FindElement(By.Id("textbox-nullable-float")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-float-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-float-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("3.141\t"); Browser.Equal("3.141", () => boundValue.Text); Assert.Equal("3.141", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("-3.141\t"); Browser.Equal("-3.141", () => boundValue.Text); Assert.Equal("-3.141", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxDouble() { var target = Browser.FindElement(By.Id("textbox-double")); var boundValue = Browser.FindElement(By.Id("textbox-double-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-double-mirror")); Assert.Equal("3.14159265359", target.GetAttribute("value")); Assert.Equal("3.14159265359", boundValue.Text); Assert.Equal("3.14159265359", mirrorValue.GetAttribute("value")); // Clear target; value resets to default target.Clear(); Browser.Equal("0", () => target.GetAttribute("value")); Assert.Equal("0", boundValue.Text); Assert.Equal("0", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Backspace); target.SendKeys("-3.14159265359\t"); Browser.Equal("-3.14159265359", () => boundValue.Text); Assert.Equal("-3.14159265359", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // Double shouldn't preserve trailing zeros target.Clear(); target.SendKeys(Keys.Backspace); target.SendKeys("0.010\t"); Browser.Equal("0.01", () => target.GetAttribute("value")); Assert.Equal("0.01", boundValue.Text); Assert.Equal("0.01", mirrorValue.GetAttribute("value")); } [Fact] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")] public void CanBindTextboxNullableDouble() { var target = Browser.FindElement(By.Id("textbox-nullable-double")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-double-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-double-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("3.14159265359\t"); Browser.Equal("3.14159265359", () => boundValue.Text); Assert.Equal("3.14159265359", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("-3.14159265359\t"); Browser.Equal("-3.14159265359", () => boundValue.Text); Assert.Equal("-3.14159265359", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // Double shouldn't preserve trailing zeros target.Clear(); target.SendKeys("0.010\t"); Browser.Equal("0.01", () => boundValue.Text); Assert.Equal("0.01", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxDecimal() { var target = Browser.FindElement(By.Id("textbox-decimal")); var boundValue = Browser.FindElement(By.Id("textbox-decimal-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-decimal-mirror")); Assert.Equal("0.0000000000000000000000000001", target.GetAttribute("value")); Assert.Equal("0.0000000000000000000000000001", boundValue.Text); Assert.Equal("0.0000000000000000000000000001", mirrorValue.GetAttribute("value")); // Clear textbox; value updates to zero because that's the default target.Clear(); Browser.Equal("0", () => target.GetAttribute("value")); Assert.Equal("0", boundValue.Text); Assert.Equal("0", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // Decimal should preserve trailing zeros target.SendKeys("0.010\t"); Browser.Equal("0.010", () => boundValue.Text); Assert.Equal("0.010", mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxNullableDecimal() { var target = Browser.FindElement(By.Id("textbox-nullable-decimal")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-decimal-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-decimal-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("0.0000000000000000000000000001\t"); Browser.Equal("0.0000000000000000000000000001", () => boundValue.Text); Assert.Equal("0.0000000000000000000000000001", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // Decimal should preserve trailing zeros target.Clear(); target.SendKeys("0.010\t"); Browser.Equal("0.010", () => boundValue.Text); Assert.Equal("0.010", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // This tests what happens you put invalid (unconvertable) input in. This is separate from the // other tests because it requires type="text" - the other tests use type="number" [Fact] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/24756")] public void CanBindTextbox_Decimal_InvalidInput() { var target = Browser.FindElement(By.Id("textbox-decimal-invalid")); var boundValue = Browser.FindElement(By.Id("textbox-decimal-invalid-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-decimal-invalid-mirror")); Assert.Equal("0.0000000000000000000000000001", target.GetAttribute("value")); Assert.Equal("0.0000000000000000000000000001", boundValue.Text); Assert.Equal("0.0000000000000000000000000001", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("0.01\t"); Browser.Equal("0.01", () => boundValue.Text); Assert.Equal("0.01", mirrorValue.GetAttribute("value")); // Modify target to something invalid - the invalid change is reverted // back to the last valid value target.SendKeys("2A"); Assert.Equal("0.012A", target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal("0.01", () => boundValue.Text); Assert.Equal("0.01", mirrorValue.GetAttribute("value")); Assert.Equal("0.01", target.GetAttribute("value")); // Continue editing with valid inputs target.SendKeys(Keys.Backspace); target.SendKeys("2\t"); Browser.Equal("0.02", () => boundValue.Text); Assert.Equal("0.02", mirrorValue.GetAttribute("value")); } // This tests what happens you put invalid (unconvertable) input in. This is separate from the // other tests because it requires type="text" - the other tests use type="number" [Fact] public void CanBindTextbox_NullableDecimal_InvalidInput() { var target = Browser.FindElement(By.Id("textbox-nullable-decimal-invalid")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-decimal-invalid-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-decimal-invalid-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("0.01\t"); Browser.Equal("0.01", () => boundValue.Text); Assert.Equal("0.01", mirrorValue.GetAttribute("value")); // Modify target to something invalid - the invalid change is reverted // back to the last valid value target.SendKeys("2A"); Assert.Equal("0.012A", target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal("0.01", () => boundValue.Text); Assert.Equal("0.01", mirrorValue.GetAttribute("value")); Assert.Equal("0.01", target.GetAttribute("value")); // Continue editing with valid inputs target.SendKeys(Keys.Backspace); target.SendKeys("2\t"); Browser.Equal("0.02", () => boundValue.Text); Assert.Equal("0.02", mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxGenericInt() { var target = Browser.FindElement(By.Id("textbox-generic-int")); var boundValue = Browser.FindElement(By.Id("textbox-generic-int-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-generic-int-mirror")); Assert.Equal("-42", target.GetAttribute("value")); Assert.Equal("-42", boundValue.Text); Assert.Equal("-42", mirrorValue.GetAttribute("value")); // Clear target; value resets to zero target.Clear(); Browser.Equal("0", () => target.GetAttribute("value")); Assert.Equal("0", boundValue.Text); Assert.Equal("0", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("42\t"); Browser.Equal("42", () => boundValue.Text); Assert.Equal("42", mirrorValue.GetAttribute("value")); } [Fact] public void CanBindTextboxGenericGuid() { var target = Browser.FindElement(By.Id("textbox-generic-guid")); var boundValue = Browser.FindElement(By.Id("textbox-generic-guid-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-generic-guid-mirror")); Assert.Equal("00000000-0000-0000-0000-000000000000", target.GetAttribute("value")); Assert.Equal("00000000-0000-0000-0000-000000000000", boundValue.Text); Assert.Equal("00000000-0000-0000-0000-000000000000", mirrorValue.GetAttribute("value")); // Modify target; value is not updated because it's not convertable. target.Clear(); Browser.Equal("00000000-0000-0000-0000-000000000000", () => boundValue.Text); Assert.Equal("00000000-0000-0000-0000-000000000000", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated var newValue = Guid.NewGuid().ToString(); target.SendKeys(newValue + "\t"); Browser.Equal(newValue, () => boundValue.Text); Assert.Equal(newValue, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxDateTime() { var target = Browser.FindElement(By.Id("textbox-datetime")); var boundValue = Browser.FindElement(By.Id("textbox-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-datetime-mirror")); var expected = new DateTime(1985, 3, 4); Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01/02/2000 00:00:00\t"); expected = new DateTime(2000, 1, 2); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxNullableDateTime() { var target = Browser.FindElement(By.Id("textbox-nullable-datetime")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-datetime-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated var expected = new DateTime(2000, 1, 2); target.SendKeys("01/02/2000 00:00:00\t"); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxDateTimeOffset() { var target = Browser.FindElement(By.Id("textbox-datetimeoffset")); var boundValue = Browser.FindElement(By.Id("textbox-datetimeoffset-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-datetimeoffset-mirror")); var expected = new DateTimeOffset(new DateTime(1985, 3, 4), TimeSpan.FromHours(8)); Assert.Equal(expected, DateTimeOffset.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; Browser.Equal(expected, () => DateTimeOffset.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01/02/2000 00:00:00 +08:00\t"); expected = new DateTimeOffset(new DateTime(2000, 1, 2), TimeSpan.FromHours(8)); Browser.Equal(expected, () => DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxNullableDateTimeOffset() { var target = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("01/02/2000 00:00:00 +08:00" + "\t"); var expected = new DateTimeOffset(new DateTime(2000, 1, 2), TimeSpan.FromHours(8)); Browser.Equal(expected, () => DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxDateTimeWithFormat() { var target = Browser.FindElement(By.Id("textbox-datetime-format")); var boundValue = Browser.FindElement(By.Id("textbox-datetime-format-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-datetime-format-mirror")); var expected = new DateTime(1985, 3, 4); Assert.Equal("03-04", target.GetAttribute("value")); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to the default target.Clear(); target.SendKeys("\t"); expected = default; Browser.Equal("01-01", () => target.GetAttribute("value")); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01-02\t"); expected = new DateTime(DateTime.Now.Year, 1, 2); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxNullableDateTimeWithFormat() { var target = Browser.FindElement(By.Id("textbox-nullable-datetime-format")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-datetime-format-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-datetime-format-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("01-02\t"); var expected = new DateTime(DateTime.Now.Year, 1, 2); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxDateTimeOffsetWithFormat() { var target = Browser.FindElement(By.Id("textbox-datetimeoffset-format")); var boundValue = Browser.FindElement(By.Id("textbox-datetimeoffset-format-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-datetimeoffset-format-mirror")); var expected = new DateTimeOffset(new DateTime(1985, 3, 4), TimeSpan.FromHours(8)); Assert.Equal("03-04", target.GetAttribute("value")); Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to the default target.Clear(); expected = default; Browser.Equal("01-01", () => target.GetAttribute("value")); Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01-02\t"); expected = new DateTimeOffset(new DateTime(DateTime.Now.Year, 1, 2), TimeSpan.FromHours(0)); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. // // Guess what! Client-side and server-side also understand timezones differently. So for now we're comparing // the parsed output without consideration for the timezone [Fact] public void CanBindTextboxNullableDateTimeOffsetWithFormat() { var target = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("01-02" + "\t"); var expected = new DateTimeOffset(new DateTime(DateTime.Now.Year, 1, 2), TimeSpan.FromHours(0)); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxNullableDateTime_InvalidValue() { var target = Browser.FindElement(By.Id("textbox-nullable-datetime-invalid")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-datetime-invalid-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-datetime-invalid-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated var expected = new DateTime(2000, 1, 2); target.SendKeys("01/02/2000 00:00:00\t"); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target to something invalid - the invalid change is reverted // back to the last valid value target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06A"); Browser.Equal("05/06A", () => target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxDateTimeOffset_InvalidValue() { var target = Browser.FindElement(By.Id("textbox-datetimeoffset-invalid")); var boundValue = Browser.FindElement(By.Id("textbox-datetimeoffset-invalid-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-datetimeoffset-invalid-mirror")); var expected = new DateTimeOffset(new DateTime(1985, 3, 4), TimeSpan.FromHours(8)); Assert.Equal(expected, DateTimeOffset.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated expected = new DateTime(2000, 1, 2); target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01/02/2000 00:00:00\t"); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); // Modify target to something invalid - the invalid change is reverted // back to the last valid value target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06A"); Browser.Equal("05/06A", () => target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(target.GetAttribute("value")).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxDateTimeWithFormat_InvalidValue() { var target = Browser.FindElement(By.Id("textbox-datetime-format-invalid")); var boundValue = Browser.FindElement(By.Id("textbox-datetime-format-invalid-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-datetime-format-invalid-mirror")); var expected = new DateTime(1985, 3, 4); Assert.Equal("03-04", target.GetAttribute("value")); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target to something invalid - the invalid change is reverted // back to the last valid value target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06"); Browser.Equal("05/06", () => target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal("03-04", () => target.GetAttribute("value")); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05-06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTextboxNullableDateTimeOffsetWithFormat_InvalidValue() { var target = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset-format-invalid")); var boundValue = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset-format-invalid-value")); var mirrorValue = Browser.FindElement(By.Id("textbox-nullable-datetimeoffset-format-invalid-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated var expected = new DateTimeOffset(new DateTime(DateTime.Now.Year, 1, 2)); target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01-02\t"); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); // Modify target to something invalid - the invalid change is reverted // back to the last valid value target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06"); Browser.Equal("05/06", () => target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(target.GetAttribute("value")).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05-06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindDateTimeLocalTextboxDateTime() { var target = Browser.FindElement(By.Id("datetime-local-textbox-datetime")); var boundValue = Browser.FindElement(By.Id("datetime-local-textbox-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("datetime-local-textbox-datetime-mirror")); var expected = new DateTime(1985, 3, 4); Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#datetime-local-textbox-datetime", "2000-01-02T04:05:06"); expected = new DateTime(2000, 1, 2, 04, 05, 06); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindDateTimeLocalTextboxNullableDateTime() { var target = Browser.FindElement(By.Id("datetime-local-textbox-nullable-datetime")); var boundValue = Browser.FindElement(By.Id("datetime-local-textbox-nullable-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("datetime-local-textbox-nullable-datetime-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#datetime-local-textbox-nullable-datetime", "2000-01-02T04:05:06"); var expected = new DateTime(2000, 1, 2, 04, 05, 06); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindMonthTextboxDateTime() { var target = Browser.FindElement(By.Id("month-textbox-datetime")); var boundValue = Browser.FindElement(By.Id("month-textbox-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("month-textbox-datetime-mirror")); var expected = new DateTime(1985, 3, 1); Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); // When the value gets displayed the first time it gets truncated to the 1st day, // until there is no change the bound value doesn't get updated. Assert.Equal(expected.AddDays(3), DateTime.Parse(boundValue.Text)); Assert.Equal(expected.AddDays(3), DateTime.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#month-textbox-datetime", "2000-02"); expected = new DateTime(2000, 2, 1); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindMonthTextboxNullableDateTime() { var target = Browser.FindElement(By.Id("month-textbox-nullable-datetime")); var boundValue = Browser.FindElement(By.Id("month-textbox-nullable-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("month-textbox-nullable-datetime-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#month-textbox-nullable-datetime", "2000-02"); var expected = new DateTime(2000, 2, 1); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTimeTextboxDateTime() { var target = Browser.FindElement(By.Id("time-textbox-datetime")); var boundValue = Browser.FindElement(By.Id("time-textbox-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("time-textbox-datetime-mirror")); var expected = DateTime.Now.Date.AddHours(8).AddMinutes(5); Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to 00:00 because that's the default target.Clear(); expected = default; Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(default, DateTime.Parse(boundValue.Text)); Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value"))); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#time-textbox-datetime", "04:05"); expected = DateTime.Now.Date.Add(new TimeSpan(4, 5, 0)); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTimeTextboxNullableDateTime() { var target = Browser.FindElement(By.Id("time-textbox-nullable-datetime")); var boundValue = Browser.FindElement(By.Id("time-textbox-nullable-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("time-textbox-nullable-datetime-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#time-textbox-nullable-datetime", "05:06"); var expected = DateTime.Now.Date.Add(new TimeSpan(05, 06, 0)); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTimeStepTextboxDateTime() { var target = Browser.FindElement(By.Id("time-step-textbox-datetime")); var boundValue = Browser.FindElement(By.Id("time-step-textbox-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("time-step-textbox-datetime-mirror")); var expected = DateTime.Now.Date.Add(new TimeSpan(8, 5, 30)); Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(expected, DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Clear textbox; value updates to 00:00 because that's the default target.Clear(); expected = default; Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value"))); Assert.Equal(default, DateTime.Parse(boundValue.Text)); Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value"))); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#time-step-textbox-datetime", "04:05:06"); expected = DateTime.Now.Date.Add(new TimeSpan(4, 5, 6)); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side // Blazor have different formatting behaviour by default. [Fact] public void CanBindTimeStepTextboxNullableDateTime() { var target = Browser.FindElement(By.Id("time-step-textbox-nullable-datetime")); var boundValue = Browser.FindElement(By.Id("time-step-textbox-nullable-datetime-value")); var mirrorValue = Browser.FindElement(By.Id("time-step-textbox-nullable-datetime-mirror")); Assert.Equal(string.Empty, target.GetAttribute("value")); Assert.Equal(string.Empty, boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); Browser.Equal("", () => boundValue.Text); Assert.Equal("", mirrorValue.GetAttribute("value")); // Modify target; verify value is updated and that textboxes linked to the same data are updated // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#time-step-textbox-nullable-datetime", "05:06"); var expected = DateTime.Now.Date.Add(new TimeSpan(05, 06, 0)); Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); target.SendKeys("\t"); Browser.Equal(string.Empty, () => boundValue.Text); Assert.Equal(string.Empty, mirrorValue.GetAttribute("value")); } // Applies an input through javascript to datetime-local/month/time controls. private void ApplyInputValue(string cssSelector, string value) { // 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( $"var elem = document.querySelector('{cssSelector}');" + $"elem.value = '{value}';" + "elem.dispatchEvent(new KeyboardEvent('change'));"); } } }