using System.Linq; using NUnit.Framework.Constraints; using OrderDomain; namespace OrderTests; /// /// Custom NUnit matcher that bundles multiple order assertions into one. /// Participants: you do not need to understand how this works — /// just recognize the pattern and use it as an example for the agent. /// public static class Has { public static IResolveConstraint OrderState(decimal expectedTotal, decimal[] expectedLineValues) { return new OrderStateConstraint(expectedTotal, expectedLineValues); } } public class OrderStateConstraint : Constraint { private readonly decimal _expectedTotal; private readonly decimal[] _expectedLineValues; public OrderStateConstraint(decimal expectedTotal, decimal[] expectedLineValues) : base($"order with total {expectedTotal} and line values [{string.Join(", ", expectedLineValues)}]") { _expectedTotal = expectedTotal; _expectedLineValues = expectedLineValues; } public override ConstraintResult ApplyTo(TActual actual) { var order = (Order)(object)actual!; var actualTotal = order.Total; var actualLineValues = order.Lines.Select(l => l.Value).ToArray(); var totalMatch = actualTotal == _expectedTotal; var linesMatch = actualLineValues.SequenceEqual(_expectedLineValues); var messages = new List(); if (!totalMatch) messages.Add($"Total: expected {_expectedTotal}, got {actualTotal}"); if (!linesMatch) messages.Add($"Line values: expected [{string.Join(", ", _expectedLineValues)}], got [{string.Join(", ", actualLineValues)}]"); return new ConstraintResult(this, actual, totalMatch && linesMatch); } }