diff --git a/Nimble.xcodeproj/project.pbxproj b/Nimble.xcodeproj/project.pbxproj index 56164a620..ebe4e5a45 100644 --- a/Nimble.xcodeproj/project.pbxproj +++ b/Nimble.xcodeproj/project.pbxproj @@ -204,9 +204,9 @@ 1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */; }; 1F9DB8FB1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; 1F9DB8FC1A74E793002E96AD /* ObjCBeEmptyTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */; }; - 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; - 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; - 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + 1FA0C3FF1E30B14500623165 /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Matcher.swift */; }; + 1FA0C4001E30B14500623165 /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Matcher.swift */; }; + 1FA0C4011E30B14500623165 /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Matcher.swift */; }; 1FB90098195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; 1FB90099195EC4B8001D7FAE /* BeIdenticalToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */; }; 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */; }; @@ -389,10 +389,10 @@ 89C297D32A92E814002A143F /* AsyncPromiseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C297CD2A92AB34002A143F /* AsyncPromiseTest.swift */; }; 89C297D42A92E815002A143F /* AsyncPromiseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C297CD2A92AB34002A143F /* AsyncPromiseTest.swift */; }; 89C297D52A92E816002A143F /* AsyncPromiseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C297CD2A92AB34002A143F /* AsyncPromiseTest.swift */; }; - 89EEF5A52A03293100988224 /* AsyncPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncPredicate.swift */; }; - 89EEF5A62A03293100988224 /* AsyncPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncPredicate.swift */; }; - 89EEF5A72A03293100988224 /* AsyncPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncPredicate.swift */; }; - 89EEF5A82A03293100988224 /* AsyncPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncPredicate.swift */; }; + 89EEF5A52A03293100988224 /* AsyncMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncMatcher.swift */; }; + 89EEF5A62A03293100988224 /* AsyncMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncMatcher.swift */; }; + 89EEF5A72A03293100988224 /* AsyncMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncMatcher.swift */; }; + 89EEF5A82A03293100988224 /* AsyncMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5A42A03293100988224 /* AsyncMatcher.swift */; }; 89EEF5B72A032C3200988224 /* AsyncPredicateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5B22A032C2500988224 /* AsyncPredicateTest.swift */; }; 89EEF5B82A032C3300988224 /* AsyncPredicateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5B22A032C2500988224 /* AsyncPredicateTest.swift */; }; 89EEF5B92A032C3300988224 /* AsyncPredicateTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89EEF5B22A032C2500988224 /* AsyncPredicateTest.swift */; }; @@ -605,7 +605,7 @@ D95F8970267EA20A004B1B4D /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; }; D95F8971267EA20A004B1B4D /* PostNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCF91521C61C8A400B15DCB /* PostNotification.swift */; }; D95F8972267EA20A004B1B4D /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB4D5EC19FE43C200E9D9FE /* Match.swift */; }; - D95F8973267EA20A004B1B4D /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Predicate.swift */; }; + D95F8973267EA20A004B1B4D /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0C3FE1E30B14500623165 /* Matcher.swift */; }; D95F8974267EA20A004B1B4D /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; }; D95F8975267EA20A004B1B4D /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD141968AB07008ED995 /* BeIdenticalTo.swift */; }; D95F8976267EA20A004B1B4D /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD131968AB07008ED995 /* BeGreaterThanOrEqualTo.swift */; }; @@ -747,7 +747,7 @@ 1F925F0D195C18F500ED456B /* BeLessThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeLessThanOrEqualToTest.swift; sourceTree = ""; }; 1F925F10195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeGreaterThanOrEqualToTest.swift; sourceTree = ""; }; 1F9DB8FA1A74E793002E96AD /* ObjCBeEmptyTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCBeEmptyTest.m; sourceTree = ""; }; - 1FA0C3FE1E30B14500623165 /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; + 1FA0C3FE1E30B14500623165 /* Matcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Matcher.swift; sourceTree = ""; }; 1FB90097195EC4B8001D7FAE /* BeIdenticalToTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeIdenticalToTest.swift; sourceTree = ""; }; 1FC494A91C29CBA40010975C /* NimbleEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleEnvironment.swift; sourceTree = ""; }; 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostNotificationTest.swift; sourceTree = ""; }; @@ -809,7 +809,7 @@ 899441F32902EF0900C1FAF9 /* DSL+AsyncAwait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DSL+AsyncAwait.swift"; sourceTree = ""; }; 89C297CB2A911CDA002A143F /* AsyncTimerSequenceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncTimerSequenceTest.swift; sourceTree = ""; }; 89C297CD2A92AB34002A143F /* AsyncPromiseTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncPromiseTest.swift; sourceTree = ""; }; - 89EEF5A42A03293100988224 /* AsyncPredicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncPredicate.swift; sourceTree = ""; }; + 89EEF5A42A03293100988224 /* AsyncMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncMatcher.swift; sourceTree = ""; }; 89EEF5B22A032C2500988224 /* AsyncPredicateTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncPredicateTest.swift; sourceTree = ""; }; 89EEF5BB2A06210D00988224 /* AsyncHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncHelpers.swift; sourceTree = ""; }; 89F5E06C290765BB001F9377 /* PollingTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PollingTest.swift; sourceTree = ""; }; @@ -1100,7 +1100,7 @@ children = ( DDB1BC781A92235600F743C3 /* AllPass.swift */, 896962402A5FABD000A7929D /* AsyncAllPass.swift */, - 89EEF5A42A03293100988224 /* AsyncPredicate.swift */, + 89EEF5A42A03293100988224 /* AsyncMatcher.swift */, 1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */, 1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */, 1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */, @@ -1129,7 +1129,7 @@ 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */, AE7ADE441C80BF8000B94CD3 /* MatchError.swift */, 1FCF91521C61C8A400B15DCB /* PostNotification.swift */, - 1FA0C3FE1E30B14500623165 /* Predicate.swift */, + 1FA0C3FE1E30B14500623165 /* Matcher.swift */, 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */, A8F6B5BC2070186D00FCB5ED /* SatisfyAllOf.swift */, 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */, @@ -1726,9 +1726,9 @@ 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */, 891A04722AB0164500B46613 /* AsyncTimerSequence.swift in Sources */, CDFB6A4C1F7E082500AD8CC7 /* mach_excServer.c in Sources */, - 89EEF5A62A03293100988224 /* AsyncPredicate.swift in Sources */, + 89EEF5A62A03293100988224 /* AsyncMatcher.swift in Sources */, 472FD1351B9E085700C7B8DA /* HaveCount.swift in Sources */, - 1FA0C4001E30B14500623165 /* Predicate.swift in Sources */, + 1FA0C4001E30B14500623165 /* Matcher.swift in Sources */, 964CFEFD1C4FF48900513336 /* ThrowAssertion.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1861,7 +1861,7 @@ 1F5DF1851BDCA0F500C3A531 /* Equal.swift in Sources */, F8A1BE311CB3710900031679 /* XCTestObservationCenter+Register.m in Sources */, 1FE661591E6574E30035F243 /* ExpectationMessage.swift in Sources */, - 1FA0C4011E30B14500623165 /* Predicate.swift in Sources */, + 1FA0C4011E30B14500623165 /* Matcher.swift in Sources */, 1F5DF1711BDCA0F500C3A531 /* DSL+Wait.swift in Sources */, 1F1871D61CA89EEF00A34BF2 /* DSL.m in Sources */, 1F5DF17D1BDCA0F500C3A531 /* BeGreaterThanOrEqualTo.swift in Sources */, @@ -1888,7 +1888,7 @@ CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */, 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */, 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, - 89EEF5A72A03293100988224 /* AsyncPredicate.swift in Sources */, + 89EEF5A72A03293100988224 /* AsyncMatcher.swift in Sources */, 0477153723B740B800402D4E /* NimbleTimeInterval.swift in Sources */, 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */, 1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */, @@ -2055,9 +2055,9 @@ 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */, 891A04712AB0164500B46613 /* AsyncTimerSequence.swift in Sources */, CDFB6A4B1F7E082500AD8CC7 /* mach_excServer.c in Sources */, - 89EEF5A52A03293100988224 /* AsyncPredicate.swift in Sources */, + 89EEF5A52A03293100988224 /* AsyncMatcher.swift in Sources */, 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */, - 1FA0C3FF1E30B14500623165 /* Predicate.swift in Sources */, + 1FA0C3FF1E30B14500623165 /* Matcher.swift in Sources */, 472FD1391B9E0A9700C7B8DA /* HaveCount.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2164,7 +2164,7 @@ D95F8988267EA20E004B1B4D /* Errors.swift in Sources */, D95F8926267EA1CA004B1B4D /* XCTestObservationCenter+Register.m in Sources */, D95F8967267EA20A004B1B4D /* SatisfyAnyOf.swift in Sources */, - D95F8973267EA20A004B1B4D /* Predicate.swift in Sources */, + D95F8973267EA20A004B1B4D /* Matcher.swift in Sources */, D95F8976267EA20A004B1B4D /* BeGreaterThanOrEqualTo.swift in Sources */, 89F5E08F290B8D22001F9377 /* AsyncAwait.swift in Sources */, D95F8958267EA1F7004B1B4D /* AssertionRecorder.swift in Sources */, @@ -2217,7 +2217,7 @@ D95F8975267EA20A004B1B4D /* BeIdenticalTo.swift in Sources */, D95F8984267EA20E004B1B4D /* SourceLocation.swift in Sources */, D95F8929267EA1CA004B1B4D /* DSL.m in Sources */, - 89EEF5A82A03293100988224 /* AsyncPredicate.swift in Sources */, + 89EEF5A82A03293100988224 /* AsyncMatcher.swift in Sources */, D95F896B267EA20A004B1B4D /* BeEmpty.swift in Sources */, D95F896E267EA20A004B1B4D /* BeVoid.swift in Sources */, D95F8957267EA1F7004B1B4D /* AdapterProtocols.swift in Sources */, diff --git a/README.md b/README.md index 940c3b5f3..67ebab4c6 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ expect(ocean.isClean).toEventually(beTruthy()) - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers) - [Custom Validation](#custom-validation) - [Writing Your Own Matchers](#writing-your-own-matchers) - - [PredicateResult](#predicateresult) + - [MatcherResult](#matcherresult) - [Lazy Evaluation](#lazy-evaluation) - [Type Checking via Swift Generics](#type-checking-via-swift-generics) - [Customizing Failure Messages](#customizing-failure-messages) @@ -341,18 +341,18 @@ expects(await someAsyncFunction()).to(equal(1)) // Compiler error: 'async' call ### Async Matchers In addition to asserting on async functions prior to passing them to a -synchronous predicate, you can also write matchers that directly take in an -async value. These are called `AsyncPredicate`s. This is most obviously useful +synchronous matcher, you can also write matchers that directly take in an +async value. These are called `AsyncMatcher`s. This is most obviously useful when directly asserting against an actor. In addition to writing your own async matchers, Nimble currently ships with async versions of the following -predicates: +matchers: - `allPass` - `containElementSatisfying` -- `satisfyAllOf` and the `&&` operator overload accept both `AsyncPredicate` and - synchronous `Predicate`s. -- `satisfyAnyOf` and the `||` operator overload accept both `AsyncPredicate` and - synchronous `Predicate`s. +- `satisfyAllOf` and the `&&` operator overload accept both `AsyncMatcher` and + synchronous `Matcher`s. +- `satisfyAnyOf` and the `||` operator overload accept both `AsyncMatcher` and + synchronous `Matcher`s. Note: Async/Await support is different than the `toEventually`/`toEventuallyNot` feature described below. @@ -424,7 +424,7 @@ let subject = MyActor() await expect { await subject.access() }.toEventually(equal(2)) ``` -### Verifying a Predicate will Never or Always Match +### Verifying a Matcher will Never or Always Match You can also test that a value always or never matches throughout the length of the timeout. Use `toNever` and `toAlways` for this: @@ -1446,7 +1446,7 @@ expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equa expect(82).to(beLessThan(50) || beGreaterThan(80)) ``` -Note: In swift, you can mix and match synchronous and asynchronous predicates +Note: In swift, you can mix and match synchronous and asynchronous matchers using by `satisfyAnyOf`/`||`. ```objc @@ -1496,25 +1496,25 @@ When using `toEventually()` be careful not to make state changes or run process # Writing Your Own Matchers In Nimble, matchers are Swift functions that take an expected -value and return a `Predicate` closure. Take `equal`, for example: +value and return a `Matcher` closure. Take `equal`, for example: ```swift // Swift -public func equal(expectedValue: T?) -> Predicate { +public func equal(expectedValue: T?) -> Matcher { // Can be shortened to: - // Predicate { actual in ... } + // Matcher { actual in ... } // // But shown with types here for clarity. - return Predicate { (actualExpression: Expression) throws -> PredicateResult in + return Matcher { (actualExpression: Expression) throws -> MatcherResult in let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>") if let actualValue = try actualExpression.evaluate() { - return PredicateResult( + return MatcherResult( bool: actualValue == expectedValue!, message: msg ) } else { - return PredicateResult( + return MatcherResult( status: .fail, message: msg.appendedBeNilHint() ) @@ -1523,7 +1523,7 @@ public func equal(expectedValue: T?) -> Predicate { } ``` -The return value of a `Predicate` closure is a `PredicateResult` that indicates +The return value of a `Matcher` closure is a `MatcherResult` that indicates whether the actual value matches the expectation and what error message to display on failure. @@ -1543,27 +1543,27 @@ For examples of how to write your own matchers, just check out the to see how Nimble's built-in set of matchers are implemented. You can also check out the tips below. -## PredicateResult +## MatcherResult -`PredicateResult` is the return struct that `Predicate` return to indicate -success and failure. A `PredicateResult` is made up of two values: -`PredicateStatus` and `ExpectationMessage`. +`MatcherResult` is the return struct that `Matcher` return to indicate +success and failure. A `MatcherResult` is made up of two values: +`MatcherStatus` and `ExpectationMessage`. -Instead of a boolean, `PredicateStatus` captures a trinary set of values: +Instead of a boolean, `MatcherStatus` captures a trinary set of values: ```swift // Swift -public enum PredicateStatus { -// The predicate "passes" with the given expression +public enum MatcherStatus { +// The matcher "passes" with the given expression // eg - expect(1).to(equal(1)) case matches -// The predicate "fails" with the given expression +// The matcher "fails" with the given expression // eg - expect(1).toNot(equal(1)) case doesNotMatch -// The predicate never "passes" with the given expression, even if negated +// The matcher never "passes" with the given expression, even if negated // eg - expect(nil as Int?).toNot(equal(1)) case fail @@ -1589,11 +1589,11 @@ case fail(/* message: */ String) } ``` -Predicates should usually depend on either `.expectedActualValueTo(..)` or +Matchers should usually depend on either `.expectedActualValueTo(..)` or `.fail(..)` when reporting errors. Special cases can be used for the other enum cases. -Finally, if your Predicate utilizes other Predicates, you can utilize +Finally, if your Matcher utilizes other Matchers, you can utilize `.appended(details:)` and `.appended(message:)` methods to annotate an existing error with more details. @@ -1610,15 +1610,15 @@ custom matchers should call `actualExpression.evaluate()`: ```swift // Swift -public func beNil() -> Predicate { - // Predicate.simpleNilable(..) automatically generates ExpectationMessage for +public func beNil() -> Matcher { + // Matcher.simpleNilable(..) automatically generates ExpectationMessage for // us based on the string we provide to it. Also, the 'Nilable' postfix indicates - // that this Predicate supports matching against nil actualExpressions, instead of - // always resulting in a PredicateStatus.fail result -- which is true for - // Predicate.simple(..) - return Predicate.simpleNilable("be nil") { actualExpression in + // that this Matcher supports matching against nil actualExpressions, instead of + // always resulting in a MatcherStatus.fail result -- which is true for + // Matcher.simple(..) + return Matcher.simpleNilable("be nil") { actualExpression in let actualValue = try actualExpression.evaluate() - return PredicateStatus(bool: actualValue == nil) + return MatcherStatus(bool: actualValue == nil) } } ``` @@ -1640,16 +1640,16 @@ against the one provided to the matcher function, and passes if they are the sam ```swift // Swift -public func haveDescription(description: String) -> Predicate { - return Predicate.simple("have description") { actual in - return PredicateStatus(bool: actual.evaluate().description == description) +public func haveDescription(description: String) -> Matcher { + return Matcher.simple("have description") { actual in + return MatcherStatus(bool: actual.evaluate().description == description) } } ``` ## Customizing Failure Messages -When using `Predicate.simple(..)` or `Predicate.simpleNilable(..)`, Nimble +When using `Matcher.simple(..)` or `Matcher.simpleNilable(..)`, Nimble outputs the following failure message when an expectation fails: ```swift @@ -1658,36 +1658,36 @@ outputs the following failure message when an expectation fails: "expected to \(message), got <\(actual)>" ``` -You can customize this message by modifying the way you create a `Predicate`. +You can customize this message by modifying the way you create a `Matcher`. ### Basic Customization For slightly more complex error messaging, receive the created failure message -with `Predicate.define(..)`: +with `Matcher.define(..)`: ```swift // Swift -public func equal(_ expectedValue: T?) -> Predicate { - return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in +public func equal(_ expectedValue: T?) -> Matcher { + return Matcher.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in let actualValue = try actualExpression.evaluate() let matches = actualValue == expectedValue && expectedValue != nil if expectedValue == nil || actualValue == nil { if expectedValue == nil && actualValue != nil { - return PredicateResult( + return MatcherResult( status: .fail, message: msg.appendedBeNilHint() ) } - return PredicateResult(status: .fail, message: msg) + return MatcherResult(status: .fail, message: msg) } - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } ``` In the example above, `msg` is defined based on the string given to -`Predicate.define`. The code looks akin to: +`Matcher.define`. The code looks akin to: ```swift // Swift @@ -1697,10 +1697,10 @@ let msg = ExpectationMessage.expectedActualValueTo("equal <\(stringify(expectedV ### Full Customization -To fully customize the behavior of the Predicate, use the overload that expects -a `PredicateResult` to be returned. +To fully customize the behavior of the Matcher, use the overload that expects +a `MatcherResult` to be returned. -Along with `PredicateResult`, there are other `ExpectationMessage` enum values you can use: +Along with `MatcherResult`, there are other `ExpectationMessage` enum values you can use: ```swift public indirect enum ExpectationMessage { @@ -1744,10 +1744,10 @@ For a more comprehensive message that spans multiple lines, use .expectedActualValueTo("be true").appended(details: "use beFalse() for inverse\nor use beNil()") ``` -## Asynchronous Predicates +## Asynchronous Matchers -To write predicates against async expressions, return an instance of -`AsyncPredicate`. The closure passed to `AsyncPredicate` is async, and the +To write matchers against async expressions, return an instance of +`AsyncMatcher`. The closure passed to `AsyncMatcher` is async, and the expression you evaluate is also asynchronous and needs to be awaited on. ```swift @@ -1761,14 +1761,14 @@ actor CallRecorder { } } -func beCalled(with arguments: Argument) -> AsyncPredicate> { - AsyncPredicate { (expression: AsyncExpression>) in +func beCalled(with arguments: Argument) -> AsyncMatcher> { + AsyncMatcher { (expression: AsyncExpression>) in let message = ExpectationMessage.expectedActualValueTo("be called with \(arguments)") guard let calls = try await expression.evaluate()?.calls else { - return PredicateResult(status: .fail, message: message.appendedBeNilHint()) + return MatcherResult(status: .fail, message: message.appendedBeNilHint()) } - return PredicateResult(bool: calls.contains(args), message: message.appended(details: "called with \(calls)")) + return MatcherResult(bool: calls.contains(args), message: message.appended(details: "called with \(calls)")) } } ``` @@ -1780,16 +1780,16 @@ actor has received a call with the given arguments. ## Supporting Objective-C To use a custom matcher written in Swift from Objective-C, you'll have -to extend the `NMBPredicate` class, adding a new class method for your +to extend the `NMBMatcher` class, adding a new class method for your custom matcher. The example below defines the class method -`+[NMBPredicate beNilMatcher]`: +`+[NMBMatcher beNilMatcher]`: ```swift // Swift -extension NMBPredicate { - @objc public class func beNilMatcher() -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beNilMatcher() -> NMBMatcher { + return NMBMatcher { actualExpression in return try beNil().satisfies(actualExpression).toObjectiveC() } } @@ -1801,7 +1801,7 @@ The above allows you to use the matcher from Objective-C: ```objc // Objective-C -expect(actual).to([NMBPredicate beNilMatcher]()); +expect(actual).to([NMBMatcher beNilMatcher]()); ``` To make the syntax easier to use, define a C function that calls the @@ -1810,8 +1810,8 @@ class method: ```objc // Objective-C -FOUNDATION_EXPORT NMBPredicate *beNil() { - return [NMBPredicate beNilMatcher]; +FOUNDATION_EXPORT NMBMatcher *beNil() { + return [NMBMatcher beNilMatcher]; } ``` @@ -1833,22 +1833,22 @@ expect(nil).to(equal(nil)); // fails expect(nil).to(beNil()); // passes ``` -If your matcher does not want to match with nil, you use `Predicate.define` or `Predicate.simple`. +If your matcher does not want to match with nil, you use `Matcher.define` or `Matcher.simple`. Using those factory methods will automatically generate expected value failure messages when they're nil. ```swift -public func beginWith(_ startingElement: S.Element) -> Predicate where S.Element: Equatable { - return Predicate.simple("begin with <\(startingElement)>") { actualExpression in +public func beginWith(_ startingElement: S.Element) -> Matcher where S.Element: Equatable { + return Matcher.simple("begin with <\(startingElement)>") { actualExpression in guard let actualValue = try actualExpression.evaluate() else { return .fail } var actualGenerator = actualValue.makeIterator() - return PredicateStatus(bool: actualGenerator.next() == startingElement) + return MatcherStatus(bool: actualGenerator.next() == startingElement) } } -extension NMBPredicate { - @objc public class func beginWithMatcher(_ expected: Any) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beginWithMatcher(_ expected: Any) -> NMBMatcher { + return NMBMatcher { actualExpression in let actual = try actualExpression.evaluate() let expr = actualExpression.cast { $0 as? NMBOrderedCollection } return try beginWith(expected).satisfies(expr).toObjectiveC() diff --git a/Sources/Nimble/Adapters/NMBExpectation.swift b/Sources/Nimble/Adapters/NMBExpectation.swift index a7edcd7d4..44ced6562 100644 --- a/Sources/Nimble/Adapters/NMBExpectation.swift +++ b/Sources/Nimble/Adapters/NMBExpectation.swift @@ -4,9 +4,9 @@ import class Foundation.NSObject import typealias Foundation.TimeInterval -private func from(objcPredicate: NMBPredicate) -> Predicate { - return Predicate { actualExpression in - let result = objcPredicate.satisfies(({ try actualExpression.evaluate() }), +private func from(objcMatcher: NMBMatcher) -> Matcher { + return Matcher { actualExpression in + let result = objcMatcher.satisfies(({ try actualExpression.evaluate() }), location: actualExpression.location) return result.toSwift() } @@ -37,139 +37,139 @@ public class NMBExpectation: NSObject { } } - @objc public var to: (NMBPredicate) -> NMBExpectation { - return { predicate in - self.expectValue.to(from(objcPredicate: predicate)) + @objc public var to: (NMBMatcher) -> NMBExpectation { + return { matcher in + self.expectValue.to(from(objcMatcher: matcher)) return self } } - @objc public var toWithDescription: (NMBPredicate, String) -> NMBExpectation { - return { predicate, description in - self.expectValue.to(from(objcPredicate: predicate), description: description) + @objc public var toWithDescription: (NMBMatcher, String) -> NMBExpectation { + return { matcher, description in + self.expectValue.to(from(objcMatcher: matcher), description: description) return self } } - @objc public var toNot: (NMBPredicate) -> NMBExpectation { - return { predicate in - self.expectValue.toNot(from(objcPredicate: predicate)) + @objc public var toNot: (NMBMatcher) -> NMBExpectation { + return { matcher in + self.expectValue.toNot(from(objcMatcher: matcher)) return self } } - @objc public var toNotWithDescription: (NMBPredicate, String) -> NMBExpectation { - return { predicate, description in - self.expectValue.toNot(from(objcPredicate: predicate), description: description) + @objc public var toNotWithDescription: (NMBMatcher, String) -> NMBExpectation { + return { matcher, description in + self.expectValue.toNot(from(objcMatcher: matcher), description: description) return self } } - @objc public var notTo: (NMBPredicate) -> NMBExpectation { return toNot } + @objc public var notTo: (NMBMatcher) -> NMBExpectation { return toNot } - @objc public var notToWithDescription: (NMBPredicate, String) -> NMBExpectation { return toNotWithDescription } + @objc public var notToWithDescription: (NMBMatcher, String) -> NMBExpectation { return toNotWithDescription } - @objc public var toEventually: (NMBPredicate) -> Void { - return { predicate in + @objc public var toEventually: (NMBMatcher) -> Void { + return { matcher in self.expectValue.toEventually( - from(objcPredicate: predicate), + from(objcMatcher: matcher), timeout: self._timeout, description: nil ) } } - @objc public var toEventuallyWithDescription: (NMBPredicate, String) -> Void { - return { predicate, description in + @objc public var toEventuallyWithDescription: (NMBMatcher, String) -> Void { + return { matcher, description in self.expectValue.toEventually( - from(objcPredicate: predicate), + from(objcMatcher: matcher), timeout: self._timeout, description: description ) } } - @objc public var toEventuallyNot: (NMBPredicate) -> Void { - return { predicate in + @objc public var toEventuallyNot: (NMBMatcher) -> Void { + return { matcher in self.expectValue.toEventuallyNot( - from(objcPredicate: predicate), + from(objcMatcher: matcher), timeout: self._timeout, description: nil ) } } - @objc public var toEventuallyNotWithDescription: (NMBPredicate, String) -> Void { - return { predicate, description in + @objc public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void { + return { matcher, description in self.expectValue.toEventuallyNot( - from(objcPredicate: predicate), + from(objcMatcher: matcher), timeout: self._timeout, description: description ) } } - @objc public var toNotEventually: (NMBPredicate) -> Void { + @objc public var toNotEventually: (NMBMatcher) -> Void { return toEventuallyNot } - @objc public var toNotEventuallyWithDescription: (NMBPredicate, String) -> Void { + @objc public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { return toEventuallyNotWithDescription } - @objc public var toNever: (NMBPredicate) -> Void { - return { predicate in + @objc public var toNever: (NMBMatcher) -> Void { + return { matcher in self.expectValue.toNever( - from(objcPredicate: predicate), + from(objcMatcher: matcher), until: self._timeout, description: nil ) } } - @objc public var toNeverWithDescription: (NMBPredicate, String) -> Void { - return { predicate, description in + @objc public var toNeverWithDescription: (NMBMatcher, String) -> Void { + return { matcher, description in self.expectValue.toNever( - from(objcPredicate: predicate), + from(objcMatcher: matcher), until: self._timeout, description: description ) } } - @objc public var neverTo: (NMBPredicate) -> Void { + @objc public var neverTo: (NMBMatcher) -> Void { return toNever } - @objc public var neverToWithDescription: (NMBPredicate, String) -> Void { + @objc public var neverToWithDescription: (NMBMatcher, String) -> Void { return toNeverWithDescription } - @objc public var toAlways: (NMBPredicate) -> Void { - return { predicate in + @objc public var toAlways: (NMBMatcher) -> Void { + return { matcher in self.expectValue.toAlways( - from(objcPredicate: predicate), + from(objcMatcher: matcher), until: self._timeout, description: nil ) } } - @objc public var toAlwaysWithDescription: (NMBPredicate, String) -> Void { - return { predicate, description in + @objc public var toAlwaysWithDescription: (NMBMatcher, String) -> Void { + return { matcher, description in self.expectValue.toAlways( - from(objcPredicate: predicate), + from(objcMatcher: matcher), until: self._timeout, description: description ) } } - @objc public var alwaysTo: (NMBPredicate) -> Void { + @objc public var alwaysTo: (NMBMatcher) -> Void { return toAlways } - @objc public var alwaysToWithDescription: (NMBPredicate, String) -> Void { + @objc public var alwaysToWithDescription: (NMBMatcher, String) -> Void { return toAlwaysWithDescription } diff --git a/Sources/Nimble/AsyncExpression.swift b/Sources/Nimble/AsyncExpression.swift index 59667840e..e5fd4bebe 100644 --- a/Sources/Nimble/AsyncExpression.swift +++ b/Sources/Nimble/AsyncExpression.swift @@ -66,7 +66,7 @@ public struct AsyncExpression { self.isClosure = isClosure } - /// Creates a new synchronous expression, for use in Predicates. + /// Creates a new synchronous expression, for use in Matchers. public func toSynchronousExpression() async -> Expression { let value: Result do { diff --git a/Sources/Nimble/Expectation.swift b/Sources/Nimble/Expectation.swift index 8312ada2a..72422c211 100644 --- a/Sources/Nimble/Expectation.swift +++ b/Sources/Nimble/Expectation.swift @@ -1,10 +1,10 @@ -internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ predicate: Predicate, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) { +internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ matcher: Matcher, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) { func run() -> (Bool, FailureMessage) { let msg = FailureMessage() msg.userDescription = description msg.to = to do { - let result = try predicate.satisfies(expression) + let result = try matcher.satisfies(expression) result.message.update(failureMessage: msg) if msg.actualValue == "" { msg.actualValue = "<\(stringify(try expression.evaluate()))>" @@ -33,12 +33,12 @@ internal func execute(_ expression: Expression, _ style: ExpectationStyle, return result } -internal func execute(_ expression: AsyncExpression, _ style: ExpectationStyle, _ predicate: AsyncPredicate, to: String, description: String?) async -> (Bool, FailureMessage) { +internal func execute(_ expression: AsyncExpression, _ style: ExpectationStyle, _ matcher: AsyncMatcher, to: String, description: String?) async -> (Bool, FailureMessage) { let msg = FailureMessage() msg.userDescription = description msg.to = to do { - let result = try await predicate.satisfies(expression) + let result = try await matcher.satisfies(expression) result.message.update(failureMessage: msg) if msg.actualValue == "" { msg.actualValue = "<\(stringify(try await expression.evaluate()))>" @@ -52,16 +52,16 @@ internal func execute(_ expression: AsyncExpression, _ style: ExpectationS public enum ExpectationStatus: Equatable { - /// No predicates have been performed. + /// No matchers have been performed. case pending - /// All predicates have passed. + /// All matchers have passed. case passed - /// All predicates have failed. + /// All matchers have failed. case failed - /// Multiple predicates have been peformed, with at least one passing and one failing. + /// Multiple matchers have been peformed, with at least one passing and one failing. case mixed } @@ -81,7 +81,7 @@ extension ExpectationStatus { public protocol Expectation { var location: SourceLocation { get } - /// The status of the test after predicates have been evaluated. + /// The status of the test after matchers have been evaluated. /// /// This property can be used for changing test behavior based whether an expectation has /// passed. @@ -121,7 +121,7 @@ extension Expectation { /// expect(array[9]).to(...) /// ``` /// - /// - Warning: This method **MUST** be called after a predicate method like `to` or `not`. + /// - Warning: This method **MUST** be called after a matcher method like `to` or `not`. /// Otherwise, this expectation will be in an indeterminate state and will /// unconditionally log an error. /// @@ -130,7 +130,7 @@ extension Expectation { switch status { case .pending: let msg = """ - Attempted to call `Expectation.onFailure(throw:) before a predicate has been applied. + Attempted to call `Expectation.onFailure(throw:) before a matcher has been applied. Try using `expect(...).to(...).onFailure(throw: ...`) instead. """ @@ -147,7 +147,7 @@ extension Expectation { public struct SyncExpectation: Expectation { public let expression: Expression - /// The status of the test after predicates have been evaluated. + /// The status of the test after matchers have been evaluated. /// /// This property can be used for changing test behavior based whether an expectation has /// passed. @@ -189,15 +189,15 @@ public struct SyncExpectation: Expectation { /// Tests the actual value using a matcher to match. @discardableResult - public func to(_ predicate: Predicate, description: String? = nil) -> Self { - let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description) + public func to(_ matcher: Matcher, description: String? = nil) -> Self { + let (pass, msg) = execute(expression, .toMatch, matcher, to: "to", description: description) return verify(pass, msg) } /// Tests the actual value using a matcher to not match. @discardableResult - public func toNot(_ predicate: Predicate, description: String? = nil) -> Self { - let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description) + public func toNot(_ matcher: Matcher, description: String? = nil) -> Self { + let (pass, msg) = execute(expression, .toNotMatch, matcher, to: "to not", description: description) return verify(pass, msg) } @@ -205,22 +205,22 @@ public struct SyncExpectation: Expectation { /// /// Alias to toNot(). @discardableResult - public func notTo(_ predicate: Predicate, description: String? = nil) -> Self { - toNot(predicate, description: description) + public func notTo(_ matcher: Matcher, description: String? = nil) -> Self { + toNot(matcher, description: description) } - // MARK: - AsyncPredicates + // MARK: - AsyncMatchers /// Tests the actual value using a matcher to match. @discardableResult - public func to(_ predicate: AsyncPredicate, description: String? = nil) async -> Self { - let (pass, msg) = await execute(expression.toAsyncExpression(), .toMatch, predicate, to: "to", description: description) + public func to(_ matcher: AsyncMatcher, description: String? = nil) async -> Self { + let (pass, msg) = await execute(expression.toAsyncExpression(), .toMatch, matcher, to: "to", description: description) return verify(pass, msg) } /// Tests the actual value using a matcher to not match. @discardableResult - public func toNot(_ predicate: AsyncPredicate, description: String? = nil) async -> Self { - let (pass, msg) = await execute(expression.toAsyncExpression(), .toNotMatch, predicate, to: "to not", description: description) + public func toNot(_ matcher: AsyncMatcher, description: String? = nil) async -> Self { + let (pass, msg) = await execute(expression.toAsyncExpression(), .toNotMatch, matcher, to: "to not", description: description) return verify(pass, msg) } @@ -228,8 +228,8 @@ public struct SyncExpectation: Expectation { /// /// Alias to toNot(). @discardableResult - public func notTo(_ predicate: AsyncPredicate, description: String? = nil) async -> Self { - await toNot(predicate, description: description) + public func notTo(_ matcher: AsyncMatcher, description: String? = nil) async -> Self { + await toNot(matcher, description: description) } // see: @@ -240,7 +240,7 @@ public struct SyncExpectation: Expectation { public struct AsyncExpectation: Expectation { public let expression: AsyncExpression - /// The status of the test after predicates have been evaluated. + /// The status of the test after matchers have been evaluated. /// /// This property can be used for changing test behavior based whether an expectation has /// passed. @@ -282,15 +282,15 @@ public struct AsyncExpectation: Expectation { /// Tests the actual value using a matcher to match. @discardableResult - public func to(_ predicate: Predicate, description: String? = nil) async -> Self { - let (pass, msg) = execute(await expression.toSynchronousExpression(), .toMatch, predicate, to: "to", description: description) + public func to(_ matcher: Matcher, description: String? = nil) async -> Self { + let (pass, msg) = execute(await expression.toSynchronousExpression(), .toMatch, matcher, to: "to", description: description) return verify(pass, msg) } /// Tests the actual value using a matcher to not match. @discardableResult - public func toNot(_ predicate: Predicate, description: String? = nil) async -> Self { - let (pass, msg) = execute(await expression.toSynchronousExpression(), .toNotMatch, predicate, to: "to not", description: description) + public func toNot(_ matcher: Matcher, description: String? = nil) async -> Self { + let (pass, msg) = execute(await expression.toSynchronousExpression(), .toNotMatch, matcher, to: "to not", description: description) return verify(pass, msg) } @@ -298,21 +298,21 @@ public struct AsyncExpectation: Expectation { /// /// Alias to toNot(). @discardableResult - public func notTo(_ predicate: Predicate, description: String? = nil) async -> Self { - await toNot(predicate, description: description) + public func notTo(_ matcher: Matcher, description: String? = nil) async -> Self { + await toNot(matcher, description: description) } /// Tests the actual value using a matcher to match. @discardableResult - public func to(_ predicate: AsyncPredicate, description: String? = nil) async -> Self { - let (pass, msg) = await execute(expression, .toMatch, predicate, to: "to", description: description) + public func to(_ matcher: AsyncMatcher, description: String? = nil) async -> Self { + let (pass, msg) = await execute(expression, .toMatch, matcher, to: "to", description: description) return verify(pass, msg) } /// Tests the actual value using a matcher to not match. @discardableResult - public func toNot(_ predicate: AsyncPredicate, description: String? = nil) async -> Self { - let (pass, msg) = await execute(expression, .toNotMatch, predicate, to: "to not", description: description) + public func toNot(_ matcher: AsyncMatcher, description: String? = nil) async -> Self { + let (pass, msg) = await execute(expression, .toNotMatch, matcher, to: "to not", description: description) return verify(pass, msg) } @@ -320,7 +320,7 @@ public struct AsyncExpectation: Expectation { /// /// Alias to toNot(). @discardableResult - public func notTo(_ predicate: AsyncPredicate, description: String? = nil) async -> Self { - await toNot(predicate, description: description) + public func notTo(_ matcher: AsyncMatcher, description: String? = nil) async -> Self { + await toNot(matcher, description: description) } } diff --git a/Sources/Nimble/Matchers/AllPass.swift b/Sources/Nimble/Matchers/AllPass.swift index 104fc9f82..133c21ec4 100644 --- a/Sources/Nimble/Matchers/AllPass.swift +++ b/Sources/Nimble/Matchers/AllPass.swift @@ -1,36 +1,36 @@ public func allPass( _ passFunc: @escaping (S.Element) throws -> Bool -) -> Predicate { - let matcher = Predicate.define("pass a condition") { actualExpression, message in +) -> Matcher { + let matcher = Matcher.define("pass a condition") { actualExpression, message in guard let actual = try actualExpression.evaluate() else { - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) } - return PredicateResult(bool: try passFunc(actual), message: message) + return MatcherResult(bool: try passFunc(actual), message: message) } - return createPredicate(matcher) + return createMatcher(matcher) } public func allPass( _ passName: String, _ passFunc: @escaping (S.Element) throws -> Bool -) -> Predicate { - let matcher = Predicate.define(passName) { actualExpression, message in +) -> Matcher { + let matcher = Matcher.define(passName) { actualExpression, message in guard let actual = try actualExpression.evaluate() else { - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) } - return PredicateResult(bool: try passFunc(actual), message: message) + return MatcherResult(bool: try passFunc(actual), message: message) } - return createPredicate(matcher) + return createMatcher(matcher) } -public func allPass(_ elementPredicate: Predicate) -> Predicate { - return createPredicate(elementPredicate) +public func allPass(_ elementMatcher: Matcher) -> Matcher { + return createMatcher(elementMatcher) } -private func createPredicate(_ elementMatcher: Predicate) -> Predicate { - return Predicate { actualExpression in +private func createMatcher(_ elementMatcher: Matcher) -> Matcher { + return Matcher { actualExpression in guard let actualValue = try actualExpression.evaluate() else { - return PredicateResult( + return MatcherResult( status: .fail, message: .appends(.expectedTo("all pass"), " (use beNil() to match nils)") ) @@ -42,24 +42,24 @@ private func createPredicate(_ elementMatcher: Predicate expression: { currentElement }, location: actualExpression.location ) - let predicateResult = try elementMatcher.satisfies(exp) - if predicateResult.status == .matches { - failure = predicateResult.message.prepended(expectation: "all ") + let matcherResult = try elementMatcher.satisfies(exp) + if matcherResult.status == .matches { + failure = matcherResult.message.prepended(expectation: "all ") } else { - failure = predicateResult.message + failure = matcherResult.message .replacedExpectation({ .expectedTo($0.expectedMessage) }) .wrappedExpectation( before: "all ", after: ", but failed first at element <\(stringify(currentElement))>" + " in <\(stringify(actualValue))>" ) - return PredicateResult(status: .doesNotMatch, message: failure) + return MatcherResult(status: .doesNotMatch, message: failure) } } failure = failure.replacedExpectation({ expectation in return .expectedTo(expectation.expectedMessage) }) - return PredicateResult(status: .matches, message: failure) + return MatcherResult(status: .matches, message: failure) } } @@ -68,9 +68,9 @@ import class Foundation.NSObject import struct Foundation.NSFastEnumerationIterator import protocol Foundation.NSFastEnumeration -extension NMBPredicate { - @objc public class func allPassMatcher(_ predicate: NMBPredicate) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func allPassMatcher(_ matcher: NMBMatcher) -> NMBMatcher { + return NMBMatcher { actualExpression in let location = actualExpression.location let actualValue = try actualExpression.evaluate() var nsObjects = [NSObject]() @@ -91,8 +91,8 @@ extension NMBPredicate { } if !collectionIsUsable { - return NMBPredicateResult( - status: NMBPredicateStatus.fail, + return NMBMatcherResult( + status: NMBMatcherStatus.fail, message: NMBExpectationMessage( // swiftlint:disable:next line_length fail: "allPass can only be used with types which implement NSFastEnumeration (NSArray, NSSet, ...), and whose elements subclass NSObject, got <\(actualValue?.description ?? "nil")>" @@ -101,8 +101,8 @@ extension NMBPredicate { } let expr = Expression(expression: ({ nsObjects }), location: location) - let pred: Predicate<[NSObject]> = createPredicate(Predicate { expr in - return predicate.satisfies(({ try expr.evaluate() }), location: expr.location).toSwift() + let pred: Matcher<[NSObject]> = createMatcher(Matcher { expr in + return matcher.satisfies(({ try expr.evaluate() }), location: expr.location).toSwift() }) return try pred.satisfies(expr).toObjectiveC() } diff --git a/Sources/Nimble/Matchers/AsyncAllPass.swift b/Sources/Nimble/Matchers/AsyncAllPass.swift index 928ca3434..ec04f9ebe 100644 --- a/Sources/Nimble/Matchers/AsyncAllPass.swift +++ b/Sources/Nimble/Matchers/AsyncAllPass.swift @@ -1,36 +1,36 @@ public func allPass( _ passFunc: @escaping (S.Element) async throws -> Bool -) -> AsyncPredicate { - let matcher = AsyncPredicate.define("pass a condition") { actualExpression, message in +) -> AsyncMatcher { + let matcher = AsyncMatcher.define("pass a condition") { actualExpression, message in guard let actual = try await actualExpression.evaluate() else { - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) } - return PredicateResult(bool: try await passFunc(actual), message: message) + return MatcherResult(bool: try await passFunc(actual), message: message) } - return createPredicate(matcher) + return createMatcher(matcher) } public func allPass( _ passName: String, _ passFunc: @escaping (S.Element) async throws -> Bool -) -> AsyncPredicate { - let matcher = AsyncPredicate.define(passName) { actualExpression, message in +) -> AsyncMatcher { + let matcher = AsyncMatcher.define(passName) { actualExpression, message in guard let actual = try await actualExpression.evaluate() else { - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) } - return PredicateResult(bool: try await passFunc(actual), message: message) + return MatcherResult(bool: try await passFunc(actual), message: message) } - return createPredicate(matcher) + return createMatcher(matcher) } -public func allPass(_ elementPredicate: AsyncPredicate) -> AsyncPredicate { - return createPredicate(elementPredicate) +public func allPass(_ elementMatcher: AsyncMatcher) -> AsyncMatcher { + return createMatcher(elementMatcher) } -private func createPredicate(_ elementMatcher: AsyncPredicate) -> AsyncPredicate { - return AsyncPredicate { actualExpression in +private func createMatcher(_ elementMatcher: AsyncMatcher) -> AsyncMatcher { + return AsyncMatcher { actualExpression in guard let actualValue = try await actualExpression.evaluate() else { - return PredicateResult( + return MatcherResult( status: .fail, message: .appends(.expectedTo("all pass"), " (use beNil() to match nils)") ) @@ -42,23 +42,23 @@ private func createPredicate(_ elementMatcher: AsyncPredicate" + " in <\(stringify(actualValue))>" ) - return PredicateResult(status: .doesNotMatch, message: failure) + return MatcherResult(status: .doesNotMatch, message: failure) } } failure = failure.replacedExpectation({ expectation in return .expectedTo(expectation.expectedMessage) }) - return PredicateResult(status: .matches, message: failure) + return MatcherResult(status: .matches, message: failure) } } diff --git a/Sources/Nimble/Matchers/AsyncMatcher.swift b/Sources/Nimble/Matchers/AsyncMatcher.swift new file mode 100644 index 000000000..96b118a99 --- /dev/null +++ b/Sources/Nimble/Matchers/AsyncMatcher.swift @@ -0,0 +1,118 @@ +public protocol AsyncableMatcher { + associatedtype Value + func satisfies(_ expression: AsyncExpression) async throws -> MatcherResult +} + +extension Matcher: AsyncableMatcher { + public func satisfies(_ expression: AsyncExpression) async throws -> MatcherResult { + try satisfies(await expression.toSynchronousExpression()) + } +} + +/// An AsyncMatcher is part of the new matcher API that provides assertions to expectations. +/// +/// Given a code snippet: +/// +/// expect(1).to(equal(2)) +/// ^^^^^^^^ +/// Called a "matcher" +/// +/// A matcher consists of two parts a constructor function and the Matcher. +/// +/// The Matcher provide the heavy lifting on how to assert against a given value. Internally, +/// matchers are simple wrappers around closures to provide static type information and +/// allow composition and wrapping of existing behaviors. +/// +/// `AsyncMatcher`s serve to allow writing matchers that must be run in async contexts. +/// These can also be used with either `Expectation`s or `AsyncExpectation`s. +/// But these can only be used from async contexts, and are unavailable in Objective-C. +/// You can, however, call regular Matchers from an AsyncMatcher, if you wish to compose one like that. +public struct AsyncMatcher: AsyncableMatcher { + fileprivate var matcher: (AsyncExpression) async throws -> MatcherResult + + public init(_ matcher: @escaping (AsyncExpression) async throws -> MatcherResult) { + self.matcher = matcher + } + + /// Uses a matcher on a given value to see if it passes the matcher. + /// + /// @param expression The value to run the matcher's logic against + /// @returns A matcher result indicate passing or failing and an associated error message. + public func satisfies(_ expression: AsyncExpression) async throws -> MatcherResult { + return try await matcher(expression) + } +} + +@available(*, deprecated, renamed: "AsyncMatcher") +public typealias AsyncPredicate = AsyncMatcher + +/// Provides convenience helpers to defining matchers +extension AsyncMatcher { + /// Like Matcher() constructor, but automatically guard against nil (actual) values + public static func define(matcher: @escaping (AsyncExpression) async throws -> MatcherResult) -> AsyncMatcher { + return AsyncMatcher { actual in + return try await matcher(actual) + }.requireNonNil + } + + /// Defines a matcher with a default message that can be returned in the closure + /// Also ensures the matcher's actual value cannot pass with `nil` given. + public static func define(_ message: String = "match", matcher: @escaping (AsyncExpression, ExpectationMessage) async throws -> MatcherResult) -> AsyncMatcher { + return AsyncMatcher { actual in + return try await matcher(actual, .expectedActualValueTo(message)) + }.requireNonNil + } + + /// Defines a matcher with a default message that can be returned in the closure + /// Unlike `define`, this allows nil values to succeed if the given closure chooses to. + public static func defineNilable(_ message: String = "match", matcher: @escaping (AsyncExpression, ExpectationMessage) async throws -> MatcherResult) -> AsyncMatcher { + return AsyncMatcher { actual in + return try await matcher(actual, .expectedActualValueTo(message)) + } + } + + /// Provides a simple matcher definition that provides no control over the predefined + /// error message. + /// + /// Also ensures the matcher's actual value cannot pass with `nil` given. + public static func simple(_ message: String = "match", matcher: @escaping (AsyncExpression) async throws -> MatcherStatus) -> AsyncMatcher { + return AsyncMatcher { actual in + return MatcherResult(status: try await matcher(actual), message: .expectedActualValueTo(message)) + }.requireNonNil + } + + /// Provides a simple matcher definition that provides no control over the predefined + /// error message. + /// + /// Unlike `simple`, this allows nil values to succeed if the given closure chooses to. + public static func simpleNilable(_ message: String = "match", matcher: @escaping (AsyncExpression) async throws -> MatcherStatus) -> AsyncMatcher { + return AsyncMatcher { actual in + return MatcherResult(status: try await matcher(actual), message: .expectedActualValueTo(message)) + } + } +} + +extension AsyncMatcher { + // Someday, make this public? Needs documentation + internal func after(f: @escaping (AsyncExpression, MatcherResult) async throws -> MatcherResult) -> AsyncMatcher { + // swiftlint:disable:previous identifier_name + return AsyncMatcher { actual -> MatcherResult in + let result = try await self.satisfies(actual) + return try await f(actual, result) + } + } + + /// Returns a new Matcher based on the current one that always fails if nil is given as + /// the actual value. + public var requireNonNil: AsyncMatcher { + return after { actual, result in + if try await actual.evaluate() == nil { + return MatcherResult( + status: .fail, + message: result.message.appendedBeNilHint() + ) + } + return result + } + } +} diff --git a/Sources/Nimble/Matchers/AsyncPredicate.swift b/Sources/Nimble/Matchers/AsyncPredicate.swift deleted file mode 100644 index 219500cac..000000000 --- a/Sources/Nimble/Matchers/AsyncPredicate.swift +++ /dev/null @@ -1,117 +0,0 @@ -public protocol AsyncablePredicate { - associatedtype Value - func satisfies(_ expression: AsyncExpression) async throws -> PredicateResult -} - -extension Predicate: AsyncablePredicate { - public func satisfies(_ expression: AsyncExpression) async throws -> PredicateResult { - try satisfies(await expression.toSynchronousExpression()) - } -} - -/// An AsyncPredicate is part of the new matcher API that provides assertions to expectations. -/// -/// Given a code snippet: -/// -/// expect(1).to(equal(2)) -/// ^^^^^^^^ -/// Called a "matcher" -/// -/// A matcher consists of two parts a constructor function and the Predicate. The term Predicate -/// is used as a separate name from Matcher to help transition custom matchers to the new Nimble -/// matcher API. -/// -/// The Predicate provide the heavy lifting on how to assert against a given value. Internally, -/// predicates are simple wrappers around closures to provide static type information and -/// allow composition and wrapping of existing behaviors. -/// -/// `AsyncPredicate`s serve to allow writing matchers that must be run in async contexts. -/// These can also be used with either `Expectation`s or `AsyncExpectation`s. -/// But these can only be used from async contexts, and are unavailable in Objective-C. -/// You can, however, call regular Predicates from an AsyncPredicate, if you wish to compose one like that. -public struct AsyncPredicate: AsyncablePredicate { - fileprivate var matcher: (AsyncExpression) async throws -> PredicateResult - - public init(_ matcher: @escaping (AsyncExpression) async throws -> PredicateResult) { - self.matcher = matcher - } - - /// Uses a predicate on a given value to see if it passes the predicate. - /// - /// @param expression The value to run the predicate's logic against - /// @returns A predicate result indicate passing or failing and an associated error message. - public func satisfies(_ expression: AsyncExpression) async throws -> PredicateResult { - return try await matcher(expression) - } -} - -/// Provides convenience helpers to defining predicates -extension AsyncPredicate { - /// Like Predicate() constructor, but automatically guard against nil (actual) values - public static func define(matcher: @escaping (AsyncExpression) async throws -> PredicateResult) -> AsyncPredicate { - return AsyncPredicate { actual in - return try await matcher(actual) - }.requireNonNil - } - - /// Defines a predicate with a default message that can be returned in the closure - /// Also ensures the predicate's actual value cannot pass with `nil` given. - public static func define(_ message: String = "match", matcher: @escaping (AsyncExpression, ExpectationMessage) async throws -> PredicateResult) -> AsyncPredicate { - return AsyncPredicate { actual in - return try await matcher(actual, .expectedActualValueTo(message)) - }.requireNonNil - } - - /// Defines a predicate with a default message that can be returned in the closure - /// Unlike `define`, this allows nil values to succeed if the given closure chooses to. - public static func defineNilable(_ message: String = "match", matcher: @escaping (AsyncExpression, ExpectationMessage) async throws -> PredicateResult) -> AsyncPredicate { - return AsyncPredicate { actual in - return try await matcher(actual, .expectedActualValueTo(message)) - } - } - - /// Provides a simple predicate definition that provides no control over the predefined - /// error message. - /// - /// Also ensures the predicate's actual value cannot pass with `nil` given. - public static func simple(_ message: String = "match", matcher: @escaping (AsyncExpression) async throws -> PredicateStatus) -> AsyncPredicate { - return AsyncPredicate { actual in - return PredicateResult(status: try await matcher(actual), message: .expectedActualValueTo(message)) - }.requireNonNil - } - - /// Provides a simple predicate definition that provides no control over the predefined - /// error message. - /// - /// Unlike `simple`, this allows nil values to succeed if the given closure chooses to. - public static func simpleNilable(_ message: String = "match", matcher: @escaping (AsyncExpression) async throws -> PredicateStatus) -> AsyncPredicate { - return AsyncPredicate { actual in - return PredicateResult(status: try await matcher(actual), message: .expectedActualValueTo(message)) - } - } -} - -extension AsyncPredicate { - // Someday, make this public? Needs documentation - internal func after(f: @escaping (AsyncExpression, PredicateResult) async throws -> PredicateResult) -> AsyncPredicate { - // swiftlint:disable:previous identifier_name - return AsyncPredicate { actual -> PredicateResult in - let result = try await self.satisfies(actual) - return try await f(actual, result) - } - } - - /// Returns a new Predicate based on the current one that always fails if nil is given as - /// the actual value. - public var requireNonNil: AsyncPredicate { - return after { actual, result in - if try await actual.evaluate() == nil { - return PredicateResult( - status: .fail, - message: result.message.appendedBeNilHint() - ) - } - return result - } - } -} diff --git a/Sources/Nimble/Matchers/BeAKindOf.swift b/Sources/Nimble/Matchers/BeAKindOf.swift index f01ca7707..6b010ece0 100644 --- a/Sources/Nimble/Matchers/BeAKindOf.swift +++ b/Sources/Nimble/Matchers/BeAKindOf.swift @@ -6,21 +6,21 @@ private func matcherMessage(forClass expectedClass: AnyClass) -> String { } /// A Nimble matcher that succeeds when the actual value is an instance of the given class. -public func beAKindOf(_ expectedType: T.Type) -> Predicate { - return Predicate.define { actualExpression in +public func beAKindOf(_ expectedType: T.Type) -> Matcher { + return Matcher.define { actualExpression in let message: ExpectationMessage let instance = try actualExpression.evaluate() guard let validInstance = instance else { message = .expectedCustomValueTo(matcherMessage(forType: expectedType), actual: "") - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) } message = .expectedCustomValueTo( "be a kind of \(String(describing: expectedType))", actual: "<\(String(describing: type(of: validInstance))) instance>" ) - return PredicateResult( + return MatcherResult( bool: validInstance is T, message: message ) @@ -32,14 +32,14 @@ import class Foundation.NSObject /// A Nimble matcher that succeeds when the actual value is an instance of the given class. /// @see beAnInstanceOf if you want to match against the exact class -public func beAKindOf(_ expectedClass: AnyClass) -> Predicate { - return Predicate.define { actualExpression in +public func beAKindOf(_ expectedClass: AnyClass) -> Matcher { + return Matcher.define { actualExpression in let message: ExpectationMessage - let status: PredicateStatus + let status: MatcherStatus let instance = try actualExpression.evaluate() if let validInstance = instance { - status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass)) + status = MatcherStatus(bool: instance != nil && instance!.isKind(of: expectedClass)) message = .expectedCustomValueTo( matcherMessage(forClass: expectedClass), actual: "<\(String(describing: type(of: validInstance))) instance>" @@ -52,13 +52,13 @@ public func beAKindOf(_ expectedClass: AnyClass) -> Predicate { ) } - return PredicateResult(status: status, message: message) + return MatcherResult(status: status, message: message) } } -extension NMBPredicate { - @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBMatcher { actualExpression in return try beAKindOf(expected).satisfies(actualExpression).toObjectiveC() } } diff --git a/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Sources/Nimble/Matchers/BeAnInstanceOf.swift index 47ea663a1..d8a13112f 100644 --- a/Sources/Nimble/Matchers/BeAnInstanceOf.swift +++ b/Sources/Nimble/Matchers/BeAnInstanceOf.swift @@ -1,12 +1,12 @@ import Foundation /// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class. -public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { +public func beAnInstanceOf(_ expectedType: T.Type) -> Matcher { let errorMessage = "be an instance of \(String(describing: expectedType))" - return Predicate.define { actualExpression in + return Matcher.define { actualExpression in let instance = try actualExpression.evaluate() guard let validInstance = instance else { - return PredicateResult( + return MatcherResult( status: .doesNotMatch, message: .expectedActualValueTo(errorMessage) ) @@ -14,8 +14,8 @@ public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { let actualString = "<\(String(describing: type(of: validInstance))) instance>" - return PredicateResult( - status: PredicateStatus(bool: type(of: validInstance) == expectedType), + return MatcherResult( + status: MatcherStatus(bool: type(of: validInstance) == expectedType), message: .expectedCustomValueTo(errorMessage, actual: actualString) ) } @@ -23,9 +23,9 @@ public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { /// A Nimble matcher that succeeds when the actual value is an instance of the given class. /// @see beAKindOf if you want to match against subclasses -public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate { +public func beAnInstanceOf(_ expectedClass: AnyClass) -> Matcher { let errorMessage = "be an instance of \(String(describing: expectedClass))" - return Predicate.define { actualExpression in + return Matcher.define { actualExpression in let instance = try actualExpression.evaluate() let actualString: String if let validInstance = instance { @@ -38,17 +38,17 @@ public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate { #else let matches = instance != nil && type(of: instance!) == expectedClass #endif - return PredicateResult( - status: PredicateStatus(bool: matches), + return MatcherResult( + status: MatcherStatus(bool: matches), message: .expectedCustomValueTo(errorMessage, actual: actualString) ) } } #if canImport(Darwin) -extension NMBPredicate { - @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher { + return NMBMatcher { actualExpression in return try beAnInstanceOf(expected).satisfies(actualExpression).toObjectiveC() } } diff --git a/Sources/Nimble/Matchers/BeCloseTo.swift b/Sources/Nimble/Matchers/BeCloseTo.swift index 9fb3605af..36dc0e00f 100644 --- a/Sources/Nimble/Matchers/BeCloseTo.swift +++ b/Sources/Nimble/Matchers/BeCloseTo.swift @@ -9,9 +9,9 @@ internal func isCloseTo( _ actualValue: Value?, expectedValue: Value, delta: Value -) -> PredicateResult { +) -> MatcherResult { let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" - return PredicateResult( + return MatcherResult( bool: actualValue != nil && abs(actualValue! - expectedValue) < delta, message: .expectedCustomValueTo(errorMessage, actual: "<\(stringify(actualValue))>") @@ -22,9 +22,9 @@ internal func isCloseTo( _ actualValue: NMBDoubleConvertible?, expectedValue: NMBDoubleConvertible, delta: Double -) -> PredicateResult { +) -> MatcherResult { let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" - return PredicateResult( + return MatcherResult( bool: actualValue != nil && abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta, message: .expectedCustomValueTo(errorMessage, actual: "<\(stringify(actualValue))>") @@ -38,8 +38,8 @@ internal func isCloseTo( public func beCloseTo( _ expectedValue: Value, within delta: Value = defaultDelta() -) -> Predicate { - return Predicate.define { actualExpression in +) -> Matcher { + return Matcher.define { actualExpression in return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta) } } @@ -51,8 +51,8 @@ public func beCloseTo( public func beCloseTo( _ expectedValue: Value, within delta: Double = DefaultDelta -) -> Predicate { - return Predicate.define { actualExpression in +) -> Matcher { + return Matcher.define { actualExpression in return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta) } } @@ -60,38 +60,38 @@ public func beCloseTo( private func beCloseTo( _ expectedValue: NMBDoubleConvertible, within delta: Double = DefaultDelta -) -> Predicate { - return Predicate.define { actualExpression in +) -> Matcher { + return Matcher.define { actualExpression in return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta) } } #if canImport(Darwin) -public class NMBObjCBeCloseToPredicate: NMBPredicate { +public class NMBObjCBeCloseToMatcher: NMBMatcher { private let _expected: NSNumber fileprivate init(expected: NSNumber, within: CDouble) { _expected = expected - let predicate = beCloseTo(expected, within: within) - let predicateBlock: PredicateBlock = { actualExpression in + let matcher = beCloseTo(expected, within: within) + let matcherBlock: MatcherBlock = { actualExpression in let expr = actualExpression.cast { $0 as? NMBDoubleConvertible } - return try predicate.satisfies(expr).toObjectiveC() + return try matcher.satisfies(expr).toObjectiveC() } - super.init(predicate: predicateBlock) + super.init(matcher: matcherBlock) } - @objc public var within: (CDouble) -> NMBObjCBeCloseToPredicate { + @objc public var within: (CDouble) -> NMBObjCBeCloseToMatcher { let expected = _expected return { delta in - return NMBObjCBeCloseToPredicate(expected: expected, within: delta) + return NMBObjCBeCloseToMatcher(expected: expected, within: delta) } } } -extension NMBPredicate { - @objc public class func beCloseToMatcher(_ expected: NSNumber, within: CDouble) -> NMBObjCBeCloseToPredicate { - return NMBObjCBeCloseToPredicate(expected: expected, within: within) +extension NMBMatcher { + @objc public class func beCloseToMatcher(_ expected: NSNumber, within: CDouble) -> NMBObjCBeCloseToMatcher { + return NMBObjCBeCloseToMatcher(expected: expected, within: within) } } #endif @@ -99,9 +99,9 @@ extension NMBPredicate { public func beCloseTo( _ expectedValues: Values, within delta: Value = defaultDelta() -) -> Predicate where Values.Element == Value { +) -> Matcher where Values.Element == Value { let errorMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))" - return Predicate.simple(errorMessage) { actualExpression in + return Matcher.simple(errorMessage) { actualExpression in guard let actualValues = try actualExpression.evaluate() else { return .doesNotMatch } diff --git a/Sources/Nimble/Matchers/BeEmpty.swift b/Sources/Nimble/Matchers/BeEmpty.swift index 4036471db..571797ca1 100644 --- a/Sources/Nimble/Matchers/BeEmpty.swift +++ b/Sources/Nimble/Matchers/BeEmpty.swift @@ -2,48 +2,48 @@ import Foundation /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For strings, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } var generator = actual.makeIterator() - return PredicateStatus(bool: generator.next() == nil) + return MatcherStatus(bool: generator.next() == nil) } } /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For strings, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.isEmpty) + return MatcherStatus(bool: actual.isEmpty) } } /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For strings, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.isEmpty) + return MatcherStatus(bool: actual.isEmpty) } } /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For strings, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.isEmpty) + return MatcherStatus(bool: actual.isEmpty) } } /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For NSString instances, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.length == 0) + return MatcherStatus(bool: actual.length == 0) } } @@ -52,35 +52,35 @@ public func beEmpty() -> Predicate { /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For strings, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.count == 0) + return MatcherStatus(bool: actual.count == 0) } } /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For strings, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.count == 0) + return MatcherStatus(bool: actual.count == 0) } } /// A Nimble matcher that succeeds when a value is "empty". For collections, this /// means the are no items in that collection. For strings, it is an empty string. -public func beEmpty() -> Predicate { - return Predicate.simple("be empty") { actualExpression in +public func beEmpty() -> Matcher { + return Matcher.simple("be empty") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.count == 0) + return MatcherStatus(bool: actual.count == 0) } } #if canImport(Darwin) -extension NMBPredicate { - @objc public class func beEmptyMatcher() -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beEmptyMatcher() -> NMBMatcher { + return NMBMatcher { actualExpression in let location = actualExpression.location let actualValue = try actualExpression.evaluate() @@ -92,16 +92,16 @@ extension NMBPredicate { return try beEmpty().satisfies(expr).toObjectiveC() } else if let actualValue = actualValue { let badTypeErrorMsg = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" - return NMBPredicateResult( - status: NMBPredicateStatus.fail, + return NMBMatcherResult( + status: NMBMatcherStatus.fail, message: NMBExpectationMessage( expectedActualValueTo: badTypeErrorMsg, customActualValue: "\(String(describing: type(of: actualValue))) type" ) ) } - return NMBPredicateResult( - status: NMBPredicateStatus.fail, + return NMBMatcherResult( + status: NMBMatcherStatus.fail, message: NMBExpectationMessage(expectedActualValueTo: "be empty").appendedBeNilHint() ) } diff --git a/Sources/Nimble/Matchers/BeGreaterThan.swift b/Sources/Nimble/Matchers/BeGreaterThan.swift index 62aceb3e4..dc96d583d 100644 --- a/Sources/Nimble/Matchers/BeGreaterThan.swift +++ b/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -1,10 +1,10 @@ /// A Nimble matcher that succeeds when the actual value is greater than the expected value. -public func beGreaterThan(_ expectedValue: T?) -> Predicate { +public func beGreaterThan(_ expectedValue: T?) -> Matcher { let errorMessage = "be greater than <\(stringify(expectedValue))>" - return Predicate.simple(errorMessage) { actualExpression in + return Matcher.simple(errorMessage) { actualExpression in guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } - return PredicateStatus(bool: actual > expected) + return MatcherStatus(bool: actual > expected) } } @@ -20,13 +20,13 @@ public func > (lhs: AsyncExpectation, rhs: T) async { import enum Foundation.ComparisonResult /// A Nimble matcher that succeeds when the actual value is greater than the expected value. -public func beGreaterThan(_ expectedValue: T?) -> Predicate { +public func beGreaterThan(_ expectedValue: T?) -> Matcher { let errorMessage = "be greater than <\(stringify(expectedValue))>" - return Predicate.simple(errorMessage) { actualExpression in + return Matcher.simple(errorMessage) { actualExpression in let actualValue = try actualExpression.evaluate() let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } @@ -38,9 +38,9 @@ public func > (lhs: AsyncExpectation, rhs: T?) async { await lhs.to(beGreaterThan(rhs)) } -extension NMBPredicate { - @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { $0 as? NMBComparable } return try beGreaterThan(expected).satisfies(expr).toObjectiveC() } diff --git a/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift index 271456c94..14821debe 100644 --- a/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift +++ b/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift @@ -1,11 +1,11 @@ /// A Nimble matcher that succeeds when the actual value is greater than /// or equal to the expected value. -public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Matcher { let message = "be greater than or equal to <\(stringify(expectedValue))>" - return Predicate.simple(message) { actualExpression in + return Matcher.simple(message) { actualExpression in guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } - return PredicateStatus(bool: actual >= expected) + return MatcherStatus(bool: actual >= expected) } } @@ -22,12 +22,12 @@ import enum Foundation.ComparisonResult /// A Nimble matcher that succeeds when the actual value is greater than /// or equal to the expected value. -public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Matcher { let message = "be greater than or equal to <\(stringify(expectedValue))>" - return Predicate.simple(message) { actualExpression in + return Matcher.simple(message) { actualExpression in let actualValue = try actualExpression.evaluate() let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } @@ -39,9 +39,9 @@ public func >= (lhs: AsyncExpectation, rhs: T) async { await lhs.to(beGreaterThanOrEqualTo(rhs)) } -extension NMBPredicate { - @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { $0 as? NMBComparable } return try beGreaterThanOrEqualTo(expected).satisfies(expr).toObjectiveC() } diff --git a/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Sources/Nimble/Matchers/BeIdenticalTo.swift index 7a9bed4b6..3f00b187f 100644 --- a/Sources/Nimble/Matchers/BeIdenticalTo.swift +++ b/Sources/Nimble/Matchers/BeIdenticalTo.swift @@ -1,11 +1,11 @@ /// A Nimble matcher that succeeds when the actual value is the same instance /// as the expected instance. -public func beIdenticalTo(_ expected: AnyObject?) -> Predicate { - return Predicate.define { actualExpression in +public func beIdenticalTo(_ expected: AnyObject?) -> Matcher { + return Matcher.define { actualExpression in let actual = try actualExpression.evaluate() let bool = actual === expected && actual !== nil - return PredicateResult( + return MatcherResult( bool: bool, message: .expectedCustomValueTo( "be identical to \(identityAsString(expected))", @@ -35,16 +35,16 @@ public func !== (lhs: AsyncExpectation, rhs: AnyObject?) async { /// as the expected instance. /// /// Alias for "beIdenticalTo". -public func be(_ expected: AnyObject?) -> Predicate { +public func be(_ expected: AnyObject?) -> Matcher { return beIdenticalTo(expected) } #if canImport(Darwin) import class Foundation.NSObject -extension NMBPredicate { - @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBMatcher { + return NMBMatcher { actualExpression in let aExpr = actualExpression.cast { $0 as AnyObject? } return try beIdenticalTo(expected).satisfies(aExpr).toObjectiveC() } diff --git a/Sources/Nimble/Matchers/BeLessThan.swift b/Sources/Nimble/Matchers/BeLessThan.swift index 4c5cd2da4..4be83c973 100644 --- a/Sources/Nimble/Matchers/BeLessThan.swift +++ b/Sources/Nimble/Matchers/BeLessThan.swift @@ -1,10 +1,10 @@ /// A Nimble matcher that succeeds when the actual value is less than the expected value. -public func beLessThan(_ expectedValue: T?) -> Predicate { +public func beLessThan(_ expectedValue: T?) -> Matcher { let message = "be less than <\(stringify(expectedValue))>" - return Predicate.simple(message) { actualExpression in + return Matcher.simple(message) { actualExpression in guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } - return PredicateStatus(bool: actual < expected) + return MatcherStatus(bool: actual < expected) } } @@ -20,12 +20,12 @@ public func < (lhs: AsyncExpectation, rhs: V) async { import enum Foundation.ComparisonResult /// A Nimble matcher that succeeds when the actual value is less than the expected value. -public func beLessThan(_ expectedValue: T?) -> Predicate { +public func beLessThan(_ expectedValue: T?) -> Matcher { let message = "be less than <\(stringify(expectedValue))>" - return Predicate.simple(message) { actualExpression in + return Matcher.simple(message) { actualExpression in let actualValue = try actualExpression.evaluate() let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } @@ -37,9 +37,9 @@ public func < (lhs: AsyncExpectation, rhs: V?) async { await lhs.to(beLessThan(rhs)) } -extension NMBPredicate { - @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { $0 as? NMBComparable } return try beLessThan(expected).satisfies(expr).toObjectiveC() } diff --git a/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Sources/Nimble/Matchers/BeLessThanOrEqual.swift index 0bfb57cc0..830e9e62b 100644 --- a/Sources/Nimble/Matchers/BeLessThanOrEqual.swift +++ b/Sources/Nimble/Matchers/BeLessThanOrEqual.swift @@ -1,10 +1,10 @@ /// A Nimble matcher that succeeds when the actual value is less than /// or equal to the expected value. -public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { - return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Matcher { + return Matcher.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in guard let actual = try actualExpression.evaluate(), let expected = expectedValue else { return .fail } - return PredicateStatus(bool: actual <= expected) + return MatcherStatus(bool: actual <= expected) } } @@ -21,11 +21,11 @@ import enum Foundation.ComparisonResult /// A Nimble matcher that succeeds when the actual value is less than /// or equal to the expected value. -public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { - return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in +public func beLessThanOrEqualTo(_ expectedValue: T?) -> Matcher { + return Matcher.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in let actualValue = try actualExpression.evaluate() let matches = actualValue.map { $0.NMB_compare(expectedValue) != .orderedDescending } ?? false - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } @@ -37,9 +37,9 @@ public func <= (lhs: AsyncExpectation, rhs: T) async { await lhs.to(beLessThanOrEqualTo(rhs)) } -extension NMBPredicate { - @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { $0 as? NMBComparable } return try beLessThanOrEqualTo(expected).satisfies(expr).toObjectiveC() } diff --git a/Sources/Nimble/Matchers/BeLogical.swift b/Sources/Nimble/Matchers/BeLogical.swift index a4094d5fe..5170299f7 100644 --- a/Sources/Nimble/Matchers/BeLogical.swift +++ b/Sources/Nimble/Matchers/BeLogical.swift @@ -72,10 +72,10 @@ extension UInt: ExpressibleByBooleanLiteral { } } -internal func rename(_ matcher: Predicate, failureMessage message: ExpectationMessage) -> Predicate { - return Predicate { actualExpression in +internal func rename(_ matcher: Matcher, failureMessage message: ExpectationMessage) -> Matcher { + return Matcher { actualExpression in let result = try matcher.satisfies(actualExpression) - return PredicateResult(status: result.status, message: message) + return MatcherResult(status: result.status, message: message) }.requireNonNil } @@ -83,60 +83,60 @@ internal func rename(_ matcher: Predicate, failureMessage message: Expecta /// A Nimble matcher that succeeds when the actual value is exactly true. /// This matcher will not match against nils. -public func beTrue() -> Predicate { +public func beTrue() -> Matcher { return rename(equal(true), failureMessage: .expectedActualValueTo("be true")) } /// A Nimble matcher that succeeds when the actual value is exactly false. /// This matcher will not match against nils. -public func beFalse() -> Predicate { +public func beFalse() -> Matcher { return rename(equal(false), failureMessage: .expectedActualValueTo("be false")) } // MARK: beTruthy() / beFalsy() /// A Nimble matcher that succeeds when the actual value is not logically false. -public func beTruthy() -> Predicate { - return Predicate.simpleNilable("be truthy") { actualExpression in +public func beTruthy() -> Matcher { + return Matcher.simpleNilable("be truthy") { actualExpression in let actualValue = try actualExpression.evaluate() - return PredicateStatus(bool: actualValue == (true as T)) + return MatcherStatus(bool: actualValue == (true as T)) } } /// A Nimble matcher that succeeds when the actual value is logically false. /// This matcher will match against nils. -public func beFalsy() -> Predicate { - return Predicate.simpleNilable("be falsy") { actualExpression in +public func beFalsy() -> Matcher { + return Matcher.simpleNilable("be falsy") { actualExpression in let actualValue = try actualExpression.evaluate() - return PredicateStatus(bool: actualValue != (true as T)) + return MatcherStatus(bool: actualValue != (true as T)) } } #if canImport(Darwin) -extension NMBPredicate { - @objc public class func beTruthyMatcher() -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beTruthyMatcher() -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } return try beTruthy().satisfies(expr).toObjectiveC() } } - @objc public class func beFalsyMatcher() -> NMBPredicate { - return NMBPredicate { actualExpression in + @objc public class func beFalsyMatcher() -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } return try beFalsy().satisfies(expr).toObjectiveC() } } - @objc public class func beTrueMatcher() -> NMBPredicate { - return NMBPredicate { actualExpression in + @objc public class func beTrueMatcher() -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } return try beTrue().satisfies(expr).toObjectiveC() } } - @objc public class func beFalseMatcher() -> NMBPredicate { - return NMBPredicate { actualExpression in + @objc public class func beFalseMatcher() -> NMBMatcher { + return NMBMatcher { actualExpression in let expr = actualExpression.cast { value -> Bool? in guard let value = value else { return nil } return (value as? NSNumber)?.boolValue ?? false diff --git a/Sources/Nimble/Matchers/BeNil.swift b/Sources/Nimble/Matchers/BeNil.swift index 32c50c20d..eea1440e7 100644 --- a/Sources/Nimble/Matchers/BeNil.swift +++ b/Sources/Nimble/Matchers/BeNil.swift @@ -8,13 +8,13 @@ extension Optional: _OptionalProtocol { } /// A Nimble matcher that succeeds when the actual value is nil. -public func beNil() -> Predicate { - return Predicate.simpleNilable("be nil") { actualExpression in +public func beNil() -> Matcher { + return Matcher.simpleNilable("be nil") { actualExpression in let actualValue = try actualExpression.evaluate() if let actual = actualValue, let nestedOptionl = actual as? _OptionalProtocol { - return PredicateStatus(bool: nestedOptionl.isNil) + return MatcherStatus(bool: nestedOptionl.isNil) } - return PredicateStatus(bool: actualValue == nil) + return MatcherStatus(bool: actualValue == nil) } } @@ -46,9 +46,9 @@ extension AsyncExpectation { #if canImport(Darwin) import Foundation -extension NMBPredicate { - @objc public class func beNilMatcher() -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beNilMatcher() -> NMBMatcher { + return NMBMatcher { actualExpression in return try beNil().satisfies(actualExpression).toObjectiveC() } } diff --git a/Sources/Nimble/Matchers/BeResult.swift b/Sources/Nimble/Matchers/BeResult.swift index b05db7f97..7f90dfc34 100644 --- a/Sources/Nimble/Matchers/BeResult.swift +++ b/Sources/Nimble/Matchers/BeResult.swift @@ -6,8 +6,8 @@ import Foundation /// The closure only gets called when the result is success. public func beSuccess( test: ((Success) -> Void)? = nil -) -> Predicate> { - return Predicate.define { expression in +) -> Matcher> { + return Matcher.define { expression in var rawMessage = "be " if test != nil { rawMessage += " that satisfies block" @@ -15,7 +15,7 @@ public func beSuccess( let message = ExpectationMessage.expectedActualValueTo(rawMessage) guard case let .success(value)? = try expression.evaluate() else { - return PredicateResult(status: .doesNotMatch, message: message) + return MatcherResult(status: .doesNotMatch, message: message) } var matches = true @@ -29,7 +29,7 @@ public func beSuccess( } } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } @@ -39,8 +39,8 @@ public func beSuccess( /// The closure only gets called when the result is failure. public func beFailure( test: ((Failure) -> Void)? = nil -) -> Predicate> { - return Predicate.define { expression in +) -> Matcher> { + return Matcher.define { expression in var rawMessage = "be " if test != nil { rawMessage += " that satisfies block" @@ -48,7 +48,7 @@ public func beFailure( let message = ExpectationMessage.expectedActualValueTo(rawMessage) guard case let .failure(error)? = try expression.evaluate() else { - return PredicateResult(status: .doesNotMatch, message: message) + return MatcherResult(status: .doesNotMatch, message: message) } var matches = true @@ -62,6 +62,6 @@ public func beFailure( } } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } diff --git a/Sources/Nimble/Matchers/BeVoid.swift b/Sources/Nimble/Matchers/BeVoid.swift index 8b0087f23..19bf4e915 100644 --- a/Sources/Nimble/Matchers/BeVoid.swift +++ b/Sources/Nimble/Matchers/BeVoid.swift @@ -1,8 +1,8 @@ /// A Nimble matcher that succeeds when the actual value is Void. -public func beVoid() -> Predicate<()> { - return Predicate.simpleNilable("be void") { actualExpression in +public func beVoid() -> Matcher<()> { + return Matcher.simpleNilable("be void") { actualExpression in let actualValue: ()? = try actualExpression.evaluate() - return PredicateStatus(bool: actualValue != nil) + return MatcherStatus(bool: actualValue != nil) } } diff --git a/Sources/Nimble/Matchers/BeWithin.swift b/Sources/Nimble/Matchers/BeWithin.swift index 9c56e9ee6..a4e2d7c7e 100644 --- a/Sources/Nimble/Matchers/BeWithin.swift +++ b/Sources/Nimble/Matchers/BeWithin.swift @@ -1,20 +1,20 @@ /// A Nimble matcher that succeeds when the actual value is within given range. -public func beWithin(_ range: Range) -> Predicate { +public func beWithin(_ range: Range) -> Matcher { let errorMessage = "be within range <(\(range.lowerBound)..<\(range.upperBound))>" - return Predicate.simple(errorMessage) { actualExpression in + return Matcher.simple(errorMessage) { actualExpression in if let actual = try actualExpression.evaluate() { - return PredicateStatus(bool: range.contains(actual)) + return MatcherStatus(bool: range.contains(actual)) } return .fail } } /// A Nimble matcher that succeeds when the actual value is within given range. -public func beWithin(_ range: ClosedRange) -> Predicate { +public func beWithin(_ range: ClosedRange) -> Matcher { let errorMessage = "be within range <(\(range.lowerBound)...\(range.upperBound))>" - return Predicate.simple(errorMessage) { actualExpression in + return Matcher.simple(errorMessage) { actualExpression in if let actual = try actualExpression.evaluate() { - return PredicateStatus(bool: range.contains(actual)) + return MatcherStatus(bool: range.contains(actual)) } return .fail } diff --git a/Sources/Nimble/Matchers/BeginWith.swift b/Sources/Nimble/Matchers/BeginWith.swift index 90b6b5d1b..cc4a58dac 100644 --- a/Sources/Nimble/Matchers/BeginWith.swift +++ b/Sources/Nimble/Matchers/BeginWith.swift @@ -2,19 +2,19 @@ import Foundation /// A Nimble matcher that succeeds when the actual sequence's first element /// is equal to the expected value. -public func beginWith(_ startingElement: S.Element) -> Predicate where S.Element: Equatable { - return Predicate.simple("begin with <\(startingElement)>") { actualExpression in +public func beginWith(_ startingElement: S.Element) -> Matcher where S.Element: Equatable { + return Matcher.simple("begin with <\(startingElement)>") { actualExpression in guard let actualValue = try actualExpression.evaluate() else { return .fail } var actualGenerator = actualValue.makeIterator() - return PredicateStatus(bool: actualGenerator.next() == startingElement) + return MatcherStatus(bool: actualGenerator.next() == startingElement) } } /// A Nimble matcher that succeeds when the actual collection's first element /// is equal to the expected object. -public func beginWith(_ startingElement: Any) -> Predicate { - return Predicate.simple("begin with <\(startingElement)>") { actualExpression in +public func beginWith(_ startingElement: Any) -> Matcher { + return Matcher.simple("begin with <\(startingElement)>") { actualExpression in guard let collection = try actualExpression.evaluate() else { return .fail } guard collection.count > 0 else { return .doesNotMatch } #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) @@ -24,24 +24,24 @@ public func beginWith(_ startingElement: Any) -> Predicate return .fail } #endif - return PredicateStatus(bool: collectionValue.isEqual(startingElement)) + return MatcherStatus(bool: collectionValue.isEqual(startingElement)) } } /// A Nimble matcher that succeeds when the actual string contains expected substring /// where the expected substring's location is zero. -public func beginWith(_ startingSubstring: String) -> Predicate { - return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in +public func beginWith(_ startingSubstring: String) -> Matcher { + return Matcher.simple("begin with <\(startingSubstring)>") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: actual.hasPrefix(startingSubstring)) + return MatcherStatus(bool: actual.hasPrefix(startingSubstring)) } } #if canImport(Darwin) -extension NMBPredicate { - @objc public class func beginWithMatcher(_ expected: Any) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func beginWithMatcher(_ expected: Any) -> NMBMatcher { + return NMBMatcher { actualExpression in let actual = try actualExpression.evaluate() if actual is String { let expr = actualExpression.cast { $0 as? String } diff --git a/Sources/Nimble/Matchers/BeginWithPrefix.swift b/Sources/Nimble/Matchers/BeginWithPrefix.swift index c3a79b18d..8ff068d82 100644 --- a/Sources/Nimble/Matchers/BeginWithPrefix.swift +++ b/Sources/Nimble/Matchers/BeginWithPrefix.swift @@ -2,38 +2,38 @@ /// /// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2854218-starts public func beginWith(prefix expectedPrefix: Seq2?) - -> Predicate where Seq1.Element: Equatable, Seq1.Element == Seq2.Element { - return Predicate.define("begin with <\(stringify(expectedPrefix))>") { (actualExpression, msg) in + -> Matcher where Seq1.Element: Equatable, Seq1.Element == Seq2.Element { + return Matcher.define("begin with <\(stringify(expectedPrefix))>") { (actualExpression, msg) in let actualPrefix = try actualExpression.evaluate() switch (expectedPrefix, actualPrefix) { case (nil, _?): - return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) + return MatcherResult(status: .fail, message: msg.appendedBeNilHint()) case (nil, nil), (_, nil): - return PredicateResult(status: .fail, message: msg) + return MatcherResult(status: .fail, message: msg) case (let expected?, let actual?): let matches = actual.starts(with: expected) - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } } -/// A Nimble matcher that succeeds when the expected sequence is the prefix of the actual sequence, using the given predicate as the equivalence test. +/// A Nimble matcher that succeeds when the expected sequence is the prefix of the actual sequence, using the given matcher as the equivalence test. /// /// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2996828-starts public func beginWith( prefix expectedPrefix: Seq2?, by areEquivalent: @escaping (Seq1.Element, Seq2.Element) -> Bool -) -> Predicate { - return Predicate.define("begin with <\(stringify(expectedPrefix))>") { (actualExpression, msg) in +) -> Matcher { + return Matcher.define("begin with <\(stringify(expectedPrefix))>") { (actualExpression, msg) in let actualPrefix = try actualExpression.evaluate() switch (expectedPrefix, actualPrefix) { case (nil, _?): - return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) + return MatcherResult(status: .fail, message: msg.appendedBeNilHint()) case (nil, nil), (_, nil): - return PredicateResult(status: .fail, message: msg) + return MatcherResult(status: .fail, message: msg) case (let expected?, let actual?): let matches = actual.starts(with: expected, by: areEquivalent) - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } } diff --git a/Sources/Nimble/Matchers/Contain.swift b/Sources/Nimble/Matchers/Contain.swift index 38d1dab50..555d4d1ff 100644 --- a/Sources/Nimble/Matchers/Contain.swift +++ b/Sources/Nimble/Matchers/Contain.swift @@ -3,109 +3,109 @@ import Foundation #endif /// A Nimble matcher that succeeds when the actual sequence contains the expected values. -public func contain(_ items: S.Element...) -> Predicate where S.Element: Equatable { +public func contain(_ items: S.Element...) -> Matcher where S.Element: Equatable { return contain(items) } /// A Nimble matcher that succeeds when the actual sequence contains the expected values. -public func contain(_ items: [S.Element]) -> Predicate where S.Element: Equatable { - return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in +public func contain(_ items: [S.Element]) -> Matcher where S.Element: Equatable { + return Matcher.simple("contain <\(arrayAsString(items))>") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } let matches = items.allSatisfy { return actual.contains($0) } - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } /// A Nimble matcher that succeeds when the actual set contains the expected values. -public func contain(_ items: S.Element...) -> Predicate where S.Element: Equatable { +public func contain(_ items: S.Element...) -> Matcher where S.Element: Equatable { return contain(items) } /// A Nimble matcher that succeeds when the actual set contains the expected values. -public func contain(_ items: [S.Element]) -> Predicate where S.Element: Equatable { - return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in +public func contain(_ items: [S.Element]) -> Matcher where S.Element: Equatable { + return Matcher.simple("contain <\(arrayAsString(items))>") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } let matches = items.allSatisfy { return actual.contains($0) } - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } /// A Nimble matcher that succeeds when the actual set contains the expected values. -public func contain(_ items: S.Element...) -> Predicate where S.Element: Equatable { +public func contain(_ items: S.Element...) -> Matcher where S.Element: Equatable { return contain(items) } /// A Nimble matcher that succeeds when the actual set contains the expected values. -public func contain(_ items: [S.Element]) -> Predicate where S.Element: Equatable { - return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in +public func contain(_ items: [S.Element]) -> Matcher where S.Element: Equatable { + return Matcher.simple("contain <\(arrayAsString(items))>") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } let matches = items.allSatisfy { return actual.contains($0) } - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } /// A Nimble matcher that succeeds when the actual string contains the expected substring. -public func contain(_ substrings: String...) -> Predicate { +public func contain(_ substrings: String...) -> Matcher { return contain(substrings) } -public func contain(_ substrings: [String]) -> Predicate { - return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in +public func contain(_ substrings: [String]) -> Matcher { + return Matcher.simple("contain <\(arrayAsString(substrings))>") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } let matches = substrings.allSatisfy { let range = actual.range(of: $0) return range != nil && !range!.isEmpty } - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } #if canImport(Foundation) /// A Nimble matcher that succeeds when the actual string contains the expected substring. -public func contain(_ substrings: NSString...) -> Predicate { +public func contain(_ substrings: NSString...) -> Matcher { return contain(substrings) } -public func contain(_ substrings: [NSString]) -> Predicate { - return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in +public func contain(_ substrings: [NSString]) -> Matcher { + return Matcher.simple("contain <\(arrayAsString(substrings))>") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } let matches = substrings.allSatisfy { actual.range(of: $0.description).length != 0 } - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } #endif /// A Nimble matcher that succeeds when the actual collection contains the expected object. -public func contain(_ items: Any?...) -> Predicate { +public func contain(_ items: Any?...) -> Matcher { return contain(items) } -public func contain(_ items: [Any?]) -> Predicate { - return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in +public func contain(_ items: [Any?]) -> Matcher { + return Matcher.simple("contain <\(arrayAsString(items))>") { actualExpression in guard let actual = try actualExpression.evaluate() else { return .fail } let matches = items.allSatisfy { item in return item.map { actual.contains($0) } ?? false } - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } #if canImport(Darwin) -extension NMBPredicate { - @objc public class func containMatcher(_ expected: [NSObject]) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func containMatcher(_ expected: [NSObject]) -> NMBMatcher { + return NMBMatcher { actualExpression in let location = actualExpression.location let actualValue = try actualExpression.evaluate() if let value = actualValue as? NMBContainer { @@ -130,7 +130,7 @@ extension NMBPredicate { .expectedActualValueTo("contain <\(arrayAsString(expected))>") .appendedBeNilHint() } - return NMBPredicateResult(status: .fail, message: message.toObjectiveC()) + return NMBMatcherResult(status: .fail, message: message.toObjectiveC()) } } } diff --git a/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Sources/Nimble/Matchers/ContainElementSatisfying.swift index 763e781a5..68cc75304 100644 --- a/Sources/Nimble/Matchers/ContainElementSatisfying.swift +++ b/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -1,46 +1,46 @@ public func containElementSatisfying( - _ predicate: @escaping ((S.Element) -> Bool), _ predicateDescription: String = "" -) -> Predicate { - return Predicate.define { actualExpression in + _ matcher: @escaping ((S.Element) -> Bool), _ matcherDescription: String = "" +) -> Matcher { + return Matcher.define { actualExpression in let message: ExpectationMessage - if predicateDescription == "" { - message = .expectedTo("find object in collection that satisfies predicate") + if matcherDescription == "" { + message = .expectedTo("find object in collection that satisfies matcher") } else { - message = .expectedTo("find object in collection \(predicateDescription)") + message = .expectedTo("find object in collection \(matcherDescription)") } if let sequence = try actualExpression.evaluate() { - for object in sequence where predicate(object) { - return PredicateResult(bool: true, message: message) + for object in sequence where matcher(object) { + return MatcherResult(bool: true, message: message) } - return PredicateResult(bool: false, message: message) + return MatcherResult(bool: false, message: message) } - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) } } public func containElementSatisfying( - _ predicate: @escaping ((S.Element) async -> Bool), _ predicateDescription: String = "" -) -> AsyncPredicate { - return AsyncPredicate.define { actualExpression in + _ matcher: @escaping ((S.Element) async -> Bool), _ matcherDescription: String = "" +) -> AsyncMatcher { + return AsyncMatcher.define { actualExpression in let message: ExpectationMessage - if predicateDescription == "" { - message = .expectedTo("find object in collection that satisfies predicate") + if matcherDescription == "" { + message = .expectedTo("find object in collection that satisfies matcher") } else { - message = .expectedTo("find object in collection \(predicateDescription)") + message = .expectedTo("find object in collection \(matcherDescription)") } if let sequence = try await actualExpression.evaluate() { - for object in sequence where await predicate(object) { - return PredicateResult(bool: true, message: message) + for object in sequence where await matcher(object) { + return MatcherResult(bool: true, message: message) } - return PredicateResult(bool: false, message: message) + return MatcherResult(bool: false, message: message) } - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) } } @@ -49,19 +49,19 @@ import class Foundation.NSObject import struct Foundation.NSFastEnumerationIterator import protocol Foundation.NSFastEnumeration -extension NMBPredicate { - @objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func containElementSatisfyingMatcher(_ matcher: @escaping ((NSObject) -> Bool)) -> NMBMatcher { + return NMBMatcher { actualExpression in let value = try actualExpression.evaluate() guard let enumeration = value as? NSFastEnumeration else { let message = ExpectationMessage.fail( "containElementSatisfying must be provided an NSFastEnumeration object" ) - return NMBPredicateResult(status: .fail, message: message.toObjectiveC()) + return NMBMatcherResult(status: .fail, message: message.toObjectiveC()) } let message = ExpectationMessage - .expectedTo("find object in collection that satisfies predicate") + .expectedTo("find object in collection that satisfies matcher") .toObjectiveC() var iterator = NSFastEnumerationIterator(enumeration) @@ -70,12 +70,12 @@ extension NMBPredicate { continue } - if predicate(object) { - return NMBPredicateResult(status: .matches, message: message) + if matcher(object) { + return NMBMatcherResult(status: .matches, message: message) } } - return NMBPredicateResult(status: .doesNotMatch, message: message) + return NMBMatcherResult(status: .doesNotMatch, message: message) } } } diff --git a/Sources/Nimble/Matchers/ElementsEqual.swift b/Sources/Nimble/Matchers/ElementsEqual.swift index 708cf1c9c..39b2dbf21 100644 --- a/Sources/Nimble/Matchers/ElementsEqual.swift +++ b/Sources/Nimble/Matchers/ElementsEqual.swift @@ -4,39 +4,39 @@ /// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2854213-elementsequal public func elementsEqual( _ expectedValue: Seq2? -) -> Predicate where Seq1.Element: Equatable, Seq1.Element == Seq2.Element { - return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in +) -> Matcher where Seq1.Element: Equatable, Seq1.Element == Seq2.Element { + return Matcher.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in let actualValue = try actualExpression.evaluate() switch (expectedValue, actualValue) { case (nil, _?): - return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) + return MatcherResult(status: .fail, message: msg.appendedBeNilHint()) case (nil, nil), (_, nil): - return PredicateResult(status: .fail, message: msg) + return MatcherResult(status: .fail, message: msg) case (let expected?, let actual?): let matches = expected.elementsEqual(actual) - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } } /// A Nimble matcher that succeeds when the actual sequence and the exepected sequence contain equivalent elements in -/// the same order, using the given predicate as the equivalence test. +/// the same order, using the given matcher as the equivalence test. /// /// This is a matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal public func elementsEqual( _ expectedValue: Seq2?, by areEquivalent: @escaping (Seq1.Element, Seq2.Element) -> Bool -) -> Predicate { - return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in +) -> Matcher { + return Matcher.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in let actualValue = try actualExpression.evaluate() switch (expectedValue, actualValue) { case (nil, _?): - return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) + return MatcherResult(status: .fail, message: msg.appendedBeNilHint()) case (nil, nil), (_, nil): - return PredicateResult(status: .fail, message: msg) + return MatcherResult(status: .fail, message: msg) case (let expected?, let actual?): let matches = actual.elementsEqual(expected, by: areEquivalent) - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } } diff --git a/Sources/Nimble/Matchers/EndWith.swift b/Sources/Nimble/Matchers/EndWith.swift index 950d9d5f7..d1fffc42e 100644 --- a/Sources/Nimble/Matchers/EndWith.swift +++ b/Sources/Nimble/Matchers/EndWith.swift @@ -2,8 +2,8 @@ import Foundation /// A Nimble matcher that succeeds when the actual sequence's last element /// is equal to the expected value. -public func endWith(_ endingElement: S.Element) -> Predicate where S.Element: Equatable { - return Predicate.simple("end with <\(endingElement)>") { actualExpression in +public func endWith(_ endingElement: S.Element) -> Matcher where S.Element: Equatable { + return Matcher.simple("end with <\(endingElement)>") { actualExpression in guard let actualValue = try actualExpression.evaluate() else { return .fail } var actualGenerator = actualValue.makeIterator() @@ -14,17 +14,17 @@ public func endWith(_ endingElement: S.Element) -> Predicate whe item = actualGenerator.next() } while(item != nil) - return PredicateStatus(bool: lastItem == endingElement) + return MatcherStatus(bool: lastItem == endingElement) } } /// A Nimble matcher that succeeds when the actual collection's last element /// is equal to the expected object. -public func endWith(_ endingElement: Any) -> Predicate { - return Predicate.simple("end with <\(endingElement)>") { actualExpression in +public func endWith(_ endingElement: Any) -> Matcher { + return Matcher.simple("end with <\(endingElement)>") { actualExpression in guard let collection = try actualExpression.evaluate() else { return .fail } - guard collection.count > 0 else { return PredicateStatus(bool: false) } + guard collection.count > 0 else { return MatcherStatus(bool: false) } #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) let collectionValue = collection.object(at: collection.count - 1) as AnyObject #else @@ -33,25 +33,25 @@ public func endWith(_ endingElement: Any) -> Predicate { } #endif - return PredicateStatus(bool: collectionValue.isEqual(endingElement)) + return MatcherStatus(bool: collectionValue.isEqual(endingElement)) } } /// A Nimble matcher that succeeds when the actual string contains the expected substring /// where the expected substring's location is the actual string's length minus the /// expected substring's length. -public func endWith(_ endingSubstring: String) -> Predicate { - return Predicate.simple("end with <\(endingSubstring)>") { actualExpression in +public func endWith(_ endingSubstring: String) -> Matcher { + return Matcher.simple("end with <\(endingSubstring)>") { actualExpression in guard let collection = try actualExpression.evaluate() else { return .fail } - return PredicateStatus(bool: collection.hasSuffix(endingSubstring)) + return MatcherStatus(bool: collection.hasSuffix(endingSubstring)) } } #if canImport(Darwin) -extension NMBPredicate { - @objc public class func endWithMatcher(_ expected: Any) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func endWithMatcher(_ expected: Any) -> NMBMatcher { + return NMBMatcher { actualExpression in let actual = try actualExpression.evaluate() if actual is String { let expr = actualExpression.cast { $0 as? String } diff --git a/Sources/Nimble/Matchers/Equal+Tuple.swift b/Sources/Nimble/Matchers/Equal+Tuple.swift index b8d9ec6b2..17b2f2e5f 100644 --- a/Sources/Nimble/Matchers/Equal+Tuple.swift +++ b/Sources/Nimble/Matchers/Equal+Tuple.swift @@ -6,7 +6,7 @@ /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: (T1, T2)? -) -> Predicate<(T1, T2)> { +) -> Matcher<(T1, T2)> { equal(expectedValue, by: ==) } @@ -44,7 +44,7 @@ public func != ( /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: (T1, T2, T3)? -) -> Predicate<(T1, T2, T3)> { +) -> Matcher<(T1, T2, T3)> { equal(expectedValue, by: ==) } @@ -84,7 +84,7 @@ public func != ( /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: (T1, T2, T3, T4)? -) -> Predicate<(T1, T2, T3, T4)> { +) -> Matcher<(T1, T2, T3, T4)> { equal(expectedValue, by: ==) } @@ -123,7 +123,7 @@ public func != ( /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: (T1, T2, T3, T4, T5)? -) -> Predicate<(T1, T2, T3, T4, T5)> { +) -> Matcher<(T1, T2, T3, T4, T5)> { equal(expectedValue, by: ==) } @@ -163,7 +163,7 @@ public func != ( _ expectedValue: (T1, T2, T3, T4, T5, T6)? -) -> Predicate<(T1, T2, T3, T4, T5, T6)> { +) -> Matcher<(T1, T2, T3, T4, T5, T6)> { equal(expectedValue, by: ==) } diff --git a/Sources/Nimble/Matchers/Equal+TupleArray.swift b/Sources/Nimble/Matchers/Equal+TupleArray.swift index 10a2cd604..eff6168d0 100644 --- a/Sources/Nimble/Matchers/Equal+TupleArray.swift +++ b/Sources/Nimble/Matchers/Equal+TupleArray.swift @@ -6,7 +6,7 @@ /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: [(T1, T2)]? -) -> Predicate<[(T1, T2)]> { +) -> Matcher<[(T1, T2)]> { equalTupleArray(expectedValue, by: ==) } @@ -44,7 +44,7 @@ public func != ( /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: [(T1, T2, T3)]? -) -> Predicate<[(T1, T2, T3)]> { +) -> Matcher<[(T1, T2, T3)]> { equalTupleArray(expectedValue, by: ==) } @@ -82,7 +82,7 @@ public func != ( /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: [(T1, T2, T3, T4)]? -) -> Predicate<[(T1, T2, T3, T4)]> { +) -> Matcher<[(T1, T2, T3, T4)]> { equalTupleArray(expectedValue, by: ==) } @@ -120,7 +120,7 @@ public func != ( /// Values can support equal by supporting the Equatable protocol. public func equal( _ expectedValue: [(T1, T2, T3, T4, T5)]? -) -> Predicate<[(T1, T2, T3, T4, T5)]> { +) -> Matcher<[(T1, T2, T3, T4, T5)]> { equalTupleArray(expectedValue, by: ==) } @@ -158,7 +158,7 @@ public func != ( _ expectedValue: [(T1, T2, T3, T4, T5, T6)]? -) -> Predicate<[(T1, T2, T3, T4, T5, T6)]> { +) -> Matcher<[(T1, T2, T3, T4, T5, T6)]> { equalTupleArray(expectedValue, by: ==) } @@ -197,7 +197,7 @@ public func != ( _ expectedValue: [(Tuple)]?, by areTuplesEquivalent: @escaping (Tuple, Tuple) -> Bool -) -> Predicate<[Tuple]> { +) -> Matcher<[Tuple]> { equal(expectedValue) { $0.elementsEqual($1, by: areTuplesEquivalent) } diff --git a/Sources/Nimble/Matchers/Equal.swift b/Sources/Nimble/Matchers/Equal.swift index 324f40792..4ec21e37d 100644 --- a/Sources/Nimble/Matchers/Equal.swift +++ b/Sources/Nimble/Matchers/Equal.swift @@ -1,17 +1,17 @@ internal func equal( _ expectedValue: T?, by areEquivalent: @escaping (T, T) -> Bool -) -> Predicate { - Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in +) -> Matcher { + Matcher.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in let actualValue = try actualExpression.evaluate() switch (expectedValue, actualValue) { case (nil, _?): - return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) + return MatcherResult(status: .fail, message: msg.appendedBeNilHint()) case (_, nil): - return PredicateResult(status: .fail, message: msg) + return MatcherResult(status: .fail, message: msg) case (let expected?, let actual?): let matches = areEquivalent(expected, actual) - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } } @@ -20,22 +20,22 @@ internal func equal( /// Values can support equal by supporting the Equatable protocol. /// /// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). -public func equal(_ expectedValue: T) -> Predicate { +public func equal(_ expectedValue: T) -> Matcher { equal(expectedValue as T?) } /// A Nimble matcher allowing comparison of collection with optional type -public func equal(_ expectedValue: [T?]) -> Predicate<[T?]> { - Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in +public func equal(_ expectedValue: [T?]) -> Matcher<[T?]> { + Matcher.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in guard let actualValue = try actualExpression.evaluate() else { - return PredicateResult( + return MatcherResult( status: .fail, message: msg.appendedBeNilHint() ) } let matches = expectedValue == actualValue - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } @@ -43,46 +43,46 @@ public func equal(_ expectedValue: [T?]) -> Predicate<[T?]> { /// Values can support equal by supporting the Equatable protocol. /// /// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). -public func equal(_ expectedValue: T?) -> Predicate { +public func equal(_ expectedValue: T?) -> Matcher { equal(expectedValue, by: ==) } /// A Nimble matcher that succeeds when the actual set is equal to the expected set. -public func equal(_ expectedValue: Set) -> Predicate> { +public func equal(_ expectedValue: Set) -> Matcher> { equal(expectedValue as Set?) } /// A Nimble matcher that succeeds when the actual set is equal to the expected set. -public func equal(_ expectedValue: Set?) -> Predicate> { +public func equal(_ expectedValue: Set?) -> Matcher> { equal(expectedValue, stringify: { stringify($0) }) } /// A Nimble matcher that succeeds when the actual set is equal to the expected set. -public func equal(_ expectedValue: Set) -> Predicate> { +public func equal(_ expectedValue: Set) -> Matcher> { equal(expectedValue as Set?) } /// A Nimble matcher that succeeds when the actual set is equal to the expected set. -public func equal(_ expectedValue: Set?) -> Predicate> { +public func equal(_ expectedValue: Set?) -> Matcher> { equal(expectedValue, stringify: { set in stringify(set.map { Array($0).sorted(by: <) }) }) } -private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> Predicate> { - Predicate { actualExpression in +private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> Matcher> { + Matcher { actualExpression in var errorMessage: ExpectationMessage = .expectedActualValueTo("equal <\(stringify(expectedValue))>") guard let expectedValue = expectedValue else { - return PredicateResult( + return MatcherResult( status: .fail, message: errorMessage.appendedBeNilHint() ) } guard let actualValue = try actualExpression.evaluate() else { - return PredicateResult( + return MatcherResult( status: .fail, message: errorMessage.appendedBeNilHint() ) @@ -94,7 +94,7 @@ private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) - ) if expectedValue == actualValue { - return PredicateResult( + return MatcherResult( status: .matches, message: errorMessage ) @@ -109,7 +109,7 @@ private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) - if extra.count > 0 { errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>") } - return PredicateResult( + return MatcherResult( status: .doesNotMatch, message: errorMessage ) @@ -117,17 +117,17 @@ private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) - } /// A Nimble matcher that succeeds when the actual dictionary is equal to the expected dictionary -public func equal(_ expectedValue: [K: V?]) -> Predicate<[K: V]> { - Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in +public func equal(_ expectedValue: [K: V?]) -> Matcher<[K: V]> { + Matcher.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in guard let actualValue = try actualExpression.evaluate() else { - return PredicateResult( + return MatcherResult( status: .fail, message: msg.appendedBeNilHint() ) } let matches = expectedValue == actualValue - return PredicateResult(bool: matches, message: msg) + return MatcherResult(bool: matches, message: msg) } } @@ -262,9 +262,9 @@ public func != (lhs: AsyncExpectation<[T: C]>, rhs: [T: C]?) as #if canImport(Darwin) import class Foundation.NSObject -extension NMBPredicate { - @objc public class func equalMatcher(_ expected: NSObject) -> NMBPredicate { - NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher { + NMBMatcher { actualExpression in try equal(expected).satisfies(actualExpression).toObjectiveC() } } diff --git a/Sources/Nimble/Matchers/HaveCount.swift b/Sources/Nimble/Matchers/HaveCount.swift index cb4c9a415..7b476d738 100644 --- a/Sources/Nimble/Matchers/HaveCount.swift +++ b/Sources/Nimble/Matchers/HaveCount.swift @@ -5,8 +5,8 @@ /// A Nimble matcher that succeeds when the actual Collection's count equals /// the expected value -public func haveCount(_ expectedValue: Int) -> Predicate { - return Predicate.define { actualExpression in +public func haveCount(_ expectedValue: Int) -> Matcher { + return Matcher.define { actualExpression in if let actualValue = try actualExpression.evaluate() { let message = ExpectationMessage .expectedCustomValueTo( @@ -16,17 +16,17 @@ public func haveCount(_ expectedValue: Int) -> Predicate { .appended(details: "Actual Value: \(stringify(actualValue))") let result = expectedValue == actualValue.count - return PredicateResult(bool: result, message: message) + return MatcherResult(bool: result, message: message) } else { - return PredicateResult(status: .fail, message: .fail("")) + return MatcherResult(status: .fail, message: .fail("")) } } } /// A Nimble matcher that succeeds when the actual collection's count equals /// the expected value -public func haveCount(_ expectedValue: Int) -> Predicate { - return Predicate { actualExpression in +public func haveCount(_ expectedValue: Int) -> Matcher { + return Matcher { actualExpression in if let actualValue = try actualExpression.evaluate() { let message = ExpectationMessage .expectedCustomValueTo( @@ -35,9 +35,9 @@ public func haveCount(_ expectedValue: Int) -> Predicate { ) let result = expectedValue == actualValue.count - return PredicateResult(bool: result, message: message) + return MatcherResult(bool: result, message: message) } else { - return PredicateResult(status: .fail, message: .fail("")) + return MatcherResult(status: .fail, message: .fail("")) } } } @@ -45,9 +45,9 @@ public func haveCount(_ expectedValue: Int) -> Predicate { #if canImport(Darwin) import Foundation -extension NMBPredicate { - @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBMatcher { + return NMBMatcher { actualExpression in let location = actualExpression.location let actualValue = try actualExpression.evaluate() if let value = actualValue as? NMBCollection { @@ -66,7 +66,7 @@ extension NMBPredicate { .expectedActualValueTo("have a collection with count \(stringify(expected.intValue))") .appendedBeNilHint() } - return NMBPredicateResult(status: .fail, message: message.toObjectiveC()) + return NMBMatcherResult(status: .fail, message: message.toObjectiveC()) } } } diff --git a/Sources/Nimble/Matchers/Match.swift b/Sources/Nimble/Matchers/Match.swift index 93363b324..b634ad31c 100644 --- a/Sources/Nimble/Matchers/Match.swift +++ b/Sources/Nimble/Matchers/Match.swift @@ -1,20 +1,20 @@ /// A Nimble matcher that succeeds when the actual string satisfies the regular expression /// described by the expected string. -public func match(_ expectedValue: String?) -> Predicate { - return Predicate.simple("match <\(stringify(expectedValue))>") { actualExpression in +public func match(_ expectedValue: String?) -> Matcher { + return Matcher.simple("match <\(stringify(expectedValue))>") { actualExpression in guard let actual = try actualExpression.evaluate(), let regexp = expectedValue else { return .fail } let bool = actual.range(of: regexp, options: .regularExpression) != nil - return PredicateStatus(bool: bool) + return MatcherStatus(bool: bool) } } #if canImport(Darwin) import class Foundation.NSString -extension NMBPredicate { - @objc public class func matchMatcher(_ expected: NSString) -> NMBPredicate { - return NMBPredicate { actualExpression in +extension NMBMatcher { + @objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher { + return NMBMatcher { actualExpression in let actual = actualExpression.cast { $0 as? String } return try match(expected.description).satisfies(actual).toObjectiveC() } diff --git a/Sources/Nimble/Matchers/MatchError.swift b/Sources/Nimble/Matchers/MatchError.swift index 3edc99bcb..10ed86b83 100644 --- a/Sources/Nimble/Matchers/MatchError.swift +++ b/Sources/Nimble/Matchers/MatchError.swift @@ -3,8 +3,8 @@ /// /// Errors are tried to be compared by their implementation of Equatable, /// otherwise they fallback to comparison by _domain and _code. -public func matchError(_ error: T) -> Predicate { - return Predicate.define { actualExpression in +public func matchError(_ error: T) -> Matcher { + return Matcher.define { actualExpression in let actualError = try actualExpression.evaluate() let message = messageForError( @@ -18,7 +18,7 @@ public func matchError(_ error: T) -> Predicate { matches = true } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } @@ -27,8 +27,8 @@ public func matchError(_ error: T) -> Predicate { /// /// Errors are tried to be compared by their implementation of Equatable, /// otherwise they fallback to comparision by _domain and _code. -public func matchError(_ error: T) -> Predicate { - return Predicate.define { actualExpression in +public func matchError(_ error: T) -> Matcher { + return Matcher.define { actualExpression in let actualError = try actualExpression.evaluate() let message = messageForError( @@ -42,14 +42,14 @@ public func matchError(_ error: T) -> Predicate { matches = true } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } /// A Nimble matcher that succeeds when the actual expression evaluates to an /// error of the specified type -public func matchError(_ errorType: T.Type) -> Predicate { - return Predicate.define { actualExpression in +public func matchError(_ errorType: T.Type) -> Matcher { + return Matcher.define { actualExpression in let actualError = try actualExpression.evaluate() let message = messageForError( @@ -63,6 +63,6 @@ public func matchError(_ errorType: T.Type) -> Predicate { matches = true } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } diff --git a/Sources/Nimble/Matchers/Matcher.swift b/Sources/Nimble/Matchers/Matcher.swift new file mode 100644 index 000000000..375419e4c --- /dev/null +++ b/Sources/Nimble/Matchers/Matcher.swift @@ -0,0 +1,324 @@ +// New Matcher API +// + +/// A Matcher is part of the new matcher API that provides assertions to expectations. +/// +/// Given a code snippet: +/// +/// expect(1).to(equal(2)) +/// ^^^^^^^^ +/// Called a "matcher" +/// +/// A matcher consists of two parts a constructor function and the Matcher. +/// +/// The Matcher provide the heavy lifting on how to assert against a given value. Internally, +/// matchers are simple wrappers around closures to provide static type information and +/// allow composition and wrapping of existing behaviors. +/// +/// In the 2023 Apple Platform releases (macOS 14, iOS 17, watchOS 10, tvOS 17, visionOS 1), Apple +/// renamed `NSMatcher` to `Matcher`. In response, we decided to rename `Matcher` to +/// `Matcher`. +public struct Matcher { + fileprivate var matcher: (Expression) throws -> MatcherResult + + /// Constructs a matcher that knows how take a given value + public init(_ matcher: @escaping (Expression) throws -> MatcherResult) { + self.matcher = matcher + } + + /// Uses a matcher on a given value to see if it passes the matcher. + /// + /// @param expression The value to run the matcher's logic against + /// @returns A matcher result indicate passing or failing and an associated error message. + public func satisfies(_ expression: Expression) throws -> MatcherResult { + return try matcher(expression) + } +} + +/// Provides an easy upgrade path for custom Matchers to be renamed to Matchers +@available(*, deprecated, renamed: "Matcher") +public typealias Predicate = Matcher + +/// Provides convenience helpers to defining matchers +extension Matcher { + /// Like Matcher() constructor, but automatically guard against nil (actual) values + public static func define(matcher: @escaping (Expression) throws -> MatcherResult) -> Matcher { + return Matcher { actual in + return try matcher(actual) + }.requireNonNil + } + + /// Defines a matcher with a default message that can be returned in the closure + /// Also ensures the matcher's actual value cannot pass with `nil` given. + public static func define(_ message: String = "match", matcher: @escaping (Expression, ExpectationMessage) throws -> MatcherResult) -> Matcher { + return Matcher { actual in + return try matcher(actual, .expectedActualValueTo(message)) + }.requireNonNil + } + + /// Defines a matcher with a default message that can be returned in the closure + /// Unlike `define`, this allows nil values to succeed if the given closure chooses to. + public static func defineNilable(_ message: String = "match", matcher: @escaping (Expression, ExpectationMessage) throws -> MatcherResult) -> Matcher { + return Matcher { actual in + return try matcher(actual, .expectedActualValueTo(message)) + } + } +} + +extension Matcher { + /// Provides a simple matcher definition that provides no control over the predefined + /// error message. + /// + /// Also ensures the matcher's actual value cannot pass with `nil` given. + public static func simple(_ message: String = "match", matcher: @escaping (Expression) throws -> MatcherStatus) -> Matcher { + return Matcher { actual in + return MatcherResult(status: try matcher(actual), message: .expectedActualValueTo(message)) + }.requireNonNil + } + + /// Provides a simple matcher definition that provides no control over the predefined + /// error message. + /// + /// Unlike `simple`, this allows nil values to succeed if the given closure chooses to. + public static func simpleNilable(_ message: String = "match", matcher: @escaping (Expression) throws -> MatcherStatus) -> Matcher { + return Matcher { actual in + return MatcherResult(status: try matcher(actual), message: .expectedActualValueTo(message)) + } + } +} + +/// The Expectation style intended for comparison to a MatcherStatus. +public enum ExpectationStyle { + case toMatch, toNotMatch +} + +/// The value that a Matcher returns to describe if the given (actual) value matches the +/// matcher. +public struct MatcherResult { + /// Status indicates if the matcher matches, does not match, or fails. + public var status: MatcherStatus + /// The error message that can be displayed if it does not match + public var message: ExpectationMessage + + /// Constructs a new MatcherResult with a given status and error message + public init(status: MatcherStatus, message: ExpectationMessage) { + self.status = status + self.message = message + } + + /// Shorthand to MatcherResult(status: MatcherStatus(bool: bool), message: message) + public init(bool: Bool, message: ExpectationMessage) { + self.status = MatcherStatus(bool: bool) + self.message = message + } + + /// Converts the result to a boolean based on what the expectation intended + public func toBoolean(expectation style: ExpectationStyle) -> Bool { + return status.toBoolean(expectation: style) + } +} + +/// Provides an easy upgrade path for custom Matchers to be renamed to Matchers +@available(*, deprecated, renamed: "MatcherResult") +public typealias PredicateResult = MatcherResult + +/// MatcherStatus is a trinary that indicates if a Matcher matches a given value or not +public enum MatcherStatus { + /// Matches indicates if the matcher / matcher passes with the given value + /// + /// For example, `equals(1)` returns `.matches` for `expect(1).to(equal(1))`. + case matches + /// DoesNotMatch indicates if the matcher fails with the given value, but *would* + /// succeed if the expectation was inverted. + /// + /// For example, `equals(2)` returns `.doesNotMatch` for `expect(1).toNot(equal(2))`. + case doesNotMatch + /// Fail indicates the matcher will never satisfy with the given value in any case. + /// A perfect example is that most matchers fail whenever given `nil`. + /// + /// Using `equal(1)` fails both `expect(nil).to(equal(1))` and `expect(nil).toNot(equal(1))`. + /// Note: Matcher's `requireNonNil` property will also provide this feature mostly for free. + /// Your matcher will still need to guard against nils, but error messaging will be + /// handled for you. + case fail + + /// Converts a boolean to either .matches (if true) or .doesNotMatch (if false). + public init(bool matches: Bool) { + if matches { + self = .matches + } else { + self = .doesNotMatch + } + } + + private func shouldMatch() -> Bool { + switch self { + case .matches: return true + case .doesNotMatch, .fail: return false + } + } + + private func shouldNotMatch() -> Bool { + switch self { + case .doesNotMatch: return true + case .matches, .fail: return false + } + } + + /// Converts the MatcherStatus result to a boolean based on what the expectation intended + internal func toBoolean(expectation style: ExpectationStyle) -> Bool { + if style == .toMatch { + return shouldMatch() + } else { + return shouldNotMatch() + } + } +} + +/// Provides an easy upgrade path for custom Matchers to be renamed to Matchers +@available(*, deprecated, renamed: "MatcherStatus") +public typealias PredicateStatus = MatcherStatus + +extension Matcher { + // Someday, make this public? Needs documentation + internal func after(f: @escaping (Expression, MatcherResult) throws -> MatcherResult) -> Matcher { + // swiftlint:disable:previous identifier_name + return Matcher { actual -> MatcherResult in + let result = try self.satisfies(actual) + return try f(actual, result) + } + } + + /// Returns a new Matcher based on the current one that always fails if nil is given as + /// the actual value. + public var requireNonNil: Matcher { + return after { actual, result in + if try actual.evaluate() == nil { + return MatcherResult( + status: .fail, + message: result.message.appendedBeNilHint() + ) + } + return result + } + } +} + +#if canImport(Darwin) +import class Foundation.NSObject + +public typealias MatcherBlock = (_ actualExpression: Expression) throws -> NMBMatcherResult + +/// Provides an easy upgrade path for custom Matchers to be renamed to Matchers +@available(*, deprecated, renamed: "MatcherBlock") +public typealias PredicateBlock = MatcherBlock + +public class NMBMatcher: NSObject { + private let matcher: MatcherBlock + + public init(matcher: @escaping MatcherBlock) { + self.matcher = matcher + } + + @available(*, deprecated, renamed: "init(matcher:)") + public convenience init(predicate: @escaping MatcherBlock) { + self.init(matcher: predicate) + } + + func satisfies(_ expression: @escaping () throws -> NSObject?, location: SourceLocation) -> NMBMatcherResult { + let expr = Expression(expression: expression, location: location) + do { + return try self.matcher(expr) + } catch let error { + return MatcherResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")).toObjectiveC() + } + } +} + +/// Provides an easy upgrade path for custom Matchers to be renamed to Matchers +@available(*, deprecated, renamed: "NMBMatcher") +public typealias NMBPredicate = NMBMatcher + +final public class NMBMatcherResult: NSObject { + public var status: NMBMatcherStatus + public var message: NMBExpectationMessage + + public init(status: NMBMatcherStatus, message: NMBExpectationMessage) { + self.status = status + self.message = message + } + + public init(bool success: Bool, message: NMBExpectationMessage) { + self.status = NMBMatcherStatus.from(bool: success) + self.message = message + } + + public func toSwift() -> MatcherResult { + return MatcherResult(status: status.toSwift(), + message: message.toSwift()) + } +} + +/// Provides an easy upgrade path for custom Matchers to be renamed to Matchers +@available(*, deprecated, renamed: "NMBMatcherResult") +public typealias NMBPredicateResult = NMBMatcherResult + +extension MatcherResult { + public func toObjectiveC() -> NMBMatcherResult { + return NMBMatcherResult(status: status.toObjectiveC(), message: message.toObjectiveC()) + } +} + +final public class NMBMatcherStatus: NSObject { + private let status: Int + private init(status: Int) { + self.status = status + } + + public static let matches: NMBMatcherStatus = NMBMatcherStatus(status: 0) + public static let doesNotMatch: NMBMatcherStatus = NMBMatcherStatus(status: 1) + public static let fail: NMBMatcherStatus = NMBMatcherStatus(status: 2) + + public override var hash: Int { return self.status.hashValue } + + public override func isEqual(_ object: Any?) -> Bool { + guard let otherMatcher = object as? NMBMatcherStatus else { + return false + } + return self.status == otherMatcher.status + } + + public static func from(status: MatcherStatus) -> NMBMatcherStatus { + switch status { + case .matches: return self.matches + case .doesNotMatch: return self.doesNotMatch + case .fail: return self.fail + } + } + + public static func from(bool success: Bool) -> NMBMatcherStatus { + return self.from(status: MatcherStatus(bool: success)) + } + + public func toSwift() -> MatcherStatus { + switch status { + case NMBMatcherStatus.matches.status: return .matches + case NMBMatcherStatus.doesNotMatch.status: return .doesNotMatch + case NMBMatcherStatus.fail.status: return .fail + default: + internalError("Unhandle status for NMBMatcherStatus") + } + } +} + +/// Provides an easy upgrade path for custom Matchers to be renamed to Matchers +@available(*, deprecated, renamed: "NMBMatcherStatus") +public typealias NMBPredicateStatus = NMBMatcherStatus + +extension MatcherStatus { + public func toObjectiveC() -> NMBMatcherStatus { + return NMBMatcherStatus.from(status: self) + } +} + +#endif diff --git a/Sources/Nimble/Matchers/PostNotification.swift b/Sources/Nimble/Matchers/PostNotification.swift index c848b968a..5144cc13f 100644 --- a/Sources/Nimble/Matchers/PostNotification.swift +++ b/Sources/Nimble/Matchers/PostNotification.swift @@ -50,16 +50,16 @@ private let mainThread = Thread.mainThread #endif private func _postNotifications( - _ predicate: Predicate<[Notification]>, + _ matcher: Matcher<[Notification]>, from center: NotificationCenter, names: Set = [] -) -> Predicate { +) -> Matcher { _ = mainThread // Force lazy-loading of this value let collector = NotificationCollector(notificationCenter: center, names: names) collector.startObserving() var once: Bool = false - return Predicate { actualExpression in + return Matcher { actualExpression in let collectorNotificationsExpression = Expression( memoizedExpression: { _ in return collector.observedNotifications @@ -81,7 +81,7 @@ private func _postNotifications( actualValue = "<\(stringify(collector.observedNotificationDescriptions))>" } - var result = try predicate.satisfies(collectorNotificationsExpression) + var result = try matcher.satisfies(collectorNotificationsExpression) result.message = result.message.replacedExpectation { message in return .expectedCustomValueTo(message.expectedMessage, actual: actualValue) } @@ -90,19 +90,19 @@ private func _postNotifications( } public func postNotifications( - _ predicate: Predicate<[Notification]>, + _ matcher: Matcher<[Notification]>, from center: NotificationCenter = .default -) -> Predicate { - _postNotifications(predicate, from: center) +) -> Matcher { + _postNotifications(matcher, from: center) } #if os(macOS) public func postDistributedNotifications( - _ predicate: Predicate<[Notification]>, + _ matcher: Matcher<[Notification]>, from center: DistributedNotificationCenter = .default(), names: Set -) -> Predicate { - _postNotifications(predicate, from: center, names: names) +) -> Matcher { + _postNotifications(matcher, from: center, names: names) } #endif diff --git a/Sources/Nimble/Matchers/Predicate.swift b/Sources/Nimble/Matchers/Predicate.swift deleted file mode 100644 index ce20c6b1c..000000000 --- a/Sources/Nimble/Matchers/Predicate.swift +++ /dev/null @@ -1,289 +0,0 @@ -// New Matcher API -// - -/// A Predicate is part of the new matcher API that provides assertions to expectations. -/// -/// Given a code snippet: -/// -/// expect(1).to(equal(2)) -/// ^^^^^^^^ -/// Called a "matcher" -/// -/// A matcher consists of two parts a constructor function and the Predicate. The term Predicate -/// is used as a separate name from Matcher to help transition custom matchers to the new Nimble -/// matcher API. -/// -/// The Predicate provide the heavy lifting on how to assert against a given value. Internally, -/// predicates are simple wrappers around closures to provide static type information and -/// allow composition and wrapping of existing behaviors. -public struct Predicate { - fileprivate var matcher: (Expression) throws -> PredicateResult - - /// Constructs a predicate that knows how take a given value - public init(_ matcher: @escaping (Expression) throws -> PredicateResult) { - self.matcher = matcher - } - - /// Uses a predicate on a given value to see if it passes the predicate. - /// - /// @param expression The value to run the predicate's logic against - /// @returns A predicate result indicate passing or failing and an associated error message. - public func satisfies(_ expression: Expression) throws -> PredicateResult { - return try matcher(expression) - } -} - -/// Provides convenience helpers to defining predicates -extension Predicate { - /// Like Predicate() constructor, but automatically guard against nil (actual) values - public static func define(matcher: @escaping (Expression) throws -> PredicateResult) -> Predicate { - return Predicate { actual in - return try matcher(actual) - }.requireNonNil - } - - /// Defines a predicate with a default message that can be returned in the closure - /// Also ensures the predicate's actual value cannot pass with `nil` given. - public static func define(_ message: String = "match", matcher: @escaping (Expression, ExpectationMessage) throws -> PredicateResult) -> Predicate { - return Predicate { actual in - return try matcher(actual, .expectedActualValueTo(message)) - }.requireNonNil - } - - /// Defines a predicate with a default message that can be returned in the closure - /// Unlike `define`, this allows nil values to succeed if the given closure chooses to. - public static func defineNilable(_ message: String = "match", matcher: @escaping (Expression, ExpectationMessage) throws -> PredicateResult) -> Predicate { - return Predicate { actual in - return try matcher(actual, .expectedActualValueTo(message)) - } - } -} - -extension Predicate { - /// Provides a simple predicate definition that provides no control over the predefined - /// error message. - /// - /// Also ensures the predicate's actual value cannot pass with `nil` given. - public static func simple(_ message: String = "match", matcher: @escaping (Expression) throws -> PredicateStatus) -> Predicate { - return Predicate { actual in - return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(message)) - }.requireNonNil - } - - /// Provides a simple predicate definition that provides no control over the predefined - /// error message. - /// - /// Unlike `simple`, this allows nil values to succeed if the given closure chooses to. - public static func simpleNilable(_ message: String = "match", matcher: @escaping (Expression) throws -> PredicateStatus) -> Predicate { - return Predicate { actual in - return PredicateResult(status: try matcher(actual), message: .expectedActualValueTo(message)) - } - } -} - -// The Expectation style intended for comparison to a PredicateStatus. -public enum ExpectationStyle { - case toMatch, toNotMatch -} - -/// The value that a Predicates return to describe if the given (actual) value matches the -/// predicate. -public struct PredicateResult { - /// Status indicates if the predicate matches, does not match, or fails. - public var status: PredicateStatus - /// The error message that can be displayed if it does not match - public var message: ExpectationMessage - - /// Constructs a new PredicateResult with a given status and error message - public init(status: PredicateStatus, message: ExpectationMessage) { - self.status = status - self.message = message - } - - /// Shorthand to PredicateResult(status: PredicateStatus(bool: bool), message: message) - public init(bool: Bool, message: ExpectationMessage) { - self.status = PredicateStatus(bool: bool) - self.message = message - } - - /// Converts the result to a boolean based on what the expectation intended - public func toBoolean(expectation style: ExpectationStyle) -> Bool { - return status.toBoolean(expectation: style) - } -} - -/// PredicateStatus is a trinary that indicates if a Predicate matches a given value or not -public enum PredicateStatus { - /// Matches indicates if the predicate / matcher passes with the given value - /// - /// For example, `equals(1)` returns `.matches` for `expect(1).to(equal(1))`. - case matches - /// DoesNotMatch indicates if the predicate / matcher fails with the given value, but *would* - /// succeed if the expectation was inverted. - /// - /// For example, `equals(2)` returns `.doesNotMatch` for `expect(1).toNot(equal(2))`. - case doesNotMatch - /// Fail indicates the predicate will never satisfy with the given value in any case. - /// A perfect example is that most matchers fail whenever given `nil`. - /// - /// Using `equal(1)` fails both `expect(nil).to(equal(1))` and `expect(nil).toNot(equal(1))`. - /// Note: Predicate's `requireNonNil` property will also provide this feature mostly for free. - /// Your predicate will still need to guard against nils, but error messaging will be - /// handled for you. - case fail - - /// Converts a boolean to either .matches (if true) or .doesNotMatch (if false). - public init(bool matches: Bool) { - if matches { - self = .matches - } else { - self = .doesNotMatch - } - } - - private func shouldMatch() -> Bool { - switch self { - case .matches: return true - case .doesNotMatch, .fail: return false - } - } - - private func shouldNotMatch() -> Bool { - switch self { - case .doesNotMatch: return true - case .matches, .fail: return false - } - } - - /// Converts the PredicateStatus result to a boolean based on what the expectation intended - internal func toBoolean(expectation style: ExpectationStyle) -> Bool { - if style == .toMatch { - return shouldMatch() - } else { - return shouldNotMatch() - } - } -} - -extension Predicate { - // Someday, make this public? Needs documentation - internal func after(f: @escaping (Expression, PredicateResult) throws -> PredicateResult) -> Predicate { - // swiftlint:disable:previous identifier_name - return Predicate { actual -> PredicateResult in - let result = try self.satisfies(actual) - return try f(actual, result) - } - } - - /// Returns a new Predicate based on the current one that always fails if nil is given as - /// the actual value. - public var requireNonNil: Predicate { - return after { actual, result in - if try actual.evaluate() == nil { - return PredicateResult( - status: .fail, - message: result.message.appendedBeNilHint() - ) - } - return result - } - } -} - -#if canImport(Darwin) -import class Foundation.NSObject - -public typealias PredicateBlock = (_ actualExpression: Expression) throws -> NMBPredicateResult - -public class NMBPredicate: NSObject { - private let predicate: PredicateBlock - - public init(predicate: @escaping PredicateBlock) { - self.predicate = predicate - } - - func satisfies(_ expression: @escaping () throws -> NSObject?, location: SourceLocation) -> NMBPredicateResult { - let expr = Expression(expression: expression, location: location) - do { - return try self.predicate(expr) - } catch let error { - return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")).toObjectiveC() - } - } -} - -final public class NMBPredicateResult: NSObject { - public var status: NMBPredicateStatus - public var message: NMBExpectationMessage - - public init(status: NMBPredicateStatus, message: NMBExpectationMessage) { - self.status = status - self.message = message - } - - public init(bool success: Bool, message: NMBExpectationMessage) { - self.status = NMBPredicateStatus.from(bool: success) - self.message = message - } - - public func toSwift() -> PredicateResult { - return PredicateResult(status: status.toSwift(), - message: message.toSwift()) - } -} - -extension PredicateResult { - public func toObjectiveC() -> NMBPredicateResult { - return NMBPredicateResult(status: status.toObjectiveC(), message: message.toObjectiveC()) - } -} - -final public class NMBPredicateStatus: NSObject { - private let status: Int - private init(status: Int) { - self.status = status - } - - public static let matches: NMBPredicateStatus = NMBPredicateStatus(status: 0) - public static let doesNotMatch: NMBPredicateStatus = NMBPredicateStatus(status: 1) - public static let fail: NMBPredicateStatus = NMBPredicateStatus(status: 2) - - public override var hash: Int { return self.status.hashValue } - - public override func isEqual(_ object: Any?) -> Bool { - guard let otherPredicate = object as? NMBPredicateStatus else { - return false - } - return self.status == otherPredicate.status - } - - public static func from(status: PredicateStatus) -> NMBPredicateStatus { - switch status { - case .matches: return self.matches - case .doesNotMatch: return self.doesNotMatch - case .fail: return self.fail - } - } - - public static func from(bool success: Bool) -> NMBPredicateStatus { - return self.from(status: PredicateStatus(bool: success)) - } - - public func toSwift() -> PredicateStatus { - switch status { - case NMBPredicateStatus.matches.status: return .matches - case NMBPredicateStatus.doesNotMatch.status: return .doesNotMatch - case NMBPredicateStatus.fail.status: return .fail - default: - internalError("Unhandle status for NMBPredicateStatus") - } - } -} - -extension PredicateStatus { - public func toObjectiveC() -> NMBPredicateStatus { - return NMBPredicateStatus.from(status: self) - } -} - -#endif diff --git a/Sources/Nimble/Matchers/RaisesException.swift b/Sources/Nimble/Matchers/RaisesException.swift index 7c1b2b26c..2bb94094d 100644 --- a/Sources/Nimble/Matchers/RaisesException.swift +++ b/Sources/Nimble/Matchers/RaisesException.swift @@ -18,7 +18,7 @@ public func raiseException( reason: String? = nil, userInfo: NSDictionary? = nil, closure: ((NSException) -> Void)? = nil -) -> Predicate { +) -> Matcher { return raiseException(named: named?.rawValue, reason: reason, userInfo: userInfo, closure: closure) } @@ -36,8 +36,8 @@ public func raiseException( reason: String? = nil, userInfo: NSDictionary? = nil, closure: ((NSException) -> Void)? = nil -) -> Predicate { - return Predicate { actualExpression in +) -> Matcher { + return Matcher { actualExpression in var exception: NSException? let capture = NMBExceptionCapture(handler: ({ e in exception = e @@ -48,7 +48,7 @@ public func raiseException( _ = try actualExpression.evaluate() } } catch { - return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) + return MatcherResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) } let message = messageForException( @@ -66,7 +66,7 @@ public func raiseException( userInfo: userInfo, closure: closure ) - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } @@ -141,7 +141,7 @@ internal func exceptionMatchesNonNilFieldsOrClosure( return matches } -public class NMBObjCRaiseExceptionPredicate: NMBPredicate { +public class NMBObjCRaiseExceptionMatcher: NMBMatcher { private let _name: String? private let _reason: String? private let _userInfo: NSDictionary? @@ -153,22 +153,22 @@ public class NMBObjCRaiseExceptionPredicate: NMBPredicate { _userInfo = userInfo _block = block - let predicate: Predicate = raiseException( + let matcher: Matcher = raiseException( named: name, reason: reason, userInfo: userInfo, closure: block ) - let predicateBlock: PredicateBlock = { actualExpression in - return try predicate.satisfies(actualExpression).toObjectiveC() + let matcherBlock: MatcherBlock = { actualExpression in + return try matcher.satisfies(actualExpression).toObjectiveC() } - super.init(predicate: predicateBlock) + super.init(matcher: matcherBlock) } - @objc public var named: (_ name: String) -> NMBObjCRaiseExceptionPredicate { + @objc public var named: (_ name: String) -> NMBObjCRaiseExceptionMatcher { let (reason, userInfo, block) = (_reason, _userInfo, _block) return { name in - return NMBObjCRaiseExceptionPredicate( + return NMBObjCRaiseExceptionMatcher( name: name, reason: reason, userInfo: userInfo, @@ -177,10 +177,10 @@ public class NMBObjCRaiseExceptionPredicate: NMBPredicate { } } - @objc public var reason: (_ reason: String?) -> NMBObjCRaiseExceptionPredicate { + @objc public var reason: (_ reason: String?) -> NMBObjCRaiseExceptionMatcher { let (name, userInfo, block) = (_name, _userInfo, _block) return { reason in - return NMBObjCRaiseExceptionPredicate( + return NMBObjCRaiseExceptionMatcher( name: name, reason: reason, userInfo: userInfo, @@ -189,10 +189,10 @@ public class NMBObjCRaiseExceptionPredicate: NMBPredicate { } } - @objc public var userInfo: (_ userInfo: NSDictionary?) -> NMBObjCRaiseExceptionPredicate { + @objc public var userInfo: (_ userInfo: NSDictionary?) -> NMBObjCRaiseExceptionMatcher { let (name, reason, block) = (_name, _reason, _block) return { userInfo in - return NMBObjCRaiseExceptionPredicate( + return NMBObjCRaiseExceptionMatcher( name: name, reason: reason, userInfo: userInfo, @@ -201,10 +201,10 @@ public class NMBObjCRaiseExceptionPredicate: NMBPredicate { } } - @objc public var satisfyingBlock: (_ block: ((NSException) -> Void)?) -> NMBObjCRaiseExceptionPredicate { + @objc public var satisfyingBlock: (_ block: ((NSException) -> Void)?) -> NMBObjCRaiseExceptionMatcher { let (name, reason, userInfo) = (_name, _reason, _userInfo) return { block in - return NMBObjCRaiseExceptionPredicate( + return NMBObjCRaiseExceptionMatcher( name: name, reason: reason, userInfo: userInfo, @@ -214,9 +214,9 @@ public class NMBObjCRaiseExceptionPredicate: NMBPredicate { } } -extension NMBPredicate { - @objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionPredicate { - return NMBObjCRaiseExceptionPredicate(name: nil, reason: nil, userInfo: nil, block: nil) +extension NMBMatcher { + @objc public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) } } #endif diff --git a/Sources/Nimble/Matchers/SatisfyAllOf.swift b/Sources/Nimble/Matchers/SatisfyAllOf.swift index e95d3fe54..30f9045ac 100644 --- a/Sources/Nimble/Matchers/SatisfyAllOf.swift +++ b/Sources/Nimble/Matchers/SatisfyAllOf.swift @@ -1,18 +1,18 @@ /// A Nimble matcher that succeeds when the actual value matches with all of the matchers /// provided in the variable list of matchers. -public func satisfyAllOf(_ predicates: Predicate...) -> Predicate { - return satisfyAllOf(predicates) +public func satisfyAllOf(_ matchers: Matcher...) -> Matcher { + return satisfyAllOf(matchers) } /// A Nimble matcher that succeeds when the actual value matches with all of the matchers /// provided in the array of matchers. -public func satisfyAllOf(_ predicates: [Predicate]) -> Predicate { - return Predicate.define { actualExpression in +public func satisfyAllOf(_ matchers: [Matcher]) -> Matcher { + return Matcher.define { actualExpression in let cachedExpression = actualExpression.withCaching() var postfixMessages = [String]() - var status: PredicateStatus = .matches - for predicate in predicates { - let result = try predicate.satisfies(cachedExpression) + var status: MatcherStatus = .matches + for matcher in matchers { + let result = try matcher.satisfies(cachedExpression) if result.status == .fail { status = .fail } else if result.status == .doesNotMatch, status != .fail { @@ -33,35 +33,35 @@ public func satisfyAllOf(_ predicates: [Predicate]) -> Predicate { ) } - return PredicateResult(status: status, message: msg) + return MatcherResult(status: status, message: msg) } } -public func && (left: Predicate, right: Predicate) -> Predicate { +public func && (left: Matcher, right: Matcher) -> Matcher { return satisfyAllOf(left, right) } // There's a compiler bug in swift 5.7.2 and earlier (xcode 14.2 and earlier) -// which causes runtime crashes when you use `[any AsyncablePredicate]`. +// which causes runtime crashes when you use `[any AsyncableMatcher]`. // https://github.com/apple/swift/issues/61403 #if swift(>=5.8.0) /// A Nimble matcher that succeeds when the actual value matches with all of the matchers /// provided in the variable list of matchers. @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) -public func satisfyAllOf(_ predicates: any AsyncablePredicate...) -> AsyncPredicate { - return satisfyAllOf(predicates) +public func satisfyAllOf(_ matchers: any AsyncableMatcher...) -> AsyncMatcher { + return satisfyAllOf(matchers) } /// A Nimble matcher that succeeds when the actual value matches with all of the matchers /// provided in the array of matchers. @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) -public func satisfyAllOf(_ predicates: [any AsyncablePredicate]) -> AsyncPredicate { - return AsyncPredicate.define { actualExpression in +public func satisfyAllOf(_ matchers: [any AsyncableMatcher]) -> AsyncMatcher { + return AsyncMatcher.define { actualExpression in let cachedExpression = actualExpression.withCaching() var postfixMessages = [String]() - var status: PredicateStatus = .matches - for predicate in predicates { - let result = try await predicate.satisfies(cachedExpression) + var status: MatcherStatus = .matches + for matcher in matchers { + let result = try await matcher.satisfies(cachedExpression) if result.status == .fail { status = .fail } else if result.status == .doesNotMatch, status != .fail { @@ -82,12 +82,12 @@ public func satisfyAllOf(_ predicates: [any AsyncablePredicate]) -> AsyncP ) } - return PredicateResult(status: status, message: msg) + return MatcherResult(status: status, message: msg) } } @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) -public func && (left: some AsyncablePredicate, right: some AsyncablePredicate) -> AsyncPredicate { +public func && (left: some AsyncableMatcher, right: some AsyncableMatcher) -> AsyncMatcher { return satisfyAllOf(left, right) } #endif // swift(>=5.8.0) @@ -95,22 +95,22 @@ public func && (left: some AsyncablePredicate, right: some AsyncablePredic #if canImport(Darwin) import class Foundation.NSObject -extension NMBPredicate { - @objc public class func satisfyAllOfMatcher(_ predicates: [NMBPredicate]) -> NMBPredicate { - return NMBPredicate { actualExpression in - if predicates.isEmpty { - return NMBPredicateResult( - status: NMBPredicateStatus.fail, +extension NMBMatcher { + @objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBMatcher { + return NMBMatcher { actualExpression in + if matchers.isEmpty { + return NMBMatcherResult( + status: NMBMatcherStatus.fail, message: NMBExpectationMessage( fail: "satisfyAllOf must be called with at least one matcher" ) ) } - var elementEvaluators = [Predicate]() - for predicate in predicates { - let elementEvaluator = Predicate { expression in - return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() + var elementEvaluators = [Matcher]() + for matcher in matchers { + let elementEvaluator = Matcher { expression in + return matcher.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() } elementEvaluators.append(elementEvaluator) diff --git a/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Sources/Nimble/Matchers/SatisfyAnyOf.swift index 19109dee4..56ffdd10d 100644 --- a/Sources/Nimble/Matchers/SatisfyAnyOf.swift +++ b/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -1,18 +1,18 @@ /// A Nimble matcher that succeeds when the actual value matches with any of the matchers /// provided in the variable list of matchers. -public func satisfyAnyOf(_ predicates: Predicate...) -> Predicate { - return satisfyAnyOf(predicates) +public func satisfyAnyOf(_ matchers: Matcher...) -> Matcher { + return satisfyAnyOf(matchers) } /// A Nimble matcher that succeeds when the actual value matches with any of the matchers /// provided in the array of matchers. -public func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate { - return Predicate.define { actualExpression in +public func satisfyAnyOf(_ matchers: [Matcher]) -> Matcher { + return Matcher.define { actualExpression in let cachedExpression = actualExpression.withCaching() var postfixMessages = [String]() - var status: PredicateStatus = .doesNotMatch - for predicate in predicates { - let result = try predicate.satisfies(cachedExpression) + var status: MatcherStatus = .doesNotMatch + for matcher in matchers { + let result = try matcher.satisfies(cachedExpression) if result.status == .fail { status = .fail } else if result.status == .matches, status != .fail { @@ -33,35 +33,35 @@ public func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate { ) } - return PredicateResult(status: status, message: msg) + return MatcherResult(status: status, message: msg) } } -public func || (left: Predicate, right: Predicate) -> Predicate { +public func || (left: Matcher, right: Matcher) -> Matcher { return satisfyAnyOf(left, right) } // There's a compiler bug in swift 5.7.2 and earlier (xcode 14.2 and earlier) -// which causes runtime crashes when you use `[any AsyncablePredicate]`. +// which causes runtime crashes when you use `[any AsyncableMatcher]`. // https://github.com/apple/swift/issues/61403 #if swift(>=5.8.0) /// A Nimble matcher that succeeds when the actual value matches with any of the matchers /// provided in the variable list of matchers. @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) -public func satisfyAnyOf(_ predicates: any AsyncablePredicate...) -> AsyncPredicate { - return satisfyAnyOf(predicates) +public func satisfyAnyOf(_ matchers: any AsyncableMatcher...) -> AsyncMatcher { + return satisfyAnyOf(matchers) } /// A Nimble matcher that succeeds when the actual value matches with any of the matchers /// provided in the array of matchers. @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) -public func satisfyAnyOf(_ predicates: [any AsyncablePredicate]) -> AsyncPredicate { - return AsyncPredicate.define { actualExpression in +public func satisfyAnyOf(_ matchers: [any AsyncableMatcher]) -> AsyncMatcher { + return AsyncMatcher.define { actualExpression in let cachedExpression = actualExpression.withCaching() var postfixMessages = [String]() - var status: PredicateStatus = .doesNotMatch - for predicate in predicates { - let result = try await predicate.satisfies(cachedExpression) + var status: MatcherStatus = .doesNotMatch + for matcher in matchers { + let result = try await matcher.satisfies(cachedExpression) if result.status == .fail { status = .fail } else if result.status == .matches, status != .fail { @@ -82,12 +82,12 @@ public func satisfyAnyOf(_ predicates: [any AsyncablePredicate]) -> AsyncP ) } - return PredicateResult(status: status, message: msg) + return MatcherResult(status: status, message: msg) } } @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) -public func || (left: some AsyncablePredicate, right: some AsyncablePredicate) -> AsyncPredicate { +public func || (left: some AsyncableMatcher, right: some AsyncableMatcher) -> AsyncMatcher { return satisfyAnyOf(left, right) } #endif // swift(>=5.8.0) @@ -95,22 +95,22 @@ public func || (left: some AsyncablePredicate, right: some AsyncablePredic #if canImport(Darwin) import class Foundation.NSObject -extension NMBPredicate { - @objc public class func satisfyAnyOfMatcher(_ predicates: [NMBPredicate]) -> NMBPredicate { - return NMBPredicate { actualExpression in - if predicates.isEmpty { - return NMBPredicateResult( - status: NMBPredicateStatus.fail, +extension NMBMatcher { + @objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBMatcher { + return NMBMatcher { actualExpression in + if matchers.isEmpty { + return NMBMatcherResult( + status: NMBMatcherStatus.fail, message: NMBExpectationMessage( fail: "satisfyAnyOf must be called with at least one matcher" ) ) } - var elementEvaluators = [Predicate]() - for predicate in predicates { - let elementEvaluator = Predicate { expression in - return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() + var elementEvaluators = [Matcher]() + for matcher in matchers { + let elementEvaluator = Matcher { expression in + return matcher.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() } elementEvaluators.append(elementEvaluator) diff --git a/Sources/Nimble/Matchers/ThrowAssertion.swift b/Sources/Nimble/Matchers/ThrowAssertion.swift index 5cc08a009..b64a06211 100644 --- a/Sources/Nimble/Matchers/ThrowAssertion.swift +++ b/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -81,8 +81,8 @@ public func catchBadInstruction(block: @escaping () -> Void) -> BadInstructionEx } #endif -public func throwAssertion() -> Predicate { - return Predicate { actualExpression in +public func throwAssertion() -> Matcher { + return Matcher { actualExpression in #if (arch(x86_64) || arch(arm64)) && (canImport(Darwin) || canImport(Glibc)) let message = ExpectationMessage.expectedTo("throw an assertion") var actualError: Error? @@ -126,12 +126,12 @@ public func throwAssertion() -> Predicate { } if let actualError = actualError { - return PredicateResult( + return MatcherResult( bool: false, message: message.appended(message: "; threw error instead <\(actualError)>") ) } else { - return PredicateResult(bool: caughtException != nil, message: message) + return MatcherResult(bool: caughtException != nil, message: message) } #else let message = """ diff --git a/Sources/Nimble/Matchers/ThrowError.swift b/Sources/Nimble/Matchers/ThrowError.swift index d5ac732e2..32c2f6c1d 100644 --- a/Sources/Nimble/Matchers/ThrowError.swift +++ b/Sources/Nimble/Matchers/ThrowError.swift @@ -9,8 +9,8 @@ /// /// nil arguments indicates that the matcher should not attempt to match against /// that parameter. -public func throwError() -> Predicate { - return Predicate { actualExpression in +public func throwError() -> Matcher { + return Matcher { actualExpression in var actualError: Error? do { _ = try actualExpression.evaluate() @@ -19,12 +19,12 @@ public func throwError() -> Predicate { } if let actualError = actualError { - return PredicateResult( + return MatcherResult( bool: true, message: .expectedCustomValueTo("throw any error", actual: "<\(actualError)>") ) } else { - return PredicateResult( + return MatcherResult( bool: false, message: .expectedCustomValueTo("throw any error", actual: "no error") ) @@ -43,8 +43,8 @@ public func throwError() -> Predicate { /// /// nil arguments indicates that the matcher should not attempt to match against /// that parameter. -public func throwError(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate { - return Predicate { actualExpression in +public func throwError(_ error: T, closure: ((Error) -> Void)? = nil) -> Matcher { + return Matcher { actualExpression in var actualError: Error? do { _ = try actualExpression.evaluate() @@ -74,7 +74,7 @@ public func throwError(_ error: T, closure: ((Error) -> Void)? = } } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } @@ -89,8 +89,8 @@ public func throwError(_ error: T, closure: ((Error) -> Void)? = /// /// nil arguments indicates that the matcher should not attempt to match against /// that parameter. -public func throwError(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate { - return Predicate { actualExpression in +public func throwError(_ error: T, closure: ((T) -> Void)? = nil) -> Matcher { + return Matcher { actualExpression in var actualError: Error? do { _ = try actualExpression.evaluate() @@ -120,7 +120,7 @@ public func throwError(_ error: T, closure: ((T) -> V } } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } @@ -138,8 +138,8 @@ public func throwError(_ error: T, closure: ((T) -> V public func throwError( errorType: T.Type, closure: ((T) -> Void)? = nil -) -> Predicate { - return Predicate { actualExpression in +) -> Matcher { + return Matcher { actualExpression in var actualError: Error? do { _ = try actualExpression.evaluate() @@ -186,7 +186,7 @@ public func throwError( } } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } @@ -197,8 +197,8 @@ public func throwError( /// values of the existential type `Error` in the closure. /// /// The closure only gets called when an error was thrown. -public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate { - return Predicate { actualExpression in +public func throwError(closure: @escaping ((Error) -> Void)) -> Matcher { + return Matcher { actualExpression in var actualError: Error? do { _ = try actualExpression.evaluate() @@ -221,7 +221,7 @@ public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate(closure: @escaping ((Error) -> Void)) -> Predicate(closure: @escaping ((T) -> Void)) -> Predicate { - return Predicate { actualExpression in +public func throwError(closure: @escaping ((T) -> Void)) -> Matcher { + return Matcher { actualExpression in var actualError: Error? do { _ = try actualExpression.evaluate() @@ -256,6 +256,6 @@ public func throwError(closure: @escaping ((T) -> Void)) -> Predi } } - return PredicateResult(bool: matches, message: message) + return MatcherResult(bool: matches, message: message) } } diff --git a/Sources/Nimble/Matchers/ToSucceed.swift b/Sources/Nimble/Matchers/ToSucceed.swift index d9c616a68..2f22991aa 100644 --- a/Sources/Nimble/Matchers/ToSucceed.swift +++ b/Sources/Nimble/Matchers/ToSucceed.swift @@ -14,21 +14,21 @@ public enum ToSucceedResult { Return `.succeeded` when the validation succeeds. Return `.failed` with a failure reason when the validation fails. */ -public func succeed() -> Predicate { - return Predicate.define { actualExpression in +public func succeed() -> Matcher { + return Matcher.define { actualExpression in let optActual = try actualExpression.evaluate() guard let actual = optActual else { - return PredicateResult(status: .fail, message: .fail("expected a ToSucceedResult, got ")) + return MatcherResult(status: .fail, message: .fail("expected a ToSucceedResult, got ")) } switch actual { case .succeeded: - return PredicateResult( + return MatcherResult( bool: true, message: .expectedCustomValueTo("succeed", actual: "") ) case .failed(let reason): - return PredicateResult( + return MatcherResult( bool: false, message: .expectedCustomValueTo("succeed", actual: " because <\(reason)>") ) diff --git a/Sources/Nimble/Polling+AsyncAwait.swift b/Sources/Nimble/Polling+AsyncAwait.swift index 6859b5c51..110624f5b 100644 --- a/Sources/Nimble/Polling+AsyncAwait.swift +++ b/Sources/Nimble/Polling+AsyncAwait.swift @@ -4,12 +4,12 @@ import Dispatch @MainActor -private func execute(_ expression: AsyncExpression, style: ExpectationStyle, to: String, description: String?, predicateExecutor: () async throws -> PredicateResult) async -> (Bool, FailureMessage) { +private func execute(_ expression: AsyncExpression, style: ExpectationStyle, to: String, description: String?, matcherExecutor: () async throws -> MatcherResult) async -> (Bool, FailureMessage) { let msg = FailureMessage() msg.userDescription = description msg.to = to do { - let result = try await predicateExecutor() + let result = try await matcherExecutor() result.message.update(failureMessage: msg) if msg.actualValue == "" { msg.actualValue = "<\(stringify(try await expression.evaluate()))>" @@ -22,7 +22,7 @@ private func execute(_ expression: AsyncExpression, style: ExpectationStyl } private actor Poller { - private var lastPredicateResult: PredicateResult? + private var lastMatcherResult: MatcherResult? init() {} @@ -33,7 +33,7 @@ private actor Poller { timeout: NimbleTimeInterval, poll: NimbleTimeInterval, fnName: String, - predicateRunner: @escaping () async throws -> PredicateResult) async -> PredicateResult { + matcherRunner: @escaping () async throws -> MatcherResult) async -> MatcherResult { let fnName = "expect(...).\(fnName)(...)" let result = await pollBlock( pollInterval: poll, @@ -41,14 +41,14 @@ private actor Poller { file: expression.location.file, line: expression.location.line, fnName: fnName) { - self.updatePredicateResult(result: try await predicateRunner()) + self.updateMatcherResult(result: try await matcherRunner()) .toBoolean(expectation: style) } - return processPollResult(result.toPollResult(), matchStyle: matchStyle, lastPredicateResult: lastPredicateResult, fnName: fnName) + return processPollResult(result.toPollResult(), matchStyle: matchStyle, lastMatcherResult: lastMatcherResult, fnName: fnName) } - func updatePredicateResult(result: PredicateResult) -> PredicateResult { - self.lastPredicateResult = result + func updateMatcherResult(result: MatcherResult) -> MatcherResult { + self.lastMatcherResult = result return result } } @@ -61,8 +61,8 @@ private func poll( timeout: NimbleTimeInterval, poll: NimbleTimeInterval, fnName: String, - predicateRunner: @escaping () async throws -> PredicateResult -) async -> PredicateResult { + matcherRunner: @escaping () async throws -> MatcherResult +) async -> MatcherResult { let poller = Poller() return await poller.poll( expression: expression, @@ -71,16 +71,16 @@ private func poll( timeout: timeout, poll: poll, fnName: fnName, - predicateRunner: predicateRunner + matcherRunner: matcherRunner ) } extension SyncExpectation { - // MARK: - With Synchronous Predicates + // MARK: - With Synchronous Matchers /// Tests the actual value using a matcher to match by checking continuously /// at each pollInterval until the timeout is reached. @discardableResult - public func toEventually(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventually(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -97,7 +97,7 @@ extension SyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventually") { @MainActor in - try predicate.satisfies(expression.withoutCaching()) + try matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -106,7 +106,7 @@ extension SyncExpectation { /// Tests the actual value using a matcher to not match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toEventuallyNot(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventuallyNot(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -123,7 +123,7 @@ extension SyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventuallyNot") { @MainActor in - try predicate.satisfies(expression.withoutCaching()) + try matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -134,14 +134,14 @@ extension SyncExpectation { /// /// Alias of toEventuallyNot() @discardableResult - public func toNotEventually(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + public func toNotEventually(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to never match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toNever(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toNever(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -157,7 +157,7 @@ extension SyncExpectation { timeout: until, poll: pollInterval, fnName: "toNever") { @MainActor in - try predicate.satisfies(expression.withoutCaching()) + try matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -168,14 +168,14 @@ extension SyncExpectation { /// /// Alias of toNever() @discardableResult - public func neverTo(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toNever(predicate, until: until, pollInterval: pollInterval, description: description) + public func neverTo(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toNever(matcher, until: until, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to always match by checking /// continusouly at each pollInterval until the timeout is reached @discardableResult - public func toAlways(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toAlways(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -191,7 +191,7 @@ extension SyncExpectation { timeout: until, poll: pollInterval, fnName: "toAlways") { @MainActor in - try predicate.satisfies(expression.withoutCaching()) + try matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -202,15 +202,15 @@ extension SyncExpectation { /// /// Alias of toAlways() @discardableResult - public func alwaysTo(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toAlways(predicate, until: until, pollInterval: pollInterval, description: description) + public func alwaysTo(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toAlways(matcher, until: until, pollInterval: pollInterval, description: description) } - // MARK: - With AsyncPredicates + // MARK: - With AsyncMatchers /// Tests the actual value using a matcher to match by checking continuously /// at each pollInterval until the timeout is reached. @discardableResult - public func toEventually(_ predicate: AsyncPredicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventually(_ matcher: AsyncMatcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -227,7 +227,7 @@ extension SyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventually") { @MainActor in - try await predicate.satisfies(expression.withoutCaching().toAsyncExpression()) + try await matcher.satisfies(expression.withoutCaching().toAsyncExpression()) } } return verify(pass, msg) @@ -236,7 +236,7 @@ extension SyncExpectation { /// Tests the actual value using a matcher to not match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toEventuallyNot(_ predicate: AsyncPredicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventuallyNot(_ matcher: AsyncMatcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -253,7 +253,7 @@ extension SyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventuallyNot") { @MainActor in - try await predicate.satisfies(expression.withoutCaching().toAsyncExpression()) + try await matcher.satisfies(expression.withoutCaching().toAsyncExpression()) } } return verify(pass, msg) @@ -264,14 +264,14 @@ extension SyncExpectation { /// /// Alias of toEventuallyNot() @discardableResult - public func toNotEventually(_ predicate: AsyncPredicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + public func toNotEventually(_ matcher: AsyncMatcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to never match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toNever(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toNever(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -287,7 +287,7 @@ extension SyncExpectation { timeout: until, poll: pollInterval, fnName: "toNever") { @MainActor in - try await predicate.satisfies(expression.withoutCaching().toAsyncExpression()) + try await matcher.satisfies(expression.withoutCaching().toAsyncExpression()) } } return verify(pass, msg) @@ -298,14 +298,14 @@ extension SyncExpectation { /// /// Alias of toNever() @discardableResult - public func neverTo(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toNever(predicate, until: until, pollInterval: pollInterval, description: description) + public func neverTo(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toNever(matcher, until: until, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to always match by checking /// continusouly at each pollInterval until the timeout is reached @discardableResult - public func toAlways(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toAlways(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let asyncExpression = expression.toAsyncExpression() @@ -321,7 +321,7 @@ extension SyncExpectation { timeout: until, poll: pollInterval, fnName: "toAlways") { @MainActor in - try await predicate.satisfies(expression.withoutCaching().toAsyncExpression()) + try await matcher.satisfies(expression.withoutCaching().toAsyncExpression()) } } return verify(pass, msg) @@ -332,17 +332,17 @@ extension SyncExpectation { /// /// Alias of toAlways() @discardableResult - public func alwaysTo(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toAlways(predicate, until: until, pollInterval: pollInterval, description: description) + public func alwaysTo(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toAlways(matcher, until: until, pollInterval: pollInterval, description: description) } } extension AsyncExpectation { - // MARK: - With Synchronous Predicates + // MARK: - With Synchronous Matchers /// Tests the actual value using a matcher to match by checking continuously /// at each pollInterval until the timeout is reached. @discardableResult - public func toEventually(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventually(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -357,7 +357,7 @@ extension AsyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventually") { - try predicate.satisfies(await expression.withoutCaching().toSynchronousExpression()) + try matcher.satisfies(await expression.withoutCaching().toSynchronousExpression()) } } return verify(pass, msg) @@ -366,7 +366,7 @@ extension AsyncExpectation { /// Tests the actual value using a matcher to not match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toEventuallyNot(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventuallyNot(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -381,7 +381,7 @@ extension AsyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventuallyNot") { - try predicate.satisfies(await expression.withoutCaching().toSynchronousExpression()) + try matcher.satisfies(await expression.withoutCaching().toSynchronousExpression()) } } return verify(pass, msg) @@ -392,14 +392,14 @@ extension AsyncExpectation { /// /// Alias of toEventuallyNot() @discardableResult - public func toNotEventually(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + public func toNotEventually(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to never match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toNever(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toNever(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -414,7 +414,7 @@ extension AsyncExpectation { timeout: until, poll: pollInterval, fnName: "toNever") { - try predicate.satisfies(await expression.withoutCaching().toSynchronousExpression()) + try matcher.satisfies(await expression.withoutCaching().toSynchronousExpression()) } } return verify(pass, msg) @@ -425,14 +425,14 @@ extension AsyncExpectation { /// /// Alias of toNever() @discardableResult - public func neverTo(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toNever(predicate, until: until, pollInterval: pollInterval, description: description) + public func neverTo(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toNever(matcher, until: until, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to always match by checking /// continusouly at each pollInterval until the timeout is reached @discardableResult - public func toAlways(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toAlways(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -447,7 +447,7 @@ extension AsyncExpectation { timeout: until, poll: pollInterval, fnName: "toAlways") { - try predicate.satisfies(await expression.withoutCaching().toSynchronousExpression()) + try matcher.satisfies(await expression.withoutCaching().toSynchronousExpression()) } } return verify(pass, msg) @@ -458,15 +458,15 @@ extension AsyncExpectation { /// /// Alias of toAlways() @discardableResult - public func alwaysTo(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toAlways(predicate, until: until, pollInterval: pollInterval, description: description) + public func alwaysTo(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toAlways(matcher, until: until, pollInterval: pollInterval, description: description) } - // MARK: - With AsyncPredicates + // MARK: - With AsyncMatchers /// Tests the actual value using a matcher to match by checking continuously /// at each pollInterval until the timeout is reached. @discardableResult - public func toEventually(_ predicate: AsyncPredicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventually(_ matcher: AsyncMatcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -481,7 +481,7 @@ extension AsyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventually") { - try await predicate.satisfies(expression.withoutCaching()) + try await matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -490,7 +490,7 @@ extension AsyncExpectation { /// Tests the actual value using a matcher to not match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toEventuallyNot(_ predicate: AsyncPredicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toEventuallyNot(_ matcher: AsyncMatcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -505,7 +505,7 @@ extension AsyncExpectation { timeout: timeout, poll: pollInterval, fnName: "toEventuallyNot") { - try await predicate.satisfies(expression.withoutCaching()) + try await matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -516,14 +516,14 @@ extension AsyncExpectation { /// /// Alias of toEventuallyNot() @discardableResult - public func toNotEventually(_ predicate: AsyncPredicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + public func toNotEventually(_ matcher: AsyncMatcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to never match by checking /// continuously at each pollInterval until the timeout is reached. @discardableResult - public func toNever(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toNever(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -538,7 +538,7 @@ extension AsyncExpectation { timeout: until, poll: pollInterval, fnName: "toNever") { - try await predicate.satisfies(expression.withoutCaching()) + try await matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -549,14 +549,14 @@ extension AsyncExpectation { /// /// Alias of toNever() @discardableResult - public func neverTo(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toNever(predicate, until: until, pollInterval: pollInterval, description: description) + public func neverTo(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toNever(matcher, until: until, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to always match by checking /// continusouly at each pollInterval until the timeout is reached @discardableResult - public func toAlways(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + public func toAlways(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = await execute( @@ -571,7 +571,7 @@ extension AsyncExpectation { timeout: until, poll: pollInterval, fnName: "toAlways") { - try await predicate.satisfies(expression.withoutCaching()) + try await matcher.satisfies(expression.withoutCaching()) } } return verify(pass, msg) @@ -582,8 +582,8 @@ extension AsyncExpectation { /// /// Alias of toAlways() @discardableResult - public func alwaysTo(_ predicate: AsyncPredicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { - return await toAlways(predicate, until: until, pollInterval: pollInterval, description: description) + public func alwaysTo(_ matcher: AsyncMatcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) async -> Self { + return await toAlways(matcher, until: until, pollInterval: pollInterval, description: description) } } diff --git a/Sources/Nimble/Polling.swift b/Sources/Nimble/Polling.swift index 2780a8a9d..4d11fbb0b 100644 --- a/Sources/Nimble/Polling.swift +++ b/Sources/Nimble/Polling.swift @@ -47,64 +47,64 @@ internal enum AsyncMatchStyle { private func poll( style: ExpectationStyle, matchStyle: AsyncMatchStyle, - predicate: Predicate, + matcher: Matcher, timeout: NimbleTimeInterval, poll: NimbleTimeInterval, fnName: String -) -> Predicate { - return Predicate { actualExpression in +) -> Matcher { + return Matcher { actualExpression in let uncachedExpression = actualExpression.withoutCaching() let fnName = "expect(...).\(fnName)(...)" - var lastPredicateResult: PredicateResult? + var lastMatcherResult: MatcherResult? let result = pollBlock( pollInterval: poll, timeoutInterval: timeout, file: actualExpression.location.file, line: actualExpression.location.line, fnName: fnName) { - lastPredicateResult = try predicate.satisfies(uncachedExpression) - return lastPredicateResult!.toBoolean(expectation: style) + lastMatcherResult = try matcher.satisfies(uncachedExpression) + return lastMatcherResult!.toBoolean(expectation: style) } - return processPollResult(result, matchStyle: matchStyle, lastPredicateResult: lastPredicateResult, fnName: fnName) + return processPollResult(result, matchStyle: matchStyle, lastMatcherResult: lastMatcherResult, fnName: fnName) } } // swiftlint:disable:next cyclomatic_complexity -internal func processPollResult(_ result: PollResult, matchStyle: AsyncMatchStyle, lastPredicateResult: PredicateResult?, fnName: String) -> PredicateResult { +internal func processPollResult(_ result: PollResult, matchStyle: AsyncMatchStyle, lastMatcherResult: MatcherResult?, fnName: String) -> MatcherResult { switch result { case .completed: switch matchStyle { case .eventually: - return lastPredicateResult! + return lastMatcherResult! case .never: - return PredicateResult( + return MatcherResult( status: .fail, - message: lastPredicateResult?.message ?? .fail("matched the predicate when it shouldn't have") + message: lastMatcherResult?.message ?? .fail("matched the matcher when it shouldn't have") ) case .always: - return PredicateResult( + return MatcherResult( status: .fail, - message: lastPredicateResult?.message ?? .fail("didn't match the predicate when it should have") + message: lastMatcherResult?.message ?? .fail("didn't match the matcher when it should have") ) } case .timedOut: switch matchStyle { case .eventually: - let message = lastPredicateResult?.message ?? .fail("timed out before returning a value") - return PredicateResult(status: .fail, message: message) + let message = lastMatcherResult?.message ?? .fail("timed out before returning a value") + return MatcherResult(status: .fail, message: message) case .never: - return PredicateResult(status: .doesNotMatch, message: .expectedTo("never match the predicate")) + return MatcherResult(status: .doesNotMatch, message: .expectedTo("never match the matcher")) case .always: - return PredicateResult(status: .matches, message: .expectedTo("always match the predicate")) + return MatcherResult(status: .matches, message: .expectedTo("always match the matcher")) } case let .errorThrown(error): - return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) + return MatcherResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")) case let .raisedException(exception): - return PredicateResult(status: .fail, message: .fail("unexpected exception raised: \(exception)")) + return MatcherResult(status: .fail, message: .fail("unexpected exception raised: \(exception)")) case .blockedRunLoop: - let message = lastPredicateResult?.message.appended(message: " (timed out, but main run loop was unresponsive).") ?? + let message = lastMatcherResult?.message.appended(message: " (timed out, but main run loop was unresponsive).") ?? .fail("main run loop was unresponsive") - return PredicateResult(status: .fail, message: message) + return MatcherResult(status: .fail, message: message) case .incomplete: internalError("Reached .incomplete state for \(fnName)(...).") } @@ -129,7 +129,7 @@ extension SyncExpectation { /// This form of `toEventually` does not work in any kind of async context. Use the async form of `toEventually` if you are running tests in an async context. @discardableResult @available(*, noasync, message: "the sync variant of `toEventually` does not work in async contexts. Use the async variant as a drop-in replacement") - public func toEventually(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { + public func toEventually(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = execute( @@ -138,7 +138,7 @@ extension SyncExpectation { poll( style: .toMatch, matchStyle: .eventually, - predicate: predicate, + matcher: matcher, timeout: timeout, poll: pollInterval, fnName: "toEventually" @@ -162,7 +162,7 @@ extension SyncExpectation { /// Use the async form of `toEventuallyNot` if you are running tests in an async context. @discardableResult @available(*, noasync, message: "the sync variant of `toEventuallyNot` does not work in async contexts. Use the async variant as a drop-in replacement") - public func toEventuallyNot(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { + public func toEventuallyNot(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = execute( @@ -171,7 +171,7 @@ extension SyncExpectation { poll( style: .toNotMatch, matchStyle: .eventually, - predicate: predicate, + matcher: matcher, timeout: timeout, poll: pollInterval, fnName: "toEventuallyNot" @@ -197,8 +197,8 @@ extension SyncExpectation { /// Use the async form of `toNotEventually` if you are running tests in an async context. @discardableResult @available(*, noasync, message: "the sync variant of `toNotEventually` does not work in async contexts. Use the async variant as a drop-in replacement") - public func toNotEventually(_ predicate: Predicate, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { - return toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) + public func toNotEventually(_ matcher: Matcher, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { + return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to never match by checking @@ -213,7 +213,7 @@ extension SyncExpectation { /// Use the async form of `toNever` if you are running tests in an async context. @discardableResult @available(*, noasync, message: "the sync variant of `toNever` does not work in async contexts. Use the async variant as a drop-in replacement") - public func toNever(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { + public func toNever(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = execute( @@ -222,7 +222,7 @@ extension SyncExpectation { poll( style: .toMatch, matchStyle: .never, - predicate: predicate, + matcher: matcher, timeout: until, poll: pollInterval, fnName: "toNever" @@ -248,8 +248,8 @@ extension SyncExpectation { /// Use the async form of `neverTo` if you are running tests in an async context. @discardableResult @available(*, noasync, message: "the sync variant of `neverTo` does not work in async contexts. Use the async variant as a drop-in replacement") - public func neverTo(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { - return toNever(predicate, until: until, pollInterval: pollInterval, description: description) + public func neverTo(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { + return toNever(matcher, until: until, pollInterval: pollInterval, description: description) } /// Tests the actual value using a matcher to always match by checking @@ -264,7 +264,7 @@ extension SyncExpectation { /// Use the async form of `toAlways` if you are running tests in an async context. @discardableResult @available(*, noasync, message: "the sync variant of `toAlways` does not work in async contexts. Use the async variant as a drop-in replacement") - public func toAlways(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { + public func toAlways(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = execute( @@ -273,7 +273,7 @@ extension SyncExpectation { poll( style: .toNotMatch, matchStyle: .always, - predicate: predicate, + matcher: matcher, timeout: until, poll: pollInterval, fnName: "toAlways" @@ -299,8 +299,8 @@ extension SyncExpectation { /// Use the async form of `alwaysTo` if you are running tests in an async context. @discardableResult @available(*, noasync, message: "the sync variant of `alwaysTo` does not work in async contexts. Use the async variant as a drop-in replacement") - public func alwaysTo(_ predicate: Predicate, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { - return toAlways(predicate, until: until, pollInterval: pollInterval, description: description) + public func alwaysTo(_ matcher: Matcher, until: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil) -> Self { + return toAlways(matcher, until: until, pollInterval: pollInterval, description: description) } } diff --git a/Sources/NimbleObjectiveC/DSL.m b/Sources/NimbleObjectiveC/DSL.m index a98a8dc6c..2ab37efe3 100644 --- a/Sources/NimbleObjectiveC/DSL.m +++ b/Sources/NimbleObjectiveC/DSL.m @@ -32,71 +32,71 @@ NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger return [NMBExpectation failWithMessage:msg file:file line:line]; } -NIMBLE_EXPORT NMBPredicate *NMB_beAnInstanceOf(Class expectedClass) { - return [NMBPredicate beAnInstanceOfMatcher:expectedClass]; +NIMBLE_EXPORT NMBMatcher *NMB_beAnInstanceOf(Class expectedClass) { + return [NMBMatcher beAnInstanceOfMatcher:expectedClass]; } -NIMBLE_EXPORT NMBPredicate *NMB_beAKindOf(Class expectedClass) { - return [NMBPredicate beAKindOfMatcher:expectedClass]; +NIMBLE_EXPORT NMBMatcher *NMB_beAKindOf(Class expectedClass) { + return [NMBMatcher beAKindOfMatcher:expectedClass]; } -NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToPredicate *NMB_beCloseTo(NSNumber *expectedValue) { - return [NMBPredicate beCloseToMatcher:expectedValue within:0.001]; +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue) { + return [NMBMatcher beCloseToMatcher:expectedValue within:0.001]; } -NIMBLE_EXPORT NMBPredicate *NMB_beginWith(id itemElementOrSubstring) { - return [NMBPredicate beginWithMatcher:itemElementOrSubstring]; +NIMBLE_EXPORT NMBMatcher *NMB_beginWith(id itemElementOrSubstring) { + return [NMBMatcher beginWithMatcher:itemElementOrSubstring]; } -NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBPredicate *NMB_beGreaterThan(NSNumber *expectedValue) { - return [NMBPredicate beGreaterThanMatcher:expectedValue]; +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBMatcher *NMB_beGreaterThan(NSNumber *expectedValue) { + return [NMBMatcher beGreaterThanMatcher:expectedValue]; } -NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBPredicate *NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) { - return [NMBPredicate beGreaterThanOrEqualToMatcher:expectedValue]; +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBMatcher *NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) { + return [NMBMatcher beGreaterThanOrEqualToMatcher:expectedValue]; } -NIMBLE_EXPORT NMBPredicate *NMB_beIdenticalTo(id expectedInstance) { - return [NMBPredicate beIdenticalToMatcher:expectedInstance]; +NIMBLE_EXPORT NMBMatcher *NMB_beIdenticalTo(id expectedInstance) { + return [NMBMatcher beIdenticalToMatcher:expectedInstance]; } -NIMBLE_EXPORT NMBPredicate *NMB_be(id expectedInstance) { - return [NMBPredicate beIdenticalToMatcher:expectedInstance]; +NIMBLE_EXPORT NMBMatcher *NMB_be(id expectedInstance) { + return [NMBMatcher beIdenticalToMatcher:expectedInstance]; } -NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBPredicate *NMB_beLessThan(NSNumber *expectedValue) { - return [NMBPredicate beLessThanMatcher:expectedValue]; +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBMatcher *NMB_beLessThan(NSNumber *expectedValue) { + return [NMBMatcher beLessThanMatcher:expectedValue]; } -NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBPredicate *NMB_beLessThanOrEqualTo(NSNumber *expectedValue) { - return [NMBPredicate beLessThanOrEqualToMatcher:expectedValue]; +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBMatcher *NMB_beLessThanOrEqualTo(NSNumber *expectedValue) { + return [NMBMatcher beLessThanOrEqualToMatcher:expectedValue]; } -NIMBLE_EXPORT NMBPredicate *NMB_beTruthy(void) { - return [NMBPredicate beTruthyMatcher]; +NIMBLE_EXPORT NMBMatcher *NMB_beTruthy(void) { + return [NMBMatcher beTruthyMatcher]; } -NIMBLE_EXPORT NMBPredicate *NMB_beFalsy(void) { - return [NMBPredicate beFalsyMatcher]; +NIMBLE_EXPORT NMBMatcher *NMB_beFalsy(void) { + return [NMBMatcher beFalsyMatcher]; } -NIMBLE_EXPORT NMBPredicate *NMB_beTrue(void) { - return [NMBPredicate beTrueMatcher]; +NIMBLE_EXPORT NMBMatcher *NMB_beTrue(void) { + return [NMBMatcher beTrueMatcher]; } -NIMBLE_EXPORT NMBPredicate *NMB_beFalse(void) { - return [NMBPredicate beFalseMatcher]; +NIMBLE_EXPORT NMBMatcher *NMB_beFalse(void) { + return [NMBMatcher beFalseMatcher]; } -NIMBLE_EXPORT NMBPredicate *NMB_beNil(void) { - return [NMBPredicate beNilMatcher]; +NIMBLE_EXPORT NMBMatcher *NMB_beNil(void) { + return [NMBMatcher beNilMatcher]; } -NIMBLE_EXPORT NMBPredicate *NMB_beEmpty(void) { - return [NMBPredicate beEmptyMatcher]; +NIMBLE_EXPORT NMBMatcher *NMB_beEmpty(void) { + return [NMBMatcher beEmptyMatcher]; } -NIMBLE_EXPORT NMBPredicate *NMB_containWithNilTermination(id itemOrSubstring, ...) { +NIMBLE_EXPORT NMBMatcher *NMB_containWithNilTermination(id itemOrSubstring, ...) { NSMutableArray *itemOrSubstringArray = [NSMutableArray array]; if (itemOrSubstring) { @@ -111,44 +111,44 @@ NIMBLE_EXPORT void NMB_failWithMessage(NSString *msg, NSString *file, NSUInteger va_end(args); } - return [NMBPredicate containMatcher:itemOrSubstringArray]; + return [NMBMatcher containMatcher:itemOrSubstringArray]; } -NIMBLE_EXPORT NMBPredicate *NMB_containElementSatisfying(BOOL(^predicate)(id)) { - return [NMBPredicate containElementSatisfyingMatcher:predicate]; +NIMBLE_EXPORT NMBMatcher *NMB_containElementSatisfying(BOOL(^matcher)(id)) { + return [NMBMatcher containElementSatisfyingMatcher:matcher]; } -NIMBLE_EXPORT NMBPredicate *NMB_endWith(id itemElementOrSubstring) { - return [NMBPredicate endWithMatcher:itemElementOrSubstring]; +NIMBLE_EXPORT NMBMatcher *NMB_endWith(id itemElementOrSubstring) { + return [NMBMatcher endWithMatcher:itemElementOrSubstring]; } -NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBPredicate *NMB_equal(__nullable id expectedValue) { - return [NMBPredicate equalMatcher:expectedValue]; +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBMatcher *NMB_equal(__nullable id expectedValue) { + return [NMBMatcher equalMatcher:expectedValue]; } -NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBPredicate *NMB_haveCount(id expectedValue) { - return [NMBPredicate haveCountMatcher:expectedValue]; +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBMatcher *NMB_haveCount(id expectedValue) { + return [NMBMatcher haveCountMatcher:expectedValue]; } -NIMBLE_EXPORT NMBPredicate *NMB_match(id expectedValue) { - return [NMBPredicate matchMatcher:expectedValue]; +NIMBLE_EXPORT NMBMatcher *NMB_match(id expectedValue) { + return [NMBMatcher matchMatcher:expectedValue]; } -NIMBLE_EXPORT NMBPredicate *NMB_allPass(id expectedValue) { - return [NMBPredicate allPassMatcher:expectedValue]; +NIMBLE_EXPORT NMBMatcher *NMB_allPass(id expectedValue) { + return [NMBMatcher allPassMatcher:expectedValue]; } -NIMBLE_EXPORT NMBPredicate *NMB_satisfyAnyOfWithMatchers(id matchers) { - return [NMBPredicate satisfyAnyOfMatcher:matchers]; +NIMBLE_EXPORT NMBMatcher *NMB_satisfyAnyOfWithMatchers(id matchers) { + return [NMBMatcher satisfyAnyOfMatcher:matchers]; } -NIMBLE_EXPORT NMBPredicate *NMB_satisfyAllOfWithMatchers(id matchers) { - return [NMBPredicate satisfyAllOfMatcher:matchers]; +NIMBLE_EXPORT NMBMatcher *NMB_satisfyAllOfWithMatchers(id matchers) { + return [NMBMatcher satisfyAllOfMatcher:matchers]; } #if !SWIFT_PACKAGE -NIMBLE_EXPORT NMBObjCRaiseExceptionPredicate *NMB_raiseException(void) { - return [NMBPredicate raiseExceptionMatcher]; +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void) { + return [NMBMatcher raiseExceptionMatcher]; } #endif diff --git a/Sources/NimbleObjectiveC/include/DSL.h b/Sources/NimbleObjectiveC/include/DSL.h index 9ae06a4d1..5d20fb1c2 100644 --- a/Sources/NimbleObjectiveC/include/DSL.h +++ b/Sources/NimbleObjectiveC/include/DSL.h @@ -1,9 +1,9 @@ #import @class NMBExpectation; -@class NMBPredicate; -@class NMBObjCBeCloseToPredicate; -@class NMBObjCRaiseExceptionPredicate; +@class NMBMatcher; +@class NMBObjCBeCloseToMatcher; +@class NMBObjCRaiseExceptionMatcher; NS_ASSUME_NONNULL_BEGIN @@ -66,16 +66,16 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin #define DEFINE_OVERLOAD(TYPE, EXPR) \ NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ - NMBPredicate *NMB_equal(TYPE expectedValue) { \ + NMBMatcher *NMB_equal(TYPE expectedValue) { \ return NMB_equal((EXPR)); \ } \ - NIMBLE_SHORT_OVERLOADED(NMBPredicate *equal(TYPE expectedValue), NMB_equal(expectedValue)); + NIMBLE_SHORT_OVERLOADED(NMBMatcher *equal(TYPE expectedValue), NMB_equal(expectedValue)); NIMBLE_EXPORT NIMBLE_OVERLOADABLE - NMBPredicate *NMB_equal(__nullable id expectedValue); + NMBMatcher *NMB_equal(__nullable id expectedValue); - NIMBLE_SHORT_OVERLOADED(NMBPredicate *equal(__nullable id expectedValue), + NIMBLE_SHORT_OVERLOADED(NMBMatcher *equal(__nullable id expectedValue), NMB_equal(expectedValue)); // overloaded dispatch for nils - expect(nil) @@ -101,17 +101,17 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin #define DEFINE_OVERLOAD(TYPE, EXPR) \ NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ - NMBPredicate *NMB_haveCount(TYPE expectedValue) { \ + NMBMatcher *NMB_haveCount(TYPE expectedValue) { \ return NMB_haveCount((EXPR)); \ } \ - NIMBLE_SHORT_OVERLOADED(NMBPredicate *haveCount(TYPE expectedValue), \ + NIMBLE_SHORT_OVERLOADED(NMBMatcher *haveCount(TYPE expectedValue), \ NMB_haveCount(expectedValue)); NIMBLE_EXPORT NIMBLE_OVERLOADABLE - NMBPredicate *NMB_haveCount(id expectedValue); + NMBMatcher *NMB_haveCount(id expectedValue); - NIMBLE_SHORT_OVERLOADED(NMBPredicate *haveCount(id expectedValue), + NIMBLE_SHORT_OVERLOADED(NMBMatcher *haveCount(id expectedValue), NMB_haveCount(expectedValue)); DEFINE_OVERLOAD(long, @(expectedValue)) @@ -127,14 +127,14 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin #define DEFINE_OVERLOAD(TYPE, EXPR) \ NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ - NMBObjCBeCloseToPredicate *NMB_beCloseTo(TYPE expectedValue) { \ + NMBObjCBeCloseToMatcher *NMB_beCloseTo(TYPE expectedValue) { \ return NMB_beCloseTo((NSNumber *)(EXPR)); \ } \ - NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToPredicate *beCloseTo(TYPE expectedValue), \ + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(TYPE expectedValue), \ NMB_beCloseTo(expectedValue)); - NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToPredicate *NMB_beCloseTo(NSNumber *expectedValue); - NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToPredicate *beCloseTo(NSNumber *expectedValue), + NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue); + NIMBLE_SHORT_OVERLOADED(NMBObjCBeCloseToMatcher *beCloseTo(NSNumber *expectedValue), NMB_beCloseTo(expectedValue)); // it would be better to only overload float & double, but zero becomes ambigious @@ -152,33 +152,33 @@ NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(void), NSStrin #undef DEFINE_OVERLOAD -NIMBLE_EXPORT NMBPredicate *NMB_beAnInstanceOf(Class expectedClass); -NIMBLE_EXPORT_INLINE NMBPredicate *beAnInstanceOf(Class expectedClass) { +NIMBLE_EXPORT NMBMatcher *NMB_beAnInstanceOf(Class expectedClass); +NIMBLE_EXPORT_INLINE NMBMatcher *beAnInstanceOf(Class expectedClass) { return NMB_beAnInstanceOf(expectedClass); } -NIMBLE_EXPORT NMBPredicate *NMB_beAKindOf(Class expectedClass); -NIMBLE_EXPORT_INLINE NMBPredicate *beAKindOf(Class expectedClass) { +NIMBLE_EXPORT NMBMatcher *NMB_beAKindOf(Class expectedClass); +NIMBLE_EXPORT_INLINE NMBMatcher *beAKindOf(Class expectedClass) { return NMB_beAKindOf(expectedClass); } -NIMBLE_EXPORT NMBPredicate *NMB_beginWith(id itemElementOrSubstring); -NIMBLE_EXPORT_INLINE NMBPredicate *beginWith(id itemElementOrSubstring) { +NIMBLE_EXPORT NMBMatcher *NMB_beginWith(id itemElementOrSubstring); +NIMBLE_EXPORT_INLINE NMBMatcher *beginWith(id itemElementOrSubstring) { return NMB_beginWith(itemElementOrSubstring); } #define DEFINE_OVERLOAD(TYPE, EXPR) \ NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ - NMBPredicate *NMB_beGreaterThan(TYPE expectedValue) { \ + NMBMatcher *NMB_beGreaterThan(TYPE expectedValue) { \ return NMB_beGreaterThan((EXPR)); \ } \ - NIMBLE_SHORT_OVERLOADED(NMBPredicate *beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue)); + NIMBLE_SHORT_OVERLOADED(NMBMatcher *beGreaterThan(TYPE expectedValue), NMB_beGreaterThan(expectedValue)); NIMBLE_EXPORT NIMBLE_OVERLOADABLE - NMBPredicate *NMB_beGreaterThan(NSNumber *expectedValue); + NMBMatcher *NMB_beGreaterThan(NSNumber *expectedValue); NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE - NMBPredicate *beGreaterThan(NSNumber *expectedValue) { + NMBMatcher *beGreaterThan(NSNumber *expectedValue) { return NMB_beGreaterThan(expectedValue); } @@ -197,17 +197,17 @@ NIMBLE_EXPORT_INLINE NMBPredicate *beginWith(id itemElementOrSubstring) { #define DEFINE_OVERLOAD(TYPE, EXPR) \ NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ - NMBPredicate *NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \ + NMBMatcher *NMB_beGreaterThanOrEqualTo(TYPE expectedValue) { \ return NMB_beGreaterThanOrEqualTo((EXPR)); \ } \ - NIMBLE_SHORT_OVERLOADED(NMBPredicate *beGreaterThanOrEqualTo(TYPE expectedValue), \ + NIMBLE_SHORT_OVERLOADED(NMBMatcher *beGreaterThanOrEqualTo(TYPE expectedValue), \ NMB_beGreaterThanOrEqualTo(expectedValue)); NIMBLE_EXPORT NIMBLE_OVERLOADABLE - NMBPredicate *NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue); + NMBMatcher *NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue); NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE - NMBPredicate *beGreaterThanOrEqualTo(NSNumber *expectedValue) { + NMBMatcher *beGreaterThanOrEqualTo(NSNumber *expectedValue) { return NMB_beGreaterThanOrEqualTo(expectedValue); } @@ -225,28 +225,28 @@ NIMBLE_EXPORT_INLINE NMBPredicate *beginWith(id itemElementOrSubstring) { #undef DEFINE_OVERLOAD -NIMBLE_EXPORT NMBPredicate *NMB_beIdenticalTo(id expectedInstance); -NIMBLE_SHORT(NMBPredicate *beIdenticalTo(id expectedInstance), +NIMBLE_EXPORT NMBMatcher *NMB_beIdenticalTo(id expectedInstance); +NIMBLE_SHORT(NMBMatcher *beIdenticalTo(id expectedInstance), NMB_beIdenticalTo(expectedInstance)); -NIMBLE_EXPORT NMBPredicate *NMB_be(id expectedInstance); -NIMBLE_SHORT(NMBPredicate *be(id expectedInstance), +NIMBLE_EXPORT NMBMatcher *NMB_be(id expectedInstance); +NIMBLE_SHORT(NMBMatcher *be(id expectedInstance), NMB_be(expectedInstance)); #define DEFINE_OVERLOAD(TYPE, EXPR) \ NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ - NMBPredicate *NMB_beLessThan(TYPE expectedValue) { \ + NMBMatcher *NMB_beLessThan(TYPE expectedValue) { \ return NMB_beLessThan((EXPR)); \ } \ - NIMBLE_SHORT_OVERLOADED(NMBPredicate *beLessThan(TYPE expectedValue), \ + NIMBLE_SHORT_OVERLOADED(NMBMatcher *beLessThan(TYPE expectedValue), \ NMB_beLessThan(expectedValue)); NIMBLE_EXPORT NIMBLE_OVERLOADABLE - NMBPredicate *NMB_beLessThan(NSNumber *expectedValue); + NMBMatcher *NMB_beLessThan(NSNumber *expectedValue); NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE - NMBPredicate *beLessThan(NSNumber *expectedValue) { + NMBMatcher *beLessThan(NSNumber *expectedValue) { return NMB_beLessThan(expectedValue); } @@ -266,18 +266,18 @@ NIMBLE_SHORT(NMBPredicate *be(id expectedInstance), #define DEFINE_OVERLOAD(TYPE, EXPR) \ NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE \ - NMBPredicate *NMB_beLessThanOrEqualTo(TYPE expectedValue) { \ + NMBMatcher *NMB_beLessThanOrEqualTo(TYPE expectedValue) { \ return NMB_beLessThanOrEqualTo((EXPR)); \ } \ - NIMBLE_SHORT_OVERLOADED(NMBPredicate *beLessThanOrEqualTo(TYPE expectedValue), \ + NIMBLE_SHORT_OVERLOADED(NMBMatcher *beLessThanOrEqualTo(TYPE expectedValue), \ NMB_beLessThanOrEqualTo(expectedValue)); NIMBLE_EXPORT NIMBLE_OVERLOADABLE - NMBPredicate *NMB_beLessThanOrEqualTo(NSNumber *expectedValue); + NMBMatcher *NMB_beLessThanOrEqualTo(NSNumber *expectedValue); NIMBLE_EXPORT_INLINE NIMBLE_OVERLOADABLE - NMBPredicate *beLessThanOrEqualTo(NSNumber *expectedValue) { + NMBMatcher *beLessThanOrEqualTo(NSNumber *expectedValue) { return NMB_beLessThanOrEqualTo(expectedValue); } @@ -294,63 +294,63 @@ NIMBLE_SHORT(NMBPredicate *be(id expectedInstance), #undef DEFINE_OVERLOAD -NIMBLE_EXPORT NMBPredicate *NMB_beTruthy(void); -NIMBLE_SHORT(NMBPredicate *beTruthy(void), +NIMBLE_EXPORT NMBMatcher *NMB_beTruthy(void); +NIMBLE_SHORT(NMBMatcher *beTruthy(void), NMB_beTruthy()); -NIMBLE_EXPORT NMBPredicate *NMB_beFalsy(void); -NIMBLE_SHORT(NMBPredicate *beFalsy(void), +NIMBLE_EXPORT NMBMatcher *NMB_beFalsy(void); +NIMBLE_SHORT(NMBMatcher *beFalsy(void), NMB_beFalsy()); -NIMBLE_EXPORT NMBPredicate *NMB_beTrue(void); -NIMBLE_SHORT(NMBPredicate *beTrue(void), +NIMBLE_EXPORT NMBMatcher *NMB_beTrue(void); +NIMBLE_SHORT(NMBMatcher *beTrue(void), NMB_beTrue()); -NIMBLE_EXPORT NMBPredicate *NMB_beFalse(void); -NIMBLE_SHORT(NMBPredicate *beFalse(void), +NIMBLE_EXPORT NMBMatcher *NMB_beFalse(void); +NIMBLE_SHORT(NMBMatcher *beFalse(void), NMB_beFalse()); -NIMBLE_EXPORT NMBPredicate *NMB_beNil(void); -NIMBLE_SHORT(NMBPredicate *beNil(void), +NIMBLE_EXPORT NMBMatcher *NMB_beNil(void); +NIMBLE_SHORT(NMBMatcher *beNil(void), NMB_beNil()); -NIMBLE_EXPORT NMBPredicate *NMB_beEmpty(void); -NIMBLE_SHORT(NMBPredicate *beEmpty(void), +NIMBLE_EXPORT NMBMatcher *NMB_beEmpty(void); +NIMBLE_SHORT(NMBMatcher *beEmpty(void), NMB_beEmpty()); -NIMBLE_EXPORT NMBPredicate *NMB_containWithNilTermination(id itemOrSubstring, ...) NS_REQUIRES_NIL_TERMINATION; +NIMBLE_EXPORT NMBMatcher *NMB_containWithNilTermination(id itemOrSubstring, ...) NS_REQUIRES_NIL_TERMINATION; #define NMB_contain(...) NMB_containWithNilTermination(__VA_ARGS__, nil) #ifndef NIMBLE_DISABLE_SHORT_SYNTAX #define contain(...) NMB_contain(__VA_ARGS__) #endif -NIMBLE_EXPORT NMBPredicate *NMB_containElementSatisfying(BOOL(^predicate)(id)); -NIMBLE_SHORT(NMBPredicate *containElementSatisfying(BOOL(^predicate)(id)), - NMB_containElementSatisfying(predicate)); +NIMBLE_EXPORT NMBMatcher *NMB_containElementSatisfying(BOOL(^matcher)(id)); +NIMBLE_SHORT(NMBMatcher *containElementSatisfying(BOOL(^matcher)(id)), + NMB_containElementSatisfying(matcher)); -NIMBLE_EXPORT NMBPredicate *NMB_endWith(id itemElementOrSubstring); -NIMBLE_SHORT(NMBPredicate *endWith(id itemElementOrSubstring), +NIMBLE_EXPORT NMBMatcher *NMB_endWith(id itemElementOrSubstring); +NIMBLE_SHORT(NMBMatcher *endWith(id itemElementOrSubstring), NMB_endWith(itemElementOrSubstring)); -NIMBLE_EXPORT NMBObjCRaiseExceptionPredicate *NMB_raiseException(void); -NIMBLE_SHORT(NMBObjCRaiseExceptionPredicate *raiseException(void), +NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void); +NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void), NMB_raiseException()); -NIMBLE_EXPORT NMBPredicate *NMB_match(id expectedValue); -NIMBLE_SHORT(NMBPredicate *match(id expectedValue), +NIMBLE_EXPORT NMBMatcher *NMB_match(id expectedValue); +NIMBLE_SHORT(NMBMatcher *match(id expectedValue), NMB_match(expectedValue)); -NIMBLE_EXPORT NMBPredicate *NMB_allPass(id matcher); -NIMBLE_SHORT(NMBPredicate *allPass(id matcher), +NIMBLE_EXPORT NMBMatcher *NMB_allPass(id matcher); +NIMBLE_SHORT(NMBMatcher *allPass(id matcher), NMB_allPass(matcher)); -NIMBLE_EXPORT NMBPredicate *NMB_satisfyAnyOfWithMatchers(id matchers); +NIMBLE_EXPORT NMBMatcher *NMB_satisfyAnyOfWithMatchers(id matchers); #define NMB_satisfyAnyOf(...) NMB_satisfyAnyOfWithMatchers(@[__VA_ARGS__]) #ifndef NIMBLE_DISABLE_SHORT_SYNTAX #define satisfyAnyOf(...) NMB_satisfyAnyOf(__VA_ARGS__) #endif -NIMBLE_EXPORT NMBPredicate *NMB_satisfyAllOfWithMatchers(id matchers); +NIMBLE_EXPORT NMBMatcher *NMB_satisfyAllOfWithMatchers(id matchers); #define NMB_satisfyAllOf(...) NMB_satisfyAllOfWithMatchers(@[__VA_ARGS__]) #ifndef NIMBLE_DISABLE_SHORT_SYNTAX #define satisfyAllOf(...) NMB_satisfyAllOf(__VA_ARGS__) diff --git a/Tests/NimbleObjectiveCTests/ObjCContainElementSatisfyingTest.m b/Tests/NimbleObjectiveCTests/ObjCContainElementSatisfyingTest.m index cdb8453b1..8d4a634d5 100644 --- a/Tests/NimbleObjectiveCTests/ObjCContainElementSatisfyingTest.m +++ b/Tests/NimbleObjectiveCTests/ObjCContainElementSatisfyingTest.m @@ -36,7 +36,7 @@ - (void)testPassingMatches { } - (void)testFailingMatches { - expectFailureMessage(@"expected to find object in collection that satisfies predicate", ^{ + expectFailureMessage(@"expected to find object in collection that satisfies matcher", ^{ expect(@[@1]).to(containElementSatisfying(^BOOL(id object) { return [object isEqualToNumber:@2]; })); diff --git a/Tests/NimbleTests/Helpers/AsyncHelpers.swift b/Tests/NimbleTests/Helpers/AsyncHelpers.swift index 05574fd5c..2770e359f 100644 --- a/Tests/NimbleTests/Helpers/AsyncHelpers.swift +++ b/Tests/NimbleTests/Helpers/AsyncHelpers.swift @@ -4,43 +4,43 @@ import XCTest import NimbleSharedTestHelpers #endif -func asyncEqual(_ expectedValue: T) -> AsyncPredicate { - AsyncPredicate.define { expression in +func asyncEqual(_ expectedValue: T) -> AsyncMatcher { + AsyncMatcher.define { expression in let message = ExpectationMessage.expectedActualValueTo("equal \(expectedValue)") if let value = try await expression.evaluate() { - return PredicateResult(bool: value == expectedValue, message: message) + return MatcherResult(bool: value == expectedValue, message: message) } else { - return PredicateResult(status: .fail, message: message.appendedBeNilHint()) + return MatcherResult(status: .fail, message: message.appendedBeNilHint()) } } } -func asyncContain(_ items: S.Element...) -> AsyncPredicate where S.Element: Equatable { +func asyncContain(_ items: S.Element...) -> AsyncMatcher where S.Element: Equatable { return asyncContain(items) } -func asyncContain(_ items: [S.Element]) -> AsyncPredicate where S.Element: Equatable { - return AsyncPredicate.simple("contain <\(String(describing: items))>") { actualExpression in +func asyncContain(_ items: [S.Element]) -> AsyncMatcher where S.Element: Equatable { + return AsyncMatcher.simple("contain <\(String(describing: items))>") { actualExpression in guard let actual = try await actualExpression.evaluate() else { return .fail } let matches = items.allSatisfy { return actual.contains($0) } - return PredicateStatus(bool: matches) + return MatcherStatus(bool: matches) } } func asyncBeCloseTo( _ expectedValue: Value -) -> AsyncPredicate { +) -> AsyncMatcher { let delta: Value = 1/10000 let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" - return AsyncPredicate.simple(errorMessage) { actualExpression in + return AsyncMatcher.simple(errorMessage) { actualExpression in guard let actualValue = try await actualExpression.evaluate() else { return .doesNotMatch } - return PredicateStatus(bool: abs(actualValue - expectedValue) < delta) + return MatcherStatus(bool: abs(actualValue - expectedValue) < delta) } } diff --git a/Tests/NimbleTests/Matchers/AlwaysFailMatcher.swift b/Tests/NimbleTests/Matchers/AlwaysFailMatcher.swift index c95ef9360..876aa6bbe 100644 --- a/Tests/NimbleTests/Matchers/AlwaysFailMatcher.swift +++ b/Tests/NimbleTests/Matchers/AlwaysFailMatcher.swift @@ -4,15 +4,15 @@ import Nimble import NimbleSharedTestHelpers #endif -func alwaysFail() -> Predicate { - return Predicate { _ throws -> PredicateResult in - return PredicateResult(status: .fail, message: .fail("This matcher should always fail")) +func alwaysFail() -> Nimble.Matcher { + return Matcher { _ throws -> MatcherResult in + return MatcherResult(status: .fail, message: .fail("This matcher should always fail")) } } -func asyncAlwaysFail() -> AsyncPredicate { - return AsyncPredicate { _ throws -> PredicateResult in - return PredicateResult(status: .fail, message: .fail("This matcher should always fail")) +func asyncAlwaysFail() -> AsyncMatcher { + return AsyncMatcher { _ throws -> MatcherResult in + return MatcherResult(status: .fail, message: .fail("This matcher should always fail")) } } diff --git a/Tests/NimbleTests/Matchers/AsyncAllPassTest.swift b/Tests/NimbleTests/Matchers/AsyncAllPassTest.swift index 0baf7b367..e6d22f42f 100644 --- a/Tests/NimbleTests/Matchers/AsyncAllPassTest.swift +++ b/Tests/NimbleTests/Matchers/AsyncAllPassTest.swift @@ -8,28 +8,28 @@ private func asyncCheck(_ closure: () -> Bool) async -> Bool { closure() } -private func asyncBeLessThan(_ expectedValue: T?) -> AsyncPredicate { +private func asyncBeLessThan(_ expectedValue: T?) -> AsyncMatcher { let message = "be less than <\(stringify(expectedValue))>" - return AsyncPredicate.simple(message) { actualExpression in + return AsyncMatcher.simple(message) { actualExpression in guard let actual = try await actualExpression.evaluate(), let expected = expectedValue else { return .fail } - return PredicateStatus(bool: actual < expected) + return MatcherStatus(bool: actual < expected) } } -private func asyncBeGreaterThan(_ expectedValue: T?) -> AsyncPredicate { +private func asyncBeGreaterThan(_ expectedValue: T?) -> AsyncMatcher { let message = "be greater than <\(stringify(expectedValue))>" - return AsyncPredicate.simple(message) { actualExpression in + return AsyncMatcher.simple(message) { actualExpression in guard let actual = try await actualExpression.evaluate(), let expected = expectedValue else { return .fail } - return PredicateStatus(bool: actual > expected) + return MatcherStatus(bool: actual > expected) } } -private func asyncBeNil() -> AsyncPredicate { - return AsyncPredicate.simpleNilable("be nil") { actualExpression in +private func asyncBeNil() -> AsyncMatcher { + return AsyncMatcher.simpleNilable("be nil") { actualExpression in let actualValue = try await actualExpression.evaluate() - return PredicateStatus(bool: actualValue == nil) + return MatcherStatus(bool: actualValue == nil) } } diff --git a/Tests/NimbleTests/Matchers/AsyncPredicateTest.swift b/Tests/NimbleTests/Matchers/AsyncPredicateTest.swift index 7ff341864..a92c88eaf 100644 --- a/Tests/NimbleTests/Matchers/AsyncPredicateTest.swift +++ b/Tests/NimbleTests/Matchers/AsyncPredicateTest.swift @@ -5,13 +5,13 @@ import Nimble import NimbleSharedTestHelpers #endif -private func beCalled(times: UInt) -> AsyncPredicate { - AsyncPredicate.define { expression in +private func beCalled(times: UInt) -> AsyncMatcher { + AsyncMatcher.define { expression in let message = ExpectationMessage.expectedActualValueTo("be called \(times) times") if let value = try await expression.evaluate()?.callCount { - return PredicateResult(bool: value == times, message: message) + return MatcherResult(bool: value == times, message: message) } else { - return PredicateResult(status: .fail, message: message.appendedBeNilHint()) + return MatcherResult(status: .fail, message: message.appendedBeNilHint()) } } } @@ -26,19 +26,19 @@ private actor CallCounter { private func asyncFunction(value: T) async -> T { return value } -final class AsyncPredicateTest: XCTestCase { - func testAsyncPredicatesWithAsyncExpectations() async { +final class AsyncMatcherTest: XCTestCase { + func testAsyncMatchersWithAsyncExpectations() async { await expecta(await asyncFunction(value: 1)).to(asyncEqual(1)) } - func testAsyncPredicatesWithSyncExpectations() async { + func testAsyncMatchersWithSyncExpectations() async { let subject = CallCounter() await subject.call() await expects(subject).to(beCalled(times: 1)) } #if !os(WASI) - func testAsyncPollingWithAsyncPredicates() async { + func testAsyncPollingWithAsyncMatchers() async { let subject = CallCounter() await expect { @@ -54,7 +54,7 @@ final class AsyncPredicateTest: XCTestCase { await expect { await asyncFunction(value: 1) }.toAlways(asyncEqual(1)) } - func testSyncPollingWithAsyncPredicates() async { + func testSyncPollingWithAsyncMatchers() async { await expects(1).toEventually(asyncEqual(1)) await expects(1).toAlways(asyncEqual(1)) await expects(1).toEventuallyNot(asyncEqual(0)) diff --git a/Tests/NimbleTests/Matchers/BeginWithPrefixTest.swift b/Tests/NimbleTests/Matchers/BeginWithPrefixTest.swift index 30582ff1a..ed1859ccd 100644 --- a/Tests/NimbleTests/Matchers/BeginWithPrefixTest.swift +++ b/Tests/NimbleTests/Matchers/BeginWithPrefixTest.swift @@ -32,7 +32,7 @@ final class BeginWithPrefixTest: XCTestCase { expect([]).to(beginWith(prefix: [] as [Int])) } - func testBeginWithSequencePrefixUsingPredicateClosure() { + func testBeginWithSequencePrefixUsingMatcherClosure() { failsWithErrorMessageForNil("expected to begin with , got ") { expect(nil as [Int]?).to(beginWith(prefix: nil as [Int]?, by: { $0 == $1 })) } diff --git a/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift b/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift index 35d09249d..38a3eac10 100644 --- a/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift +++ b/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift @@ -6,7 +6,7 @@ import NimbleSharedTestHelpers #endif final class ContainElementSatisfyingTest: XCTestCase { - // MARK: - Predicate variant + // MARK: - Matcher variant func testContainElementSatisfying() { var orderIndifferentArray = [1, 2, 3] expect(orderIndifferentArray).to(containElementSatisfying({ number in @@ -33,7 +33,7 @@ final class ContainElementSatisfyingTest: XCTestCase { func testContainElementSatisfyingDefaultErrorMessage() { let orderIndifferentArray = [1, 2, 3] - failsWithErrorMessage("expected to find object in collection that satisfies predicate") { + failsWithErrorMessage("expected to find object in collection that satisfies matcher") { expect(orderIndifferentArray).to(containElementSatisfying({ number in return number == 4 })) @@ -58,7 +58,7 @@ final class ContainElementSatisfyingTest: XCTestCase { func testContainElementSatisfyingNegativeCaseDefaultErrorMessage() { let orderIndifferentArray = ["puppies", "kittens", "turtles"] - failsWithErrorMessage("expected to not find object in collection that satisfies predicate") { + failsWithErrorMessage("expected to not find object in collection that satisfies matcher") { expect(orderIndifferentArray).toNot(containElementSatisfying({ string in return string == "kittens" })) @@ -74,7 +74,7 @@ final class ContainElementSatisfyingTest: XCTestCase { } } - // MARK: - AsyncPredicate variant + // MARK: - AsyncMatcher variant func testAsyncContainElementSatisfying() async { var orderIndifferentArray = [1, 2, 3] await expect(orderIndifferentArray).to(containElementSatisfying({ number in @@ -101,7 +101,7 @@ final class ContainElementSatisfyingTest: XCTestCase { func testAsyncContainElementSatisfyingDefaultErrorMessage() async { let orderIndifferentArray = [1, 2, 3] - await failsWithErrorMessage("expected to find object in collection that satisfies predicate") { + await failsWithErrorMessage("expected to find object in collection that satisfies matcher") { await expect(orderIndifferentArray).to(containElementSatisfying({ number in await asyncEqualityCheck(number, 4) })) @@ -126,7 +126,7 @@ final class ContainElementSatisfyingTest: XCTestCase { func testAsyncContainElementSatisfyingNegativeCaseDefaultErrorMessage() async { let orderIndifferentArray = ["puppies", "kittens", "turtles"] - await failsWithErrorMessage("expected to not find object in collection that satisfies predicate") { + await failsWithErrorMessage("expected to not find object in collection that satisfies matcher") { await expect(orderIndifferentArray).toNot(containElementSatisfying({ string in await asyncEqualityCheck(string, "kittens") })) diff --git a/Tests/NimbleTests/Matchers/ElementsEqualTest.swift b/Tests/NimbleTests/Matchers/ElementsEqualTest.swift index e6faf8445..b389c983f 100644 --- a/Tests/NimbleTests/Matchers/ElementsEqualTest.swift +++ b/Tests/NimbleTests/Matchers/ElementsEqualTest.swift @@ -27,7 +27,7 @@ final class ElementsEqualTest: XCTestCase { expect(sequence1).to(elementsEqual([1, 2, 3])) } - func testSequenceElementsEqualityUsingPredicateClosure() { + func testSequenceElementsEqualityUsingMatcherClosure() { failsWithErrorMessageForNil("expected to elementsEqual , got ") { expect(nil as [Int]?).to(elementsEqual(nil as [Int]?, by: { $0 == $1 })) } diff --git a/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift b/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift index b924cae01..73bebac0d 100644 --- a/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift +++ b/Tests/NimbleTests/Matchers/SatisfyAllOfTest.swift @@ -54,7 +54,7 @@ final class SatisfyAllOfTest: XCTestCase { } #if !os(WASI) - func testSatisfyAllOfCachesExpressionBeforePassingToPredicates() { + func testSatisfyAllOfCachesExpressionBeforePassingToMatchers() { // This is not a great example of assertion writing - functions being asserted on in Expressions should not have side effects. // But we should still handle those cases anyway. var value: Int = 0 @@ -68,10 +68,10 @@ final class SatisfyAllOfTest: XCTestCase { #endif // There's a compiler bug in swift 5.7.2 and earlier (xcode 14.2 and earlier) - // which causes runtime crashes when you use `[any AsyncablePredicate]`. + // which causes runtime crashes when you use `[any AsyncableMatcher]`. // https://github.com/apple/swift/issues/61403 #if swift(>=5.8.0) - // MARK: - AsyncPredicate variant + // MARK: - AsyncMatcher variant @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) func testAsyncSatisfyAllOf() async { await expect(2).to(satisfyAllOf(asyncEqual(2), beLessThan(3))) @@ -122,7 +122,7 @@ final class SatisfyAllOfTest: XCTestCase { #if !os(WASI) @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) - func testAsyncSatisfyAllOfCachesExpressionBeforePassingToPredicates() async { + func testAsyncSatisfyAllOfCachesExpressionBeforePassingToMatchers() async { // This is not a great example of assertion writing - functions being asserted on in Expressions should not have side effects. // But we should still handle those cases anyway. actor Counter { diff --git a/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift b/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift index 56c6a4348..f908d1b3b 100644 --- a/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift +++ b/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift @@ -52,7 +52,7 @@ final class SatisfyAnyOfTest: XCTestCase { } #if !os(WASI) - func testSatisfyAllOfCachesExpressionBeforePassingToPredicates() { + func testSatisfyAllOfCachesExpressionBeforePassingToMatchers() { // This is not a great example of assertion writing - functions being asserted on in Expressions should not have side effects. // But we should still handle those cases anyway. var value: Int = 0 @@ -68,7 +68,7 @@ final class SatisfyAnyOfTest: XCTestCase { #endif // There's a compiler bug in swift 5.7 and earlier (xcode 14.2 and earlier) - // which causes runtime crashes when you use `[any AsyncablePredicate]`. + // which causes runtime crashes when you use `[any AsyncableMatcher]`. // https://github.com/apple/swift/issues/61403 #if swift(>=5.8.0) // MARK: - Async Variant @@ -120,7 +120,7 @@ final class SatisfyAnyOfTest: XCTestCase { #if !os(WASI) @available(macOS 13.0.0, iOS 16.0.0, tvOS 16.0.0, watchOS 9.0.0, *) - func testAsyncSatisfyAllOfCachesExpressionBeforePassingToPredicates() async { + func testAsyncSatisfyAllOfCachesExpressionBeforePassingToMatchers() async { // This is not a great example of assertion writing - functions being asserted on in Expressions should not have side effects. // But we should still handle those cases anyway. actor Counter { diff --git a/Tests/NimbleTests/OnFailureThrowsTest.swift b/Tests/NimbleTests/OnFailureThrowsTest.swift index 46f1ed88b..e822fbbcd 100644 --- a/Tests/NimbleTests/OnFailureThrowsTest.swift +++ b/Tests/NimbleTests/OnFailureThrowsTest.swift @@ -11,7 +11,7 @@ final class OnFailureThrowsTest: XCTestCase { } func testUnexecutedLogsAnError() { - failsWithErrorMessage("Attempted to call `Expectation.onFailure(throw:) before a predicate has been applied.\nTry using `expect(...).to(...).onFailure(throw: ...`) instead.") { + failsWithErrorMessage("Attempted to call `Expectation.onFailure(throw:) before a matcher has been applied.\nTry using `expect(...).to(...).onFailure(throw: ...`) instead.") { try expect(true).onFailure(throw: MyError.error1) } } diff --git a/Tests/NimbleTests/PredicateTest.swift b/Tests/NimbleTests/PredicateTest.swift index c47201108..6ab3fb431 100644 --- a/Tests/NimbleTests/PredicateTest.swift +++ b/Tests/NimbleTests/PredicateTest.swift @@ -4,28 +4,28 @@ import Nimble import NimbleSharedTestHelpers #endif -final class PredicateTest: XCTestCase { +final class MatcherTest: XCTestCase { func testDefineDefaultMessage() { failsWithErrorMessage("expected to match, got <1>") { - expect(1).to(Predicate.define { _, msg in PredicateResult(status: .fail, message: msg) }) + expect(1).to(Matcher.define { _, msg in MatcherResult(status: .fail, message: msg) }) } } func testDefineNilableDefaultMessage() { failsWithErrorMessage("expected to match, got <1>") { - expect(1).to(Predicate.defineNilable { _, msg in PredicateResult(status: .fail, message: msg) }) + expect(1).to(Matcher.defineNilable { _, msg in MatcherResult(status: .fail, message: msg) }) } } func testSimpleDefaultMessage() { failsWithErrorMessage("expected to match, got <1>") { - expect(1).to(Predicate.simple { _ in .fail }) + expect(1).to(Matcher.simple { _ in .fail }) } } func testSimpleNilableDefaultMessage() { failsWithErrorMessage("expected to match, got <1>") { - expect(1).to(Predicate.simpleNilable { _ in .fail }) + expect(1).to(Matcher.simpleNilable { _ in .fail }) } } } diff --git a/Tests/NimbleTests/SynchronousTest.swift b/Tests/NimbleTests/SynchronousTest.swift index 4c5eeac74..98171f961 100644 --- a/Tests/NimbleTests/SynchronousTest.swift +++ b/Tests/NimbleTests/SynchronousTest.swift @@ -32,19 +32,19 @@ final class SynchronousTest: XCTestCase { } func testToMatchesIfMatcherReturnsTrue() { - expect(1).to(Predicate.simple { _ in .matches }) - expect {1}.to(Predicate.simple { _ in .matches }) + expect(1).to(Matcher.simple { _ in .matches }) + expect {1}.to(Matcher.simple { _ in .matches }) } func testToProvidesActualValueExpression() { var value: Int? - expect(1).to(Predicate.simple { expr in value = try expr.evaluate(); return .matches }) + expect(1).to(Matcher.simple { expr in value = try expr.evaluate(); return .matches }) expect(value).to(equal(1)) } func testToProvidesAMemoizedActualValueExpression() { var callCount = 0 - expect { callCount += 1 }.to(Predicate.simple { expr in + expect { callCount += 1 }.to(Matcher.simple { expr in _ = try expr.evaluate() _ = try expr.evaluate() return .matches @@ -54,7 +54,7 @@ final class SynchronousTest: XCTestCase { func testToProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { var callCount = 0 - expect { callCount += 1 }.to(Predicate.simple { expr in + expect { callCount += 1 }.to(Matcher.simple { expr in expect(callCount).to(equal(0)) _ = try expr.evaluate() return .matches @@ -71,19 +71,19 @@ final class SynchronousTest: XCTestCase { // repeated tests from to() for toNot() func testToNotMatchesIfMatcherReturnsTrue() { - expect(1).toNot(Predicate.simple { _ in .doesNotMatch }) - expect {1}.toNot(Predicate.simple { _ in .doesNotMatch }) + expect(1).toNot(Matcher.simple { _ in .doesNotMatch }) + expect {1}.toNot(Matcher.simple { _ in .doesNotMatch }) } func testToNotProvidesActualValueExpression() { var value: Int? - expect(1).toNot(Predicate.simple { expr in value = try expr.evaluate(); return .doesNotMatch }) + expect(1).toNot(Matcher.simple { expr in value = try expr.evaluate(); return .doesNotMatch }) expect(value).to(equal(1)) } func testToNotProvidesAMemoizedActualValueExpression() { var callCount = 0 - expect { callCount += 1 }.toNot(Predicate.simple { expr in + expect { callCount += 1 }.toNot(Matcher.simple { expr in _ = try expr.evaluate() _ = try expr.evaluate() return .doesNotMatch @@ -93,7 +93,7 @@ final class SynchronousTest: XCTestCase { func testToNotProvidesAMemoizedActualValueExpressionIsEvaluatedAtMatcherControl() { var callCount = 0 - expect { callCount += 1 }.toNot(Predicate.simple { expr in + expect { callCount += 1 }.toNot(Matcher.simple { expr in expect(callCount).to(equal(0)) _ = try expr.evaluate() return .doesNotMatch @@ -103,18 +103,18 @@ final class SynchronousTest: XCTestCase { func testToNegativeMatches() { failsWithErrorMessage("expected to match, got <1>") { - expect(1).to(Predicate.simple { _ in .doesNotMatch }) + expect(1).to(Matcher.simple { _ in .doesNotMatch }) } } func testToNotNegativeMatches() { failsWithErrorMessage("expected to not match, got <1>") { - expect(1).toNot(Predicate.simple { _ in .matches }) + expect(1).toNot(Matcher.simple { _ in .matches }) } } func testNotToMatchesLikeToNot() { - expect(1).notTo(Predicate.simple { _ in .doesNotMatch }) + expect(1).notTo(Matcher.simple { _ in .doesNotMatch }) } // MARK: Assertion chaining diff --git a/Tests/NimbleTests/UserDescriptionTest.swift b/Tests/NimbleTests/UserDescriptionTest.swift index d9dbb35d6..c4345e282 100644 --- a/Tests/NimbleTests/UserDescriptionTest.swift +++ b/Tests/NimbleTests/UserDescriptionTest.swift @@ -12,7 +12,7 @@ final class UserDescriptionTest: XCTestCase { expected to match, got <1> """ ) { - expect(1).to(Predicate.simple { _ in .doesNotMatch }, description: "These aren't equal!") + expect(1).to(Matcher.simple { _ in .doesNotMatch }, description: "These aren't equal!") } } @@ -23,7 +23,7 @@ final class UserDescriptionTest: XCTestCase { expected to not match, got <1> """ ) { - expect(1).notTo(Predicate.simple { _ in .matches }, description: "These aren't equal!") + expect(1).notTo(Matcher.simple { _ in .matches }, description: "These aren't equal!") } } @@ -34,7 +34,7 @@ final class UserDescriptionTest: XCTestCase { expected to not match, got <1> """ ) { - expect(1).toNot(Predicate.simple { _ in .matches }, description: "These aren't equal!") + expect(1).toNot(Matcher.simple { _ in .matches }, description: "These aren't equal!") } }