From e4c5d497c210cb3011063ca60d16bd458ee5510f Mon Sep 17 00:00:00 2001 From: Rachel Brindle Date: Mon, 25 Sep 2023 17:02:33 -0700 Subject: [PATCH] Rename Predicate to Matcher Because I couldn't think of a better name, This re-uses the name of the old Matcher API (removed since Nimble 10.0). This change is due to the 2023 Apple Platforms release renaming NSPredicate to Predicate, which causes friction for developers creating custom matchers. --- Nimble.xcodeproj/project.pbxproj | 40 +-- README.md | 144 ++++---- Sources/Nimble/Adapters/NMBExpectation.swift | 94 ++--- Sources/Nimble/AsyncExpression.swift | 2 +- Sources/Nimble/Expectation.swift | 76 ++-- Sources/Nimble/Matchers/AllPass.swift | 56 +-- Sources/Nimble/Matchers/AsyncAllPass.swift | 42 +-- Sources/Nimble/Matchers/AsyncMatcher.swift | 115 +++++++ Sources/Nimble/Matchers/AsyncPredicate.swift | 117 ------- Sources/Nimble/Matchers/BeAKindOf.swift | 24 +- Sources/Nimble/Matchers/BeAnInstanceOf.swift | 24 +- Sources/Nimble/Matchers/BeCloseTo.swift | 44 +-- Sources/Nimble/Matchers/BeEmpty.swift | 62 ++-- Sources/Nimble/Matchers/BeGreaterThan.swift | 18 +- .../Matchers/BeGreaterThanOrEqualTo.swift | 18 +- Sources/Nimble/Matchers/BeIdenticalTo.swift | 14 +- Sources/Nimble/Matchers/BeLessThan.swift | 18 +- .../Nimble/Matchers/BeLessThanOrEqual.swift | 18 +- Sources/Nimble/Matchers/BeLogical.swift | 40 +-- Sources/Nimble/Matchers/BeNil.swift | 14 +- Sources/Nimble/Matchers/BeResult.swift | 16 +- Sources/Nimble/Matchers/BeVoid.swift | 6 +- Sources/Nimble/Matchers/BeWithin.swift | 12 +- Sources/Nimble/Matchers/BeginWith.swift | 24 +- Sources/Nimble/Matchers/BeginWithPrefix.swift | 22 +- Sources/Nimble/Matchers/Contain.swift | 56 +-- .../Matchers/ContainElementSatisfying.swift | 56 +-- Sources/Nimble/Matchers/ElementsEqual.swift | 22 +- Sources/Nimble/Matchers/EndWith.swift | 26 +- Sources/Nimble/Matchers/Equal+Tuple.swift | 10 +- .../Nimble/Matchers/Equal+TupleArray.swift | 12 +- Sources/Nimble/Matchers/Equal.swift | 56 +-- Sources/Nimble/Matchers/HaveCount.swift | 24 +- Sources/Nimble/Matchers/Match.swift | 12 +- Sources/Nimble/Matchers/MatchError.swift | 18 +- Sources/Nimble/Matchers/Matcher.swift | 324 ++++++++++++++++++ .../Nimble/Matchers/PostNotification.swift | 20 +- Sources/Nimble/Matchers/Predicate.swift | 289 ---------------- Sources/Nimble/Matchers/RaisesException.swift | 42 +-- Sources/Nimble/Matchers/SatisfyAllOf.swift | 58 ++-- Sources/Nimble/Matchers/SatisfyAnyOf.swift | 58 ++-- Sources/Nimble/Matchers/ThrowAssertion.swift | 8 +- Sources/Nimble/Matchers/ThrowError.swift | 38 +- Sources/Nimble/Matchers/ToSucceed.swift | 10 +- Sources/Nimble/Polling+AsyncAwait.swift | 142 ++++---- Sources/Nimble/Polling.swift | 70 ++-- Sources/NimbleObjectiveC/DSL.m | 104 +++--- Sources/NimbleObjectiveC/include/DSL.h | 134 ++++---- .../ObjCContainElementSatisfyingTest.m | 2 +- Tests/NimbleTests/Helpers/AsyncHelpers.swift | 22 +- .../Matchers/AlwaysFailMatcher.swift | 12 +- .../Matchers/AsyncAllPassTest.swift | 18 +- .../Matchers/AsyncPredicateTest.swift | 18 +- .../Matchers/BeginWithPrefixTest.swift | 2 +- .../ContainElementSatisfyingTest.swift | 12 +- .../Matchers/ElementsEqualTest.swift | 2 +- .../Matchers/SatisfyAllOfTest.swift | 8 +- .../Matchers/SatisfyAnyOfTest.swift | 6 +- Tests/NimbleTests/OnFailureThrowsTest.swift | 2 +- Tests/NimbleTests/PredicateTest.swift | 10 +- Tests/NimbleTests/SynchronousTest.swift | 26 +- Tests/NimbleTests/UserDescriptionTest.swift | 6 +- 62 files changed, 1414 insertions(+), 1381 deletions(-) create mode 100644 Sources/Nimble/Matchers/AsyncMatcher.swift delete mode 100644 Sources/Nimble/Matchers/AsyncPredicate.swift create mode 100644 Sources/Nimble/Matchers/Matcher.swift delete mode 100644 Sources/Nimble/Matchers/Predicate.swift 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..10b200ff7 --- /dev/null +++ b/Sources/Nimble/Matchers/AsyncMatcher.swift @@ -0,0 +1,115 @@ +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) + } +} + +/// 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 6f604ae8c..83dbd4fed 100644 --- a/Sources/Nimble/Matchers/PostNotification.swift +++ b/Sources/Nimble/Matchers/PostNotification.swift @@ -46,16 +46,16 @@ internal class NotificationCollector { private let mainThread = pthread_self() 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 @@ -77,7 +77,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) } @@ -86,19 +86,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!") } }