@@ -15,7 +15,19 @@ extension AsyncDefaults {
15
15
public static var PollInterval : TimeInterval = 0.01
16
16
}
17
17
18
- private func async < T> ( style: ExpectationStyle , predicate: Predicate < T > , timeout: DispatchTimeInterval , poll: DispatchTimeInterval , fnName: String ) -> Predicate < T > {
18
+ private enum AsyncMatchStyle {
19
+ case eventually, never
20
+ }
21
+
22
+ // swiftlint:disable:next function_parameter_count
23
+ private func async < T> (
24
+ style: ExpectationStyle ,
25
+ matchStyle: AsyncMatchStyle ,
26
+ predicate: Predicate < T > ,
27
+ timeout: DispatchTimeInterval ,
28
+ poll: DispatchTimeInterval ,
29
+ fnName: String
30
+ ) -> Predicate < T > {
19
31
return Predicate { actualExpression in
20
32
let uncachedExpression = actualExpression. withoutCaching ( )
21
33
let fnName = " expect(...). \( fnName) (...) "
@@ -30,10 +42,24 @@ private func async<T>(style: ExpectationStyle, predicate: Predicate<T>, timeout:
30
42
return lastPredicateResult!. toBoolean ( expectation: style)
31
43
}
32
44
switch result {
33
- case . completed: return lastPredicateResult!
45
+ case . completed:
46
+ switch matchStyle {
47
+ case . eventually:
48
+ return lastPredicateResult!
49
+ case . never:
50
+ return PredicateResult (
51
+ status: . fail,
52
+ message: lastPredicateResult? . message ?? . fail( " matched the predicate when it shouldn't have " )
53
+ )
54
+ }
34
55
case . timedOut:
35
- let message = lastPredicateResult? . message ?? . fail( " timed out before returning a value " )
36
- return PredicateResult ( status: . fail, message: message)
56
+ switch matchStyle {
57
+ case . eventually:
58
+ let message = lastPredicateResult? . message ?? . fail( " timed out before returning a value " )
59
+ return PredicateResult ( status: . fail, message: message)
60
+ case . never:
61
+ return PredicateResult ( status: . doesNotMatch, message: . expectedTo( " never match the predicate " ) )
62
+ }
37
63
case let . errorThrown( error) :
38
64
return PredicateResult ( status: . fail, message: . fail( " unexpected error thrown: < \( error) > " ) )
39
65
case let . raisedException( exception) :
@@ -68,7 +94,14 @@ extension Expectation {
68
94
let ( pass, msg) = execute (
69
95
expression,
70
96
. toMatch,
71
- async ( style: . toMatch, predicate: predicate, timeout: timeout, poll: pollInterval, fnName: " toEventually " ) ,
97
+ async (
98
+ style: . toMatch,
99
+ matchStyle: . eventually,
100
+ predicate: predicate,
101
+ timeout: timeout,
102
+ poll: pollInterval,
103
+ fnName: " toEventually "
104
+ ) ,
72
105
to: " to eventually " ,
73
106
description: description,
74
107
captureExceptions: false
@@ -90,6 +123,7 @@ extension Expectation {
90
123
. toNotMatch,
91
124
async (
92
125
style: . toNotMatch,
126
+ matchStyle: . eventually,
93
127
predicate: predicate,
94
128
timeout: timeout,
95
129
poll: pollInterval,
@@ -113,4 +147,43 @@ extension Expectation {
113
147
public func toNotEventually( _ predicate: Predicate < T > , timeout: DispatchTimeInterval = AsyncDefaults . timeout, pollInterval: DispatchTimeInterval = AsyncDefaults . pollInterval, description: String ? = nil ) {
114
148
return toEventuallyNot ( predicate, timeout: timeout, pollInterval: pollInterval, description: description)
115
149
}
150
+
151
+ /// Tests the actual value using a matcher to never match by checking
152
+ /// continuously at each pollInterval until the timeout is reached.
153
+ ///
154
+ /// @discussion
155
+ /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function
156
+ /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior.
157
+ public func toNever( _ predicate: Predicate < T > , until: DispatchTimeInterval = AsyncDefaults . timeout, pollInterval: DispatchTimeInterval = AsyncDefaults . pollInterval, description: String ? = nil ) {
158
+ nimblePrecondition ( expression. isClosure, " NimbleInternalError " , toEventuallyRequiresClosureError. stringValue)
159
+
160
+ let ( pass, msg) = execute (
161
+ expression,
162
+ . toNotMatch,
163
+ async (
164
+ style: . toMatch,
165
+ matchStyle: . never,
166
+ predicate: predicate,
167
+ timeout: until,
168
+ poll: pollInterval,
169
+ fnName: " toNever "
170
+ ) ,
171
+ to: " to never " ,
172
+ description: description,
173
+ captureExceptions: false
174
+ )
175
+ verify ( pass, msg)
176
+ }
177
+
178
+ /// Tests the actual value using a matcher to never match by checking
179
+ /// continuously at each pollInterval until the timeout is reached.
180
+ ///
181
+ /// Alias of toNever()
182
+ ///
183
+ /// @discussion
184
+ /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function
185
+ /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior.
186
+ public func neverTo( _ predicate: Predicate < T > , until: DispatchTimeInterval = AsyncDefaults . timeout, pollInterval: DispatchTimeInterval = AsyncDefaults . pollInterval, description: String ? = nil ) {
187
+ return toNever ( predicate, until: until, pollInterval: pollInterval, description: description)
188
+ }
116
189
}
0 commit comments