2
0

LayoutTestValidator.cs 4.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. namespace QuestPDF.LayoutTests.TestEngine;
  2. internal static class LayoutTestValidator
  3. {
  4. public static void Validate(LayoutTestResult result)
  5. {
  6. if (result.ActualLayout.GeneratesInfiniteLayout && !result.ExpectedLayout.GeneratesInfiniteLayout)
  7. throw new LayoutTestException("Provided content generates unexpected infinite layout");
  8. if (!result.ActualLayout.GeneratesInfiniteLayout && result.ExpectedLayout.GeneratesInfiniteLayout)
  9. throw new LayoutTestException("Provided content is expected to generate infinite layout but it does not");
  10. var actualPages = result.ActualLayout.Pages;
  11. var expectedPages = result.ExpectedLayout.Pages;
  12. if (actualPages.Count != expectedPages.Count)
  13. throw new LayoutTestException($"Content return layout with {actualPages.Count} pages but expected {expectedPages.Count} pages");
  14. foreach (var i in Enumerable.Range(0, actualPages.Count))
  15. {
  16. try
  17. {
  18. var actualPage = actualPages.ElementAt(i);
  19. var expectedPage = expectedPages.ElementAt(i);
  20. ValidatePage(actualPage, expectedPage);
  21. }
  22. catch (LayoutTestException exception)
  23. {
  24. throw new LayoutTestException($"Found issue on page number {i + 1}: {exception.Message}");
  25. }
  26. catch (Exception exception)
  27. {
  28. throw new LayoutTestException($"Encountered exception during validating page number {i + 1}", exception);
  29. }
  30. }
  31. static void ValidatePage(LayoutTestResult.PageLayout actualLayout, LayoutTestResult.PageLayout expectedLayout)
  32. {
  33. if (Math.Abs(actualLayout.RequiredArea.Width - expectedLayout.RequiredArea.Width) > Size.Epsilon)
  34. throw new LayoutTestException($"Required horizontal area is equal to {actualLayout.RequiredArea.Width} but expected {expectedLayout.RequiredArea.Width}");
  35. if (Math.Abs(actualLayout.RequiredArea.Height - expectedLayout.RequiredArea.Height) > Size.Epsilon)
  36. throw new LayoutTestException($"Required vertical area is equal to {actualLayout.RequiredArea.Height} but expected {expectedLayout.RequiredArea.Height}");
  37. if (actualLayout.Mocks.Count != expectedLayout.Mocks.Count)
  38. throw new LayoutTestException($"Visible {actualLayout.Mocks.Count} mocks but expected {expectedLayout.Mocks.Count}");
  39. ValidatePositionAndSizeOfMocks(actualLayout, expectedLayout);
  40. ValidateDrawingOrder(actualLayout, expectedLayout);
  41. }
  42. static void ValidatePositionAndSizeOfMocks(LayoutTestResult.PageLayout actualLayout, LayoutTestResult.PageLayout expectedLayout)
  43. {
  44. foreach (var expectedMock in expectedLayout.Mocks)
  45. {
  46. var matchingActualMock = actualLayout
  47. .Mocks
  48. .Where(x => x.MockId == expectedMock.MockId)
  49. .Where(x => Position.Equal(x.Position, expectedMock.Position))
  50. .Where(x => Size.Equal(x.Size, expectedMock.Size))
  51. .Count();
  52. if (matchingActualMock == 0)
  53. throw new Exception($"Cannot find '{expectedMock.MockId}' mock on position {expectedMock.Position.ToString()} and size {expectedMock.Size}");
  54. if (matchingActualMock > 1)
  55. throw new Exception($"Found multiple '{expectedMock.MockId}' mocks on position {expectedMock.Position} and size {expectedMock.Size}");
  56. }
  57. }
  58. static void ValidateDrawingOrder(LayoutTestResult.PageLayout actualLayout, LayoutTestResult.PageLayout expectedLayout)
  59. {
  60. var actualOverlaps = actualLayout.Mocks.GetOverlappingItems().ToList();
  61. var expectedOverlaps = expectedLayout.Mocks.GetOverlappingItems().ToList();
  62. foreach (var expectedOverlap in expectedOverlaps)
  63. {
  64. var matchingActualElements = actualOverlaps.Count(actualOverlap => actualOverlap.Below.MockId == expectedOverlap.Below.MockId && actualOverlap.Above.MockId == expectedOverlap.Above.MockId);
  65. if (matchingActualElements != 1)
  66. throw new Exception($"Mock '{expectedOverlap.Below.MockId}' should be visible below '{expectedOverlap.Above.MockId}' mock");
  67. }
  68. }
  69. }
  70. }