PriorityValueTests.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. using System;
  2. using System.Linq;
  3. using System.Reactive.Disposables;
  4. using Avalonia.Data;
  5. using Avalonia.PropertyStore;
  6. using Moq;
  7. using Xunit;
  8. namespace Avalonia.Base.UnitTests
  9. {
  10. public class PriorityValueTests
  11. {
  12. private static readonly IValueSink NullSink = Mock.Of<IValueSink>();
  13. private static readonly IAvaloniaObject Owner = Mock.Of<IAvaloniaObject>();
  14. private static readonly StyledProperty<string> TestProperty = new StyledProperty<string>(
  15. "Test",
  16. typeof(PriorityValueTests),
  17. new StyledPropertyMetadata<string>());
  18. [Fact]
  19. public void Constructor_Should_Set_Value_Based_On_Initial_Entry()
  20. {
  21. var target = new PriorityValue<string>(
  22. Owner,
  23. TestProperty,
  24. NullSink,
  25. new ConstantValueEntry<string>(
  26. TestProperty,
  27. "1",
  28. BindingPriority.StyleTrigger,
  29. NullSink));
  30. Assert.Equal("1", target.Value.Value);
  31. Assert.Equal(BindingPriority.StyleTrigger, target.ValuePriority);
  32. }
  33. [Fact]
  34. public void SetValue_LocalValue_Should_Not_Add_Entries()
  35. {
  36. var target = new PriorityValue<string>(
  37. Owner,
  38. TestProperty,
  39. NullSink);
  40. target.SetValue("1", BindingPriority.LocalValue);
  41. target.SetValue("2", BindingPriority.LocalValue);
  42. Assert.Empty(target.Entries);
  43. }
  44. [Fact]
  45. public void SetValue_Non_LocalValue_Should_Add_Entries()
  46. {
  47. var target = new PriorityValue<string>(
  48. Owner,
  49. TestProperty,
  50. NullSink);
  51. target.SetValue("1", BindingPriority.Style);
  52. target.SetValue("2", BindingPriority.Animation);
  53. var result = target.Entries
  54. .OfType<ConstantValueEntry<string>>()
  55. .Select(x => x.Value.Value)
  56. .ToList();
  57. Assert.Equal(new[] { "1", "2" }, result);
  58. }
  59. [Fact]
  60. public void Binding_With_Same_Priority_Should_Be_Appended()
  61. {
  62. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  63. var source1 = new Source("1");
  64. var source2 = new Source("2");
  65. target.AddBinding(source1, BindingPriority.LocalValue);
  66. target.AddBinding(source2, BindingPriority.LocalValue);
  67. var result = target.Entries
  68. .OfType<BindingEntry<string>>()
  69. .Select(x => x.Source)
  70. .OfType<Source>()
  71. .Select(x => x.Id)
  72. .ToList();
  73. Assert.Equal(new[] { "1", "2" }, result);
  74. }
  75. [Fact]
  76. public void Binding_With_Higher_Priority_Should_Be_Appended()
  77. {
  78. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  79. var source1 = new Source("1");
  80. var source2 = new Source("2");
  81. target.AddBinding(source1, BindingPriority.LocalValue);
  82. target.AddBinding(source2, BindingPriority.Animation);
  83. var result = target.Entries
  84. .OfType<BindingEntry<string>>()
  85. .Select(x => x.Source)
  86. .OfType<Source>()
  87. .Select(x => x.Id)
  88. .ToList();
  89. Assert.Equal(new[] { "1", "2" }, result);
  90. }
  91. [Fact]
  92. public void Binding_With_Lower_Priority_Should_Be_Prepended()
  93. {
  94. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  95. var source1 = new Source("1");
  96. var source2 = new Source("2");
  97. target.AddBinding(source1, BindingPriority.LocalValue);
  98. target.AddBinding(source2, BindingPriority.Style);
  99. var result = target.Entries
  100. .OfType<BindingEntry<string>>()
  101. .Select(x => x.Source)
  102. .OfType<Source>()
  103. .Select(x => x.Id)
  104. .ToList();
  105. Assert.Equal(new[] { "2", "1" }, result);
  106. }
  107. [Fact]
  108. public void Second_Binding_With_Lower_Priority_Should_Be_Inserted_In_Middle()
  109. {
  110. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  111. var source1 = new Source("1");
  112. var source2 = new Source("2");
  113. var source3 = new Source("3");
  114. target.AddBinding(source1, BindingPriority.LocalValue);
  115. target.AddBinding(source2, BindingPriority.Style);
  116. target.AddBinding(source3, BindingPriority.Style);
  117. var result = target.Entries
  118. .OfType<BindingEntry<string>>()
  119. .Select(x => x.Source)
  120. .OfType<Source>()
  121. .Select(x => x.Id)
  122. .ToList();
  123. Assert.Equal(new[] { "2", "3", "1" }, result);
  124. }
  125. [Fact]
  126. public void Competed_Binding_Should_Be_Removed()
  127. {
  128. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  129. var source1 = new Source("1");
  130. var source2 = new Source("2");
  131. var source3 = new Source("3");
  132. target.AddBinding(source1, BindingPriority.LocalValue).Start();
  133. target.AddBinding(source2, BindingPriority.Style).Start();
  134. target.AddBinding(source3, BindingPriority.Style).Start();
  135. source3.OnCompleted();
  136. var result = target.Entries
  137. .OfType<BindingEntry<string>>()
  138. .Select(x => x.Source)
  139. .OfType<Source>()
  140. .Select(x => x.Id)
  141. .ToList();
  142. Assert.Equal(new[] { "2", "1" }, result);
  143. }
  144. [Fact]
  145. public void Value_Should_Come_From_Last_Entry()
  146. {
  147. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  148. var source1 = new Source("1");
  149. var source2 = new Source("2");
  150. var source3 = new Source("3");
  151. target.AddBinding(source1, BindingPriority.LocalValue).Start();
  152. target.AddBinding(source2, BindingPriority.Style).Start();
  153. target.AddBinding(source3, BindingPriority.Style).Start();
  154. Assert.Equal("1", target.Value.Value);
  155. }
  156. [Fact]
  157. public void LocalValue_Should_Override_LocalValue_Binding()
  158. {
  159. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  160. var source1 = new Source("1");
  161. target.AddBinding(source1, BindingPriority.LocalValue).Start();
  162. target.SetValue("2", BindingPriority.LocalValue);
  163. Assert.Equal("2", target.Value.Value);
  164. }
  165. [Fact]
  166. public void LocalValue_Should_Override_Style_Binding()
  167. {
  168. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  169. var source1 = new Source("1");
  170. target.AddBinding(source1, BindingPriority.Style).Start();
  171. target.SetValue("2", BindingPriority.LocalValue);
  172. Assert.Equal("2", target.Value.Value);
  173. }
  174. [Fact]
  175. public void LocalValue_Should_Not_Override_Animation_Binding()
  176. {
  177. var target = new PriorityValue<string>(Owner, TestProperty, NullSink);
  178. var source1 = new Source("1");
  179. target.AddBinding(source1, BindingPriority.Animation).Start();
  180. target.SetValue("2", BindingPriority.LocalValue);
  181. Assert.Equal("1", target.Value.Value);
  182. }
  183. private class Source : IObservable<BindingValue<string>>
  184. {
  185. private IObserver<BindingValue<string>> _observer;
  186. public Source(string id) => Id = id;
  187. public string Id { get; }
  188. public IDisposable Subscribe(IObserver<BindingValue<string>> observer)
  189. {
  190. _observer = observer;
  191. observer.OnNext(Id);
  192. return Disposable.Empty;
  193. }
  194. public void OnCompleted() => _observer.OnCompleted();
  195. }
  196. }
  197. }