// Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. namespace Shouldly; public static class ShouldlyExtensions { /// /// Asserts that the actual DateTime is within the specified TimeSpan of the expected DateTime. /// /// The actual DateTime value. /// The expected DateTime value. /// The allowed TimeSpan difference. /// A custom error message if the assertion fails. public static void ShouldBeCloseTo(this DateTime actual, DateTime expected, TimeSpan tolerance, string? customMessage = null) { var difference = (actual - expected).Duration(); if (difference <= tolerance) { return; } var errorMessage = customMessage ?? $"Expected {actual} to be within {tolerance} of {expected}, but the difference was {difference}."; throw new ShouldAssertException(errorMessage); } /// /// Asserts that the actual DateTime is within the specified TimeSpan of the expected DateTime. /// /// The actual DateTime value. /// The expected DateTime value. /// The allowed TimeSpan difference. /// A custom error message if the assertion fails. public static void ShouldBeCloseTo(this DateTimeOffset actual, DateTimeOffset expected, TimeSpan tolerance, string? customMessage = null) { var difference = (actual - expected).Duration(); if (difference <= tolerance) { return; } var errorMessage = customMessage ?? $"Expected {actual} to be within {tolerance} of {expected}, but the difference was {difference}."; throw new ShouldAssertException(errorMessage); } /// /// Asserts that each item in the expected collection is contained in the actual collection. /// /// /// /// /// public static void ShouldContain(this IEnumerable actual, IEnumerable expected) { var missingItems = expected.Where(item => !actual.Contains(item)).ToList(); if (missingItems.Count > 0) { throw new ShouldAssertException( $"Expected collection to contain all items, but these were missing: {string.Join(", ", missingItems)}.\n" + $"Actual: [{string.Join(", ", actual)}]\n" + $"Expected: [{string.Join(", ", expected)}]" ); } } }