Compare commits
226 Commits
0.3.1
..
async-fixes
| Author | SHA1 | Date | |
|---|---|---|---|
| 76d9dc17af | |||
| 8ceb0216a0 | |||
| db41634631 | |||
| 15843b5fe8 | |||
| 4241b484b2 | |||
| 92bf0b96b6 | |||
| 457dff7c01 | |||
| c90e9c4976 | |||
| 649bb01e89 | |||
| 965f7dbbe1 | |||
| 536414bd44 | |||
| b7d5db0a55 | |||
| d0907b16c8 | |||
| 60eb4b4676 | |||
| 4ec9e9c2a2 | |||
| b2efdf4d65 | |||
| d9badfec9b | |||
| 4d0f29adf6 | |||
| f817bc5840 | |||
| 5755b70e1b | |||
| 83ac2af5d6 | |||
| a2f001a968 | |||
| 9390064581 | |||
| 7a45ee9e47 | |||
| 17a4b18333 | |||
| ad01101d3c | |||
| d1bbc94bdd | |||
| fb5a8dde6c | |||
| 9b71040f43 | |||
| 5e50ea48d6 | |||
| 92a804e9e4 | |||
| af4635d047 | |||
| addebef7f9 | |||
| 46022ef0d6 | |||
| 386dc5202c | |||
| 17166093c2 | |||
| c06b8ce64c | |||
| aab8a2302b | |||
| 5c8c83f914 | |||
| ef2d9f5a90 | |||
| 08ebb473f2 | |||
| d32a041159 | |||
| 1057a7fca6 | |||
| cee2be50e2 | |||
| 8161c3cf02 | |||
| bb0f301383 | |||
| 9da1347d12 | |||
| 4a512c6aa0 | |||
| f8026d0915 | |||
| 9d6534f2c9 | |||
| c55c25686c | |||
| 852578c914 | |||
| 0ae0427556 | |||
| 9170be5e36 | |||
| 3930096357 | |||
| 9e8ebdfca1 | |||
| 31f4745bae | |||
| 4a8af1bce3 | |||
| 8e6b72613d | |||
| ae760c4cac | |||
| b3856e0a7a | |||
| 757e5f476c | |||
| 1f5eae407d | |||
| 29660371c9 | |||
| c2530a0193 | |||
| 6804cf5163 | |||
| 6ea2e082b0 | |||
| b6b4599ef5 | |||
| 3ccf9ed20e | |||
| d6eb187788 | |||
| 1febb782d8 | |||
| c4c6f42ac0 | |||
| d8b4466629 | |||
| cb9dec49b2 | |||
| 7e46a91e73 | |||
| 8ca4a873a5 | |||
| 3f54de70bc | |||
| cae549a401 | |||
| 85fecef45e | |||
| e2375f7a82 | |||
| 3c8402503b | |||
| 4c46137498 | |||
| a4e023d75f | |||
| fe549a522a | |||
| 6cc0638a70 | |||
| 34c1f493ae | |||
| 30750a0c81 | |||
| e57cf9d2e5 | |||
| 0eeedc6467 | |||
| e96cbf6337 | |||
| debc1c519f | |||
| 09bec023a9 | |||
| 44e022389c | |||
| 05ca97b8eb | |||
| f6ff2b4cc0 | |||
| 9e3f5c0291 | |||
| 8ba40ca45f | |||
| 9919bde9fe | |||
| 3ba62d8657 | |||
| 0f283b171f | |||
| f6b5e30e85 | |||
| 04296fa681 | |||
| 252ed947d2 | |||
| b5fdb5c54e | |||
| 1b4c0b0d3b | |||
| e0aa2a09a9 | |||
| ab0eb4f8eb | |||
| 99e7c65bbc | |||
| 9072259631 | |||
| eb9af1007a | |||
| 69d3a9c0c0 | |||
| 43821c68a9 | |||
| 610ff4c7f3 | |||
| 1fc533214f | |||
| 71f22c3e25 | |||
| 8a5e6d18cc | |||
| a7f53bfec9 | |||
| 7b10f0476b | |||
| 618da75339 | |||
| 0694f5d8a0 | |||
| 61268b45eb | |||
| 962e64fe24 | |||
| 0f9b2656a1 | |||
| 5e871fc7e2 | |||
| fdf8fc9482 | |||
| a9eb713964 | |||
| a0efa5f408 | |||
| 74cafd4c42 | |||
| 53780ac03e | |||
| ba438c8ede | |||
| 06cb6577c1 | |||
| 5a0f379275 | |||
| 11e793f963 | |||
| d094067ac7 | |||
| 4bacd5f1ff | |||
| 73089bbe8b | |||
| b4f919e8f4 | |||
| 7e33789644 | |||
| 843ba9f450 | |||
| 4305110867 | |||
| cd43ecc6f9 | |||
| 274377af3f | |||
| ef41885eaf | |||
| 21da2da43b | |||
| 336d5586bf | |||
| e917867220 | |||
| 7897a79a79 | |||
| 43824a9700 | |||
| 460af7ab1e | |||
| 670bf0e09e | |||
| 238c02db12 | |||
| 20190152eb | |||
| 9e6683674b | |||
| b27332aafb | |||
| 18688ab766 | |||
| 6835738754 | |||
| 9f05915993 | |||
| 2f9a5481ff | |||
| 079f8c8ce1 | |||
| 720b4739b4 | |||
| 2b150b5652 | |||
| 4adc84aaf3 | |||
| 76f2d22e7a | |||
| 3c409200ee | |||
| b44777fcd7 | |||
| d682fd9468 | |||
| 10e6c46c18 | |||
| 89715d9d38 | |||
| 99bd43769c | |||
| ce5e5e886f | |||
| 521141ba0d | |||
| d3d354d5bd | |||
| 664c56b79c | |||
| 7bb83e87e0 | |||
| 6cad96b4f8 | |||
| 50a58c2306 | |||
| 2dbaf3d4dc | |||
| 851d8704d9 | |||
| 7c4dc27868 | |||
| 0df6386786 | |||
| b58c40e7c3 | |||
| 77a3206633 | |||
| d7c8c0fc0d | |||
| e8354dfdfb | |||
| 2e9c8733fc | |||
| 97353b98d9 | |||
| 0e3e8ec5b9 | |||
| f8dbe9d312 | |||
| 9f4ef3aa9e | |||
| 4097b66aac | |||
| 454e036449 | |||
| 8fb3b8424d | |||
| 731863a900 | |||
| 45582b3f43 | |||
| 534b62da9e | |||
| e3cb3c4a51 | |||
| a0e05a885a | |||
| 1a13887a65 | |||
| da6e83f64a | |||
| 0f2bfb3e79 | |||
| eabeca93a0 | |||
| 6a93840463 | |||
| 1261f88803 | |||
| 6239d6d5e6 | |||
| a63771a040 | |||
| 7d27ef286f | |||
| bf0d3a79dd | |||
| 22dec9d6b1 | |||
| b7be6338c6 | |||
| 97b70d056a | |||
| c9bce64bc1 | |||
| dafcbdfe3e | |||
| 24666c3ab5 | |||
| 8de5d678b8 | |||
| 70a55f22e0 | |||
| e180fc7a72 | |||
| 9008c6f9a0 | |||
| d49c522032 | |||
| 7681d5d983 | |||
| 8b1e57b3c0 | |||
| 1c4f5ec738 | |||
| d2ed064295 | |||
| 0d4060eb68 | |||
| 15a8bc4abd | |||
| da5b7702f7 | |||
| 0066a4121c |
@@ -0,0 +1,2 @@
|
||||
ignore:
|
||||
- "Example/.*"
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
If needed, include code examples for the problem or steps to reproduce.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Version [e.g. 0.7.0]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6, Simulator iPhone6 ...]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Version [e.g. 0.7.0]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution or feature you would like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
+1
-1
@@ -1 +1 @@
|
||||
4.0
|
||||
4.2
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
# references:
|
||||
# * http://www.objc.io/issue-6/travis-ci.html
|
||||
# * https://github.com/supermarin/xcpretty#usage
|
||||
|
||||
osx_image: xcode9.2
|
||||
language: objective-c
|
||||
cache: cocoapods
|
||||
podfile: Example/Podfile
|
||||
before_install:
|
||||
- gem install cocoapods # Since Travis is not always on latest version
|
||||
- pod install --project-directory=Example
|
||||
script:
|
||||
- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/SwiftAudio.xcworkspace -scheme SwiftAudio-Example -sdk iphonesimulator11.2 -destination "OS=11.2,name=iPhone X" | xcpretty
|
||||
- pod lib lint
|
||||
+2
-2
@@ -7,8 +7,8 @@ target 'SwiftAudio_Example' do
|
||||
target 'SwiftAudio_Tests' do
|
||||
inherit! :search_paths
|
||||
|
||||
pod 'Quick'
|
||||
pod 'Nimble'
|
||||
pod 'Quick', '~> 2.0.0'
|
||||
pod 'Nimble' , '~> 8.0.0'
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
+16
-11
@@ -1,22 +1,27 @@
|
||||
PODS:
|
||||
- Nimble (7.0.3)
|
||||
- Quick (1.2.0)
|
||||
- SwiftAudio (0.1.0)
|
||||
- Nimble (8.0.1)
|
||||
- Quick (2.0.0)
|
||||
- SwiftAudio (0.7.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Nimble
|
||||
- Quick
|
||||
- Nimble (~> 8.0.0)
|
||||
- Quick (~> 2.0.0)
|
||||
- SwiftAudio (from `../`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- Nimble
|
||||
- Quick
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
SwiftAudio:
|
||||
:path: ../
|
||||
:path: "../"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Nimble: 7f5a9c447a33002645a071bddafbfb24ea70e0ac
|
||||
Quick: 58d203b1c5e27fff7229c4c1ae445ad7069a7a08
|
||||
SwiftAudio: a3a2d2c800a7d47687dcfd7c35ab757462b75856
|
||||
Nimble: 45f786ae66faa9a709624227fae502db55a8bdd0
|
||||
Quick: ce1276c7c27ba2da3cb2fd0cde053c3648b3b22d
|
||||
SwiftAudio: a7bb22e98fd48fd908f7ffca992166e0057ce8ea
|
||||
|
||||
PODFILE CHECKSUM: 4725c63cba8dedecdf397c1768967bd269bf4532
|
||||
PODFILE CHECKSUM: 08ea4075437f8ff3c4f84ed70827a8132461373f
|
||||
|
||||
COCOAPODS: 1.3.1
|
||||
COCOAPODS: 1.5.3
|
||||
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "SwiftAudio",
|
||||
"version": "0.1.0",
|
||||
"summary": "A short description of SwiftAudio.",
|
||||
"description": "TODO: Add long description of the pod here.",
|
||||
"homepage": "https://github.com/Jørgen Henrichsen/SwiftAudio",
|
||||
"version": "0.7.2",
|
||||
"summary": "Easy audio streaming for iOS",
|
||||
"description": "SwiftAudio is an audio player written in Swift, making it simpler to work with audio playback from streams and files.",
|
||||
"homepage": "https://github.com/jorgenhenrichsen/SwiftAudio",
|
||||
"license": {
|
||||
"type": "MIT",
|
||||
"file": "LICENSE"
|
||||
@@ -12,8 +12,8 @@
|
||||
"Jørgen Henrichsen": "jh.henrichs@gmail.com"
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/Jørgen Henrichsen/SwiftAudio.git",
|
||||
"tag": "0.1.0"
|
||||
"git": "https://github.com/jorgenhenrichsen/SwiftAudio.git",
|
||||
"tag": "0.7.2"
|
||||
},
|
||||
"platforms": {
|
||||
"ios": "10.0"
|
||||
|
||||
Generated
+16
-11
@@ -1,22 +1,27 @@
|
||||
PODS:
|
||||
- Nimble (7.0.3)
|
||||
- Quick (1.2.0)
|
||||
- SwiftAudio (0.1.0)
|
||||
- Nimble (8.0.1)
|
||||
- Quick (2.0.0)
|
||||
- SwiftAudio (0.7.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Nimble
|
||||
- Quick
|
||||
- Nimble (~> 8.0.0)
|
||||
- Quick (~> 2.0.0)
|
||||
- SwiftAudio (from `../`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- Nimble
|
||||
- Quick
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
SwiftAudio:
|
||||
:path: ../
|
||||
:path: "../"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Nimble: 7f5a9c447a33002645a071bddafbfb24ea70e0ac
|
||||
Quick: 58d203b1c5e27fff7229c4c1ae445ad7069a7a08
|
||||
SwiftAudio: a3a2d2c800a7d47687dcfd7c35ab757462b75856
|
||||
Nimble: 45f786ae66faa9a709624227fae502db55a8bdd0
|
||||
Quick: ce1276c7c27ba2da3cb2fd0cde053c3648b3b22d
|
||||
SwiftAudio: a7bb22e98fd48fd908f7ffca992166e0057ce8ea
|
||||
|
||||
PODFILE CHECKSUM: 4725c63cba8dedecdf397c1768967bd269bf4532
|
||||
PODFILE CHECKSUM: 08ea4075437f8ff3c4f84ed70827a8132461373f
|
||||
|
||||
COCOAPODS: 1.3.1
|
||||
COCOAPODS: 1.5.3
|
||||
|
||||
Generated
Vendored
-2
@@ -25,13 +25,11 @@ import CwlCatchExceptionSupport
|
||||
#endif
|
||||
|
||||
private func catchReturnTypeConverter<T: NSException>(_ type: T.Type, block: () -> Void) -> T? {
|
||||
// Get the type from an *instance*, instead of a receiving the type directly
|
||||
return catchExceptionOfKind(type, block) as? T
|
||||
}
|
||||
|
||||
extension NSException {
|
||||
public static func catchException(in block: () -> Void) -> Self? {
|
||||
// Use a dummy instance of Self to provide the type
|
||||
return catchReturnTypeConverter(self, block: block)
|
||||
}
|
||||
}
|
||||
|
||||
Generated
Vendored
+4
-2
@@ -97,8 +97,9 @@ import Foundation
|
||||
// Request the next mach message from the port
|
||||
request.Head.msgh_local_port = context.currentExceptionPort
|
||||
request.Head.msgh_size = UInt32(MemoryLayout<request_mach_exception_raise_t>.size)
|
||||
let requestSize = request.Head.msgh_size
|
||||
try kernCheck { request.withMsgHeaderPointer { requestPtr in
|
||||
mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, request.Head.msgh_size, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL))
|
||||
mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, requestSize, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL))
|
||||
} }
|
||||
|
||||
// Prepare the reply structure
|
||||
@@ -121,8 +122,9 @@ import Foundation
|
||||
}
|
||||
|
||||
// Send the reply
|
||||
let replySize = reply.Head.msgh_size
|
||||
try kernCheck { reply.withMsgHeaderPointer { replyPtr in
|
||||
mach_msg(replyPtr, MACH_SEND_MSG, reply.Head.msgh_size, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL))
|
||||
mach_msg(replyPtr, MACH_SEND_MSG, replySize, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL))
|
||||
} }
|
||||
} catch let error as NSError where (error.domain == NSMachErrorDomain && (error.code == Int(MACH_RCV_PORT_CHANGED) || error.code == Int(MACH_RCV_INVALID_NAME))) {
|
||||
// Port was already closed before we started or closed while we were listening.
|
||||
|
||||
Generated
Vendored
+2
@@ -20,6 +20,8 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern bool _swift_reportFatalErrorsToDebugger;
|
||||
|
||||
//! Project version number for CwlUtils.
|
||||
FOUNDATION_EXPORT double CwlPreconditionTestingVersionNumber;
|
||||
|
||||
|
||||
Generated
+48
-63
@@ -4,6 +4,7 @@
|
||||
[](https://cocoapods.org/pods/Nimble)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://cocoapods.org/pods/Nimble)
|
||||
[](https://houndci.com)
|
||||
|
||||
Use Nimble to express the expected outcomes of Swift
|
||||
or Objective-C expressions. Inspired by
|
||||
@@ -226,9 +227,9 @@ exception once evaluated:
|
||||
// that Nimble will catch.
|
||||
// (see https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)
|
||||
let exception = NSException(
|
||||
name: NSInternalInconsistencyException,
|
||||
reason: "Not enough fish in the sea.",
|
||||
userInfo: ["something": "is fishy"])
|
||||
name: NSInternalInconsistencyException,
|
||||
reason: "Not enough fish in the sea.",
|
||||
userInfo: ["something": "is fishy"])
|
||||
expect { exception.raise() }.to(raiseException())
|
||||
|
||||
// Also, you can customize raiseException to be more specific
|
||||
@@ -306,8 +307,7 @@ In Nimble, it's easy to make expectations on values that are updated
|
||||
asynchronously. Just use `toEventually` or `toEventuallyNot`:
|
||||
|
||||
```swift
|
||||
// Swift 3.0 and later
|
||||
|
||||
// Swift
|
||||
DispatchQueue.main.async {
|
||||
ocean.add("dolphins")
|
||||
ocean.add("whales")
|
||||
@@ -316,17 +316,6 @@ expect(ocean).toEventually(contain("dolphins", "whales"))
|
||||
```
|
||||
|
||||
|
||||
```swift
|
||||
// Swift 2.3 and earlier
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
ocean.add("dolphins")
|
||||
ocean.add("whales")
|
||||
}
|
||||
expect(ocean).toEventually(contain("dolphins", "whales"))
|
||||
```
|
||||
|
||||
|
||||
```objc
|
||||
// Objective-C
|
||||
|
||||
@@ -714,7 +703,7 @@ expect(actual) ≈ expected
|
||||
expect(actual) ≈ (expected, delta)
|
||||
|
||||
```
|
||||
(Type Option-x to get ≈ on a U.S. keyboard)
|
||||
(Type <kbd>option</kbd>+<kbd>x</kbd> to get `≈` on a U.S. keyboard)
|
||||
|
||||
The former version uses the default delta of 0.0001. Here is yet another way to do this:
|
||||
|
||||
@@ -725,7 +714,7 @@ expect(actual) ≈ expected ± delta
|
||||
expect(actual) == expected ± delta
|
||||
|
||||
```
|
||||
(Type Option-Shift-= to get ± on a U.S. keyboard)
|
||||
(Type <kbd>option</kbd>+<kbd>shift</kbd>+<kbd>=</kbd> to get `±` on a U.S. keyboard)
|
||||
|
||||
If you are comparing arrays of floating point numbers, you'll find the following useful:
|
||||
|
||||
@@ -857,11 +846,7 @@ Notes:
|
||||
|
||||
## Swift Error Handling
|
||||
|
||||
If you're using Swift 2.0 or newer, you can use the `throwError` matcher to check if an error is thrown.
|
||||
|
||||
Note:
|
||||
The following code sample references the `Swift.Error` protocol.
|
||||
This is `Swift.ErrorProtocol` in versions of Swift prior to version 3.0.
|
||||
You can use the `throwError` matcher to check if an error is thrown.
|
||||
|
||||
```swift
|
||||
// Swift
|
||||
@@ -1043,10 +1028,10 @@ let turtles: [Turtle] = functionThatReturnsSomeTurtlesInAnyOrder()
|
||||
// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]:
|
||||
|
||||
expect(turtles).to(containElementSatisfying({ turtle in
|
||||
return turtle.color == "green"
|
||||
return turtle.color == "green"
|
||||
}))
|
||||
expect(turtles).to(containElementSatisfying({ turtle in
|
||||
return turtle.color == "blue"
|
||||
return turtle.color == "blue"
|
||||
}, "that is a turtle with color 'blue'"))
|
||||
|
||||
// The second matcher will incorporate the provided string in the error message
|
||||
@@ -1069,10 +1054,10 @@ NSArray<Turtle *> * __nonnull turtles = functionThatReturnsSomeTurtlesInAnyOrder
|
||||
// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]:
|
||||
|
||||
expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) {
|
||||
return [[turtle color] isEqualToString:@"green"];
|
||||
return [[turtle color] isEqualToString:@"green"];
|
||||
}));
|
||||
expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) {
|
||||
return [[turtle color] isEqualToString:@"blue"];
|
||||
return [[turtle color] isEqualToString:@"blue"];
|
||||
}));
|
||||
```
|
||||
|
||||
@@ -1273,24 +1258,24 @@ value and return a `Predicate` closure. Take `equal`, for example:
|
||||
// Swift
|
||||
|
||||
public func equal<T: Equatable>(expectedValue: T?) -> Predicate<T> {
|
||||
// Can be shortened to:
|
||||
// Predicate { actual in ... }
|
||||
//
|
||||
// But shown with types here for clarity.
|
||||
return Predicate { (actual: Expression<T>) throws -> PredicateResult in
|
||||
let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>")
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
return PredicateResult(
|
||||
bool: actualValue == expectedValue!,
|
||||
message: msg
|
||||
)
|
||||
} else {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: msg.appendedBeNilHint()
|
||||
)
|
||||
// Can be shortened to:
|
||||
// Predicate { actual in ... }
|
||||
//
|
||||
// But shown with types here for clarity.
|
||||
return Predicate { (actualExpression: Expression<T>) throws -> PredicateResult in
|
||||
let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>")
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
return PredicateResult(
|
||||
bool: actualValue == expectedValue!,
|
||||
message: msg
|
||||
)
|
||||
} else {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: msg.appendedBeNilHint()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1382,11 +1367,11 @@ custom matchers should call `actualExpression.evaluate()`:
|
||||
// Swift
|
||||
|
||||
public func beNil<T>() -> Predicate<T> {
|
||||
// Predicate.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(..)
|
||||
// Predicate.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
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
return PredicateStatus(bool: actualValue == nil)
|
||||
@@ -1412,9 +1397,9 @@ against the one provided to the matcher function, and passes if they are the sam
|
||||
// Swift
|
||||
|
||||
public func haveDescription(description: String) -> Predicate<Printable?> {
|
||||
return Predicate.simple("have description") { actual in
|
||||
return PredicateStatus(bool: actual.evaluate().description == description)
|
||||
}
|
||||
return Predicate.simple("have description") { actual in
|
||||
return PredicateStatus(bool: actual.evaluate().description == description)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1489,7 +1474,7 @@ case expectedCustomValueTo(/* message: */ String, /* actual: */ String)
|
||||
|
||||
// Emits standard error message without mentioning the actual value
|
||||
// eg - "expected to <message>"
|
||||
case expectedTo(/* message: */ String, /* actual: */ String)
|
||||
case expectedTo(/* message: */ String)
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -1526,13 +1511,13 @@ custom matcher. The example below defines the class method
|
||||
// Swift
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beNilMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualBlock, failureMessage, location in
|
||||
let block = ({ actualBlock() as NSObject? })
|
||||
let expr = Expression(expression: block, location: location)
|
||||
return beNil().matches(expr, failureMessage: failureMessage)
|
||||
public class func beNilMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualBlock, failureMessage, location in
|
||||
let block = ({ actualBlock() as NSObject? })
|
||||
let expr = Expression(expression: block, location: location)
|
||||
return beNil().matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1551,7 +1536,7 @@ class method:
|
||||
// Objective-C
|
||||
|
||||
FOUNDATION_EXPORT id<NMBMatcher> beNil() {
|
||||
return [NMBObjCMatcher beNilMatcher];
|
||||
return [NMBObjCMatcher beNilMatcher];
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1673,11 +1658,11 @@ backported.
|
||||
The deprecating plan is a 3 major versions removal. Which is as follows:
|
||||
|
||||
1. Introduce new `Predicate` API, deprecation warning for old matcher APIs.
|
||||
(Nimble `v7.x.x`)
|
||||
(Nimble `v7.x.x` and `v8.x.x`)
|
||||
2. Introduce warnings on migration-path features (`.predicate`,
|
||||
`Predicate`-constructors with similar arguments to old API). (Nimble
|
||||
`v8.x.x`)
|
||||
3. Remove old API. (Nimble `v9.x.x`)
|
||||
`v9.x.x`)
|
||||
3. Remove old API. (Nimble `v10.x.x`)
|
||||
|
||||
|
||||
# Installing Nimble
|
||||
|
||||
@@ -13,5 +13,6 @@ public protocol AssertionHandler {
|
||||
///
|
||||
/// @see AssertionHandler
|
||||
public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in
|
||||
// swiftlint:disable:previous identifier_name
|
||||
return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler()
|
||||
}()
|
||||
|
||||
@@ -37,21 +37,48 @@ public class AssertionRecorder: AssertionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBExceptionCapture {
|
||||
internal func tryBlockThrows(_ unsafeBlock: () throws -> Void) throws {
|
||||
var catchedError: Error?
|
||||
tryBlock {
|
||||
do {
|
||||
try unsafeBlock()
|
||||
} catch {
|
||||
catchedError = error
|
||||
}
|
||||
}
|
||||
if let error = catchedError {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows you to temporarily replace the current Nimble assertion handler with
|
||||
/// the one provided for the scope of the closure.
|
||||
///
|
||||
/// Once the closure finishes, then the original Nimble assertion handler is restored.
|
||||
///
|
||||
/// @see AssertionHandler
|
||||
public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, closure: () throws -> Void) {
|
||||
public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler,
|
||||
file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
closure: () throws -> Void) {
|
||||
let environment = NimbleEnvironment.activeInstance
|
||||
let oldRecorder = environment.assertionHandler
|
||||
let capturer = NMBExceptionCapture(handler: nil, finally: ({
|
||||
environment.assertionHandler = oldRecorder
|
||||
}))
|
||||
environment.assertionHandler = tempAssertionHandler
|
||||
capturer.tryBlock {
|
||||
try! closure()
|
||||
|
||||
do {
|
||||
try capturer.tryBlockThrows {
|
||||
try closure()
|
||||
}
|
||||
} catch {
|
||||
let failureMessage = FailureMessage()
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
let location = SourceLocation(file: file, line: line)
|
||||
tempAssertionHandler.assert(false, message: failureMessage, location: location)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +92,7 @@ public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, closu
|
||||
/// assertion handler when this is true. Defaults to false.
|
||||
///
|
||||
/// @see gatherFailingExpectations
|
||||
public func gatherExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] {
|
||||
public func gatherExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] {
|
||||
let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler
|
||||
let recorder = AssertionRecorder()
|
||||
let handlers: [AssertionHandler]
|
||||
@@ -92,7 +119,7 @@ public func gatherExpectations(silently: Bool = false, closure: @escaping () ->
|
||||
///
|
||||
/// @see gatherExpectations
|
||||
/// @see raiseException source for an example use case.
|
||||
public func gatherFailingExpectations(silently: Bool = false, closure: @escaping () -> Void) -> [AssertionRecord] {
|
||||
public func gatherFailingExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] {
|
||||
let assertions = gatherExpectations(silently: silently, closure: closure)
|
||||
return assertions.filter { assertion in
|
||||
!assertion.success
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
|
||||
private func from(objcPredicate: NMBPredicate) -> Predicate<NSObject> {
|
||||
return Predicate { actualExpression in
|
||||
let result = objcPredicate.satisfies(({ try! actualExpression.evaluate() }),
|
||||
let result = objcPredicate.satisfies(({ try actualExpression.evaluate() }),
|
||||
location: actualExpression.location)
|
||||
return result.toSwift()
|
||||
}
|
||||
@@ -15,6 +15,7 @@ internal struct ObjCMatcherWrapper: Matcher {
|
||||
|
||||
func matches(_ actualExpression: Expression<NSObject>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher.matches(
|
||||
// swiftlint:disable:next force_try
|
||||
({ try! actualExpression.evaluate() }),
|
||||
failureMessage: failureMessage,
|
||||
location: actualExpression.location)
|
||||
@@ -22,6 +23,7 @@ internal struct ObjCMatcherWrapper: Matcher {
|
||||
|
||||
func doesNotMatch(_ actualExpression: Expression<NSObject>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher.doesNotMatch(
|
||||
// swiftlint:disable:next force_try
|
||||
({ try! actualExpression.evaluate() }),
|
||||
failureMessage: failureMessage,
|
||||
location: actualExpression.location)
|
||||
@@ -30,13 +32,15 @@ internal struct ObjCMatcherWrapper: Matcher {
|
||||
|
||||
// Equivalent to Expectation, but for Nimble's Objective-C interface
|
||||
public class NMBExpectation: NSObject {
|
||||
internal let _actualBlock: () -> NSObject!
|
||||
// swiftlint:disable identifier_name
|
||||
internal let _actualBlock: () -> NSObject?
|
||||
internal var _negative: Bool
|
||||
internal let _file: FileString
|
||||
internal let _line: UInt
|
||||
internal var _timeout: TimeInterval = 1.0
|
||||
// swiftlint:enable identifier_name
|
||||
|
||||
@objc public init(actualBlock: @escaping () -> NSObject!, negative: Bool, file: FileString, line: UInt) {
|
||||
@objc public init(actualBlock: @escaping () -> NSObject?, negative: Bool, file: FileString, line: UInt) {
|
||||
self._actualBlock = actualBlock
|
||||
self._negative = negative
|
||||
self._file = file
|
||||
|
||||
+26
-14
@@ -1,15 +1,17 @@
|
||||
import Foundation
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
|
||||
// swiftlint:disable line_length
|
||||
public typealias MatcherBlock = (_ actualExpression: Expression<NSObject>, _ failureMessage: FailureMessage) -> Bool
|
||||
public typealias FullMatcherBlock = (_ actualExpression: Expression<NSObject>, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) -> Bool
|
||||
public typealias MatcherBlock = (_ actualExpression: Expression<NSObject>, _ failureMessage: FailureMessage) throws -> Bool
|
||||
public typealias FullMatcherBlock = (_ actualExpression: Expression<NSObject>, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) throws -> Bool
|
||||
// swiftlint:enable line_length
|
||||
|
||||
public class NMBObjCMatcher: NSObject, NMBMatcher {
|
||||
// swiftlint:disable identifier_name
|
||||
let _match: MatcherBlock
|
||||
let _doesNotMatch: MatcherBlock
|
||||
// swiftlint:enable identifier_name
|
||||
let canMatchNil: Bool
|
||||
|
||||
public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) {
|
||||
@@ -24,7 +26,7 @@ public class NMBObjCMatcher: NSObject, NMBMatcher {
|
||||
|
||||
public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) {
|
||||
self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in
|
||||
return !matcher(actualExpression, failureMessage)
|
||||
return try !matcher(actualExpression, failureMessage)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -34,9 +36,9 @@ public class NMBObjCMatcher: NSObject, NMBMatcher {
|
||||
|
||||
public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) {
|
||||
self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in
|
||||
return matcher(actualExpression, failureMessage, false)
|
||||
return try matcher(actualExpression, failureMessage, false)
|
||||
}), notMatcher: ({ actualExpression, failureMessage in
|
||||
return matcher(actualExpression, failureMessage, true)
|
||||
return try matcher(actualExpression, failureMessage, true)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -55,11 +57,16 @@ public class NMBObjCMatcher: NSObject, NMBMatcher {
|
||||
return true
|
||||
}
|
||||
|
||||
public func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let result = _match(
|
||||
expr,
|
||||
failureMessage)
|
||||
let result: Bool
|
||||
do {
|
||||
result = try _match(expr, failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
}
|
||||
|
||||
if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
|
||||
return result
|
||||
} else {
|
||||
@@ -67,11 +74,16 @@ public class NMBObjCMatcher: NSObject, NMBMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let result = _doesNotMatch(
|
||||
expr,
|
||||
failureMessage)
|
||||
let result: Bool
|
||||
do {
|
||||
result = try _doesNotMatch(expr, failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
}
|
||||
|
||||
if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
|
||||
return result
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,7 @@ import Foundation
|
||||
|
||||
/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this
|
||||
/// class' existence
|
||||
internal class NimbleEnvironment {
|
||||
internal class NimbleEnvironment: NSObject {
|
||||
static var activeInstance: NimbleEnvironment {
|
||||
get {
|
||||
let env = Thread.current.threadDictionary["NimbleEnvironment"]
|
||||
@@ -20,6 +20,7 @@ internal class NimbleEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable:next todo
|
||||
// TODO: eventually migrate the global to this environment value
|
||||
var assertionHandler: AssertionHandler {
|
||||
get { return NimbleAssertionHandler }
|
||||
@@ -29,17 +30,14 @@ internal class NimbleEnvironment {
|
||||
var suppressTVOSAssertionWarning: Bool = false
|
||||
var awaiter: Awaiter
|
||||
|
||||
init() {
|
||||
let timeoutQueue: DispatchQueue
|
||||
if #available(OSX 10.10, *) {
|
||||
timeoutQueue = DispatchQueue.global(qos: .userInitiated)
|
||||
} else {
|
||||
timeoutQueue = DispatchQueue.global(priority: .high)
|
||||
}
|
||||
|
||||
override init() {
|
||||
let timeoutQueue = DispatchQueue.global(qos: .userInitiated)
|
||||
awaiter = Awaiter(
|
||||
waitLock: AssertionWaitLock(),
|
||||
asyncQueue: .main,
|
||||
timeoutQueue: timeoutQueue)
|
||||
timeoutQueue: timeoutQueue
|
||||
)
|
||||
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,18 +42,29 @@ class NimbleXCTestUnavailableHandler: AssertionHandler {
|
||||
|
||||
private(set) var currentTestCase: XCTestCase?
|
||||
|
||||
private var stashed_swift_reportFatalErrorsToDebugger: Bool = false
|
||||
|
||||
@objc func testCaseWillStart(_ testCase: XCTestCase) {
|
||||
#if swift(>=3.2)
|
||||
stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger
|
||||
_swift_reportFatalErrorsToDebugger = false
|
||||
#endif
|
||||
|
||||
currentTestCase = testCase
|
||||
}
|
||||
|
||||
@objc func testCaseDidFinish(_ testCase: XCTestCase) {
|
||||
currentTestCase = nil
|
||||
|
||||
#if swift(>=3.2)
|
||||
_swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
func isXCTestAvailable() -> Bool {
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
// XCTest is weakly linked and so may not be present
|
||||
return NSClassFromString("XCTestCase") != nil
|
||||
#else
|
||||
@@ -61,20 +72,19 @@ func isXCTestAvailable() -> Bool {
|
||||
#endif
|
||||
}
|
||||
|
||||
private func recordFailure(_ message: String, location: SourceLocation) {
|
||||
public func recordFailure(_ message: String, location: SourceLocation) {
|
||||
#if SWIFT_PACKAGE
|
||||
XCTFail("\(message)", file: location.file, line: location.line)
|
||||
#else
|
||||
if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase {
|
||||
#if swift(>=4)
|
||||
let line = Int(location.line)
|
||||
#else
|
||||
let line = location.line
|
||||
#endif
|
||||
testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true)
|
||||
} else {
|
||||
let msg = "Attempted to report a test failure to XCTest while no test case was running. " +
|
||||
"The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)"
|
||||
let msg = """
|
||||
Attempted to report a test failure to XCTest while no test case was running. The failure was:
|
||||
\"\(message)\"
|
||||
It occurred at: \(location.file):\(location.line)
|
||||
"""
|
||||
NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise()
|
||||
}
|
||||
#endif
|
||||
|
||||
+11
-5
@@ -14,7 +14,7 @@ internal class NMBWait: NSObject {
|
||||
// About these kind of lines, `@objc` attributes are only required for Objective-C
|
||||
// support, so that should be conditional on Darwin platforms and normal Xcode builds
|
||||
// (non-SwiftPM builds).
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objc
|
||||
internal class func until(
|
||||
timeout: TimeInterval,
|
||||
@@ -87,13 +87,19 @@ internal class NMBWait: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objc(untilFile:line:action:)
|
||||
internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) {
|
||||
internal class func until(
|
||||
_ file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
action: @escaping (@escaping () -> Void) -> Void) {
|
||||
until(timeout: 1, file: file, line: line, action: action)
|
||||
}
|
||||
#else
|
||||
internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) {
|
||||
internal class func until(
|
||||
_ file: FileString = #file,
|
||||
line: UInt = #line,
|
||||
action: @escaping (@escaping () -> Void) -> Void) {
|
||||
until(timeout: 1, file: file, line: line, action: action)
|
||||
}
|
||||
#endif
|
||||
@@ -111,6 +117,6 @@ internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterv
|
||||
///
|
||||
/// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function
|
||||
/// is executing. Any attempts to touch the run loop may cause non-deterministic behavior.
|
||||
public func waitUntil(timeout: TimeInterval = 1, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) {
|
||||
public func waitUntil(timeout: TimeInterval = AsyncDefaults.Timeout, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) {
|
||||
NMBWait.until(timeout: timeout, file: file, line: line, action: action)
|
||||
}
|
||||
|
||||
+11
-7
@@ -43,12 +43,13 @@ internal func nimblePrecondition(
|
||||
line: UInt = #line) {
|
||||
let result = expr()
|
||||
if !result {
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
let e = NSException(
|
||||
#if canImport(Darwin)
|
||||
let exception = NSException(
|
||||
name: NSExceptionName(name()),
|
||||
reason: message(),
|
||||
userInfo: nil)
|
||||
e.raise()
|
||||
userInfo: nil
|
||||
)
|
||||
exception.raise()
|
||||
#else
|
||||
preconditionFailure("\(name()) - \(message())", file: file, line: line)
|
||||
#endif
|
||||
@@ -56,9 +57,12 @@ internal func nimblePrecondition(
|
||||
}
|
||||
|
||||
internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never {
|
||||
// swiftlint:disable line_length
|
||||
fatalError(
|
||||
"Nimble Bug Found: \(msg) at \(file):\(line).\n" +
|
||||
"Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the " +
|
||||
"code snippet that caused this error."
|
||||
"""
|
||||
Nimble Bug Found: \(msg) at \(file):\(line).
|
||||
Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the code snippet that caused this error.
|
||||
"""
|
||||
)
|
||||
// swiftlint:enable line_length
|
||||
}
|
||||
|
||||
+14
-21
@@ -1,23 +1,5 @@
|
||||
import Foundation
|
||||
|
||||
// Deprecated
|
||||
internal func expressionMatches<T, U>(_ expression: Expression<T>, matcher: U, to: String, description: String?) -> (Bool, FailureMessage)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
let msg = FailureMessage()
|
||||
msg.userDescription = description
|
||||
msg.to = to
|
||||
do {
|
||||
let pass = try matcher.matches(expression, failureMessage: msg)
|
||||
if msg.actualValue == "" {
|
||||
msg.actualValue = "<\(stringify(try expression.evaluate()))>"
|
||||
}
|
||||
return (pass, msg)
|
||||
} catch let error {
|
||||
msg.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return (false, msg)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
internal func expressionDoesNotMatch<T, U>(_ expression: Expression<T>, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
@@ -75,6 +57,10 @@ public struct Expectation<T> {
|
||||
|
||||
public let expression: Expression<T>
|
||||
|
||||
public init(expression: Expression<T>) {
|
||||
self.expression = expression
|
||||
}
|
||||
|
||||
public func verify(_ pass: Bool, _ message: FailureMessage) {
|
||||
let handler = NimbleEnvironment.activeInstance.assertionHandler
|
||||
handler.assert(pass, message: message, location: expression.location)
|
||||
@@ -85,8 +71,15 @@ public struct Expectation<T> {
|
||||
/// DEPRECATED: Tests the actual value using a matcher to match.
|
||||
public func to<U>(_ matcher: U, description: String? = nil)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
let (pass, msg) = expressionMatches(expression, matcher: matcher, to: "to", description: description)
|
||||
verify(pass, msg)
|
||||
let (pass, msg) = execute(
|
||||
expression,
|
||||
.toMatch,
|
||||
matcher.predicate,
|
||||
to: "to",
|
||||
description: description,
|
||||
captureExceptions: false
|
||||
)
|
||||
verify(pass, msg)
|
||||
}
|
||||
|
||||
/// DEPRECATED: Tests the actual value using a matcher to not match.
|
||||
@@ -127,6 +120,6 @@ public struct Expectation<T> {
|
||||
}
|
||||
|
||||
// see:
|
||||
// - AsyncMatcherWrapper for extension
|
||||
// - `async` for extension
|
||||
// - NMBExpectation for Objective-C interface
|
||||
}
|
||||
|
||||
+19
-14
@@ -75,6 +75,7 @@ public indirect enum ExpectationMessage {
|
||||
}
|
||||
|
||||
internal func visitLeafs(_ f: (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage {
|
||||
// swiftlint:disable:previous identifier_name
|
||||
switch self {
|
||||
case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo:
|
||||
return f(self)
|
||||
@@ -90,6 +91,7 @@ public indirect enum ExpectationMessage {
|
||||
/// Replaces a primary expectation with one returned by f. Preserves all composite expectations
|
||||
/// that were built upon it (aka - all appended(message:) and appended(details:).
|
||||
public func replacedExpectation(_ f: @escaping (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage {
|
||||
// swiftlint:disable:previous identifier_name
|
||||
func walk(_ msg: ExpectationMessage) -> ExpectationMessage {
|
||||
switch msg {
|
||||
case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo:
|
||||
@@ -124,6 +126,7 @@ public indirect enum ExpectationMessage {
|
||||
return visitLeafs(walk)
|
||||
}
|
||||
|
||||
// swiftlint:disable:next todo
|
||||
// TODO: test & verify correct behavior
|
||||
internal func prepended(message: String) -> ExpectationMessage {
|
||||
return .prepends(message, self)
|
||||
@@ -152,8 +155,10 @@ public indirect enum ExpectationMessage {
|
||||
// Backwards compatibility: converts ExpectationMessage tree to FailureMessage
|
||||
internal func update(failureMessage: FailureMessage) {
|
||||
switch self {
|
||||
case let .fail(msg):
|
||||
case let .fail(msg) where !msg.isEmpty:
|
||||
failureMessage.stringValue = msg
|
||||
case .fail:
|
||||
break
|
||||
case let .expectedTo(msg):
|
||||
failureMessage.actualValue = nil
|
||||
failureMessage.postfixMessage = msg
|
||||
@@ -181,32 +186,32 @@ public indirect enum ExpectationMessage {
|
||||
|
||||
extension FailureMessage {
|
||||
internal func toExpectationMessage() -> ExpectationMessage {
|
||||
let defaultMsg = FailureMessage()
|
||||
if expected != defaultMsg.expected || _stringValueOverride != nil {
|
||||
let defaultMessage = FailureMessage()
|
||||
if expected != defaultMessage.expected || _stringValueOverride != nil {
|
||||
return .fail(stringValue)
|
||||
}
|
||||
|
||||
var msg: ExpectationMessage = .fail(userDescription ?? "")
|
||||
var message: ExpectationMessage = .fail(userDescription ?? "")
|
||||
if actualValue != "" && actualValue != nil {
|
||||
msg = .expectedCustomValueTo(postfixMessage, actualValue ?? "")
|
||||
} else if postfixMessage != defaultMsg.postfixMessage {
|
||||
message = .expectedCustomValueTo(postfixMessage, actualValue ?? "")
|
||||
} else if postfixMessage != defaultMessage.postfixMessage {
|
||||
if actualValue == nil {
|
||||
msg = .expectedTo(postfixMessage)
|
||||
message = .expectedTo(postfixMessage)
|
||||
} else {
|
||||
msg = .expectedActualValueTo(postfixMessage)
|
||||
message = .expectedActualValueTo(postfixMessage)
|
||||
}
|
||||
}
|
||||
if postfixActual != defaultMsg.postfixActual {
|
||||
msg = .appends(msg, postfixActual)
|
||||
if postfixActual != defaultMessage.postfixActual {
|
||||
message = .appends(message, postfixActual)
|
||||
}
|
||||
if let m = extendedMessage {
|
||||
msg = .details(msg, m)
|
||||
if let extended = extendedMessage {
|
||||
message = .details(message, extended)
|
||||
}
|
||||
return msg
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
|
||||
public class NMBExpectationMessage: NSObject {
|
||||
private let msg: ExpectationMessage
|
||||
|
||||
@@ -24,8 +24,10 @@ internal func memoizedClosure<T>(_ closure: @escaping () throws -> T) -> (Bool)
|
||||
/// This provides a common consumable API for matchers to utilize to allow
|
||||
/// Nimble to change internals to how the captured closure is managed.
|
||||
public struct Expression<T> {
|
||||
// swiftlint:disable identifier_name
|
||||
internal let _expression: (Bool) throws -> T?
|
||||
internal let _withoutCaching: Bool
|
||||
// swiftlint:enable identifier_name
|
||||
public let location: SourceLocation
|
||||
public let isClosure: Bool
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ public class FailureMessage: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
internal var _stringValueOverride: String?
|
||||
internal var hasOverriddenStringValue: Bool {
|
||||
return _stringValueOverride != nil
|
||||
|
||||
+5
-4
@@ -63,12 +63,12 @@ private func createPredicate<S>(_ elementMatcher: Predicate<S.Iterator.Element>)
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func allPassMatcher(_ matcher: NMBMatcher) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
let actualValue = try! actualExpression.evaluate()
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
var nsObjects = [NSObject]()
|
||||
|
||||
var collectionIsUsable = true
|
||||
@@ -99,10 +99,11 @@ extension NMBObjCMatcher {
|
||||
let expr = Expression(expression: ({ nsObjects }), location: location)
|
||||
let pred: Predicate<[NSObject]> = createPredicate(Predicate { expr in
|
||||
if let predicate = matcher as? NMBPredicate {
|
||||
return predicate.satisfies(({ try! expr.evaluate() }), location: expr.location).toSwift()
|
||||
return predicate.satisfies(({ try expr.evaluate() }), location: expr.location).toSwift()
|
||||
} else {
|
||||
let failureMessage = FailureMessage()
|
||||
let result = matcher.matches(
|
||||
// swiftlint:disable:next force_try
|
||||
({ try! expr.evaluate() }),
|
||||
failureMessage: failureMessage,
|
||||
location: expr.location
|
||||
@@ -114,7 +115,7 @@ extension NMBObjCMatcher {
|
||||
)
|
||||
}
|
||||
})
|
||||
return try! pred.satisfies(expr).toObjectiveC()
|
||||
return try pred.satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+29
-84
@@ -23,92 +23,29 @@ private func async<T>(style: ExpectationStyle, predicate: Predicate<T>, timeout:
|
||||
}
|
||||
switch result {
|
||||
case .completed: return lastPredicateResult!
|
||||
case .timedOut: return PredicateResult(status: .fail, message: lastPredicateResult!.message)
|
||||
case .timedOut:
|
||||
let message = lastPredicateResult?.message ?? .fail("timed out before returning a value")
|
||||
return PredicateResult(status: .fail, message: message)
|
||||
case let .errorThrown(error):
|
||||
return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>"))
|
||||
case let .raisedException(exception):
|
||||
return PredicateResult(status: .fail, message: .fail("unexpected exception raised: \(exception)"))
|
||||
case .blockedRunLoop:
|
||||
// swiftlint:disable:next line_length
|
||||
return PredicateResult(status: .fail, message: lastPredicateResult!.message.appended(message: " (timed out, but main thread was unresponsive)."))
|
||||
let message = lastPredicateResult?.message.appended(message: " (timed out, but main run loop was unresponsive).") ??
|
||||
.fail("main run loop was unresponsive")
|
||||
return PredicateResult(status: .fail, message: message)
|
||||
case .incomplete:
|
||||
internalError("Reached .incomplete state for toEventually(...).")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
internal struct AsyncMatcherWrapper<T, U>: Matcher
|
||||
where U: Matcher, U.ValueType == T {
|
||||
let fullMatcher: U
|
||||
let timeoutInterval: TimeInterval
|
||||
let pollInterval: TimeInterval
|
||||
|
||||
init(fullMatcher: U, timeoutInterval: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval) {
|
||||
self.fullMatcher = fullMatcher
|
||||
self.timeoutInterval = timeoutInterval
|
||||
self.pollInterval = pollInterval
|
||||
}
|
||||
|
||||
func matches(_ actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
let uncachedExpression = actualExpression.withoutCaching()
|
||||
let fnName = "expect(...).toEventually(...)"
|
||||
let result = pollBlock(
|
||||
pollInterval: pollInterval,
|
||||
timeoutInterval: timeoutInterval,
|
||||
file: actualExpression.location.file,
|
||||
line: actualExpression.location.line,
|
||||
fnName: fnName) {
|
||||
try self.fullMatcher.matches(uncachedExpression, failureMessage: failureMessage)
|
||||
}
|
||||
switch result {
|
||||
case let .completed(isSuccessful): return isSuccessful
|
||||
case .timedOut: return false
|
||||
case let .errorThrown(error):
|
||||
failureMessage.stringValue = "an unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
case let .raisedException(exception):
|
||||
failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>"
|
||||
return false
|
||||
case .blockedRunLoop:
|
||||
failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)."
|
||||
return false
|
||||
case .incomplete:
|
||||
internalError("Reached .incomplete state for toEventually(...).")
|
||||
}
|
||||
}
|
||||
|
||||
func doesNotMatch(_ actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
let uncachedExpression = actualExpression.withoutCaching()
|
||||
let result = pollBlock(
|
||||
pollInterval: pollInterval,
|
||||
timeoutInterval: timeoutInterval,
|
||||
file: actualExpression.location.file,
|
||||
line: actualExpression.location.line,
|
||||
fnName: "expect(...).toEventuallyNot(...)") {
|
||||
try self.fullMatcher.doesNotMatch(uncachedExpression, failureMessage: failureMessage)
|
||||
}
|
||||
switch result {
|
||||
case let .completed(isSuccessful): return isSuccessful
|
||||
case .timedOut: return false
|
||||
case let .errorThrown(error):
|
||||
failureMessage.stringValue = "an unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
case let .raisedException(exception):
|
||||
failureMessage.stringValue = "an unexpected exception thrown: <\(exception)>"
|
||||
return false
|
||||
case .blockedRunLoop:
|
||||
failureMessage.postfixMessage += " (timed out, but main thread was unresponsive)."
|
||||
return false
|
||||
case .incomplete:
|
||||
internalError("Reached .incomplete state for toEventuallyNot(...).")
|
||||
internalError("Reached .incomplete state for \(fnName)(...).")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let toEventuallyRequiresClosureError = FailureMessage(
|
||||
// swiftlint:disable:next line_length
|
||||
stringValue: "expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )\nSwift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function"
|
||||
stringValue: """
|
||||
expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )
|
||||
Swift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function
|
||||
"""
|
||||
)
|
||||
|
||||
extension Expectation {
|
||||
@@ -182,14 +119,19 @@ extension Expectation {
|
||||
public func toEventually<U>(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil)
|
||||
where U: Matcher, U.ValueType == T {
|
||||
if expression.isClosure {
|
||||
let (pass, msg) = expressionMatches(
|
||||
let (pass, msg) = execute(
|
||||
expression,
|
||||
matcher: AsyncMatcherWrapper(
|
||||
fullMatcher: matcher,
|
||||
timeoutInterval: timeout,
|
||||
pollInterval: pollInterval),
|
||||
.toMatch,
|
||||
async(
|
||||
style: .toMatch,
|
||||
predicate: matcher.predicate,
|
||||
timeout: timeout,
|
||||
poll: pollInterval,
|
||||
fnName: "toEventually"
|
||||
),
|
||||
to: "to eventually",
|
||||
description: description
|
||||
description: description,
|
||||
captureExceptions: false
|
||||
)
|
||||
verify(pass, msg)
|
||||
} else {
|
||||
@@ -208,10 +150,13 @@ extension Expectation {
|
||||
if expression.isClosure {
|
||||
let (pass, msg) = expressionDoesNotMatch(
|
||||
expression,
|
||||
matcher: AsyncMatcherWrapper(
|
||||
fullMatcher: matcher,
|
||||
timeoutInterval: timeout,
|
||||
pollInterval: pollInterval),
|
||||
matcher: async(
|
||||
style: .toNotMatch,
|
||||
predicate: matcher.predicate,
|
||||
timeout: timeout,
|
||||
poll: pollInterval,
|
||||
fnName: "toEventuallyNot"
|
||||
),
|
||||
toNot: "to eventually not",
|
||||
description: description
|
||||
)
|
||||
+3
-3
@@ -29,7 +29,7 @@ public func beAKindOf<T>(_ expectedType: T.Type) -> Predicate<Any> {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
|
||||
/// 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
|
||||
@@ -59,8 +59,8 @@ public func beAKindOf(_ expectedClass: AnyClass) -> Predicate<NSObject> {
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
return try! beAKindOf(expected).matches(actualExpression, failureMessage: failureMessage)
|
||||
return NMBPredicate { actualExpression in
|
||||
return try beAKindOf(expected).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate<NSObject> {
|
||||
} else {
|
||||
actualString = "<nil>"
|
||||
}
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
let matches = instance != nil && instance!.isMember(of: expectedClass)
|
||||
#else
|
||||
let matches = instance != nil && type(of: instance!) == expectedClass
|
||||
@@ -45,11 +45,11 @@ public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate<NSObject> {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
return try! beAnInstanceOf(expected).matches(actualExpression, failureMessage: failureMessage)
|
||||
return NMBPredicate { actualExpression in
|
||||
return try beAnInstanceOf(expected).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-5
@@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
public let DefaultDelta = 0.0001
|
||||
|
||||
internal func isCloseTo(_ actualValue: NMBDoubleConvertible?,
|
||||
@@ -34,31 +35,45 @@ public func beCloseTo(_ expectedValue: NMBDoubleConvertible, within delta: Doubl
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher {
|
||||
// swiftlint:disable identifier_name
|
||||
var _expected: NSNumber
|
||||
var _delta: CDouble
|
||||
// swiftlint:enable identifier_name
|
||||
init(expected: NSNumber, within: CDouble) {
|
||||
_expected = expected
|
||||
_delta = within
|
||||
}
|
||||
|
||||
@objc public func matches(_ actualExpression: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
@objc public func matches(_ actualExpression: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let actualBlock: () -> NMBDoubleConvertible? = ({
|
||||
return actualExpression() as? NMBDoubleConvertible
|
||||
})
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let matcher = beCloseTo(self._expected, within: self._delta)
|
||||
return try! matcher.matches(expr, failureMessage: failureMessage)
|
||||
|
||||
do {
|
||||
return try matcher.matches(expr, failureMessage: failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func doesNotMatch(_ actualExpression: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
@objc public func doesNotMatch(_ actualExpression: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let actualBlock: () -> NMBDoubleConvertible? = ({
|
||||
return actualExpression() as? NMBDoubleConvertible
|
||||
})
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let matcher = beCloseTo(self._expected, within: self._delta)
|
||||
return try! matcher.doesNotMatch(expr, failureMessage: failureMessage)
|
||||
|
||||
do {
|
||||
return try matcher.doesNotMatch(expr, failureMessage: failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@objc public var within: (CDouble) -> NMBObjCBeCloseToMatcher {
|
||||
@@ -98,14 +113,17 @@ public func beCloseTo(_ expectedValues: [Double], within delta: Double = Default
|
||||
|
||||
infix operator ≈ : ComparisonPrecedence
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
}
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
public func ≈(lhs: Expectation<NMBDoubleConvertible>, rhs: NMBDoubleConvertible) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
}
|
||||
|
||||
// swiftlint:disable:next identifier_name
|
||||
public func ≈(lhs: Expectation<NMBDoubleConvertible>, rhs: (expected: NMBDoubleConvertible, delta: Double)) {
|
||||
lhs.to(beCloseTo(rhs.expected, within: rhs.delta))
|
||||
}
|
||||
@@ -121,6 +139,7 @@ precedencegroup PlusMinusOperatorPrecedence {
|
||||
}
|
||||
|
||||
infix operator ± : PlusMinusOperatorPrecedence
|
||||
// swiftlint:disable:next identifier_name
|
||||
public func ±(lhs: NMBDoubleConvertible, rhs: Double) -> (expected: NMBDoubleConvertible, delta: Double) {
|
||||
return (expected: lhs, delta: rhs)
|
||||
}
|
||||
|
||||
+28
-7
@@ -4,15 +4,36 @@ import Foundation
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty<S: Sequence>() -> Predicate<S> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
let actualSeq = try actualExpression.evaluate()
|
||||
if actualSeq == nil {
|
||||
guard let actual = try actualExpression.evaluate() else {
|
||||
return .fail
|
||||
}
|
||||
var generator = actualSeq!.makeIterator()
|
||||
var generator = actual.makeIterator()
|
||||
return PredicateStatus(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<S: SetAlgebra>() -> Predicate<S> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else {
|
||||
return .fail
|
||||
}
|
||||
return PredicateStatus(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<S: Sequence & SetAlgebra>() -> Predicate<S> {
|
||||
return Predicate.simple("be empty") { actualExpression in
|
||||
guard let actual = try actualExpression.evaluate() else {
|
||||
return .fail
|
||||
}
|
||||
return PredicateStatus(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<String> {
|
||||
@@ -61,19 +82,19 @@ public func beEmpty() -> Predicate<NMBCollection> {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beEmptyMatcher() -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
let actualValue = try! actualExpression.evaluate()
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
|
||||
if let value = actualValue as? NMBCollection {
|
||||
let expr = Expression(expression: ({ value as NMBCollection }), location: location)
|
||||
return try! beEmpty().satisfies(expr).toObjectiveC()
|
||||
return try beEmpty().satisfies(expr).toObjectiveC()
|
||||
} else if let value = actualValue as? NSString {
|
||||
let expr = Expression(expression: ({ value as String }), location: location)
|
||||
return try! beEmpty().satisfies(expr).toObjectiveC()
|
||||
return try beEmpty().satisfies(expr).toObjectiveC()
|
||||
} else if let actualValue = actualValue {
|
||||
// swiftlint:disable:next line_length
|
||||
let badTypeErrorMsg = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)"
|
||||
|
||||
@@ -13,13 +13,13 @@ public func beGreaterThan<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than the expected value.
|
||||
public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate<NMBComparable> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>"
|
||||
let errorMessage = "be greater than <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(errorMessage) { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
let matches = actualValue != nil
|
||||
&& actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending
|
||||
return matches
|
||||
}.requireNonNil
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
public func ><T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
@@ -30,12 +30,12 @@ public func > (lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
|
||||
lhs.to(beGreaterThan(rhs))
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
@objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try! beGreaterThan(expected).matches(expr, failureMessage: failureMessage)
|
||||
return try beGreaterThan(expected).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -3,25 +3,25 @@ import Foundation
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than
|
||||
/// or equal to the expected value.
|
||||
public func beGreaterThanOrEqualTo<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>"
|
||||
let message = "be greater than or equal to <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(message) { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if let actual = actualValue, let expected = expectedValue {
|
||||
return actual >= expected
|
||||
return PredicateStatus(bool: actual >= expected)
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than
|
||||
/// or equal to the expected value.
|
||||
public func beGreaterThanOrEqualTo<T: NMBComparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>"
|
||||
let message = "be greater than or equal to <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(message) { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending
|
||||
return matches
|
||||
}.requireNonNil
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
public func >=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
@@ -32,12 +32,12 @@ public func >=<T: NMBComparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
@objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try! beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage)
|
||||
return try beGreaterThanOrEqualTo(expected).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-12
@@ -3,20 +3,27 @@ import Foundation
|
||||
/// A Nimble matcher that succeeds when the actual value is the same instance
|
||||
/// as the expected instance.
|
||||
public func beIdenticalTo(_ expected: Any?) -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
#if os(Linux)
|
||||
return Predicate.define { actualExpression in
|
||||
#if os(Linux) && !swift(>=4.1.50)
|
||||
let actual = try actualExpression.evaluate() as? AnyObject
|
||||
#else
|
||||
let actual = try actualExpression.evaluate() as AnyObject?
|
||||
#endif
|
||||
failureMessage.actualValue = "\(identityAsString(actual))"
|
||||
failureMessage.postfixMessage = "be identical to \(identityAsString(expected))"
|
||||
#if os(Linux)
|
||||
return actual === (expected as? AnyObject) && actual !== nil
|
||||
|
||||
let bool: Bool
|
||||
#if os(Linux) && !swift(>=4.1.50)
|
||||
bool = actual === (expected as? AnyObject) && actual !== nil
|
||||
#else
|
||||
return actual === (expected as AnyObject?) && actual !== nil
|
||||
bool = actual === (expected as AnyObject?) && actual !== nil
|
||||
#endif
|
||||
}.requireNonNil
|
||||
return PredicateResult(
|
||||
bool: bool,
|
||||
message: .expectedCustomValueTo(
|
||||
"be identical to \(identityAsString(expected))",
|
||||
"\(identityAsString(actual))"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func === (lhs: Expectation<Any>, rhs: Any?) {
|
||||
@@ -34,12 +41,12 @@ public func be(_ expected: Any?) -> Predicate<Any> {
|
||||
return beIdenticalTo(expected)
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
@objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let aExpr = actualExpression.cast { $0 as Any? }
|
||||
return try! beIdenticalTo(expected).matches(aExpr, failureMessage: failureMessage)
|
||||
return try beIdenticalTo(expected).satisfies(aExpr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -2,23 +2,23 @@ import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than the expected value.
|
||||
public func beLessThan<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>"
|
||||
let message = "be less than <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(message) { actualExpression in
|
||||
if let actual = try actualExpression.evaluate(), let expected = expectedValue {
|
||||
return actual < expected
|
||||
return PredicateStatus(bool: actual < expected)
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than the expected value.
|
||||
public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate<NMBComparable> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>"
|
||||
let message = "be less than <\(stringify(expectedValue))>"
|
||||
return Predicate.simple(message) { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending
|
||||
return matches
|
||||
}.requireNonNil
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
public func <<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
@@ -29,12 +29,12 @@ public func < (lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
|
||||
lhs.to(beLessThan(rhs))
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
@objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try! beLessThan(expected).matches(expr, failureMessage: failureMessage)
|
||||
return try beLessThan(expected).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-13
@@ -3,23 +3,22 @@ import Foundation
|
||||
/// A Nimble matcher that succeeds when the actual value is less than
|
||||
/// or equal to the expected value.
|
||||
public func beLessThanOrEqualTo<T: Comparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>"
|
||||
return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate(), let expected = expectedValue {
|
||||
return actual <= expected
|
||||
return PredicateStatus(bool: actual <= expected)
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than
|
||||
/// or equal to the expected value.
|
||||
public func beLessThanOrEqualTo<T: NMBComparable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>"
|
||||
return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
return actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedDescending
|
||||
}.requireNonNil
|
||||
let matches = actualValue.map { $0.NMB_compare(expectedValue) != .orderedDescending } ?? false
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
public func <=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
@@ -30,12 +29,12 @@ public func <=<T: NMBComparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
@objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return try! beLessThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage)
|
||||
return try beLessThanOrEqualTo(expected).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-30
@@ -100,14 +100,6 @@ public func beTruthy<T: ExpressibleByBooleanLiteral & Equatable>() -> Predicate<
|
||||
return Predicate.simpleNilable("be truthy") { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if let actualValue = actualValue {
|
||||
// FIXME: This is a workaround to SR-2290.
|
||||
// See:
|
||||
// - https://bugs.swift.org/browse/SR-2290
|
||||
// - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873
|
||||
if let number = actualValue as? NSNumber {
|
||||
return PredicateStatus(bool: number.boolValue == true)
|
||||
}
|
||||
|
||||
return PredicateStatus(bool: actualValue == (true as T))
|
||||
}
|
||||
return PredicateStatus(bool: actualValue != nil)
|
||||
@@ -120,47 +112,42 @@ public func beFalsy<T: ExpressibleByBooleanLiteral & Equatable>() -> Predicate<T
|
||||
return Predicate.simpleNilable("be falsy") { actualExpression in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if let actualValue = actualValue {
|
||||
// FIXME: This is a workaround to SR-2290.
|
||||
// See:
|
||||
// - https://bugs.swift.org/browse/SR-2290
|
||||
// - https://github.com/norio-nomura/Nimble/pull/5#issuecomment-237835873
|
||||
if let number = actualValue as? NSNumber {
|
||||
return PredicateStatus(bool: number.boolValue == false)
|
||||
}
|
||||
|
||||
return PredicateStatus(bool: actualValue == (false as T))
|
||||
}
|
||||
return PredicateStatus(bool: actualValue == nil)
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beTruthyMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage in
|
||||
@objc public class func beTruthyMatcher() -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false }
|
||||
return try! beTruthy().matches(expr, failureMessage: failureMessage)
|
||||
return try beTruthy().satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class func beFalsyMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage in
|
||||
@objc public class func beFalsyMatcher() -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false }
|
||||
return try! beFalsy().matches(expr, failureMessage: failureMessage)
|
||||
return try beFalsy().satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class func beTrueMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage in
|
||||
@objc public class func beTrueMatcher() -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false }
|
||||
return try! beTrue().matches(expr, failureMessage: failureMessage)
|
||||
return try beTrue().satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class func beFalseMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false }
|
||||
return try! beFalse().matches(expr, failureMessage: failureMessage)
|
||||
@objc public class func beFalseMatcher() -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let expr = actualExpression.cast { value -> Bool? in
|
||||
guard let value = value else { return nil }
|
||||
return (value as? NSNumber)?.boolValue ?? false
|
||||
}
|
||||
return try beFalse().satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -8,11 +8,11 @@ public func beNil<T>() -> Predicate<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beNilMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage in
|
||||
return try! beNil().matches(actualExpression, failureMessage: failureMessage)
|
||||
@objc public class func beNilMatcher() -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
return try beNil().satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-8
@@ -2,17 +2,18 @@ import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is Void.
|
||||
public func beVoid() -> Predicate<()> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be void"
|
||||
return Predicate.simpleNilable("be void") { actualExpression in
|
||||
let actualValue: ()? = try actualExpression.evaluate()
|
||||
return actualValue != nil
|
||||
return PredicateStatus(bool: actualValue != nil)
|
||||
}
|
||||
}
|
||||
|
||||
public func == (lhs: Expectation<()>, rhs: ()) {
|
||||
lhs.to(beVoid())
|
||||
}
|
||||
extension Expectation where T == () {
|
||||
public static func == (lhs: Expectation<()>, rhs: ()) {
|
||||
lhs.to(beVoid())
|
||||
}
|
||||
|
||||
public func != (lhs: Expectation<()>, rhs: ()) {
|
||||
lhs.toNot(beVoid())
|
||||
public static func != (lhs: Expectation<()>, rhs: ()) {
|
||||
lhs.toNot(beVoid())
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -35,24 +35,24 @@ public func beginWith(_ startingElement: Any) -> Predicate<NMBOrderedCollection>
|
||||
public func beginWith(_ startingSubstring: String) -> Predicate<String> {
|
||||
return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
let range = actual.range(of: startingSubstring)
|
||||
return PredicateStatus(bool: range != nil && range!.lowerBound == actual.startIndex)
|
||||
return PredicateStatus(bool: actual.hasPrefix(startingSubstring))
|
||||
}
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func beginWithMatcher(_ expected: Any) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
let actual = try! actualExpression.evaluate()
|
||||
if (actual as? String) != nil {
|
||||
@objc public class func beginWithMatcher(_ expected: Any) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let actual = try actualExpression.evaluate()
|
||||
if actual is String {
|
||||
let expr = actualExpression.cast { $0 as? String }
|
||||
return try! beginWith(expected as! String).matches(expr, failureMessage: failureMessage)
|
||||
// swiftlint:disable:next force_cast
|
||||
return try beginWith(expected as! String).satisfies(expr).toObjectiveC()
|
||||
} else {
|
||||
let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
|
||||
return try! beginWith(expected).matches(expr, failureMessage: failureMessage)
|
||||
return try beginWith(expected).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+85
-36
@@ -1,22 +1,63 @@
|
||||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence contains the expected value.
|
||||
/// A Nimble matcher that succeeds when the actual sequence contains the expected values.
|
||||
public func contain<S: Sequence, T: Equatable>(_ items: T...) -> Predicate<S>
|
||||
where S.Iterator.Element == T {
|
||||
where S.Element == T {
|
||||
return contain(items)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence contains the expected values.
|
||||
public func contain<S: Sequence, T: Equatable>(_ items: [T]) -> Predicate<S>
|
||||
where S.Iterator.Element == T {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(items))>"
|
||||
where S.Element == T {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
return items.all {
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: SetAlgebra, T: Equatable>(_ items: T...) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
return contain(items)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: SetAlgebra, T: Equatable>(_ items: [T]) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: Sequence & SetAlgebra, T: Equatable>(_ items: T...) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
return contain(items)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual set contains the expected values.
|
||||
public func contain<S: Sequence & SetAlgebra, T: Equatable>(_ items: [T]) -> Predicate<S>
|
||||
where S.Element == T {
|
||||
return Predicate.simple("contain <\(arrayAsString(items))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
let matches = items.allSatisfy {
|
||||
return actual.contains($0)
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
return .fail
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
|
||||
@@ -25,16 +66,16 @@ public func contain(_ substrings: String...) -> Predicate<String> {
|
||||
}
|
||||
|
||||
public func contain(_ substrings: [String]) -> Predicate<String> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>"
|
||||
return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
return substrings.all {
|
||||
let matches = substrings.allSatisfy {
|
||||
let range = actual.range(of: $0)
|
||||
return range != nil && !range!.isEmpty
|
||||
}
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
|
||||
@@ -43,13 +84,13 @@ public func contain(_ substrings: NSString...) -> Predicate<NSString> {
|
||||
}
|
||||
|
||||
public func contain(_ substrings: [NSString]) -> Predicate<NSString> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>"
|
||||
return Predicate.simple("contain <\(arrayAsString(substrings))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
return substrings.all { actual.range(of: $0.description).length != 0 }
|
||||
let matches = substrings.allSatisfy { actual.range(of: $0.description).length != 0 }
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection contains the expected object.
|
||||
@@ -58,37 +99,45 @@ public func contain(_ items: Any?...) -> Predicate<NMBContainer> {
|
||||
}
|
||||
|
||||
public func contain(_ items: [Any?]) -> Predicate<NMBContainer> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(items))>"
|
||||
guard let actual = try actualExpression.evaluate() else { return false }
|
||||
return items.all { item in
|
||||
return item != nil && actual.contains(item!)
|
||||
return Predicate.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
|
||||
}
|
||||
}.requireNonNil
|
||||
return PredicateStatus(bool: matches)
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func containMatcher(_ expected: [NSObject]) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
@objc public class func containMatcher(_ expected: [NSObject]) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
let actualValue = try! actualExpression.evaluate()
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if let value = actualValue as? NMBContainer {
|
||||
let expr = Expression(expression: ({ value as NMBContainer }), location: location)
|
||||
|
||||
// A straightforward cast on the array causes this to crash, so we have to cast the individual items
|
||||
let expectedOptionals: [Any?] = expected.map({ $0 as Any? })
|
||||
return try! contain(expectedOptionals).matches(expr, failureMessage: failureMessage)
|
||||
return try contain(expectedOptionals).satisfies(expr).toObjectiveC()
|
||||
} else if let value = actualValue as? NSString {
|
||||
let expr = Expression(expression: ({ value as String }), location: location)
|
||||
return try! contain(expected as! [String]).matches(expr, failureMessage: failureMessage)
|
||||
} else if actualValue != nil {
|
||||
// swiftlint:disable:next line_length
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)"
|
||||
} else {
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(expected))>"
|
||||
// swiftlint:disable:next force_cast
|
||||
return try contain(expected as! [String]).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
return false
|
||||
|
||||
let message: ExpectationMessage
|
||||
if actualValue != nil {
|
||||
message = ExpectationMessage.expectedActualValueTo(
|
||||
// swiftlint:disable:next line_length
|
||||
"contain <\(arrayAsString(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)"
|
||||
)
|
||||
} else {
|
||||
message = ExpectationMessage
|
||||
.expectedActualValueTo("contain <\(arrayAsString(expected))>")
|
||||
.appendedBeNilHint()
|
||||
}
|
||||
return NMBPredicateResult(status: .fail, message: message.toObjectiveC())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-24
@@ -2,43 +2,44 @@ import Foundation
|
||||
|
||||
public func containElementSatisfying<S: Sequence, T>(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate<S> where S.Iterator.Element == T {
|
||||
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.actualValue = nil
|
||||
|
||||
return Predicate.define { actualExpression in
|
||||
let message: ExpectationMessage
|
||||
if predicateDescription == "" {
|
||||
failureMessage.postfixMessage = "find object in collection that satisfies predicate"
|
||||
message = .expectedTo("find object in collection that satisfies predicate")
|
||||
} else {
|
||||
failureMessage.postfixMessage = "find object in collection \(predicateDescription)"
|
||||
message = .expectedTo("find object in collection \(predicateDescription)")
|
||||
}
|
||||
|
||||
if let sequence = try actualExpression.evaluate() {
|
||||
for object in sequence {
|
||||
if predicate(object) {
|
||||
return true
|
||||
return PredicateResult(bool: true, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return PredicateResult(bool: false, message: message)
|
||||
}
|
||||
|
||||
return false
|
||||
}.requireNonNil
|
||||
return PredicateResult(status: .fail, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
let value = try! actualExpression.evaluate()
|
||||
@objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let value = try actualExpression.evaluate()
|
||||
guard let enumeration = value as? NSFastEnumeration else {
|
||||
// swiftlint:disable:next line_length
|
||||
failureMessage.postfixMessage = "containElementSatisfying must be provided an NSFastEnumeration object"
|
||||
failureMessage.actualValue = nil
|
||||
failureMessage.expected = ""
|
||||
failureMessage.to = ""
|
||||
return false
|
||||
let message = ExpectationMessage.fail(
|
||||
"containElementSatisfying must be provided an NSFastEnumeration object"
|
||||
)
|
||||
return NMBPredicateResult(status: .fail, message: message.toObjectiveC())
|
||||
}
|
||||
|
||||
let message = ExpectationMessage
|
||||
.expectedTo("find object in collection that satisfies predicate")
|
||||
.toObjectiveC()
|
||||
|
||||
var iterator = NSFastEnumerationIterator(enumeration)
|
||||
while let item = iterator.next() {
|
||||
guard let object = item as? NSObject else {
|
||||
@@ -46,14 +47,11 @@ public func containElementSatisfying<S: Sequence, T>(_ predicate: @escaping ((T)
|
||||
}
|
||||
|
||||
if predicate(object) {
|
||||
return true
|
||||
return NMBPredicateResult(status: .matches, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
failureMessage.actualValue = nil
|
||||
failureMessage.postfixMessage = ""
|
||||
failureMessage.to = "to find object in collection that satisfies predicate"
|
||||
return false
|
||||
return NMBPredicateResult(status: .doesNotMatch, message: message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/// A Nimble matcher that succeeds when the actual sequence contain the same elements in the same order to the exepected sequence.
|
||||
public func elementsEqual<S: Sequence>(_ expectedValue: S?) -> Predicate<S> where S.Element: Equatable {
|
||||
// A matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal
|
||||
return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
switch (expectedValue, actualValue) {
|
||||
case (nil, _?):
|
||||
return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
|
||||
case (nil, nil), (_, nil):
|
||||
return PredicateResult(status: .fail, message: msg)
|
||||
case (let expected?, let actual?):
|
||||
let matches = expected.elementsEqual(actual)
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-25
@@ -4,9 +4,7 @@ import Foundation
|
||||
/// is equal to the expected value.
|
||||
public func endWith<S: Sequence, T: Equatable>(_ endingElement: T) -> Predicate<S>
|
||||
where S.Iterator.Element == T {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "end with <\(endingElement)>"
|
||||
|
||||
return Predicate.simple("end with <\(endingElement)>") { actualExpression in
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
var actualGenerator = actualValue.makeIterator()
|
||||
var lastItem: T?
|
||||
@@ -16,55 +14,54 @@ public func endWith<S: Sequence, T: Equatable>(_ endingElement: T) -> Predicate<
|
||||
item = actualGenerator.next()
|
||||
} while(item != nil)
|
||||
|
||||
return lastItem == endingElement
|
||||
return PredicateStatus(bool: lastItem == endingElement)
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection's last element
|
||||
/// is equal to the expected object.
|
||||
public func endWith(_ endingElement: Any) -> Predicate<NMBOrderedCollection> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "end with <\(endingElement)>"
|
||||
guard let collection = try actualExpression.evaluate() else { return false }
|
||||
guard collection.count > 0 else { return false }
|
||||
return Predicate.simple("end with <\(endingElement)>") { actualExpression in
|
||||
guard let collection = try actualExpression.evaluate() else { return .fail }
|
||||
guard collection.count > 0 else { return PredicateStatus(bool: false) }
|
||||
#if os(Linux)
|
||||
guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else {
|
||||
return false
|
||||
return .fail
|
||||
}
|
||||
#else
|
||||
let collectionValue = collection.object(at: collection.count - 1) as AnyObject
|
||||
#endif
|
||||
|
||||
return collectionValue.isEqual(endingElement)
|
||||
}.requireNonNil
|
||||
return PredicateStatus(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<String> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "end with <\(endingSubstring)>"
|
||||
return Predicate.simple("end with <\(endingSubstring)>") { actualExpression in
|
||||
if let collection = try actualExpression.evaluate() {
|
||||
return collection.hasSuffix(endingSubstring)
|
||||
return PredicateStatus(bool: collection.hasSuffix(endingSubstring))
|
||||
}
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func endWithMatcher(_ expected: Any) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
let actual = try! actualExpression.evaluate()
|
||||
if (actual as? String) != nil {
|
||||
@objc public class func endWithMatcher(_ expected: Any) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let actual = try actualExpression.evaluate()
|
||||
if actual is String {
|
||||
let expr = actualExpression.cast { $0 as? String }
|
||||
return try! endWith(expected as! String).matches(expr, failureMessage: failureMessage)
|
||||
// swiftlint:disable:next force_cast
|
||||
return try endWith(expected as! String).satisfies(expr).toObjectiveC()
|
||||
} else {
|
||||
let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
|
||||
return try! endWith(expected).matches(expr, failureMessage: failureMessage)
|
||||
return try endWith(expected).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+48
-120
@@ -7,103 +7,30 @@ import Foundation
|
||||
public func equal<T: Equatable>(_ expectedValue: T?) -> Predicate<T> {
|
||||
return Predicate.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(
|
||||
status: .fail,
|
||||
message: msg.appendedBeNilHint()
|
||||
)
|
||||
}
|
||||
switch (expectedValue, actualValue) {
|
||||
case (nil, _?):
|
||||
return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
|
||||
case (nil, nil), (_, nil):
|
||||
return PredicateResult(status: .fail, message: msg)
|
||||
case (let expected?, let actual?):
|
||||
let matches = expected == actual
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
return PredicateResult(status: PredicateStatus(bool: matches), message: msg)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is equal to the expected value.
|
||||
/// Values can support equal by supporting the Equatable protocol.
|
||||
///
|
||||
/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles).
|
||||
public func equal<T, C: Equatable>(_ expectedValue: [T: C]?) -> Predicate<[T: C]> {
|
||||
return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if expectedValue == nil || actualValue == nil {
|
||||
if expectedValue == nil && actualValue != nil {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: msg.appendedBeNilHint()
|
||||
)
|
||||
}
|
||||
return PredicateResult(status: .fail, message: msg)
|
||||
}
|
||||
return PredicateResult(
|
||||
status: PredicateStatus(bool: expectedValue! == actualValue!),
|
||||
message: msg
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection is equal to the expected collection.
|
||||
/// Items must implement the Equatable protocol.
|
||||
public func equal<T: Equatable>(_ expectedValue: [T]?) -> Predicate<[T]> {
|
||||
return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if expectedValue == nil || actualValue == nil {
|
||||
if expectedValue == nil && actualValue != nil {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: msg.appendedBeNilHint()
|
||||
)
|
||||
}
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: msg
|
||||
)
|
||||
}
|
||||
return PredicateResult(
|
||||
bool: expectedValue! == actualValue!,
|
||||
message: msg
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher allowing comparison of collection with optional type
|
||||
public func equal<T: Equatable>(_ expectedValue: [T?]) -> Predicate<[T?]> {
|
||||
return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
let doesNotMatch = PredicateResult(
|
||||
status: .doesNotMatch,
|
||||
message: msg
|
||||
)
|
||||
|
||||
if expectedValue.count != actualValue.count {
|
||||
return doesNotMatch
|
||||
}
|
||||
|
||||
for (index, item) in actualValue.enumerated() {
|
||||
let otherItem = expectedValue[index]
|
||||
if item == nil && otherItem == nil {
|
||||
continue
|
||||
} else if item == nil && otherItem != nil {
|
||||
return doesNotMatch
|
||||
} else if item != nil && otherItem == nil {
|
||||
return doesNotMatch
|
||||
} else if item! != otherItem! {
|
||||
return doesNotMatch
|
||||
}
|
||||
}
|
||||
|
||||
return PredicateResult(
|
||||
status: .matches,
|
||||
message: msg
|
||||
)
|
||||
} else {
|
||||
guard let actualValue = try actualExpression.evaluate() else {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: msg.appendedBeNilHint()
|
||||
)
|
||||
}
|
||||
|
||||
let matches = expectedValue == actualValue
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,44 +55,45 @@ private func equal<T>(_ expectedValue: Set<T>?, stringify: @escaping (Set<T>?) -
|
||||
var errorMessage: ExpectationMessage =
|
||||
.expectedActualValueTo("equal <\(stringify(expectedValue))>")
|
||||
|
||||
if let expectedValue = expectedValue {
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
errorMessage = .expectedCustomValueTo(
|
||||
"equal <\(stringify(expectedValue))>",
|
||||
"<\(stringify(actualValue))>"
|
||||
)
|
||||
|
||||
if expectedValue == actualValue {
|
||||
return PredicateResult(
|
||||
status: .matches,
|
||||
message: errorMessage
|
||||
)
|
||||
}
|
||||
|
||||
let missing = expectedValue.subtracting(actualValue)
|
||||
if missing.count > 0 {
|
||||
errorMessage = errorMessage.appended(message: ", missing <\(stringify(missing))>")
|
||||
}
|
||||
|
||||
let extra = actualValue.subtracting(expectedValue)
|
||||
if extra.count > 0 {
|
||||
errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>")
|
||||
}
|
||||
return PredicateResult(
|
||||
status: .doesNotMatch,
|
||||
message: errorMessage
|
||||
)
|
||||
}
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: errorMessage.appendedBeNilHint()
|
||||
)
|
||||
} else {
|
||||
guard let expectedValue = expectedValue else {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: errorMessage.appendedBeNilHint()
|
||||
)
|
||||
}
|
||||
|
||||
guard let actualValue = try actualExpression.evaluate() else {
|
||||
return PredicateResult(
|
||||
status: .fail,
|
||||
message: errorMessage.appendedBeNilHint()
|
||||
)
|
||||
}
|
||||
|
||||
errorMessage = .expectedCustomValueTo(
|
||||
"equal <\(stringify(expectedValue))>",
|
||||
"<\(stringify(actualValue))>"
|
||||
)
|
||||
|
||||
if expectedValue == actualValue {
|
||||
return PredicateResult(
|
||||
status: .matches,
|
||||
message: errorMessage
|
||||
)
|
||||
}
|
||||
|
||||
let missing = expectedValue.subtracting(actualValue)
|
||||
if missing.count > 0 {
|
||||
errorMessage = errorMessage.appended(message: ", missing <\(stringify(missing))>")
|
||||
}
|
||||
|
||||
let extra = actualValue.subtracting(expectedValue)
|
||||
if extra.count > 0 {
|
||||
errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>")
|
||||
}
|
||||
return PredicateResult(
|
||||
status: .doesNotMatch,
|
||||
message: errorMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,11 +137,11 @@ public func !=<T, C: Equatable>(lhs: Expectation<[T: C]>, rhs: [T: C]?) {
|
||||
lhs.toNot(equal(rhs))
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
return try! equal(expected).matches(actualExpression, failureMessage: failureMessage)
|
||||
return NMBPredicate { actualExpression in
|
||||
return try equal(expected).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+40
-25
@@ -7,52 +7,67 @@ import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual Collection's count equals
|
||||
/// the expected value
|
||||
public func haveCount<T: Collection>(_ expectedValue: T.IndexDistance) -> Predicate<T> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
public func haveCount<T: Collection>(_ expectedValue: Int) -> Predicate<T> {
|
||||
return Predicate.define { actualExpression in
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
// swiftlint:disable:next line_length
|
||||
failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))"
|
||||
let message = ExpectationMessage
|
||||
.expectedCustomValueTo(
|
||||
"have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))",
|
||||
"\(actualValue.count)"
|
||||
)
|
||||
.appended(details: "Actual Value: \(stringify(actualValue))")
|
||||
|
||||
let result = expectedValue == actualValue.count
|
||||
failureMessage.actualValue = "\(actualValue.count)"
|
||||
failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))"
|
||||
return result
|
||||
return PredicateResult(bool: result, message: message)
|
||||
} else {
|
||||
return false
|
||||
return PredicateResult(status: .fail, message: .fail(""))
|
||||
}
|
||||
}.requireNonNil
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection's count equals
|
||||
/// the expected value
|
||||
public func haveCount(_ expectedValue: Int) -> Predicate<NMBCollection> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
return Predicate { actualExpression in
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
// swiftlint:disable:next line_length
|
||||
failureMessage.postfixMessage = "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))"
|
||||
let message = ExpectationMessage
|
||||
.expectedCustomValueTo(
|
||||
"have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))",
|
||||
"\(actualValue.count)"
|
||||
)
|
||||
.appended(details: "Actual Value: \(stringify(actualValue))")
|
||||
|
||||
let result = expectedValue == actualValue.count
|
||||
failureMessage.actualValue = "\(actualValue.count)"
|
||||
failureMessage.extendedMessage = "Actual Value: \(stringify(actualValue))"
|
||||
return result
|
||||
return PredicateResult(bool: result, message: message)
|
||||
} else {
|
||||
return false
|
||||
return PredicateResult(status: .fail, message: .fail(""))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
@objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBMatcher {
|
||||
return NMBPredicate { actualExpression in
|
||||
let location = actualExpression.location
|
||||
let actualValue = try! actualExpression.evaluate()
|
||||
let actualValue = try actualExpression.evaluate()
|
||||
if let value = actualValue as? NMBCollection {
|
||||
let expr = Expression(expression: ({ value as NMBCollection}), location: location)
|
||||
return try! haveCount(expected.intValue).matches(expr, failureMessage: failureMessage)
|
||||
} else if let actualValue = actualValue {
|
||||
failureMessage.postfixMessage = "get type of NSArray, NSSet, NSDictionary, or NSHashTable"
|
||||
failureMessage.actualValue = "\(String(describing: type(of: actualValue)))"
|
||||
return try haveCount(expected.intValue).satisfies(expr).toObjectiveC()
|
||||
}
|
||||
return false
|
||||
|
||||
let message: ExpectationMessage
|
||||
if let actualValue = actualValue {
|
||||
message = ExpectationMessage.expectedCustomValueTo(
|
||||
"get type of NSArray, NSSet, NSDictionary, or NSHashTable",
|
||||
"\(String(describing: type(of: actualValue)))"
|
||||
)
|
||||
} else {
|
||||
message = ExpectationMessage
|
||||
.expectedActualValueTo("have a collection with count \(stringify(expected.intValue))")
|
||||
.appendedBeNilHint()
|
||||
}
|
||||
return NMBPredicateResult(status: .fail, message: message.toObjectiveC())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-9
@@ -3,26 +3,25 @@ import Foundation
|
||||
/// A Nimble matcher that succeeds when the actual string satisfies the regular expression
|
||||
/// described by the expected string.
|
||||
public func match(_ expectedValue: String?) -> Predicate<String> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "match <\(stringify(expectedValue))>"
|
||||
|
||||
return Predicate.simple("match <\(stringify(expectedValue))>") { actualExpression in
|
||||
if let actual = try actualExpression.evaluate() {
|
||||
if let regexp = expectedValue {
|
||||
return actual.range(of: regexp, options: .regularExpression) != nil
|
||||
let bool = actual.range(of: regexp, options: .regularExpression) != nil
|
||||
return PredicateStatus(bool: bool)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}.requireNonNil
|
||||
return .fail
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
|
||||
return NMBPredicate { actualExpression in
|
||||
let actual = actualExpression.cast { $0 as? String }
|
||||
return try! match(expected.description).matches(actual, failureMessage: failureMessage)
|
||||
return try match(expected.description).satisfies(actual).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-14
@@ -6,16 +6,24 @@ import Foundation
|
||||
/// Errors are tried to be compared by their implementation of Equatable,
|
||||
/// otherwise they fallback to comparison by _domain and _code.
|
||||
public func matchError<T: Error>(_ error: T) -> Predicate<Error> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
let actualError: Error? = try actualExpression.evaluate()
|
||||
return Predicate.define { actualExpression in
|
||||
let actualError = try actualExpression.evaluate()
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
postfixMessageVerb: "match",
|
||||
actualError: actualError,
|
||||
error: error
|
||||
)
|
||||
|
||||
setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error)
|
||||
var matches = false
|
||||
if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) {
|
||||
matches = true
|
||||
}
|
||||
return matches
|
||||
}.requireNonNil
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression evaluates to an
|
||||
@@ -24,35 +32,45 @@ public func matchError<T: Error>(_ error: T) -> Predicate<Error> {
|
||||
/// Errors are tried to be compared by their implementation of Equatable,
|
||||
/// otherwise they fallback to comparision by _domain and _code.
|
||||
public func matchError<T: Error & Equatable>(_ error: T) -> Predicate<Error> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
let actualError: Error? = try actualExpression.evaluate()
|
||||
return Predicate.define { actualExpression in
|
||||
let actualError = try actualExpression.evaluate()
|
||||
|
||||
setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error)
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
postfixMessageVerb: "match",
|
||||
actualError: actualError,
|
||||
error: error
|
||||
)
|
||||
|
||||
var matches = false
|
||||
if let actualError = actualError as? T, error == actualError {
|
||||
matches = true
|
||||
}
|
||||
return matches
|
||||
}.requireNonNil
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression evaluates to an
|
||||
/// error of the specified type
|
||||
public func matchError<T: Error>(_ errorType: T.Type) -> Predicate<Error> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
let actualError: Error? = try actualExpression.evaluate()
|
||||
return Predicate.define { actualExpression in
|
||||
let actualError = try actualExpression.evaluate()
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
postfixMessageVerb: "match",
|
||||
actualError: actualError,
|
||||
errorType: errorType
|
||||
)
|
||||
|
||||
var matches = false
|
||||
if actualError as? T != nil {
|
||||
matches = true
|
||||
}
|
||||
return matches
|
||||
}.requireNonNil
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux.
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
import CoreGraphics
|
||||
#endif
|
||||
|
||||
@@ -28,11 +28,11 @@ extension Matcher {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
/// Objective-C interface to the Swift variant of Matcher.
|
||||
@objc public protocol NMBMatcher {
|
||||
func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool
|
||||
func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool
|
||||
func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool
|
||||
func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -41,7 +41,8 @@ public protocol NMBContainer {
|
||||
func contains(_ anObject: Any) -> Bool
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
// swiftlint:disable:next todo
|
||||
// FIXME: NSHashTable can not conform to NMBContainer since swift-DEVELOPMENT-SNAPSHOT-2016-04-25-a
|
||||
//extension NSHashTable : NMBContainer {} // Corelibs Foundation does not include this class yet
|
||||
#endif
|
||||
@@ -54,7 +55,7 @@ public protocol NMBCollection {
|
||||
var count: Int { get }
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NSHashTable: NMBCollection {} // Corelibs Foundation does not include these classes yet
|
||||
extension NSMapTable: NMBCollection {}
|
||||
#endif
|
||||
@@ -131,7 +132,7 @@ extension NSDate: TestOutputStringConvertible {
|
||||
/// beGreaterThan(), beGreaterThanOrEqualTo(), and equal() matchers.
|
||||
///
|
||||
/// Types that conform to Swift's Comparable protocol will work implicitly too
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
@objc public protocol NMBComparable {
|
||||
func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult
|
||||
}
|
||||
@@ -144,11 +145,13 @@ public protocol NMBComparable {
|
||||
|
||||
extension NSNumber: NMBComparable {
|
||||
public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult {
|
||||
// swiftlint:disable:next force_cast
|
||||
return compare(otherObject as! NSNumber)
|
||||
}
|
||||
}
|
||||
extension NSString: NMBComparable {
|
||||
public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult {
|
||||
// swiftlint:disable:next force_cast
|
||||
return compare(otherObject as! String)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,9 @@
|
||||
import Foundation
|
||||
|
||||
// A workaround to SR-6419.
|
||||
extension NotificationCenter {
|
||||
#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
|
||||
#if swift(>=4.0)
|
||||
#if swift(>=4.0.2)
|
||||
#else
|
||||
func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol {
|
||||
return addObserver(forName: name, object: obj, queue: queue, usingBlock: block)
|
||||
}
|
||||
#endif
|
||||
#elseif swift(>=3.2)
|
||||
#if swift(>=3.2.2)
|
||||
#else
|
||||
// swiftlint:disable:next line_length
|
||||
func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol {
|
||||
return addObserver(forName: name, object: obj, queue: queue, usingBlock: block)
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// swiftlint:disable:next line_length
|
||||
func addObserver(forName name: Notification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol {
|
||||
return addObserver(forName: name, object: obj, queue: queue, usingBlock: block)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
internal class NotificationCollector {
|
||||
private(set) var observedNotifications: [Notification]
|
||||
private let notificationCenter: NotificationCenter
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
private var token: AnyObject?
|
||||
#else
|
||||
private var token: NSObjectProtocol?
|
||||
@@ -43,14 +16,14 @@ internal class NotificationCollector {
|
||||
|
||||
func startObserving() {
|
||||
// swiftlint:disable:next line_length
|
||||
self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil, using: { [weak self] n in
|
||||
self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { [weak self] notification in
|
||||
// linux-swift gets confused by .append(n)
|
||||
self?.observedNotifications.append(n)
|
||||
})
|
||||
self?.observedNotifications.append(notification)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
if let token = self.token {
|
||||
self.notificationCenter.removeObserver(token)
|
||||
}
|
||||
@@ -74,7 +47,8 @@ public func postNotifications<T>(
|
||||
let collector = NotificationCollector(notificationCenter: center)
|
||||
collector.startObserving()
|
||||
var once: Bool = false
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
let collectorNotificationsExpression = Expression(memoizedExpression: { _ in
|
||||
return collector.observedNotifications
|
||||
}, location: actualExpression.location, withoutCaching: true)
|
||||
@@ -85,12 +59,13 @@ public func postNotifications<T>(
|
||||
_ = try actualExpression.evaluate()
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
let match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage)
|
||||
if collector.observedNotifications.isEmpty {
|
||||
failureMessage.actualValue = "no notifications"
|
||||
} else {
|
||||
failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>"
|
||||
}
|
||||
return match
|
||||
return PredicateResult(bool: match, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
+17
-12
@@ -82,8 +82,8 @@ extension Predicate {
|
||||
}
|
||||
}
|
||||
|
||||
// Question: Should this be exposed? It's safer to not for now and decide later.
|
||||
internal enum ExpectationStyle {
|
||||
// The Expectation style intended for comparison to a PredicateStatus.
|
||||
public enum ExpectationStyle {
|
||||
case toMatch, toNotMatch
|
||||
}
|
||||
|
||||
@@ -91,9 +91,9 @@ internal enum ExpectationStyle {
|
||||
/// predicate.
|
||||
public struct PredicateResult {
|
||||
/// Status indicates if the predicate matches, does not match, or fails.
|
||||
var status: PredicateStatus
|
||||
public var status: PredicateStatus
|
||||
/// The error message that can be displayed if it does not match
|
||||
var message: ExpectationMessage
|
||||
public var message: ExpectationMessage
|
||||
|
||||
/// Constructs a new PredicateResult with a given status and error message
|
||||
public init(status: PredicateStatus, message: ExpectationMessage) {
|
||||
@@ -108,7 +108,7 @@ public struct PredicateResult {
|
||||
}
|
||||
|
||||
/// Converts the result to a boolean based on what the expectation intended
|
||||
internal func toBoolean(expectation style: ExpectationStyle) -> Bool {
|
||||
public func toBoolean(expectation style: ExpectationStyle) -> Bool {
|
||||
return status.toBoolean(expectation: style)
|
||||
}
|
||||
}
|
||||
@@ -218,6 +218,7 @@ extension Predicate: Matcher {
|
||||
extension Predicate {
|
||||
// Someday, make this public? Needs documentation
|
||||
internal func after(f: @escaping (Expression<T>, PredicateResult) throws -> PredicateResult) -> Predicate<T> {
|
||||
// swiftlint:disable:previous identifier_name
|
||||
return Predicate { actual -> PredicateResult in
|
||||
let result = try self.satisfies(actual)
|
||||
return try f(actual, result)
|
||||
@@ -241,8 +242,8 @@ extension Predicate {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
public typealias PredicateBlock = (_ actualExpression: Expression<NSObject>) -> NMBPredicateResult
|
||||
#if canImport(Darwin)
|
||||
public typealias PredicateBlock = (_ actualExpression: Expression<NSObject>) throws -> NMBPredicateResult
|
||||
|
||||
public class NMBPredicate: NSObject {
|
||||
private let predicate: PredicateBlock
|
||||
@@ -251,20 +252,24 @@ public class NMBPredicate: NSObject {
|
||||
self.predicate = predicate
|
||||
}
|
||||
|
||||
func satisfies(_ expression: @escaping () -> NSObject!, location: SourceLocation) -> NMBPredicateResult {
|
||||
func satisfies(_ expression: @escaping () throws -> NSObject?, location: SourceLocation) -> NMBPredicateResult {
|
||||
let expr = Expression(expression: expression, location: location)
|
||||
return self.predicate(expr)
|
||||
do {
|
||||
return try self.predicate(expr)
|
||||
} catch let error {
|
||||
return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>")).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBPredicate: NMBMatcher {
|
||||
public func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let result = satisfies(actualBlock, location: location).toSwift()
|
||||
result.message.update(failureMessage: failureMessage)
|
||||
return result.status.toBoolean(expectation: .toMatch)
|
||||
}
|
||||
|
||||
public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let result = satisfies(actualBlock, location: location).toSwift()
|
||||
result.message.update(failureMessage: failureMessage)
|
||||
return result.status.toBoolean(expectation: .toNotMatch)
|
||||
@@ -307,7 +312,7 @@ final public class NMBPredicateStatus: NSObject {
|
||||
public static let doesNotMatch: NMBPredicateStatus = NMBPredicateStatus(status: 1)
|
||||
public static let fail: NMBPredicateStatus = NMBPredicateStatus(status: 2)
|
||||
|
||||
public override var hashValue: Int { return self.status.hashValue }
|
||||
public override var hash: Int { return self.status.hashValue }
|
||||
|
||||
public override func isEqual(_ object: Any?) -> Bool {
|
||||
guard let otherPredicate = object as? NMBPredicateStatus else {
|
||||
|
||||
+27
-15
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression raises an
|
||||
/// exception with the specified name, reason, and/or userInfo.
|
||||
@@ -17,18 +17,21 @@ public func raiseException(
|
||||
reason: String? = nil,
|
||||
userInfo: NSDictionary? = nil,
|
||||
closure: ((NSException) -> Void)? = nil) -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
var exception: NSException?
|
||||
let capture = NMBExceptionCapture(handler: ({ e in
|
||||
exception = e
|
||||
}), finally: nil)
|
||||
|
||||
capture.tryBlock {
|
||||
_ = try! actualExpression.evaluate()
|
||||
return
|
||||
do {
|
||||
try capture.tryBlockThrows {
|
||||
_ = try actualExpression.evaluate()
|
||||
}
|
||||
} catch {
|
||||
return PredicateResult(status: .fail, message: .fail("unexpected error thrown: <\(error)>"))
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForException(
|
||||
failureMessage,
|
||||
exception: exception,
|
||||
@@ -37,13 +40,15 @@ public func raiseException(
|
||||
userInfo: userInfo,
|
||||
closure: closure
|
||||
)
|
||||
return exceptionMatchesNonNilFieldsOrClosure(
|
||||
|
||||
let matches = exceptionMatchesNonNilFieldsOrClosure(
|
||||
exception,
|
||||
named: named,
|
||||
reason: reason,
|
||||
userInfo: userInfo,
|
||||
closure: closure
|
||||
)
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,10 +122,12 @@ internal func exceptionMatchesNonNilFieldsOrClosure(
|
||||
}
|
||||
|
||||
public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher {
|
||||
// swiftlint:disable identifier_name
|
||||
internal var _name: String?
|
||||
internal var _reason: String?
|
||||
internal var _userInfo: NSDictionary?
|
||||
internal var _block: ((NSException) -> Void)?
|
||||
// swiftlint:enable identifier_name
|
||||
|
||||
internal init(name: String?, reason: String?, userInfo: NSDictionary?, block: ((NSException) -> Void)?) {
|
||||
_name = name
|
||||
@@ -129,19 +136,24 @@ public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher {
|
||||
_block = block
|
||||
}
|
||||
|
||||
@objc public func matches(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
@objc public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let block: () -> Any? = ({ _ = actualBlock(); return nil })
|
||||
let expr = Expression(expression: block, location: location)
|
||||
|
||||
return try! raiseException(
|
||||
named: _name,
|
||||
reason: _reason,
|
||||
userInfo: _userInfo,
|
||||
closure: _block
|
||||
).matches(expr, failureMessage: failureMessage)
|
||||
do {
|
||||
return try raiseException(
|
||||
named: _name,
|
||||
reason: _reason,
|
||||
userInfo: _userInfo,
|
||||
closure: _block
|
||||
).matches(expr, failureMessage: failureMessage)
|
||||
} catch let error {
|
||||
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
@objc public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
return !matches(actualBlock, failureMessage: failureMessage, location: location)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import Foundation
|
||||
|
||||
/// 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<T, U>(_ matchers: U...) -> Predicate<T>
|
||||
where U: Matcher, U.ValueType == T {
|
||||
return satisfyAllOf(matchers.map { $0.predicate })
|
||||
}
|
||||
|
||||
internal func satisfyAllOf<T>(_ predicates: [Predicate<T>]) -> Predicate<T> {
|
||||
return Predicate.define { actualExpression in
|
||||
var postfixMessages = [String]()
|
||||
var matches = true
|
||||
for predicate in predicates {
|
||||
let result = try predicate.satisfies(actualExpression)
|
||||
if result.toBoolean(expectation: .toNotMatch) {
|
||||
matches = false
|
||||
}
|
||||
postfixMessages.append("{\(result.message.expectedMessage)}")
|
||||
}
|
||||
|
||||
var msg: ExpectationMessage
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
msg = .expectedCustomValueTo(
|
||||
"match all of: " + postfixMessages.joined(separator: ", and "),
|
||||
"\(actualValue)"
|
||||
)
|
||||
} else {
|
||||
msg = .expectedActualValueTo(
|
||||
"match all of: " + postfixMessages.joined(separator: ", and ")
|
||||
)
|
||||
}
|
||||
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
}
|
||||
|
||||
public func && <T>(left: Predicate<T>, right: Predicate<T>) -> Predicate<T> {
|
||||
return satisfyAllOf(left, right)
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
if matchers.isEmpty {
|
||||
return NMBPredicateResult(
|
||||
status: NMBPredicateStatus.fail,
|
||||
message: NMBExpectationMessage(
|
||||
fail: "satisfyAllOf must be called with at least one matcher"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var elementEvaluators = [Predicate<NSObject>]()
|
||||
for matcher in matchers {
|
||||
let elementEvaluator = Predicate<NSObject> { expression in
|
||||
if let predicate = matcher as? NMBPredicate {
|
||||
// swiftlint:disable:next line_length
|
||||
return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift()
|
||||
} else {
|
||||
let failureMessage = FailureMessage()
|
||||
let success = matcher.matches(
|
||||
// swiftlint:disable:next force_try
|
||||
{ try! expression.evaluate() },
|
||||
failureMessage: failureMessage,
|
||||
location: actualExpression.location
|
||||
)
|
||||
return PredicateResult(bool: success, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
elementEvaluators.append(elementEvaluator)
|
||||
}
|
||||
|
||||
return try satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+13
-34
@@ -4,33 +4,11 @@ import Foundation
|
||||
/// provided in the variable list of matchers.
|
||||
public func satisfyAnyOf<T, U>(_ matchers: U...) -> Predicate<T>
|
||||
where U: Matcher, U.ValueType == T {
|
||||
return satisfyAnyOf(matchers)
|
||||
}
|
||||
|
||||
/// Deprecated. Please use `satisfyAnyOf<T>(_) -> Predicate<T>` instead.
|
||||
internal func satisfyAnyOf<T, U>(_ matchers: [U]) -> Predicate<T>
|
||||
where U: Matcher, U.ValueType == T {
|
||||
return NonNilMatcherFunc<T> { actualExpression, failureMessage in
|
||||
let postfixMessages = NSMutableArray()
|
||||
var matches = false
|
||||
for matcher in matchers {
|
||||
if try matcher.matches(actualExpression, failureMessage: failureMessage) {
|
||||
matches = true
|
||||
}
|
||||
postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}"))
|
||||
}
|
||||
|
||||
failureMessage.postfixMessage = "match one of: " + postfixMessages.componentsJoined(by: ", or ")
|
||||
if let actualValue = try actualExpression.evaluate() {
|
||||
failureMessage.actualValue = "\(actualValue)"
|
||||
}
|
||||
|
||||
return matches
|
||||
}.predicate
|
||||
return satisfyAnyOf(matchers.map { $0.predicate })
|
||||
}
|
||||
|
||||
internal func satisfyAnyOf<T>(_ predicates: [Predicate<T>]) -> Predicate<T> {
|
||||
return Predicate { actualExpression in
|
||||
return Predicate.define { actualExpression in
|
||||
var postfixMessages = [String]()
|
||||
var matches = false
|
||||
for predicate in predicates {
|
||||
@@ -53,11 +31,8 @@ internal func satisfyAnyOf<T>(_ predicates: [Predicate<T>]) -> Predicate<T> {
|
||||
)
|
||||
}
|
||||
|
||||
return PredicateResult(
|
||||
status: PredicateStatus(bool: matches),
|
||||
message: msg
|
||||
)
|
||||
}.requireNonNil
|
||||
return PredicateResult(bool: matches, message: msg)
|
||||
}
|
||||
}
|
||||
|
||||
public func || <T>(left: Predicate<T>, right: Predicate<T>) -> Predicate<T> {
|
||||
@@ -72,7 +47,7 @@ public func || <T>(left: MatcherFunc<T>, right: MatcherFunc<T>) -> Predicate<T>
|
||||
return satisfyAnyOf(left, right)
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
extension NMBObjCMatcher {
|
||||
@objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate {
|
||||
return NMBPredicate { actualExpression in
|
||||
@@ -90,11 +65,15 @@ extension NMBObjCMatcher {
|
||||
let elementEvaluator = Predicate<NSObject> { expression in
|
||||
if let predicate = matcher as? NMBPredicate {
|
||||
// swiftlint:disable:next line_length
|
||||
return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift()
|
||||
return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift()
|
||||
} else {
|
||||
let failureMessage = FailureMessage()
|
||||
// swiftlint:disable:next line_length
|
||||
let success = matcher.matches({ try! expression.evaluate() }, failureMessage: failureMessage, location: actualExpression.location)
|
||||
let success = matcher.matches(
|
||||
// swiftlint:disable:next force_try
|
||||
{ try! expression.evaluate() },
|
||||
failureMessage: failureMessage,
|
||||
location: actualExpression.location
|
||||
)
|
||||
return PredicateResult(bool: success, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
@@ -102,7 +81,7 @@ extension NMBObjCMatcher {
|
||||
elementEvaluators.append(elementEvaluator)
|
||||
}
|
||||
|
||||
return try! satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC()
|
||||
return try satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-20
@@ -1,13 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
public func throwAssertion() -> Predicate<Void> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
#if arch(x86_64) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
failureMessage.postfixMessage = "throw an assertion"
|
||||
failureMessage.actualValue = nil
|
||||
|
||||
var succeeded = true
|
||||
return Predicate { actualExpression in
|
||||
#if arch(x86_64) && canImport(Darwin) && !SWIFT_PACKAGE
|
||||
let message = ExpectationMessage.expectedTo("throw an assertion")
|
||||
|
||||
var actualError: Error?
|
||||
let caughtException: BadInstructionException? = catchBadInstruction {
|
||||
#if os(tvOS)
|
||||
if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning {
|
||||
@@ -27,30 +25,27 @@ public func throwAssertion() -> Predicate<Void> {
|
||||
#endif
|
||||
do {
|
||||
try actualExpression.evaluate()
|
||||
} catch let error {
|
||||
succeeded = false
|
||||
failureMessage.postfixMessage += "; threw error instead <\(error)>"
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
}
|
||||
|
||||
if !succeeded {
|
||||
return false
|
||||
if let actualError = actualError {
|
||||
return PredicateResult(
|
||||
bool: false,
|
||||
message: message.appended(message: "; threw error instead <\(actualError)>")
|
||||
)
|
||||
} else {
|
||||
return PredicateResult(bool: caughtException != nil, message: message)
|
||||
}
|
||||
|
||||
if caughtException == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
#elseif SWIFT_PACKAGE
|
||||
fatalError("The throwAssertion Nimble matcher does not currently support Swift CLI." +
|
||||
" You can silence this error by placing the test case inside an #if !SWIFT_PACKAGE" +
|
||||
" conditional statement")
|
||||
#else
|
||||
fatalError("The throwAssertion Nimble matcher can only run on x86_64 platforms with " +
|
||||
"Objective-C (e.g. Mac, iPhone 5s or later simulators). You can silence this error " +
|
||||
"by placing the test case inside an #if arch(x86_64) or (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) conditional statement")
|
||||
// swiftlint:disable:previous line_length
|
||||
"Objective-C (e.g. macOS, iPhone 5s or later simulators). You can silence this error " +
|
||||
"by placing the test case inside an #if arch(x86_64) or canImport(Darwin) conditional statement")
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
+45
-39
@@ -12,22 +12,19 @@ import Foundation
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func throwError() -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
_ = try actualExpression.evaluate()
|
||||
} catch let catchedError {
|
||||
actualError = catchedError
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
|
||||
failureMessage.postfixMessage = "throw any error"
|
||||
if let actualError = actualError {
|
||||
failureMessage.actualValue = "<\(actualError)>"
|
||||
return PredicateResult(bool: true, message: .expectedCustomValueTo("throw any error", "<\(actualError)>"))
|
||||
} else {
|
||||
failureMessage.actualValue = "no error"
|
||||
return PredicateResult(bool: false, message: .expectedCustomValueTo("throw any error", "no error"))
|
||||
}
|
||||
return actualError != nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,15 +40,15 @@ public func throwError() -> Predicate<Any> {
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func throwError<T: Error>(_ error: T, closure: ((Error) -> Void)? = nil) -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
_ = try actualExpression.evaluate()
|
||||
} catch let catchedError {
|
||||
actualError = catchedError
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
actualError: actualError,
|
||||
@@ -59,20 +56,23 @@ public func throwError<T: Error>(_ error: T, closure: ((Error) -> Void)? = nil)
|
||||
errorType: nil,
|
||||
closure: closure
|
||||
)
|
||||
|
||||
var matches = false
|
||||
if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) {
|
||||
matches = true
|
||||
|
||||
if let closure = closure {
|
||||
let assertions = gatherFailingExpectations {
|
||||
closure(actualError)
|
||||
}
|
||||
let messages = assertions.map { $0.message }
|
||||
if messages.count > 0 {
|
||||
if !messages.isEmpty {
|
||||
matches = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return matches
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,15 +88,15 @@ public func throwError<T: Error>(_ error: T, closure: ((Error) -> Void)? = nil)
|
||||
/// nil arguments indicates that the matcher should not attempt to match against
|
||||
/// that parameter.
|
||||
public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)? = nil) -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
_ = try actualExpression.evaluate()
|
||||
} catch let catchedError {
|
||||
actualError = catchedError
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
actualError: actualError,
|
||||
@@ -104,6 +104,7 @@ public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)?
|
||||
errorType: nil,
|
||||
closure: closure
|
||||
)
|
||||
|
||||
var matches = false
|
||||
if let actualError = actualError as? T, error == actualError {
|
||||
matches = true
|
||||
@@ -113,12 +114,13 @@ public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)?
|
||||
closure(actualError)
|
||||
}
|
||||
let messages = assertions.map { $0.message }
|
||||
if messages.count > 0 {
|
||||
if !messages.isEmpty {
|
||||
matches = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return matches
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,15 +138,15 @@ public func throwError<T: Error & Equatable>(_ error: T, closure: ((T) -> Void)?
|
||||
public func throwError<T: Error>(
|
||||
errorType: T.Type,
|
||||
closure: ((T) -> Void)? = nil) -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
_ = try actualExpression.evaluate()
|
||||
} catch let catchedError {
|
||||
actualError = catchedError
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(
|
||||
failureMessage,
|
||||
actualError: actualError,
|
||||
@@ -152,16 +154,18 @@ public func throwError<T: Error>(
|
||||
errorType: errorType,
|
||||
closure: closure
|
||||
)
|
||||
|
||||
var matches = false
|
||||
if let actualError = actualError {
|
||||
matches = true
|
||||
|
||||
if let actualError = actualError as? T {
|
||||
if let closure = closure {
|
||||
let assertions = gatherFailingExpectations {
|
||||
closure(actualError)
|
||||
}
|
||||
let messages = assertions.map { $0.message }
|
||||
if messages.count > 0 {
|
||||
if !messages.isEmpty {
|
||||
matches = false
|
||||
}
|
||||
}
|
||||
@@ -176,14 +180,14 @@ public func throwError<T: Error>(
|
||||
}
|
||||
}
|
||||
let messages = assertions.map { $0.message }
|
||||
if messages.count > 0 {
|
||||
if !messages.isEmpty {
|
||||
matches = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,15 +199,15 @@ public func throwError<T: Error>(
|
||||
///
|
||||
/// The closure only gets called when an error was thrown.
|
||||
public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
_ = try actualExpression.evaluate()
|
||||
} catch let catchedError {
|
||||
actualError = catchedError
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(failureMessage, actualError: actualError, closure: closure)
|
||||
|
||||
var matches = false
|
||||
@@ -214,11 +218,12 @@ public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate<Any> {
|
||||
closure(actualError)
|
||||
}
|
||||
let messages = assertions.map { $0.message }
|
||||
if messages.count > 0 {
|
||||
if !messages.isEmpty {
|
||||
matches = false
|
||||
}
|
||||
}
|
||||
return matches
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,15 +235,15 @@ public func throwError(closure: @escaping ((Error) -> Void)) -> Predicate<Any> {
|
||||
///
|
||||
/// The closure only gets called when an error was thrown.
|
||||
public func throwError<T: Error>(closure: @escaping ((T) -> Void)) -> Predicate<Any> {
|
||||
return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
|
||||
|
||||
return Predicate { actualExpression in
|
||||
var actualError: Error?
|
||||
do {
|
||||
_ = try actualExpression.evaluate()
|
||||
} catch let catchedError {
|
||||
actualError = catchedError
|
||||
} catch {
|
||||
actualError = error
|
||||
}
|
||||
|
||||
let failureMessage = FailureMessage()
|
||||
setFailureMessageForError(failureMessage, actualError: actualError, closure: closure)
|
||||
|
||||
var matches = false
|
||||
@@ -249,10 +254,11 @@ public func throwError<T: Error>(closure: @escaping ((T) -> Void)) -> Predicate<
|
||||
closure(actualError)
|
||||
}
|
||||
let messages = assertions.map { $0.message }
|
||||
if messages.count > 0 {
|
||||
if !messages.isEmpty {
|
||||
matches = false
|
||||
}
|
||||
}
|
||||
return matches
|
||||
|
||||
return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
|
||||
}
|
||||
}
|
||||
|
||||
+16
-18
@@ -2,7 +2,7 @@ import CoreFoundation
|
||||
import Dispatch
|
||||
import Foundation
|
||||
|
||||
#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
|
||||
#if canImport(CDispatch)
|
||||
import CDispatch
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,7 @@ internal class AssertionWaitLock: WaitLock {
|
||||
|
||||
func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) {
|
||||
let info = WaitingInfo(name: fnName, file: file, lineNumber: line)
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
let isMainThread = Thread.isMainThread
|
||||
#else
|
||||
let isMainThread = _CFIsMainThread()
|
||||
@@ -45,10 +45,15 @@ internal class AssertionWaitLock: WaitLock {
|
||||
nimblePrecondition(
|
||||
currentWaiter == nil,
|
||||
"InvalidNimbleAPIUsage",
|
||||
"Nested async expectations are not allowed to avoid creating flaky tests.\n\n" +
|
||||
"The call to\n\t\(info)\n" +
|
||||
"triggered this exception because\n\t\(currentWaiter!)\n" +
|
||||
"is currently managing the main run loop."
|
||||
"""
|
||||
Nested async expectations are not allowed to avoid creating flaky tests.
|
||||
|
||||
The call to
|
||||
\t\(info)
|
||||
triggered this exception because
|
||||
\t\(currentWaiter!)
|
||||
is currently managing the main run loop.
|
||||
"""
|
||||
)
|
||||
currentWaiter = info
|
||||
}
|
||||
@@ -180,25 +185,18 @@ internal class AwaitPromiseBuilder<T> {
|
||||
// checked.
|
||||
//
|
||||
// In addition, stopping the run loop is used to halt code executed on the main run loop.
|
||||
#if swift(>=4.0)
|
||||
trigger.timeoutSource.schedule(
|
||||
deadline: DispatchTime.now() + timeoutInterval,
|
||||
repeating: .never,
|
||||
leeway: timeoutLeeway
|
||||
)
|
||||
#else
|
||||
trigger.timeoutSource.scheduleOneshot(
|
||||
deadline: DispatchTime.now() + timeoutInterval,
|
||||
leeway: timeoutLeeway
|
||||
)
|
||||
#endif
|
||||
trigger.timeoutSource.setEventHandler {
|
||||
guard self.promise.asyncResult.isIncomplete() else { return }
|
||||
let timedOutSem = DispatchSemaphore(value: 0)
|
||||
let semTimedOutOrBlocked = DispatchSemaphore(value: 0)
|
||||
semTimedOutOrBlocked.signal()
|
||||
let runLoop = CFRunLoopGetMain()
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
let runLoopMode = CFRunLoopMode.defaultMode.rawValue
|
||||
#else
|
||||
let runLoopMode = kCFRunLoopDefaultMode
|
||||
@@ -263,7 +261,11 @@ internal class AwaitPromiseBuilder<T> {
|
||||
self.trigger.timeoutSource.resume()
|
||||
while self.promise.asyncResult.isIncomplete() {
|
||||
// Stopping the run loop does not work unless we run only 1 mode
|
||||
#if (swift(>=4.2) && canImport(Darwin)) || compiler(>=5.0)
|
||||
_ = RunLoop.current.run(mode: .default, before: .distantFuture)
|
||||
#else
|
||||
_ = RunLoop.current.run(mode: .defaultRunLoopMode, before: .distantFuture)
|
||||
#endif
|
||||
}
|
||||
|
||||
self.trigger.timeoutSource.cancel()
|
||||
@@ -329,11 +331,7 @@ internal class Awaiter {
|
||||
let asyncSource = createTimerSource(asyncQueue)
|
||||
let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: asyncSource) {
|
||||
let interval = DispatchTimeInterval.nanoseconds(Int(pollInterval * TimeInterval(NSEC_PER_SEC)))
|
||||
#if swift(>=4.0)
|
||||
asyncSource.schedule(deadline: .now(), repeating: interval, leeway: pollLeeway)
|
||||
#else
|
||||
asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway)
|
||||
#endif
|
||||
asyncSource.setEventHandler {
|
||||
do {
|
||||
if let result = try closure() {
|
||||
+4
-2
@@ -1,12 +1,14 @@
|
||||
import Foundation
|
||||
|
||||
#if !swift(>=4.2)
|
||||
extension Sequence {
|
||||
internal func all(_ fn: (Iterator.Element) -> Bool) -> Bool {
|
||||
internal func allSatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
|
||||
for item in self {
|
||||
if !fn(item) {
|
||||
if try !predicate(item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+6
-11
@@ -2,7 +2,7 @@ import Foundation
|
||||
|
||||
internal func identityAsString(_ value: Any?) -> String {
|
||||
let anyObject: AnyObject?
|
||||
#if os(Linux)
|
||||
#if os(Linux) && !swift(>=4.1.50)
|
||||
anyObject = value as? AnyObject
|
||||
#else
|
||||
anyObject = value as AnyObject?
|
||||
@@ -122,6 +122,7 @@ extension String: TestOutputStringConvertible {
|
||||
extension Data: TestOutputStringConvertible {
|
||||
public var testDescription: String {
|
||||
#if os(Linux)
|
||||
// swiftlint:disable:next todo
|
||||
// FIXME: Swift on Linux triggers a segfault when calling NSData's hash() (last checked on 03-11-16)
|
||||
return "Data<length=\(count)>"
|
||||
#else
|
||||
@@ -144,7 +145,9 @@ extension Data: TestOutputStringConvertible {
|
||||
/// will return the result of constructing a string from the value.
|
||||
///
|
||||
/// - SeeAlso: `TestOutputStringConvertible`
|
||||
public func stringify<T>(_ value: T) -> String {
|
||||
public func stringify<T>(_ value: T?) -> String {
|
||||
guard let value = value else { return "nil" }
|
||||
|
||||
if let value = value as? TestOutputStringConvertible {
|
||||
return value.testDescription
|
||||
}
|
||||
@@ -156,15 +159,7 @@ public func stringify<T>(_ value: T) -> String {
|
||||
return String(describing: value)
|
||||
}
|
||||
|
||||
/// -SeeAlso: `stringify<T>(value: T)`
|
||||
public func stringify<T>(_ value: T?) -> String {
|
||||
if let unboxed = value {
|
||||
return stringify(unboxed)
|
||||
}
|
||||
return "nil"
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
@objc public class NMBStringer: NSObject {
|
||||
@objc public class func stringify(_ obj: Any?) -> String {
|
||||
return Nimble.stringify(obj)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <Nimble/Nimble-Swift.h>
|
||||
|
||||
SWIFT_CLASS("_TtC6Nimble22CurrentTestCaseTracker")
|
||||
@interface CurrentTestCaseTracker : NSObject <XCTestObservation>
|
||||
+ (CurrentTestCaseTracker *)sharedInstance;
|
||||
@end
|
||||
|
||||
@interface CurrentTestCaseTracker (Register) @end
|
||||
@@ -350,6 +350,12 @@ NIMBLE_EXPORT id<NMBMatcher> NMB_satisfyAnyOfWithMatchers(id matchers);
|
||||
#define satisfyAnyOf(...) NMB_satisfyAnyOf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_satisfyAllOfWithMatchers(id matchers);
|
||||
#define NMB_satisfyAllOf(...) NMB_satisfyAllOfWithMatchers(@[__VA_ARGS__])
|
||||
#ifndef NIMBLE_DISABLE_SHORT_SYNTAX
|
||||
#define satisfyAllOf(...) NMB_satisfyAllOf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
// In order to preserve breakpoint behavior despite using macros to fill in __FILE__ and __LINE__,
|
||||
// define a builder that populates __FILE__ and __LINE__, and returns a block that takes timeout
|
||||
// and action arguments. See https://github.com/Quick/Quick/pull/185 for details.
|
||||
|
||||
+9
-8
@@ -1,13 +1,10 @@
|
||||
#import <Nimble/DSL.h>
|
||||
|
||||
#if __has_include("Nimble-Swift.h")
|
||||
#import "Nimble-Swift.h"
|
||||
#else
|
||||
#import <Nimble/Nimble-Swift.h>
|
||||
|
||||
SWIFT_CLASS("_TtC6Nimble7NMBWait")
|
||||
@interface NMBWait : NSObject
|
||||
|
||||
+ (void)untilTimeout:(NSTimeInterval)timeout file:(NSString *)file line:(NSUInteger)line action:(void (^ _Nonnull)(void (^ _Nonnull)(void)))action;
|
||||
+ (void)untilFile:(NSString *)file line:(NSUInteger)line action:(void (^ _Nonnull)(void (^ _Nonnull)(void)))action;
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -141,6 +138,10 @@ NIMBLE_EXPORT id<NMBMatcher> NMB_satisfyAnyOfWithMatchers(id matchers) {
|
||||
return [NMBObjCMatcher satisfyAnyOfMatcher:matchers];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_satisfyAllOfWithMatchers(id matchers) {
|
||||
return [NMBObjCMatcher satisfyAllOfMatcher:matchers];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException() {
|
||||
return [NMBObjCMatcher raiseExceptionMatcher];
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)tryBlock:(void(^ _Nonnull)(void))unsafeBlock {
|
||||
- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock {
|
||||
@try {
|
||||
unsafeBlock();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#import "NMBStringify.h"
|
||||
|
||||
#if __has_include("Nimble-Swift.h")
|
||||
#import "Nimble-Swift.h"
|
||||
#else
|
||||
#import <Nimble/Nimble-Swift.h>
|
||||
#endif
|
||||
|
||||
NSString *_Nonnull NMBStringify(id _Nullable anyObject) {
|
||||
return [NMBStringer stringify:anyObject];
|
||||
|
||||
+6
-1
@@ -1,7 +1,12 @@
|
||||
#import "CurrentTestCaseTracker.h"
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if __has_include("Nimble-Swift.h")
|
||||
#import "Nimble-Swift.h"
|
||||
#else
|
||||
#import <Nimble/Nimble-Swift.h>
|
||||
#endif
|
||||
|
||||
#pragma mark - Method Swizzling
|
||||
|
||||
/// Swaps the implementations between two instance methods.
|
||||
|
||||
+1203
-1055
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1010"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1AB61EB02FDF0033DCB1F8416419F110"
|
||||
BuildableName = "SwiftAudio.framework"
|
||||
BlueprintName = "SwiftAudio"
|
||||
ReferencedContainer = "container:Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1AB61EB02FDF0033DCB1F8416419F110"
|
||||
BuildableName = "SwiftAudio.framework"
|
||||
BlueprintName = "SwiftAudio"
|
||||
ReferencedContainer = "container:Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
Generated
+3
-1
@@ -4,6 +4,7 @@
|
||||
[](https://cocoapods.org/pods/Quick)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://cocoapods.org/pods/Quick)
|
||||
[](https://houndci.com)
|
||||
|
||||
Quick is a behavior-driven development framework for Swift and Objective-C.
|
||||
Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo).
|
||||
@@ -44,7 +45,8 @@ Certain versions of Quick and Nimble only support certain versions of Swift. Dep
|
||||
|
||||
|Swift version |Quick version |Nimble version |
|
||||
|:--------------------|:---------------|:--------------|
|
||||
|Swift 3 |v1.0.0 or later |v5.0.0 or later|
|
||||
|Swift 4.2 |v1.3.2 or later |v7.3.2 or later|
|
||||
|Swift 3 / Swift 4 |v1.0.0 or later |v5.0.0 or later|
|
||||
|Swift 2.2 / Swift 2.3|v0.9.3 |v4.1.0 |
|
||||
|
||||
## Documentation
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
open class Behavior<Context> {
|
||||
|
||||
open static var name: String { return String(describing: self) }
|
||||
public static var name: String { return String(describing: self) }
|
||||
/**
|
||||
override this method in your behavior to define a set of reusable examples.
|
||||
|
||||
|
||||
+3
-9
@@ -1,14 +1,8 @@
|
||||
import Foundation
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _CallsiteBase: NSObject {}
|
||||
#else
|
||||
public class _CallsiteBase: NSObject {}
|
||||
#endif
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _CallsiteBase: NSObject {}
|
||||
#else
|
||||
public class _CallsiteBase: NSObject {}
|
||||
#endif
|
||||
|
||||
@@ -72,7 +72,7 @@ final public class Configuration: NSObject {
|
||||
provided with metadata on the example that the closure is being run
|
||||
prior to.
|
||||
*/
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
@objc(beforeEachWithMetadata:)
|
||||
public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) {
|
||||
exampleHooks.appendBefore(closure)
|
||||
@@ -109,7 +109,7 @@ final public class Configuration: NSObject {
|
||||
is provided with metadata on the example that the closure is being
|
||||
run after.
|
||||
*/
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
@objc(afterEachWithMetadata:)
|
||||
public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) {
|
||||
exampleHooks.appendAfter(closure)
|
||||
|
||||
+12
-7
@@ -56,7 +56,7 @@ extension World {
|
||||
currentExampleGroup.hooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objc(beforeEachWithMetadata:)
|
||||
internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) {
|
||||
currentExampleGroup.hooks.appendBefore(closure)
|
||||
@@ -74,7 +74,7 @@ extension World {
|
||||
currentExampleGroup.hooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objc(afterEachWithMetadata:)
|
||||
internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) {
|
||||
currentExampleGroup.hooks.appendAfter(closure)
|
||||
@@ -85,6 +85,7 @@ extension World {
|
||||
}
|
||||
#endif
|
||||
|
||||
@nonobjc
|
||||
internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
if beforesCurrentlyExecuting {
|
||||
raiseError("'it' cannot be used inside 'beforeEach', 'it' may only be used inside 'context' or 'describe'. ")
|
||||
@@ -100,18 +101,21 @@ extension World {
|
||||
currentExampleGroup.appendExample(example)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
self.it(description, flags: focusedFlags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
var pendingFlags = flags
|
||||
pendingFlags[Filter.pending] = true
|
||||
self.it(description, flags: pendingFlags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) {
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ")
|
||||
@@ -131,6 +135,7 @@ extension World {
|
||||
}
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func fitBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
@@ -167,24 +172,24 @@ extension World {
|
||||
self.itBehavesLike(behavior, context: context, flags: pendingFlags, file: file, line: line)
|
||||
}
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objc(itWithDescription:flags:file:line:closure:)
|
||||
private func objc_it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
internal func objc_it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
it(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(fitWithDescription:flags:file:line:closure:)
|
||||
private func objc_fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
internal func objc_fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
fit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(xitWithDescription:flags:file:line:closure:)
|
||||
private func objc_xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
internal func objc_xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
xit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(itBehavesLikeSharedExampleNamed:sharedExampleContext:flags:file:line:)
|
||||
private func objc_itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) {
|
||||
internal func objc_itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) {
|
||||
itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line)
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
internal func raiseError(_ message: String) -> Never {
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise()
|
||||
#endif
|
||||
|
||||
|
||||
+6
-9
@@ -3,15 +3,9 @@ import Foundation
|
||||
private var numberOfExamplesRun = 0
|
||||
private var numberOfIncludedExamples = 0
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _ExampleBase: NSObject {}
|
||||
#else
|
||||
public class _ExampleBase: NSObject {}
|
||||
#endif
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _ExampleBase: NSObject {}
|
||||
#else
|
||||
public class _ExampleBase: NSObject {}
|
||||
#endif
|
||||
@@ -81,6 +75,9 @@ final public class Example: _ExampleBase {
|
||||
|
||||
let exampleMetadata = ExampleMetadata(example: self, exampleIndex: numberOfExamplesRun)
|
||||
world.currentExampleMetadata = exampleMetadata
|
||||
defer {
|
||||
world.currentExampleMetadata = nil
|
||||
}
|
||||
|
||||
world.exampleHooks.executeBefores(exampleMetadata)
|
||||
group!.phase = .beforesExecuting
|
||||
|
||||
+3
-9
@@ -1,14 +1,8 @@
|
||||
import Foundation
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _ExampleMetadataBase: NSObject {}
|
||||
#else
|
||||
public class _ExampleMetadataBase: NSObject {}
|
||||
#endif
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _ExampleMetadataBase: NSObject {}
|
||||
#else
|
||||
public class _ExampleMetadataBase: NSObject {}
|
||||
#endif
|
||||
|
||||
+3
-9
@@ -1,14 +1,8 @@
|
||||
import Foundation
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _FilterBase: NSObject {}
|
||||
#else
|
||||
public class _FilterBase: NSObject {}
|
||||
#endif
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _FilterBase: NSObject {}
|
||||
#else
|
||||
public class _FilterBase: NSObject {}
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
#if canImport(Darwin)
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
#if canImport(Darwin)
|
||||
import Foundation
|
||||
|
||||
public extension NSString {
|
||||
|
||||
extension NSString {
|
||||
private static var invalidCharacters: CharacterSet = {
|
||||
var invalidCharacters = CharacterSet()
|
||||
|
||||
@@ -22,12 +21,29 @@ public extension NSString {
|
||||
return invalidCharacters
|
||||
}()
|
||||
|
||||
/// This API is not meant to be used outside Quick, so will be unavailable in
|
||||
/// a next major version.
|
||||
@objc(qck_c99ExtendedIdentifier)
|
||||
var c99ExtendedIdentifier: String {
|
||||
public var c99ExtendedIdentifier: String {
|
||||
let validComponents = components(separatedBy: NSString.invalidCharacters)
|
||||
let result = validComponents.joined(separator: "_")
|
||||
|
||||
return result.isEmpty ? "_" : result
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods or properties for NSObject subclasses are invisible from
|
||||
/// the Objective-C runtime on static linking unless the consumers add `-ObjC`
|
||||
/// linker flag, so let's make a wrapper class to mitigate that situation.
|
||||
///
|
||||
/// See: https://github.com/Quick/Quick/issues/785 and https://github.com/Quick/Quick/pull/803
|
||||
@objc
|
||||
class QCKObjCStringUtils: NSObject {
|
||||
override private init() {}
|
||||
|
||||
@objc
|
||||
static func c99ExtendedIdentifier(from string: String) -> String {
|
||||
return string.c99ExtendedIdentifier
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
#if canImport(Darwin)
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
#if canImport(Darwin)
|
||||
|
||||
import XCTest
|
||||
|
||||
|
||||
+6
-12
@@ -12,15 +12,9 @@ public typealias SharedExampleContext = () -> [String: Any]
|
||||
*/
|
||||
public typealias SharedExampleClosure = (@escaping SharedExampleContext) -> Void
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
internal class _WorldBase: NSObject {}
|
||||
#else
|
||||
internal class _WorldBase: NSObject {}
|
||||
#endif
|
||||
#if canImport(Darwin) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
internal class _WorldBase: NSObject {}
|
||||
#else
|
||||
internal class _WorldBase: NSObject {}
|
||||
#endif
|
||||
@@ -57,7 +51,7 @@ final internal class World: _WorldBase {
|
||||
within this test suite. This is only true within the context of Quick
|
||||
functional tests.
|
||||
*/
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
// Convention of generating Objective-C selector has been changed on Swift 3
|
||||
@objc(isRunningAdditionalSuites)
|
||||
internal var isRunningAdditionalSuites = false
|
||||
@@ -158,9 +152,9 @@ final internal class World: _WorldBase {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
#if canImport(Darwin)
|
||||
@objc(examplesForSpecClass:)
|
||||
private func objc_examples(_ specClass: AnyClass) -> [Example] {
|
||||
internal func objc_examples(_ specClass: AnyClass) -> [Example] {
|
||||
return examples(specClass)
|
||||
}
|
||||
#endif
|
||||
|
||||
+6
-1
@@ -1,7 +1,12 @@
|
||||
#import "QuickConfiguration.h"
|
||||
#import "World.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if __has_include("Quick-Swift.h")
|
||||
#import "Quick-Swift.h"
|
||||
#else
|
||||
#import <Quick/Quick-Swift.h>
|
||||
#endif
|
||||
|
||||
typedef void (^QCKClassEnumerationBlock)(Class klass);
|
||||
|
||||
/**
|
||||
|
||||
+6
-2
@@ -1,6 +1,10 @@
|
||||
#import "QCKDSL.h"
|
||||
#import "World.h"
|
||||
#import "World+DSL.h"
|
||||
|
||||
#if __has_include("Quick-Swift.h")
|
||||
#import "Quick-Swift.h"
|
||||
#else
|
||||
#import <Quick/Quick-Swift.h>
|
||||
#endif
|
||||
|
||||
void qck_beforeSuite(QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] beforeSuite:closure];
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#import <Quick/Quick-Swift.h>
|
||||
|
||||
@interface World (SWIFT_EXTENSION(Quick))
|
||||
- (void)beforeSuite:(void (^ __nonnull)(void))closure;
|
||||
- (void)afterSuite:(void (^ __nonnull)(void))closure;
|
||||
- (void)sharedExamples:(NSString * __nonnull)name closure:(void (^ __nonnull)(NSDictionary * __nonnull (^ __nonnull)(void)))closure;
|
||||
- (void)describe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)context:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)fdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)xdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)beforeEach:(void (^ __nonnull)(void))closure;
|
||||
- (void)beforeEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure;
|
||||
- (void)afterEach:(void (^ __nonnull)(void))closure;
|
||||
- (void)afterEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure;
|
||||
- (void)itWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)fitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)xitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)itBehavesLikeSharedExampleNamed:(NSString * __nonnull)name sharedExampleContext:(NSDictionary * __nonnull (^ __nonnull)(void))sharedExampleContext flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line;
|
||||
- (void)pending:(NSString * __nonnull)description closure:(void (^ __nonnull)(void))closure;
|
||||
@end
|
||||
@@ -47,4 +47,10 @@
|
||||
*/
|
||||
- (void)spec;
|
||||
|
||||
/**
|
||||
Returns the currently executing spec. Use in specs that require XCTestCase
|
||||
methds, e.g. expectationWithDescription.
|
||||
*/
|
||||
@property (class, nonatomic, readonly) QuickSpec *current;
|
||||
|
||||
@end
|
||||
|
||||
+11
-3
@@ -1,7 +1,11 @@
|
||||
#import "QuickSpec.h"
|
||||
#import "QuickConfiguration.h"
|
||||
#import "World.h"
|
||||
|
||||
#if __has_include("Quick-Swift.h")
|
||||
#import "Quick-Swift.h"
|
||||
#else
|
||||
#import <Quick/Quick-Swift.h>
|
||||
#endif
|
||||
|
||||
static QuickSpec *currentSpec = nil;
|
||||
|
||||
@@ -75,6 +79,10 @@ static QuickSpec *currentSpec = nil;
|
||||
|
||||
- (void)spec { }
|
||||
|
||||
+ (QuickSpec*) current {
|
||||
return currentSpec;
|
||||
}
|
||||
|
||||
#pragma mark - Internal Methods
|
||||
|
||||
/**
|
||||
@@ -101,8 +109,8 @@ static QuickSpec *currentSpec = nil;
|
||||
});
|
||||
|
||||
const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(void), @encode(id), @encode(SEL)] UTF8String];
|
||||
|
||||
NSString *originalName = example.name.qck_c99ExtendedIdentifier;
|
||||
|
||||
NSString *originalName = [QCKObjCStringUtils c99ExtendedIdentifierFrom:example.name];
|
||||
NSString *selectorName = originalName;
|
||||
NSUInteger i = 2;
|
||||
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
#import <Quick/Quick-Swift.h>
|
||||
|
||||
@class ExampleGroup;
|
||||
@class ExampleMetadata;
|
||||
|
||||
SWIFT_CLASS("_TtC5Quick5World")
|
||||
@interface World
|
||||
|
||||
@property (nonatomic) ExampleGroup * __nullable currentExampleGroup;
|
||||
@property (nonatomic) ExampleMetadata * __nullable currentExampleMetadata;
|
||||
@property (nonatomic) BOOL isRunningAdditionalSuites;
|
||||
+ (World * __nonnull)sharedWorld;
|
||||
- (void)configure:(void (^ __nonnull)(Configuration * __nonnull))closure;
|
||||
- (void)finalizeConfiguration;
|
||||
- (ExampleGroup * __nonnull)rootExampleGroupForSpecClass:(Class __nonnull)cls;
|
||||
- (NSArray * __nonnull)examplesForSpecClass:(Class __nonnull)specClass;
|
||||
- (void)performWithCurrentExampleGroup:(ExampleGroup * __nonnull)group closure:(void (^ __nonnull)(void))closure;
|
||||
@end
|
||||
+5
@@ -1,6 +1,11 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if __has_include("Quick-Swift.h")
|
||||
#import "Quick-Swift.h"
|
||||
#else
|
||||
#import <Quick/Quick-Swift.h>
|
||||
#endif
|
||||
|
||||
@interface XCTestSuite (QuickTestSuiteBuilder)
|
||||
@end
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>7.0.3</string>
|
||||
<string>8.0.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Nimble
|
||||
APPLICATION_EXTENSION_API_ONLY = YES
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Nimble
|
||||
ENABLE_BITCODE = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
|
||||
OTHER_LDFLAGS = -weak-lswiftXCTest -weak_framework "XCTest"
|
||||
OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -weak-lswiftXCTest -weak_framework "XCTest"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -suppress-warnings $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/Nimble
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
|
||||
Generated
+49
-8
@@ -1,15 +1,28 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
|
||||
# If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
|
||||
# frameworks to, so exit 0 (signalling the script phase was successful).
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
|
||||
COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
|
||||
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
|
||||
|
||||
# Used as a return value for each invocation of `strip_invalid_archs` function.
|
||||
STRIP_BINARY_RETVAL=0
|
||||
|
||||
# This protects against multiple targets copying the same framework dependency at the same time. The solution
|
||||
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
|
||||
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
|
||||
|
||||
# Copies and strips a vendored framework
|
||||
install_framework()
|
||||
{
|
||||
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
|
||||
@@ -58,21 +71,40 @@ install_framework()
|
||||
fi
|
||||
}
|
||||
|
||||
# Copies the dSYM of a vendored framework
|
||||
# Copies and strips a vendored dSYM
|
||||
install_dsym() {
|
||||
local source="$1"
|
||||
if [ -r "$source" ]; then
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}"
|
||||
# Copy the dSYM into a the targets temp dir.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
|
||||
|
||||
local basename
|
||||
basename="$(basename -s .framework.dSYM "$source")"
|
||||
binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}"
|
||||
|
||||
# Strip invalid architectures so "fat" simulator / device frameworks work on device
|
||||
if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then
|
||||
strip_invalid_archs "$binary"
|
||||
fi
|
||||
|
||||
if [[ $STRIP_BINARY_RETVAL == 1 ]]; then
|
||||
# Move the stripped file into its final destination.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
|
||||
else
|
||||
# The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
|
||||
touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Signs a framework with the provided identity
|
||||
code_sign_if_enabled() {
|
||||
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
||||
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
||||
# Use the current code_sign_identitiy
|
||||
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
|
||||
local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
|
||||
local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
|
||||
|
||||
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
|
||||
code_sign_cmd="$code_sign_cmd &"
|
||||
@@ -85,10 +117,18 @@ code_sign_if_enabled() {
|
||||
# Strip invalid architectures
|
||||
strip_invalid_archs() {
|
||||
binary="$1"
|
||||
# Get architectures for current file
|
||||
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
|
||||
# Get architectures for current target binary
|
||||
binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
|
||||
# Intersect them with the architectures we are building for
|
||||
intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
|
||||
# If there are no archs supported by this binary then warn the user
|
||||
if [[ -z "$intersected_archs" ]]; then
|
||||
echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
|
||||
STRIP_BINARY_RETVAL=0
|
||||
return
|
||||
fi
|
||||
stripped=""
|
||||
for arch in $archs; do
|
||||
for arch in $binary_archs; do
|
||||
if ! [[ "${ARCHS}" == *"$arch"* ]]; then
|
||||
# Strip non-valid architectures in-place
|
||||
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
|
||||
@@ -98,6 +138,7 @@ strip_invalid_archs() {
|
||||
if [[ "$stripped" ]]; then
|
||||
echo "Stripped $binary of architectures:$stripped"
|
||||
fi
|
||||
STRIP_BINARY_RETVAL=1
|
||||
}
|
||||
|
||||
|
||||
|
||||
Generated
+15
-3
@@ -1,5 +1,13 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then
|
||||
# If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy
|
||||
# resources to, so exit 0 (signalling the script phase was successful).
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
|
||||
@@ -12,7 +20,7 @@ XCASSET_FILES=()
|
||||
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
|
||||
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
|
||||
|
||||
case "${TARGETED_DEVICE_FAMILY}" in
|
||||
case "${TARGETED_DEVICE_FAMILY:-}" in
|
||||
1,2)
|
||||
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
|
||||
;;
|
||||
@@ -92,7 +100,7 @@ if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
|
||||
fi
|
||||
rm -f "$RESOURCES_TO_COPY"
|
||||
|
||||
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
|
||||
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ]
|
||||
then
|
||||
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
|
||||
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
|
||||
@@ -102,5 +110,9 @@ then
|
||||
fi
|
||||
done <<<"$OTHER_XCASSETS"
|
||||
|
||||
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then
|
||||
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
else
|
||||
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist"
|
||||
fi
|
||||
fi
|
||||
|
||||
Generated
+4
-4
@@ -1,11 +1,11 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "SwiftAudio"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
Generated
+4
-4
@@ -1,11 +1,11 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "SwiftAudio"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
Generated
+49
-8
@@ -1,15 +1,28 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
|
||||
# If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
|
||||
# frameworks to, so exit 0 (signalling the script phase was successful).
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
|
||||
COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
|
||||
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
|
||||
|
||||
# Used as a return value for each invocation of `strip_invalid_archs` function.
|
||||
STRIP_BINARY_RETVAL=0
|
||||
|
||||
# This protects against multiple targets copying the same framework dependency at the same time. The solution
|
||||
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
|
||||
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
|
||||
|
||||
# Copies and strips a vendored framework
|
||||
install_framework()
|
||||
{
|
||||
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
|
||||
@@ -58,21 +71,40 @@ install_framework()
|
||||
fi
|
||||
}
|
||||
|
||||
# Copies the dSYM of a vendored framework
|
||||
# Copies and strips a vendored dSYM
|
||||
install_dsym() {
|
||||
local source="$1"
|
||||
if [ -r "$source" ]; then
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}"
|
||||
# Copy the dSYM into a the targets temp dir.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
|
||||
|
||||
local basename
|
||||
basename="$(basename -s .framework.dSYM "$source")"
|
||||
binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}"
|
||||
|
||||
# Strip invalid architectures so "fat" simulator / device frameworks work on device
|
||||
if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then
|
||||
strip_invalid_archs "$binary"
|
||||
fi
|
||||
|
||||
if [[ $STRIP_BINARY_RETVAL == 1 ]]; then
|
||||
# Move the stripped file into its final destination.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
|
||||
else
|
||||
# The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
|
||||
touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Signs a framework with the provided identity
|
||||
code_sign_if_enabled() {
|
||||
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
||||
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
||||
# Use the current code_sign_identitiy
|
||||
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
|
||||
local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
|
||||
local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
|
||||
|
||||
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
|
||||
code_sign_cmd="$code_sign_cmd &"
|
||||
@@ -85,10 +117,18 @@ code_sign_if_enabled() {
|
||||
# Strip invalid architectures
|
||||
strip_invalid_archs() {
|
||||
binary="$1"
|
||||
# Get architectures for current file
|
||||
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
|
||||
# Get architectures for current target binary
|
||||
binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
|
||||
# Intersect them with the architectures we are building for
|
||||
intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
|
||||
# If there are no archs supported by this binary then warn the user
|
||||
if [[ -z "$intersected_archs" ]]; then
|
||||
echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
|
||||
STRIP_BINARY_RETVAL=0
|
||||
return
|
||||
fi
|
||||
stripped=""
|
||||
for arch in $archs; do
|
||||
for arch in $binary_archs; do
|
||||
if ! [[ "${ARCHS}" == *"$arch"* ]]; then
|
||||
# Strip non-valid architectures in-place
|
||||
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
|
||||
@@ -98,6 +138,7 @@ strip_invalid_archs() {
|
||||
if [[ "$stripped" ]]; then
|
||||
echo "Stripped $binary of architectures:$stripped"
|
||||
fi
|
||||
STRIP_BINARY_RETVAL=1
|
||||
}
|
||||
|
||||
|
||||
|
||||
Generated
+15
-3
@@ -1,5 +1,13 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then
|
||||
# If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy
|
||||
# resources to, so exit 0 (signalling the script phase was successful).
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
|
||||
@@ -12,7 +20,7 @@ XCASSET_FILES=()
|
||||
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
|
||||
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
|
||||
|
||||
case "${TARGETED_DEVICE_FAMILY}" in
|
||||
case "${TARGETED_DEVICE_FAMILY:-}" in
|
||||
1,2)
|
||||
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
|
||||
;;
|
||||
@@ -92,7 +100,7 @@ if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
|
||||
fi
|
||||
rm -f "$RESOURCES_TO_COPY"
|
||||
|
||||
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
|
||||
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ]
|
||||
then
|
||||
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
|
||||
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
|
||||
@@ -102,5 +110,9 @@ then
|
||||
fi
|
||||
done <<<"$OTHER_XCASSETS"
|
||||
|
||||
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then
|
||||
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
else
|
||||
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist"
|
||||
fi
|
||||
fi
|
||||
|
||||
Generated
+4
-4
@@ -1,11 +1,11 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "$PODS_CONFIGURATION_BUILD_DIR/Nimble" "$PODS_CONFIGURATION_BUILD_DIR/Quick" "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "${PODS_CONFIGURATION_BUILD_DIR}/Nimble" "${PODS_CONFIGURATION_BUILD_DIR}/Quick" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Nimble/Nimble.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Quick/Quick.framework/Headers" $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Nimble/Nimble.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Quick/Quick.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "Nimble" -framework "Quick"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
Generated
+4
-4
@@ -1,11 +1,11 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "$PODS_CONFIGURATION_BUILD_DIR/Nimble" "$PODS_CONFIGURATION_BUILD_DIR/Quick" "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "${PODS_CONFIGURATION_BUILD_DIR}/Nimble" "${PODS_CONFIGURATION_BUILD_DIR}/Quick" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Nimble/Nimble.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Quick/Quick.framework/Headers" $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Nimble/Nimble.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Quick/Quick.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/SwiftAudio/SwiftAudio.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "Nimble" -framework "Quick"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.0</string>
|
||||
<string>2.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Quick
|
||||
APPLICATION_EXTENSION_API_ONLY = YES
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Quick
|
||||
ENABLE_BITCODE = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
|
||||
OTHER_LDFLAGS = -framework "XCTest"
|
||||
OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -framework "XCTest"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/Quick
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user