private static void AddRegexMatcher( ICanAddMatcher <string> matcher, Regex regex, Func <string> customMessageGenerator ) { matcher.AddMatcher( actual => { var passed = regex.IsMatch(actual); return(new MatcherResult( passed, FinalMessageFor( () => new[] { "Expected", actual.Stringify(), $"{passed.AsNot()}to match regex", $"\"{regex}\"" }, customMessageGenerator ) )); }); }
private static void RunIntersectioEqualityTest <T>( ICanAddMatcher <T> continuation, object expected, Func <string> customMessageGenerator, params object[] customEqualityComparers ) { continuation.AddMatcher( actual => { var result = DeepTestHelpers.AreIntersectionEqual( actual, expected, customEqualityComparers); return(new MatcherResult( result.AreEqual, FinalMessageFor( () => new[] { "Expected", actual.Stringify(), $"{result.AreEqual.AsNot()}to intersection equal", expected.Stringify() }.Concat(result.Errors).ToArray(), customMessageGenerator ) )); } ); }
/// <summary> /// Expects the action to throw an exception of type T /// </summary> /// <param name="src">Action to test</param> /// <typeparam name="T">Type of exception which is expected</typeparam> /// <returns>Continuaiotn which can be used to test exception messages</returns> public static IThrowContinuation Throw <T>( this ICanAddMatcher <Action> src ) where T : Exception { var continuation = new ThrowContinuation(); var expectedType = typeof(T); src.AddMatcher(fn => { MatcherResult result; try { fn(); result = new MatcherResult(false, $"Expected to throw an exception of type {expectedType.Name} but none was thrown"); } catch (Exception ex) { var passed = ex is T; var message = passed ? $"Expected not to throw an exception of type {expectedType.Name}" : $"Expected to throw an exception of type {expectedType.Name} but {ex.GetType().Name} was thrown instead ({ex.Message})"; result = new MatcherResult(passed, message); continuation.Exception = ex; } return(result); }); return(continuation); }
/// <summary> /// Use to compose expectations into one matcher /// </summary> /// <param name="continuation">Continuation to operate on</param> /// <param name="expectationsRunner">Runs your composed expectations</param> /// <param name="messageGenerator">Generates the final message, passing in the actual instance being tested as well as a boolean for passed/failed</param> /// <typeparam name="T"></typeparam> public static IMore <T> Compose <T>( this ICanAddMatcher <T> continuation, Action <T> expectationsRunner, Func <T, bool, string> messageGenerator ) { continuation.AddMatcher(actual => { try { expectationsRunner(actual); return(new MatcherResult(true, () => messageGenerator(actual, true))); } catch (UnmetExpectationException e) { return(new MatcherResult(false, () => FinalMessageFor( new[] { "Specifically:", e.Message }, messageGenerator?.Invoke(actual, false) ) )); } }); return(continuation.More()); }
/// <summary> /// Expects the action to throw an exception of type T /// </summary> /// <param name="src">Action to test</param> /// <param name="customMessageGenerator">Custom message to add to failure messages</param> /// <typeparam name="T">Type of exception which is expected</typeparam> /// <returns>Continuation which can be used to test exception messages</returns> public static IThrowContinuation <T> Throw <T>( this ICanAddMatcher <Action> src, Func <string> customMessageGenerator ) where T : Exception { var continuation = new ThrowContinuation <T>(); var expectedType = typeof(T); src.AddMatcher( fn => { MatcherResult result; try { fn(); result = new MatcherResult( false, FinalMessageFor( () => $"Expected to throw an exception of type {expectedType.Name} but none was thrown", customMessageGenerator )); } catch (Exception actual) { var passed = actual is T; result = new MatcherResult( passed, FinalMessageFor( () => { var actualType = actual.GetType(); var haveSameName = expectedType.Name == actualType.Name; var expectedName = haveSameName ? $"{expectedType.Namespace}.{expectedType.Name}" : expectedType.Name; var actualName = haveSameName ? $"{actualType.Namespace}.{actualType.Name}" : actualType.Name; return(passed ? $@"Expected not to throw an exception of type {expectedName}" : $@"Expected to throw an exception of type { expectedName } but { actualName } was thrown instead ({ actual.Message })"); }, customMessageGenerator)); continuation.Exception = actual as T; } return(result); }); return(continuation); }
public static void Equal <T>(this ICanAddMatcher <T> continuation, T expected, string customMessage) { continuation.AddMatcher(actual => { if (actual.Equals(expected)) { return(new MatcherResult(true, $"Did not expect {expected}, but got exactly that")); } return(new MatcherResult(false, FinalMessageFor( $"Expected {expected} but got {actual}", customMessage ))); }); }
/// <summary> /// Tests if the cookie has the HttpOnly flag /// </summary> /// <param name="more"></param> /// <param name="customMessageGenerator"></param> /// <returns></returns> public static IMore <Cookie> HttpOnly( this ICanAddMatcher <Cookie> more, Func <string> customMessageGenerator ) { return(more.AddMatcher(actual => { var passed = actual?.HttpOnly ?? false; return new MatcherResult( passed, () => $"Expected {actual.Name()} {passed.AsNot()}to be http-only", customMessageGenerator ); })); }
/// <summary> /// Tests if the cookie has the Domain flag /// </summary> /// <param name="more"></param> /// <param name="expectedDomain"></param> /// <param name="customMessageGenerator"></param> /// <returns></returns> public static IMore <Cookie> Domain( this ICanAddMatcher <Cookie> more, string expectedDomain, Func <string> customMessageGenerator ) { return(more.AddMatcher(actual => { var passed = actual?.Domain == expectedDomain; return new MatcherResult( passed, () => $"Expected {actual.Name()} to be for domain '{expectedDomain}'", customMessageGenerator ); })); }
private static void AddContainsMatcherTo( ICanAddMatcher <string> continuation, string search ) { continuation.AddMatcher(s => { var passed = s?.Contains(search) ?? false; return(new MatcherResult( passed, MessageHelpers.MessageForContainsResult( passed, s, search ) )); }); }
private static IMore <Type> AddInheritsMatcher <TBase>( this ICanAddMatcher <Type> addTo, Func <string> customMessageGenerator ) { addTo.AddMatcher( actual => { var expected = typeof(TBase); if (expected.IsInterface()) { return(new MatcherResult( false, FinalMessageFor( () => new[] { actual.Stringify(), "is not a class." }, customMessageGenerator))); } var passed = expected.IsAssignableFrom(actual); return(new MatcherResult( passed, FinalMessageFor( () => new[] { "Expected", actual.Stringify(), $"{passed.AsNot()}to inherit", expected.Stringify() }, customMessageGenerator ) )); }); return(addTo.More()); }
private static IMore <Type> AddImplementsMatcher( this ICanAddMatcher <Type> addTo, Type shouldImplement, Func <string> customMessage) { addTo.AddMatcher( actual => { var interfaces = actual?.GetAllImplementedInterfaces() ?? new Type[0]; if (!shouldImplement.IsInterface()) { return(new MatcherResult( false, FinalMessageFor( () => new[] { actual.Stringify(), "is not an interface." }, customMessage))); } var passed = interfaces.Contains(shouldImplement); return(new MatcherResult( passed, FinalMessageFor( () => new[] { "Expected", actual.Stringify(), $"{passed.AsNot()}to implement", shouldImplement.Stringify() }, customMessage ) )); }); return(addTo.More()); }
/// <summary> /// Expects the action to throw an exception of type T /// </summary> /// <param name="src">Action to test</param> /// <param name="customMessageGenerator">Custom message to add to failure messages</param> /// <typeparam name="T">Type of exception which is expected</typeparam> /// <returns>Continuation which can be used to test exception messages</returns> public static IThrowContinuation <T> Throw <T>( this ICanAddMatcher <Action> src, Func <string> customMessageGenerator ) where T : Exception { var continuation = new ThrowContinuation <T>(); var expectedType = typeof(T); src.AddMatcher( fn => { MatcherResult result; try { fn(); result = new MatcherResult( false, FinalMessageFor( () => $"Expected to throw an exception of type {expectedType.Name} but none was thrown", customMessageGenerator )); } catch (Exception ex) { var passed = ex is T; result = new MatcherResult( passed, FinalMessageFor( () => passed ? $"Expected not to throw an exception of type {expectedType.Name}" : $"Expected to throw an exception of type {expectedType.Name} but {ex.GetType().Name} was thrown instead ({ex.Message})", customMessageGenerator)); continuation.Exception = ex as T; } return(result); }); return(continuation); }
private static void DoDeepEqualityTesting <T>( this ICanAddMatcher <T> continuation, object expected, Func <string> customMessageGenerator, params object[] customEqualityComparers ) { continuation.AddMatcher( actual => { var deepEqualResult = DeepTestHelpers.AreDeepEqual( actual, expected, customEqualityComparers); return(new MatcherResult( deepEqualResult.AreEqual, MH.FinalMessageFor( () => { var result = new[] { "Expected", actual.Stringify(), $"{deepEqualResult.AreEqual.AsNot()}to deep equal", expected.Stringify() }.Concat(deepEqualResult.Errors).ToArray(); return customEqualityComparers.Any() ? result .And("Using custom equality comparers:") .And(customEqualityComparers.Select(o => o.GetType()).ToArray().Stringify()) : result; }, customMessageGenerator ) )); } ); }
/// <summary> /// Expects the Action to throw any kind of exception /// </summary> /// <param name="src">Action to run</param> /// <param name="customMessageGenerator">Custom message to add to failure messages</param> /// <returns>Continuation which can be used to test exception messages</returns> public static IThrowContinuation <Exception> Throw( this ICanAddMatcher <Action> src, Func <string> customMessageGenerator ) { var continuation = new ThrowContinuation <Exception>(); src.AddMatcher( fn => { MatcherResult result; try { fn(); result = new MatcherResult( false, FinalMessageFor( () => "Expected to throw an exception but none was thrown", customMessageGenerator ) ); } catch (Exception ex) { continuation.Exception = ex; result = new MatcherResult( true, FinalMessageFor( () => $"Exception thrown:\n{ex.Message}\n{ex.StackTrace}", customMessageGenerator ), ex); } return(result); }); return(continuation); }
private static void AddContainsMatcherTo( ICanAddMatcher <string> continuation, string search, Func <string> customMessage, StringContainContinuation next ) { continuation.AddMatcher( s => { var priorOffset = continuation.GetMetadata <int>(SEARCH_OFFSET); var nextOffset = GetNextOffsetOf(search, s, priorOffset); next.SetMetadata(SEARCH_OFFSET, nextOffset); var passed = nextOffset > -1; return(new MatcherResult( passed, () => { var offsetMessage = priorOffset > 0 ? $" after index {priorOffset}" : ""; return FinalMessageFor( () => new[] { "Expected", s.Stringify(), $"{passed.AsNot()}to contain", search.Stringify(), offsetMessage }, customMessage ); } )); }); }
private static IStringPropertyContinuation RunContainFor( ICanAddMatcher <string> continuation, string search, Func <string> customMessageGenerator, int offset) { var result = ContinuationFactory.Create <string, StringPropertyContinuation>( null, continuation as IExpectationContext <string> ); continuation.AddMatcher( s => { if (search == null) { throw new InvalidOperationException("Cannot search for NULL in a string"); } result.Actual = s; var foundAt = s?.IndexOf(search, StringComparison.InvariantCulture) ?? -1; var passed = offset < 0 ? foundAt >= 0 : foundAt >= offset; s?.SetMetadata(SEARCH_OFFSET, foundAt + search.Length); return(new MatcherResult( passed, MessageForNotContainsResult( passed, s, search, customMessageGenerator ) )); }); return(result); }
/// <summary> /// Expects the Action to throw any kind of exception /// </summary> /// <param name="src">Action to run</param> /// <returns>Continuation which can be used to test exception messages</returns> public static IThrowContinuation Throw( this ICanAddMatcher <Action> src ) { var continuation = new ThrowContinuation(); src.AddMatcher(fn => { MatcherResult result; try { fn(); result = new MatcherResult(false, "Expected to throw an exception but none was thrown"); } catch (Exception ex) { continuation.Exception = ex; result = new MatcherResult(true, $"Exception thrown:\n${ex.Message}\n${ex.StackTrace}"); } return(result); }); return(continuation); }