TextBoxTests_DataValidation.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using Avalonia.Controls.Presenters;
  7. using Avalonia.Controls.Templates;
  8. using Avalonia.Data;
  9. using Avalonia.Markup.Data;
  10. using Avalonia.Platform;
  11. using Avalonia.UnitTests;
  12. using Moq;
  13. using Xunit;
  14. namespace Avalonia.Controls.UnitTests
  15. {
  16. public class TextBoxTests_DataValidation
  17. {
  18. [Fact]
  19. public void Setter_Exceptions_Should_Set_Error_Pseudoclass()
  20. {
  21. using (UnitTestApplication.Start(Services))
  22. {
  23. var target = new TextBox
  24. {
  25. DataContext = new ExceptionTest(),
  26. [!TextBox.TextProperty] = new Binding(nameof(ExceptionTest.LessThan10), BindingMode.TwoWay),
  27. Template = CreateTemplate(),
  28. };
  29. target.ApplyTemplate();
  30. Assert.DoesNotContain(":error", target.Classes);
  31. target.Text = "20";
  32. Assert.Contains(":error", target.Classes);
  33. target.Text = "1";
  34. Assert.DoesNotContain(":error", target.Classes);
  35. }
  36. }
  37. [Fact]
  38. public void Setter_Exceptions_Should_Set_DataValidationErrors_Errors()
  39. {
  40. using (UnitTestApplication.Start(Services))
  41. {
  42. var target = new TextBox
  43. {
  44. DataContext = new ExceptionTest(),
  45. [!TextBox.TextProperty] = new Binding(nameof(ExceptionTest.LessThan10), BindingMode.TwoWay),
  46. Template = CreateTemplate(),
  47. };
  48. target.ApplyTemplate();
  49. Assert.Null(DataValidationErrors.GetErrors(target));
  50. target.Text = "20";
  51. IEnumerable<object> errors = DataValidationErrors.GetErrors(target);
  52. Assert.Single(errors);
  53. Assert.IsType<InvalidOperationException>(errors.Single());
  54. target.Text = "1";
  55. Assert.Null(DataValidationErrors.GetErrors(target));
  56. }
  57. }
  58. [Fact]
  59. public void Setter_Exceptions_Should_Set_DataValidationErrors_HasErrors()
  60. {
  61. using (UnitTestApplication.Start(Services))
  62. {
  63. var target = new TextBox
  64. {
  65. DataContext = new ExceptionTest(),
  66. [!TextBox.TextProperty] = new Binding(nameof(ExceptionTest.LessThan10), BindingMode.TwoWay),
  67. Template = CreateTemplate(),
  68. };
  69. target.ApplyTemplate();
  70. Assert.False(DataValidationErrors.GetHasErrors(target));
  71. target.Text = "20";
  72. Assert.True(DataValidationErrors.GetHasErrors(target));
  73. target.Text = "1";
  74. Assert.False(DataValidationErrors.GetHasErrors(target));
  75. }
  76. }
  77. private static TestServices Services => TestServices.MockThreadingInterface.With(
  78. standardCursorFactory: Mock.Of<ICursorFactory>());
  79. private IControlTemplate CreateTemplate()
  80. {
  81. return new FuncControlTemplate<TextBox>((control, scope) =>
  82. new TextPresenter
  83. {
  84. Name = "PART_TextPresenter",
  85. [!!TextPresenter.TextProperty] = new Binding
  86. {
  87. Path = "Text",
  88. Mode = BindingMode.TwoWay,
  89. Priority = BindingPriority.TemplatedParent,
  90. RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
  91. },
  92. }.RegisterInNameScope(scope));
  93. }
  94. private class ExceptionTest
  95. {
  96. private int _lessThan10;
  97. public int LessThan10
  98. {
  99. get { return _lessThan10; }
  100. set
  101. {
  102. if (value < 10)
  103. {
  104. _lessThan10 = value;
  105. }
  106. else
  107. {
  108. throw new InvalidOperationException("More than 10.");
  109. }
  110. }
  111. }
  112. }
  113. private class IndeiTest : INotifyDataErrorInfo
  114. {
  115. private int _lessThan10;
  116. private Dictionary<string, IList<string>> _errors = new Dictionary<string, IList<string>>();
  117. public int LessThan10
  118. {
  119. get { return _lessThan10; }
  120. set
  121. {
  122. if (value < 10)
  123. {
  124. _lessThan10 = value;
  125. _errors.Remove(nameof(LessThan10));
  126. ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(LessThan10)));
  127. }
  128. else
  129. {
  130. _errors[nameof(LessThan10)] = new[] { "More than 10" };
  131. ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(LessThan10)));
  132. }
  133. }
  134. }
  135. public bool HasErrors => _lessThan10 >= 10;
  136. public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
  137. public IEnumerable GetErrors(string propertyName)
  138. {
  139. IList<string> result;
  140. _errors.TryGetValue(propertyName, out result);
  141. return result;
  142. }
  143. }
  144. }
  145. }