@@ -48,6 +48,43 @@ private func async<T>(style: ExpectationStyle, predicate: Predicate<T>, timeout:
48
48
}
49
49
}
50
50
51
+ private func toNeverPredicate< T> ( predicate: Predicate < T > , timeout: DispatchTimeInterval , poll: DispatchTimeInterval , fnName: String ) -> Predicate < T > {
52
+ return Predicate { actualExpression in
53
+ let uncachedExpression = actualExpression. withoutCaching ( )
54
+ let fnName = " expect(...). \( fnName) (...) "
55
+ var lastPredicateResult : PredicateResult ?
56
+ let result = pollBlock (
57
+ pollInterval: poll,
58
+ timeoutInterval: timeout,
59
+ file: actualExpression. location. file,
60
+ line: actualExpression. location. line,
61
+ fnName: fnName) {
62
+ lastPredicateResult = try predicate. satisfies ( uncachedExpression)
63
+ return lastPredicateResult!. toBoolean ( expectation: . toMatch)
64
+ }
65
+ switch result {
66
+ case . completed:
67
+ return PredicateResult (
68
+ status: . fail,
69
+ message: lastPredicateResult? . message ?? . fail( " matched the predicate when it shouldn't have " )
70
+ )
71
+ case . timedOut:
72
+ return PredicateResult ( status: . doesNotMatch, message: . expectedTo( " never match the predicate " ) )
73
+ case let . errorThrown( error) :
74
+ return PredicateResult ( status: . fail, message: . fail( " unexpected error thrown: < \( error) > " ) )
75
+ case let . raisedException( exception) :
76
+ return PredicateResult ( status: . fail, message: . fail( " unexpected exception raised: \( exception) " ) )
77
+ case . blockedRunLoop:
78
+ // swiftlint:disable:next line_length
79
+ let message = lastPredicateResult? . message. appended ( message: " (timed out, but main run loop was unresponsive). " ) ??
80
+ . fail( " main run loop was unresponsive " )
81
+ return PredicateResult ( status: . fail, message: message)
82
+ case . incomplete:
83
+ internalError ( " Reached .incomplete state for \( fnName) (...). " )
84
+ }
85
+ }
86
+ }
87
+
51
88
private let toEventuallyRequiresClosureError = FailureMessage (
52
89
stringValue: """
53
90
expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )
@@ -113,4 +150,23 @@ extension Expectation {
113
150
public func toNotEventually( _ predicate: Predicate < T > , timeout: DispatchTimeInterval = AsyncDefaults . timeout, pollInterval: DispatchTimeInterval = AsyncDefaults . pollInterval, description: String ? = nil ) {
114
151
return toEventuallyNot ( predicate, timeout: timeout, pollInterval: pollInterval, description: description)
115
152
}
153
+
154
+ public func toNever( _ predicate: Predicate < T > , until: DispatchTimeInterval = AsyncDefaults . timeout, pollInterval: DispatchTimeInterval = AsyncDefaults . pollInterval, description: String ? = nil ) {
155
+ nimblePrecondition ( expression. isClosure, " NimbleInternalError " , toEventuallyRequiresClosureError. stringValue)
156
+
157
+
158
+ let ( pass, msg) = execute (
159
+ expression,
160
+ . toNotMatch,
161
+ toNeverPredicate ( predicate: predicate, timeout: until, poll: pollInterval, fnName: " toNever " ) ,
162
+ to: " to never " ,
163
+ description: description,
164
+ captureExceptions: false
165
+ )
166
+ verify ( pass, msg)
167
+ }
168
+
169
+ public func neverTo( _ predicate: Predicate < T > , until: DispatchTimeInterval = AsyncDefaults . timeout, pollInterval: DispatchTimeInterval = AsyncDefaults . pollInterval, description: String ? = nil ) {
170
+ return toNever ( predicate, until: until, pollInterval: pollInterval, description: description)
171
+ }
116
172
}
0 commit comments