TestPlan.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text.Json;
  4. using FluentAssertions;
  5. using NUnit.Framework;
  6. using QuestPDF.Drawing;
  7. using QuestPDF.Elements;
  8. using QuestPDF.Helpers;
  9. using QuestPDF.Infrastructure;
  10. using QuestPDF.UnitTests.TestEngine.Operations;
  11. namespace QuestPDF.UnitTests.TestEngine
  12. {
  13. internal class TestPlan
  14. {
  15. private const string DefaultChildName = "child";
  16. private static Random Random { get; } = new Random();
  17. private Element Element { get; set; }
  18. private ICanvas Canvas { get; }
  19. private Size OperationInput { get; set; }
  20. private Queue<OperationBase> Operations { get; } = new Queue<OperationBase>();
  21. public TestPlan()
  22. {
  23. Canvas = CreateCanvas();
  24. }
  25. public static TestPlan For(Func<TestPlan, Element> create)
  26. {
  27. var plan = new TestPlan();
  28. plan.Element = create(plan);
  29. return plan;
  30. }
  31. private T GetExpected<T>() where T : OperationBase
  32. {
  33. if (Operations.TryDequeue(out var value) && value is T result)
  34. return result;
  35. var gotType = value?.GetType()?.Name ?? "null";
  36. Assert.Fail($"Expected: {typeof(T).Name}, got {gotType}: {JsonSerializer.Serialize(value)}");
  37. return null;
  38. }
  39. private ICanvas CreateCanvas()
  40. {
  41. return new MockCanvas
  42. {
  43. TranslateFunc = position =>
  44. {
  45. var expected = GetExpected<CanvasTranslateOperation>();
  46. Assert.AreEqual(expected.Position.X, position.X, "Translate X");
  47. Assert.AreEqual(expected.Position.Y, position.Y, "Translate Y");
  48. },
  49. RotateFunc = angle =>
  50. {
  51. var expected = GetExpected<CanvasRotateOperation>();
  52. Assert.AreEqual(expected.Angle, angle, "Rotate angle");
  53. },
  54. ScaleFunc = (scaleX, scaleY) =>
  55. {
  56. var expected = GetExpected<CanvasScaleOperation>();
  57. Assert.AreEqual(expected.ScaleX, scaleX, "Scale X");
  58. Assert.AreEqual(expected.ScaleY, scaleY, "Scale Y");
  59. },
  60. DrawRectFunc = (position, size, color) =>
  61. {
  62. var expected = GetExpected<CanvasDrawRectangleOperation>();
  63. Assert.AreEqual(expected.Position.X, position.X, "Draw rectangle: X");
  64. Assert.AreEqual(expected.Position.Y, position.Y, "Draw rectangle: Y");
  65. Assert.AreEqual(expected.Size.Width, size.Width, "Draw rectangle: width");
  66. Assert.AreEqual(expected.Size.Height, size.Height, "Draw rectangle: height");
  67. Assert.AreEqual(expected.Color, color, "Draw rectangle: color");
  68. },
  69. DrawTextFunc = (text, position, style) =>
  70. {
  71. var expected = GetExpected<CanvasDrawTextOperation>();
  72. Assert.AreEqual(expected.Text, text);
  73. Assert.AreEqual(expected.Position.X, position.X, "Draw text: X");
  74. Assert.AreEqual(expected.Position.Y, position.Y, "Draw text: Y");
  75. Assert.AreEqual(expected.Style.Color, style.Color, "Draw text: color");
  76. Assert.AreEqual(expected.Style.FontFamily, style.FontFamily, "Draw text: font");
  77. Assert.AreEqual(expected.Style.Size, style.Size, "Draw text: size");
  78. },
  79. DrawImageFunc = (image, position, size) =>
  80. {
  81. var expected = GetExpected<CanvasDrawImageOperation>();
  82. Assert.AreEqual(expected.Position.X, position.X, "Draw image: X");
  83. Assert.AreEqual(expected.Position.Y, position.Y, "Draw image: Y");
  84. Assert.AreEqual(expected.Size.Width, size.Width, "Draw image: width");
  85. Assert.AreEqual(expected.Size.Height, size.Height, "Draw image: height");
  86. }
  87. };
  88. }
  89. public Element CreateChild() => CreateChild(DefaultChildName);
  90. public Element CreateChild(string id)
  91. {
  92. return new ElementMock
  93. {
  94. Id = id,
  95. MeasureFunc = availableSpace =>
  96. {
  97. var expected = GetExpected<ChildMeasureOperation>();
  98. Assert.AreEqual(expected.ChildId, id);
  99. Assert.AreEqual(expected.Input.Width, availableSpace.Width, $"Measure: width of child '{expected.ChildId}'");
  100. Assert.AreEqual(expected.Input.Height, availableSpace.Height, $"Measure: height of child '{expected.ChildId}'");
  101. return expected.Output;
  102. },
  103. DrawFunc = availableSpace =>
  104. {
  105. var expected = GetExpected<ChildDrawOperation>();
  106. Assert.AreEqual(expected.ChildId, id);
  107. Assert.AreEqual(expected.Input.Width, availableSpace.Width, $"Draw: width of child '{expected.ChildId}'");
  108. Assert.AreEqual(expected.Input.Height, availableSpace.Height, $"Draw: width of child '{expected.ChildId}'");
  109. }
  110. };
  111. }
  112. public TestPlan MeasureElement(Size input)
  113. {
  114. OperationInput = input;
  115. return this;
  116. }
  117. public TestPlan DrawElement(Size input)
  118. {
  119. OperationInput = input;
  120. return this;
  121. }
  122. private TestPlan AddOperation(OperationBase operationBase)
  123. {
  124. Operations.Enqueue(operationBase);
  125. return this;
  126. }
  127. public TestPlan ExpectChildMeasure(Size expectedInput, SpacePlan returns)
  128. {
  129. return ExpectChildMeasure(DefaultChildName, expectedInput, returns);
  130. }
  131. public TestPlan ExpectChildMeasure(string child, Size expectedInput, SpacePlan returns)
  132. {
  133. return AddOperation(new ChildMeasureOperation(child, expectedInput, returns));
  134. }
  135. public TestPlan ExpectChildDraw(Size expectedInput)
  136. {
  137. return ExpectChildDraw(DefaultChildName, expectedInput);
  138. }
  139. public TestPlan ExpectChildDraw(string child, Size expectedInput)
  140. {
  141. return AddOperation(new ChildDrawOperation(child, expectedInput));
  142. }
  143. public TestPlan ExpectCanvasTranslate(Position position)
  144. {
  145. return AddOperation(new CanvasTranslateOperation(position));
  146. }
  147. public TestPlan ExpectCanvasTranslate(float left, float top)
  148. {
  149. return AddOperation(new CanvasTranslateOperation(new Position(left, top)));
  150. }
  151. public TestPlan ExpectCanvasScale(float scaleX, float scaleY)
  152. {
  153. return AddOperation(new CanvasScaleOperation(scaleX, scaleY));
  154. }
  155. public TestPlan ExpectCanvasRotate(float angle)
  156. {
  157. return AddOperation(new CanvasRotateOperation(angle));
  158. }
  159. public TestPlan ExpectCanvasDrawRectangle(Position position, Size size, string color)
  160. {
  161. return AddOperation(new CanvasDrawRectangleOperation(position, size, color));
  162. }
  163. public TestPlan ExpectCanvasDrawText(string text, Position position, TextStyle style)
  164. {
  165. return AddOperation(new CanvasDrawTextOperation(text, position, style));
  166. }
  167. public TestPlan ExpectCanvasDrawImage(Position position, Size size)
  168. {
  169. return AddOperation(new CanvasDrawImageOperation(position, size));
  170. }
  171. public TestPlan CheckMeasureResult(SpacePlan expected)
  172. {
  173. Element.VisitChildren(x => x?.Initialize(null, Canvas));
  174. var actual = Element.Measure(OperationInput);
  175. Assert.AreEqual(expected.GetType(), actual.GetType());
  176. Assert.AreEqual(expected.Width, actual.Width, "Measure: width");
  177. Assert.AreEqual(expected.Height, actual.Height, "Measure: height");
  178. Assert.AreEqual(expected.Type, actual.Type, "Measure: height");
  179. return this;
  180. }
  181. public TestPlan CheckDrawResult()
  182. {
  183. Element.VisitChildren(x => x?.Initialize(null, Canvas));
  184. Element.Draw(OperationInput);
  185. return this;
  186. }
  187. public TestPlan CheckState(Func<Element, bool> condition)
  188. {
  189. Assert.IsTrue(condition(Element), "Checking condition");
  190. return this;
  191. }
  192. public TestPlan CheckState<T>(Func<T, bool> condition) where T : Element
  193. {
  194. Assert.IsTrue(Element is T);
  195. Assert.IsTrue(condition(Element as T), "Checking condition");
  196. return this;
  197. }
  198. public static Element CreateUniqueElement()
  199. {
  200. return new Constrained
  201. {
  202. MinWidth = 90,
  203. MinHeight = 60,
  204. Child = new DynamicImage
  205. {
  206. Source = Placeholders.Image
  207. }
  208. };
  209. }
  210. public static void CompareOperations(Element value, Element expected, Size? availableSpace = null)
  211. {
  212. CompareMeasureOperations(value, expected, availableSpace);
  213. CompareDrawOperations(value, expected, availableSpace);
  214. }
  215. private static void CompareMeasureOperations(Element value, Element expected, Size? availableSpace = null)
  216. {
  217. availableSpace ??= new Size(400, 300);
  218. var canvas = new FreeCanvas();
  219. value.VisitChildren(x => x.Initialize(null, canvas));
  220. var valueMeasure = value.Measure(availableSpace.Value);
  221. expected.VisitChildren(x => x.Initialize(null, canvas));
  222. var expectedMeasure = expected.Measure(availableSpace.Value);
  223. valueMeasure.Should().BeEquivalentTo(expectedMeasure);
  224. }
  225. private static void CompareDrawOperations(Element value, Element expected, Size? availableSpace = null)
  226. {
  227. availableSpace ??= new Size(400, 300);
  228. var valueCanvas = new OperationRecordingCanvas();
  229. value.VisitChildren(x => x.Initialize(null, valueCanvas));
  230. value.Draw(availableSpace.Value);
  231. var expectedCanvas = new OperationRecordingCanvas();
  232. expected.VisitChildren(x => x.Initialize(null, expectedCanvas));
  233. expected.Draw(availableSpace.Value);
  234. valueCanvas.Operations.Should().BeEquivalentTo(expectedCanvas.Operations);
  235. }
  236. }
  237. }