PriorityValueTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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 AvaloniaObject Owner = new AvaloniaObject();
  13. private static readonly ValueStore ValueStore = new ValueStore(Owner);
  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. ValueStore,
  25. new ConstantValueEntry<string>(
  26. TestProperty,
  27. "1",
  28. BindingPriority.StyleTrigger,
  29. new(ValueStore)));
  30. Assert.Equal("1", target.GetValue().Value);
  31. Assert.Equal(BindingPriority.StyleTrigger, target.Priority);
  32. }
  33. [Fact]
  34. public void GetValue_Should_Respect_MaxPriority()
  35. {
  36. var target = new PriorityValue<string>(
  37. Owner,
  38. TestProperty,
  39. ValueStore);
  40. target.SetValue("animation", BindingPriority.Animation);
  41. target.SetValue("local", BindingPriority.LocalValue);
  42. target.SetValue("styletrigger", BindingPriority.StyleTrigger);
  43. target.SetValue("style", BindingPriority.Style);
  44. Assert.Equal("animation", target.GetValue(BindingPriority.Animation));
  45. Assert.Equal("local", target.GetValue(BindingPriority.LocalValue));
  46. Assert.Equal("styletrigger", target.GetValue(BindingPriority.StyleTrigger));
  47. Assert.Equal("style", target.GetValue(BindingPriority.TemplatedParent));
  48. Assert.Equal("style", target.GetValue(BindingPriority.Style));
  49. }
  50. [Fact]
  51. public void SetValue_LocalValue_Should_Not_Add_Entries()
  52. {
  53. var target = new PriorityValue<string>(
  54. Owner,
  55. TestProperty,
  56. ValueStore);
  57. target.SetValue("1", BindingPriority.LocalValue);
  58. target.SetValue("2", BindingPriority.LocalValue);
  59. Assert.Empty(target.Entries);
  60. }
  61. [Fact]
  62. public void SetValue_Non_LocalValue_Should_Add_Entries()
  63. {
  64. var target = new PriorityValue<string>(
  65. Owner,
  66. TestProperty,
  67. ValueStore);
  68. target.SetValue("1", BindingPriority.Style);
  69. target.SetValue("2", BindingPriority.Animation);
  70. var result = target.Entries
  71. .OfType<ConstantValueEntry<string>>()
  72. .Select(x => x.GetValue().Value)
  73. .ToList();
  74. Assert.Equal(new[] { "1", "2" }, result);
  75. }
  76. [Fact]
  77. public void Priority_Should_Be_Set()
  78. {
  79. var target = new PriorityValue<string>(
  80. Owner,
  81. TestProperty,
  82. ValueStore);
  83. Assert.Equal(BindingPriority.Unset, target.Priority);
  84. target.SetValue("style", BindingPriority.Style);
  85. Assert.Equal(BindingPriority.Style, target.Priority);
  86. target.SetValue("local", BindingPriority.LocalValue);
  87. Assert.Equal(BindingPriority.LocalValue, target.Priority);
  88. target.SetValue("animation", BindingPriority.Animation);
  89. Assert.Equal(BindingPriority.Animation, target.Priority);
  90. target.SetValue("local2", BindingPriority.LocalValue);
  91. Assert.Equal(BindingPriority.Animation, target.Priority);
  92. }
  93. [Fact]
  94. public void Binding_With_Same_Priority_Should_Be_Appended()
  95. {
  96. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  97. var source1 = new Source("1");
  98. var source2 = new Source("2");
  99. target.AddBinding(source1, BindingPriority.LocalValue);
  100. target.AddBinding(source2, BindingPriority.LocalValue);
  101. var result = target.Entries
  102. .OfType<BindingEntry<string>>()
  103. .Select(x => x.Source)
  104. .OfType<Source>()
  105. .Select(x => x.Id)
  106. .ToList();
  107. Assert.Equal(new[] { "1", "2" }, result);
  108. }
  109. [Fact]
  110. public void Binding_With_Higher_Priority_Should_Be_Appended()
  111. {
  112. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  113. var source1 = new Source("1");
  114. var source2 = new Source("2");
  115. target.AddBinding(source1, BindingPriority.LocalValue);
  116. target.AddBinding(source2, BindingPriority.Animation);
  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[] { "1", "2" }, result);
  124. }
  125. [Fact]
  126. public void Binding_With_Lower_Priority_Should_Be_Prepended()
  127. {
  128. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  129. var source1 = new Source("1");
  130. var source2 = new Source("2");
  131. target.AddBinding(source1, BindingPriority.LocalValue);
  132. target.AddBinding(source2, BindingPriority.Style);
  133. var result = target.Entries
  134. .OfType<BindingEntry<string>>()
  135. .Select(x => x.Source)
  136. .OfType<Source>()
  137. .Select(x => x.Id)
  138. .ToList();
  139. Assert.Equal(new[] { "2", "1" }, result);
  140. }
  141. [Fact]
  142. public void Second_Binding_With_Lower_Priority_Should_Be_Inserted_In_Middle()
  143. {
  144. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  145. var source1 = new Source("1");
  146. var source2 = new Source("2");
  147. var source3 = new Source("3");
  148. target.AddBinding(source1, BindingPriority.LocalValue);
  149. target.AddBinding(source2, BindingPriority.Style);
  150. target.AddBinding(source3, BindingPriority.Style);
  151. var result = target.Entries
  152. .OfType<BindingEntry<string>>()
  153. .Select(x => x.Source)
  154. .OfType<Source>()
  155. .Select(x => x.Id)
  156. .ToList();
  157. Assert.Equal(new[] { "2", "3", "1" }, result);
  158. }
  159. [Fact]
  160. public void Competed_Binding_Should_Be_Removed()
  161. {
  162. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  163. var source1 = new Source("1");
  164. var source2 = new Source("2");
  165. var source3 = new Source("3");
  166. target.AddBinding(source1, BindingPriority.LocalValue).Start();
  167. target.AddBinding(source2, BindingPriority.Style).Start();
  168. target.AddBinding(source3, BindingPriority.Style).Start();
  169. source3.OnCompleted();
  170. var result = target.Entries
  171. .OfType<BindingEntry<string>>()
  172. .Select(x => x.Source)
  173. .OfType<Source>()
  174. .Select(x => x.Id)
  175. .ToList();
  176. Assert.Equal(new[] { "2", "1" }, result);
  177. }
  178. [Fact]
  179. public void Value_Should_Come_From_Last_Entry()
  180. {
  181. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  182. var source1 = new Source("1");
  183. var source2 = new Source("2");
  184. var source3 = new Source("3");
  185. target.AddBinding(source1, BindingPriority.LocalValue).Start();
  186. target.AddBinding(source2, BindingPriority.Style).Start();
  187. target.AddBinding(source3, BindingPriority.Style).Start();
  188. Assert.Equal("1", target.GetValue().Value);
  189. }
  190. [Fact]
  191. public void LocalValue_Should_Override_LocalValue_Binding()
  192. {
  193. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  194. var source1 = new Source("1");
  195. target.AddBinding(source1, BindingPriority.LocalValue).Start();
  196. target.SetValue("2", BindingPriority.LocalValue);
  197. Assert.Equal("2", target.GetValue().Value);
  198. }
  199. [Fact]
  200. public void LocalValue_Should_Override_Style_Binding()
  201. {
  202. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  203. var source1 = new Source("1");
  204. target.AddBinding(source1, BindingPriority.Style).Start();
  205. target.SetValue("2", BindingPriority.LocalValue);
  206. Assert.Equal("2", target.GetValue().Value);
  207. }
  208. [Fact]
  209. public void LocalValue_Should_Not_Override_Animation_Binding()
  210. {
  211. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  212. var source1 = new Source("1");
  213. target.AddBinding(source1, BindingPriority.Animation).Start();
  214. target.SetValue("2", BindingPriority.LocalValue);
  215. Assert.Equal("1", target.GetValue().Value);
  216. }
  217. [Fact]
  218. public void NonAnimated_Value_Should_Be_Correct_1()
  219. {
  220. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  221. var source1 = new Source("1");
  222. var source2 = new Source("2");
  223. var source3 = new Source("3");
  224. target.AddBinding(source1, BindingPriority.LocalValue).Start();
  225. target.AddBinding(source2, BindingPriority.Style).Start();
  226. target.AddBinding(source3, BindingPriority.Animation).Start();
  227. Assert.Equal("3", target.GetValue().Value);
  228. Assert.Equal("1", target.GetValue(BindingPriority.LocalValue).Value);
  229. }
  230. [Fact]
  231. public void NonAnimated_Value_Should_Be_Correct_2()
  232. {
  233. var target = new PriorityValue<string>(Owner, TestProperty, ValueStore);
  234. var source1 = new Source("1");
  235. var source2 = new Source("2");
  236. var source3 = new Source("3");
  237. target.AddBinding(source1, BindingPriority.Animation).Start();
  238. target.AddBinding(source2, BindingPriority.Style).Start();
  239. target.AddBinding(source3, BindingPriority.Style).Start();
  240. Assert.Equal("1", target.GetValue().Value);
  241. Assert.Equal("3", target.GetValue(BindingPriority.LocalValue).Value);
  242. }
  243. private class Source : IObservable<BindingValue<string>>
  244. {
  245. private IObserver<BindingValue<string>> _observer;
  246. public Source(string id) => Id = id;
  247. public string Id { get; }
  248. public IDisposable Subscribe(IObserver<BindingValue<string>> observer)
  249. {
  250. _observer = observer;
  251. observer.OnNext(Id);
  252. return Disposable.Empty;
  253. }
  254. public void OnCompleted() => _observer.OnCompleted();
  255. }
  256. }
  257. }