Skip to content

Commit b5ffcc7

Browse files
authored
Merge branch 'main' into feature/sendable-done
2 parents 6254a6d + 9aaef11 commit b5ffcc7

29 files changed

+495
-90
lines changed

.github/workflows/carthage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ jobs:
1818
- uses: actions/checkout@v4
1919
- uses: ruby/setup-ruby@v1
2020
with:
21-
ruby-version: 2.7
21+
ruby-version: 3.2
2222
bundler-cache: true
2323
- run: ./test carthage

.github/workflows/cocoapods.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ jobs:
1818
- uses: actions/checkout@v4
1919
- uses: ruby/setup-ruby@v1
2020
with:
21-
ruby-version: 2.7
21+
ruby-version: 3.2
2222
bundler-cache: true
2323
- run: ./test podspec

Gemfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# A sample Gemfile
22
source "https://rubygems.org"
33

4-
gem 'cocoapods', '~> 1.15'
5-
gem 'jazzy', '~> 0.14'
4+
gem 'cocoapods', '~> 1.16'
5+
gem 'jazzy', '~> 0.15'

Gemfile.lock

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
11
GEM
22
remote: https://rubygems.org/
33
specs:
4-
CFPropertyList (3.0.6)
4+
CFPropertyList (3.0.7)
5+
base64
6+
nkf
57
rexml
6-
activesupport (7.1.3)
8+
activesupport (7.2.2)
79
base64
10+
benchmark (>= 0.3)
811
bigdecimal
9-
concurrent-ruby (~> 1.0, >= 1.0.2)
12+
concurrent-ruby (~> 1.0, >= 1.3.1)
1013
connection_pool (>= 2.2.5)
1114
drb
1215
i18n (>= 1.6, < 2)
16+
logger (>= 1.4.2)
1317
minitest (>= 5.1)
14-
mutex_m
15-
tzinfo (~> 2.0)
16-
addressable (2.8.6)
17-
public_suffix (>= 2.0.2, < 6.0)
18+
securerandom (>= 0.3)
19+
tzinfo (~> 2.0, >= 2.0.5)
20+
addressable (2.8.7)
21+
public_suffix (>= 2.0.2, < 7.0)
1822
algoliasearch (1.27.5)
1923
httpclient (~> 2.8, >= 2.8.3)
2024
json (>= 1.5.1)
2125
atomos (0.1.3)
2226
base64 (0.2.0)
23-
bigdecimal (3.1.6)
27+
benchmark (0.4.0)
28+
bigdecimal (3.1.8)
2429
claide (1.1.0)
25-
cocoapods (1.15.2)
30+
cocoapods (1.16.2)
2631
addressable (~> 2.8)
2732
claide (>= 1.0.2, < 2.0)
28-
cocoapods-core (= 1.15.2)
33+
cocoapods-core (= 1.16.2)
2934
cocoapods-deintegrate (>= 1.0.3, < 2.0)
3035
cocoapods-downloader (>= 2.1, < 3.0)
3136
cocoapods-plugins (>= 1.0.0, < 2.0)
@@ -39,8 +44,8 @@ GEM
3944
molinillo (~> 0.8.0)
4045
nap (~> 1.0)
4146
ruby-macho (>= 2.3.0, < 3.0)
42-
xcodeproj (>= 1.23.0, < 2.0)
43-
cocoapods-core (1.15.2)
47+
xcodeproj (>= 1.27.0, < 2.0)
48+
cocoapods-core (1.16.2)
4449
activesupport (>= 5.0, < 8)
4550
addressable (~> 2.8)
4651
algoliasearch (~> 1.0)
@@ -60,73 +65,71 @@ GEM
6065
netrc (~> 0.11)
6166
cocoapods-try (1.2.0)
6267
colored2 (3.1.2)
63-
concurrent-ruby (1.2.3)
68+
concurrent-ruby (1.3.4)
6469
connection_pool (2.4.1)
65-
drb (2.2.0)
66-
ruby2_keywords
70+
drb (2.2.1)
6771
escape (0.0.4)
6872
ethon (0.16.0)
6973
ffi (>= 1.15.0)
70-
ffi (1.16.3)
74+
ffi (1.17.0)
7175
fourflusher (2.3.1)
7276
fuzzy_match (2.0.4)
7377
gh_inspector (1.1.3)
7478
httpclient (2.8.3)
75-
i18n (1.14.1)
79+
i18n (1.14.6)
7680
concurrent-ruby (~> 1.0)
77-
jazzy (0.14.4)
81+
jazzy (0.15.3)
7882
cocoapods (~> 1.5)
7983
mustache (~> 1.1)
8084
open4 (~> 1.3)
8185
redcarpet (~> 3.4)
82-
rexml (~> 3.2)
86+
rexml (>= 3.2.7, < 4.0)
8387
rouge (>= 2.0.6, < 5.0)
8488
sassc (~> 2.1)
8589
sqlite3 (~> 1.3)
8690
xcinvoke (~> 0.3.0)
87-
json (2.7.1)
91+
json (2.8.1)
8892
liferaft (0.0.6)
89-
mini_portile2 (2.8.5)
90-
minitest (5.22.2)
93+
logger (1.6.1)
94+
mini_portile2 (2.8.7)
95+
minitest (5.25.1)
9196
molinillo (0.8.0)
9297
mustache (1.1.1)
93-
mutex_m (0.2.0)
94-
nanaimo (0.3.0)
98+
nanaimo (0.4.0)
9599
nap (1.1.0)
96100
netrc (0.11.0)
101+
nkf (0.2.0)
97102
open4 (1.3.4)
98103
public_suffix (4.0.7)
99104
redcarpet (3.6.0)
100-
rexml (3.3.6)
101-
strscan
102-
rouge (4.2.0)
105+
rexml (3.3.9)
106+
rouge (4.4.0)
103107
ruby-macho (2.5.1)
104-
ruby2_keywords (0.0.5)
105108
sassc (2.4.0)
106109
ffi (~> 1.9)
107-
sqlite3 (1.6.9)
110+
securerandom (0.3.1)
111+
sqlite3 (1.7.3)
108112
mini_portile2 (~> 2.8.0)
109-
strscan (3.1.0)
110113
typhoeus (1.4.1)
111114
ethon (>= 0.9.0)
112115
tzinfo (2.0.6)
113116
concurrent-ruby (~> 1.0)
114117
xcinvoke (0.3.0)
115118
liferaft (~> 0.0.6)
116-
xcodeproj (1.25.0)
119+
xcodeproj (1.27.0)
117120
CFPropertyList (>= 2.3.3, < 4.0)
118121
atomos (~> 0.1.3)
119122
claide (>= 1.0.2, < 2.0)
120123
colored2 (~> 3.1)
121-
nanaimo (~> 0.3.0)
122-
rexml (>= 3.3.2, < 4.0)
124+
nanaimo (~> 0.4.0)
125+
rexml (>= 3.3.6, < 4.0)
123126

124127
PLATFORMS
125128
ruby
126129

127130
DEPENDENCIES
128-
cocoapods (~> 1.15)
129-
jazzy (~> 0.14)
131+
cocoapods (~> 1.16)
132+
jazzy (~> 0.15)
130133

131134
BUNDLED WITH
132135
2.1.4

Nimble.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "Nimble"
3-
s.version = "13.5.0"
3+
s.version = "13.7.0"
44
s.summary = "A Matcher Framework for Swift and Objective-C"
55
s.description = <<-DESC
66
Use Nimble to express the expected outcomes of Swift or Objective-C expressions. Inspired by Cedar.

Sources/Nimble/Adapters/AssertionRecorder+Async.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler,
1515
closure: () async throws -> Void) async {
1616
let environment = NimbleEnvironment.activeInstance
1717
let oldRecorder = environment.assertionHandler
18-
_ = NMBExceptionCapture(handler: nil, finally: ({
18+
defer {
1919
environment.assertionHandler = oldRecorder
20-
}))
20+
}
2121
environment.assertionHandler = tempAssertionHandler
2222

2323
do {
2424
try await closure()
25+
} catch is RequireError {
26+
// ignore this
2527
} catch {
2628
let failureMessage = FailureMessage()
2729
failureMessage.stringValue = "unexpected error thrown: <\(error)>"

Sources/Nimble/Adapters/AssertionRecorder.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler,
7979
try capturer.tryBlockThrows {
8080
try closure()
8181
}
82+
} catch is RequireError {
83+
// specifically ignore RequireError, will be caught by the assertion handler.
8284
} catch {
8385
let failureMessage = FailureMessage()
8486
failureMessage.stringValue = "unexpected error thrown: <\(error)>"

Sources/Nimble/Adapters/NimbleSwiftTestingHandler.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import Foundation
22
#if canImport(Testing)
3-
import Testing
3+
// See https://github.com/pointfreeco/swift-snapshot-testing/discussions/901#discussioncomment-10605497
4+
// tl;dr: Swift Testing is not available when using UI tests.
5+
// And apparently `private import` - the preferred way to do this - doesn't work.
6+
// So we use a deprecated approach that does work with this.
7+
@_implementationOnly import Testing
48
#endif
59

610
public class NimbleSwiftTestingHandler: AssertionHandler {

Sources/Nimble/DSL+Require.swift

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ public func requirea<T>(fileID: String = #fileID, file: FileString = #filePath,
216216
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
217217
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
218218
@discardableResult
219-
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
220-
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
219+
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
220+
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
221221
}
222222

223223
/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
@@ -226,8 +226,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
226226
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
227227
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
228228
@discardableResult
229-
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
230-
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
229+
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
230+
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
231231
}
232232

233233
/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
@@ -236,8 +236,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
236236
/// `unwraps` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
237237
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
238238
@discardableResult
239-
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
240-
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
239+
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
240+
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
241241
}
242242

243243
/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
@@ -246,8 +246,8 @@ public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, l
246246
/// `unwraps` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
247247
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
248248
@discardableResult
249-
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
250-
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
249+
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
250+
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
251251
}
252252

253253
/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
@@ -256,8 +256,8 @@ public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, l
256256
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
257257
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
258258
@discardableResult
259-
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @escaping () async throws -> T?) async throws -> T {
260-
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil())
259+
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @escaping () async throws -> T?) async throws -> T {
260+
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil(), description: description)
261261
}
262262

263263
/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
@@ -266,8 +266,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
266266
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
267267
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
268268
@discardableResult
269-
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: () -> (() async throws -> T?)) async throws -> T {
270-
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
269+
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: () -> (() async throws -> T?)) async throws -> T {
270+
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
271271
}
272272

273273
/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
@@ -276,8 +276,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
276276
/// `unwrapa` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
277277
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
278278
@discardableResult
279-
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure @escaping () async throws -> T?) async throws -> T {
280-
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil())
279+
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure @escaping () async throws -> T?) async throws -> T {
280+
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil(), description: description)
281281
}
282282

283283
/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
@@ -286,6 +286,20 @@ public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, l
286286
/// `unwrapa` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
287287
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
288288
@discardableResult
289-
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure () -> (() async throws -> T?)) async throws -> T {
290-
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
289+
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure () -> (() async throws -> T?)) async throws -> T {
290+
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
291+
}
292+
293+
/// Always fails the test and throw an error to prevent further test execution.
294+
///
295+
/// - Parameter message: A custom message to use in place of the default one.
296+
/// - Parameter customError: A custom error to throw in place of a ``RequireError``.
297+
public func requireFail(_ message: String? = nil, customError: Error? = nil, fileID: String = #fileID, filePath: FileString = #filePath, line: UInt = #line, column: UInt = #column) throws {
298+
let location = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column)
299+
let handler = NimbleEnvironment.activeInstance.assertionHandler
300+
301+
let msg = message ?? "requireFail() always fails"
302+
handler.assert(false, message: FailureMessage(stringValue: msg), location: location)
303+
304+
throw customError ?? RequireError(message: msg, location: location)
291305
}

Sources/Nimble/DSL+Wait.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public class NMBWait: NSObject {
127127

128128
internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: NimbleTimeInterval) -> String {
129129
// swiftlint:disable:next line_length
130-
return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive (\(leeway.description) is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run."
130+
return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive. (\(leeway.description) is allowed after the wait times out) Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped the run loop which may cause future failures in test runs."
131131
}
132132

133133
/// Wait asynchronously until the done closure is called or the timeout has been reached.

0 commit comments

Comments
 (0)