| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- using System.Collections;
- using QuestPDF.Drawing;
- using QuestPDF.Drawing.Proxy;
- using QuestPDF.Elements;
- using QuestPDF.Fluent;
- using QuestPDF.Helpers;
- using QuestPDF.Infrastructure;
- using SkiaSharp;
- namespace QuestPDF.LayoutTests.TestEngine;
- internal class LayoutBuilderDescriptor
- {
- public void Compose(Action<IContainer> container)
- {
-
- }
- }
- internal class DocumentLayoutBuilder
- {
- public List<LayoutTestResult.PageLayoutSnapshot> Commands { get; } = new();
-
- public PageLayoutDescriptor Page()
- {
- var page = new LayoutTestResult.PageLayoutSnapshot();
- Commands.Add(page);
- return new PageLayoutDescriptor(page);
- }
- }
- internal class PageLayoutDescriptor
- {
- private LayoutTestResult.PageLayoutSnapshot Command { get; }
- public PageLayoutDescriptor(LayoutTestResult.PageLayoutSnapshot command)
- {
- Command = command;
- }
- public PageLayoutDescriptor TakenAreaSize(float width, float height)
- {
- Command.RequiredArea = new Size(width, height);
- return this;
- }
-
- public PageLayoutDescriptor Content(Action<PageLayoutBuilder> content)
- {
- var pageContent = new PageLayoutBuilder();
- content(pageContent);
- Command.MockPositions = pageContent.Commands;
- return this;
- }
- }
- internal class PageLayoutBuilder
- {
- public List<LayoutTestResult.MockLayoutPosition> Commands { get;} = new();
-
- public ChildLayoutDescriptor Child(string mockId)
- {
- var child = new LayoutTestResult.MockLayoutPosition { MockId = mockId };
- Commands.Add(child);
- return new ChildLayoutDescriptor(child);
- }
- }
- internal class ChildLayoutDescriptor
- {
- private LayoutTestResult.MockLayoutPosition Command { get; }
- public ChildLayoutDescriptor(LayoutTestResult.MockLayoutPosition command)
- {
- Command = command;
- }
- public ChildLayoutDescriptor Position(float x, float y)
- {
- Command.Position = new Position(x, y);
- return this;
- }
-
- public ChildLayoutDescriptor Size(float width, float height)
- {
- Command.Size = new Size(width, height);
- return this;
- }
- }
- internal static class ElementExtensions
- {
- public static MockDescriptor Mock(this IContainer element, string id)
- {
- var mock = new ElementMock
- {
- MockId = id
- };
-
- element.Element(mock);
- return new MockDescriptor(mock);
- }
- }
- internal class MockDescriptor
- {
- private ElementMock Mock { get; }
- public MockDescriptor(ElementMock mock)
- {
- Mock = mock;
- }
- public MockDescriptor Size(float width, float height)
- {
- Mock.TotalWidth = width;
- Mock.TotalHeight = height;
- return this;
- }
- }
- internal class LayoutTest
- {
- private LayoutTestResult TestResult { get; } = new LayoutTestResult();
-
- public static LayoutTest HavingSpaceOfSize(float width, float height)
- {
- var result = new LayoutTest();
- result.TestResult.PageSize = new Size(width, height);
- return result;
- }
- public LayoutTest WithContent(Action<IContainer> handler)
- {
- // compose content
- var container = new Container();
- container.Element(handler);
- TestResult.GeneratedLayout = LayoutTestExecutor.Execute(TestResult.PageSize, container);
-
- return this;
- }
-
- public void ExpectWrap()
- {
-
- }
-
- public LayoutTest ExpectedDrawResult(Action<DocumentLayoutBuilder> handler)
- {
- var builder = new DocumentLayoutBuilder();
- handler(builder);
- TestResult.ExpectedLayout = builder.Commands;
- return this;
- }
- public void CompareVisually()
- {
- var path = "output.pdf";
-
- if (File.Exists(path))
- File.Delete(path);
-
- var stream = new FileStream(path, FileMode.CreateNew);
- LayoutTestResultVisualization.Visualize(TestResult, stream);
- stream.Dispose();
-
- GenerateExtensions.OpenFileUsingDefaultProgram(path);
- }
- public void Validate()
- {
- if (TestResult.GeneratedLayout.Count != TestResult.ExpectedLayout.Count)
- throw new Exception($"Generated {TestResult.GeneratedLayout.Count} but expected {TestResult.ExpectedLayout.Count} pages.");
- var numberOfPages = TestResult.GeneratedLayout.Count;
-
- foreach (var i in Enumerable.Range(0, numberOfPages))
- {
- try
- {
- var actual = TestResult.GeneratedLayout.ElementAt(i);
- var expected = TestResult.ExpectedLayout.ElementAt(i);
- if (Math.Abs(actual.RequiredArea.Width - expected.RequiredArea.Width) > Size.Epsilon)
- throw new Exception($"Taken area width is equal to {actual.RequiredArea.Width} but expected {expected.RequiredArea.Width}");
-
- if (Math.Abs(actual.RequiredArea.Height - expected.RequiredArea.Height) > Size.Epsilon)
- throw new Exception($"Taken area height is equal to {actual.RequiredArea.Height} but expected {expected.RequiredArea.Height}");
-
- if (actual.MockPositions.Count != expected.MockPositions.Count)
- throw new Exception($"Visible {actual.MockPositions.Count} but expected {expected.MockPositions.Count}");
- foreach (var child in expected.MockPositions)
- {
- var matchingActualElements = actual
- .MockPositions
- .Where(x => x.MockId == child.MockId)
- .Where(x => Position.Equal(x.Position, child.Position))
- .Where(x => Size.Equal(x.Size, child.Size))
- .Count();
- if (matchingActualElements == 0)
- throw new Exception($"Cannot find actual drawing command for child {child.MockId} on position {child.Position} and size {child.Size}");
-
- if (matchingActualElements > 1)
- throw new Exception($"Found multiple drawing commands for child {child.MockId} on position {child.Position} and size {child.Size}");
- }
-
- // todo: add z-depth testing
- var actualOverlaps = GetOverlappingItems(actual.MockPositions);
- var expectedOverlaps = GetOverlappingItems(expected.MockPositions);
-
- foreach (var overlap in expectedOverlaps)
- {
- var matchingActualElements = actualOverlaps.Count(x => x.Item1 == overlap.Item1 && x.Item2 == overlap.Item2);
- if (matchingActualElements != 1)
- throw new Exception($"Element {overlap.Item1} should be visible underneath element {overlap.Item2}");
- }
-
- IEnumerable<(string, string)> GetOverlappingItems(ICollection<LayoutTestResult.MockLayoutPosition> items)
- {
- for (var i = 0; i < items.Count; i++)
- {
- for (var j = i; j < items.Count; j++)
- {
- var beforeChild = items.ElementAt(i);
- var afterChild = items.ElementAt(j);
- var beforeBoundingBox = BoundingBox.From(beforeChild.Position, beforeChild.Size);
- var afterBoundingBox = BoundingBox.From(afterChild.Position, afterChild.Size);
- var intersection = BoundingBoxExtensions.Intersection(beforeBoundingBox, afterBoundingBox);
-
- if (intersection == null)
- continue;
- yield return (beforeChild.MockId, afterChild.MockId);
- }
- }
- }
- }
- catch (Exception e)
- {
- throw new Exception($"Error on page {i + 1}: {e.Message}");
- }
- }
- }
- }
|