Merge branch 'master' into release-1.6.4

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
Ben Chatelain 2020-05-12 22:52:24 -06:00
commit 70f0a6fd47
748 changed files with 9539 additions and 13183 deletions

View file

@ -12,5 +12,5 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.rb]
[{script/*,*.rb,*.yml}]
indent_size = 2

View file

@ -1 +1 @@
2.3.1
2.4.3

View file

@ -1 +0,0 @@
4.2

View file

@ -2,13 +2,17 @@
# .travis.yml
# mas-cli
#
# https://travis-ci.org/mas-cli/mas
# https://travis-ci.com/mas-cli/mas
# https://docs.travis-ci.com/user/reference/osx/
# https://docs.travis-ci.com/user/languages/objective-c/
#
# https://docs.travis-ci.com/user/build-config-validation
version: ~> 1.0
# https://docs.travis-ci.com/user/reference/osx/#macos-version
os: osx
osx_image: xcode10.1 # macOS 10.13
osx_image: xcode11.3 # macOS 10.14
env:
global:
@ -16,6 +20,11 @@ env:
- LC_ALL=en_US.UTF-8
- LANGUAGE=en_US.UTF-8
# Bundler 2
# https://docs.travis-ci.com/user/languages/ruby/#bundler-20
before_install:
- gem install bundler
install:
- script/bootstrap

View file

@ -1,4 +1,2 @@
brew "carthage"
brew "mint"
brew "shellcheck"
brew "swiftlint"
brew "swiftformat"

56
Brewfile.lock.json Normal file
View file

@ -0,0 +1,56 @@
{
"entries": {
"brew": {
"mint": {
"version": "0.14.2",
"bottle": {
"cellar": ":any_skip_relocation",
"prefix": "/usr/local",
"files": {
"catalina": {
"url": "https://homebrew.bintray.com/bottles/mint-0.14.2.catalina.bottle.tar.gz",
"sha256": "cc7a17ee517fe97f12852c71252896c9ca30dfe8236f816f2990b2d0553ff5b3"
},
"mojave": {
"url": "https://homebrew.bintray.com/bottles/mint-0.14.2.mojave.bottle.tar.gz",
"sha256": "f70e96558839243a845c67f15defbd8718ad5a9e094ae1c1b998ac9faf4399b0"
}
}
}
},
"shellcheck": {
"version": "0.7.1",
"bottle": {
"cellar": ":any_skip_relocation",
"prefix": "/usr/local",
"files": {
"catalina": {
"url": "https://homebrew.bintray.com/bottles/shellcheck-0.7.1.catalina.bottle.tar.gz",
"sha256": "77e5385a84164971cd75df484031c79e41eab8454deede5b40b278859a039115"
},
"mojave": {
"url": "https://homebrew.bintray.com/bottles/shellcheck-0.7.1.mojave.bottle.tar.gz",
"sha256": "983f1eb4590e9be83584d68f5b7db13b3c3f2dbc50ad61b1896e8070e2e0d375"
},
"high_sierra": {
"url": "https://homebrew.bintray.com/bottles/shellcheck-0.7.1.high_sierra.bottle.tar.gz",
"sha256": "6f371407500c5bfffb2c44e69482c524d8cb96d682ce93d06d148eccd6e4d052"
}
}
}
}
}
},
"system": {
"macos": {
"catalina": {
"HOMEBREW_VERSION": "2.2.13",
"HOMEBREW_PREFIX": "/usr/local",
"Homebrew/homebrew-core": "474ad1d25ce77de5836bfbe9824716667f853797",
"CLT": "11.4.1.0.1.1586360307",
"Xcode": "11.4.1",
"macOS": "10.15.4"
}
}
}
}

View file

@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
- 🕊 Swift 5 #255
- ⚒️ Xcode 10.2 and macOS 10.14 required to build
- ⬆️ Commandant (0.17.0) #255
- ⬆️ Nimble (8.0.4) #255
- ⬆️ Quick (2.2.0) #255
- Result #255
- Seriously more interactive fish completions #242
thanks, [@lwolfsonkin](https://github.com/lwolfsonkin)!
- 💡 Update readme with simpler tap usage #241
## [v1.6.4] 🔎 Search Fix - 2020-05-11
- 🐛 Fix search parameters #269
@ -90,83 +100,102 @@ Use the `mas.pkg` package to install manually.
## [v1.4.0] 🧟‍♂️ It's Alive! - 2018-02-16
### ✨ Enhancements
- Info command #26, #55
- 🍀 Lucky command #88
- 🕵🏽‍♀️ Include version number in search output #131
- ☝🏻 Support app name(s) arugments for upgrade command #100
### 🔨 Xcode Project
- ⬆️ Swift 4 #114
- ✅ Added test target #127
- 📛 Add build badge to readme #121
- 💎 Configure bundler #118
### 🐙 GitHub
- ⚠️ Added Danger for PR feedback #124
- 📝🤝🎨 Added Contributing Guidelines, Code of Conduct and style guide #117, #126
- 📝 Added CHANGELOG #119
- 📝 Added note about installing through app store first #93
### 🏛 Dependencies #122
- ⬆️ Commandant (0.13.0)
- ⬆️ Result (3.2.4)
- ⬆️ cocoaseeds (0.8.3)
- ⬆️ xcpretty (0.2.8)
### 👷🏻‍♀️ CI Build
- 🍎 Now using [`xcode9.2`](https://docs.travis-ci.com/user/reference/osx#Xcode-9.2) image for `macosx10.13` SDK #120
## [v1.3.1] Better Errors - 2016-09-25
- Descriptive error messages instead of exit codes
- Fixed nullability issue with `list` command
- Simpler upgrade checking
## [v1.3.0] Multiple app install - 2016-09-14
- Fix install of Free apps (#19)
- Install / Upgrade multiple apps at once
- Skip Install if the app is already installed
## [v1.2.2] Secure Password entry - 2016-09-14
- Support reading password from STDIN
- Fix building with Swift 2.3/Xcode 8
## [v1.2.1] - 2016-09-13
- Support reading password from STDIN
- Fix building with Swift 2.3/Xcode 8
## [v1.2.0] Search - 2016-04-16
- `search` command
- Fix `mas list` illegal instruction (#16)
## [v1.1.3] - 2016-02-21
- Fix Illegal Instruction: 4 error (#10)
## [v1.1.2] Upload dSYM correctly - 2016-02-21
- Move the dSYM to the xcarchive
## [v1.1.1] Upload dSYM - 2016-02-21
- Upload dSYM from Travis release
## [v1.1.0] Sign In - 2016-02-13
- Added `signin` command (#3)
- Added `signout` command
## [v1.0.2] Upgrade all - 2015-12-30
### Features
- Added `upgrade` command (#1)
### Fixes
- Updated to latest version of Commandant
- Broken `install` command after updating Commandant
## [v1.0.1] - 2015-12-30
- Bump version to 1.0.1
## [v1.0.0] - 2015-09-20
- Initial Release
[Unreleased]: https://github.com/mas-cli/mas/compare/v1.6.1...HEAD
[v1.6.0]: https://github.com/mas-cli/mas/compare/v1.6.0...v1.6.1
[Unreleased]: https://github.com/mas-cli/mas/compare/v1.6.3...HEAD
[v1.6.3]: https://github.com/mas-cli/mas/compare/v1.6.2...v1.6.3
[v1.6.2]: https://github.com/mas-cli/mas/compare/v1.6.1...v1.6.2
[v1.6.1]: https://github.com/mas-cli/mas/compare/v1.6.0...v1.6.1
[v1.6.0]: https://github.com/mas-cli/mas/compare/v1.5.0...v1.6.0
[v1.5.0]: https://github.com/mas-cli/mas/compare/v1.4.4...v1.5.0
[v1.4.4]: https://github.com/mas-cli/mas/compare/v1.4.3...v1.4.4

View file

@ -1,2 +1 @@
github "Carthage/Commandant"
github "antitypical/Result"

View file

@ -1,4 +1,3 @@
github "Carthage/Commandant" "0.15.0"
github "Quick/Nimble" "v7.3.2"
github "Quick/Quick" "v1.3.2"
github "antitypical/Result" "4.1.0"
github "Carthage/Commandant" "0.17.0"
github "Quick/Nimble" "v8.0.4"
github "Quick/Quick" "v2.2.0"

View file

@ -7,6 +7,3 @@
[submodule "Carthage/Checkouts/xcconfigs"]
path = Carthage/Checkouts/xcconfigs
url = https://github.com/jspahrsummers/xcconfigs.git
[submodule "Carthage/Checkouts/Result"]
path = Carthage/Checkouts/Result
url = https://github.com/antitypical/Result.git

View file

@ -0,0 +1,2 @@
swiftlint:
config_file: .swiftlint.yml

View file

@ -1 +1 @@
4.1.2
5.0

View file

@ -0,0 +1,13 @@
included:
- Sources
- Tests
disabled_rules:
- function_body_length
- identifier_name
- line_length
- opening_brace
- operator_whitespace
trailing_comma:
mandatory_comma: true

View file

@ -8,6 +8,7 @@ aliases:
- &cocoapods
script:
- rm .swift-version
- gem update cocoapods
- pod repo update master
- pod lib lint --verbose
os: osx
@ -31,7 +32,7 @@ aliases:
dist: trusty
language: generic
install:
- eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)"
- eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
branches:
only:
@ -40,28 +41,20 @@ branches:
matrix:
include:
- <<: *xcode
osx_image: xcode9.2
env: JOB=Xcode9.2
- <<: *xcode
osx_image: xcode9.4
env: JOB=Xcode9.4
name: Xcode 10.2 / Swift 5.0
osx_image: xcode10.2
env: JOB=Xcode10.2
- <<: *cocoapods
osx_image: xcode9.4
name: CocoaPods Lint
osx_image: xcode10.2
- <<: *swiftpm_darwin
osx_image: xcode9.2
- <<: *swiftpm_darwin
osx_image: xcode9.4
name: SwiftPM / Swift 5.0
osx_image: xcode10.2
- <<: *swiftpm_linux
name: Linux / Swift 5.0
env:
- JOB=Linux
- SWIFT_VERSION=4.0.3
- <<: *swiftpm_linux
env:
- JOB=Linux
- <<: *swiftpm_linux
env:
- JOB=Linux
- SWIFT_VERSION=4.2-DEVELOPMENT-SNAPSHOT-2018-07-05-a
- SWIFT_VERSION=5.0
notifications:
email: false
@ -83,4 +76,4 @@ deploy:
on:
repo: Carthage/Commandant
tags: true
condition: $JOB = Xcode9.4
condition: $JOB = Xcode10.1

View file

@ -1 +0,0 @@
github "antitypical/Result" ~> 4.0

View file

@ -1,3 +1,3 @@
github "jspahrsummers/xcconfigs" ~> 0.9
github "Quick/Quick" ~> 1.3
github "Quick/Nimble" ~> 7.1.2
github "Quick/Quick" ~> 2.0
github "Quick/Nimble" ~> 8.0

View file

@ -1,4 +1,3 @@
github "Quick/Nimble" "v7.1.2"
github "Quick/Quick" "v1.3.0"
github "antitypical/Result" "4.0.0"
github "Quick/Nimble" "v8.0.0"
github "Quick/Quick" "v2.0.0"
github "jspahrsummers/xcconfigs" "0.9"

View file

@ -1,8 +1,5 @@
disabled_rules:
- todo
- variable_name
- force_try
- force_cast
-
included:
- Sources
@ -10,6 +7,8 @@ included:
excluded:
- Carthage/Checkouts
- Tests/NimbleTests/XCTestManifests.swift
- Tests/NimbleTests/Helpers/XCTestCaseProvider.swift
trailing_comma:
mandatory_comma: true
@ -17,3 +16,16 @@ trailing_comma:
line_length:
ignores_comments: true
ignores_function_declarations: true
identifier_name:
max_length: 50
excluded:
- x
- l
- r
- e
- n1
- n2
- to
allowed_symbols:
- _

View file

@ -1,39 +1,52 @@
osx_image: xcode8.3
osx_image: xcode10.1
language: generic
matrix:
include:
- os: osx
sudo: required
env: TYPE=podspec
install: bundle install
name: CocoaPods Lint
- os: osx
env: TYPE=ios NIMBLE_RUNTIME_IOS_SDK_VERSION=10.0
env: TYPE=ios
name: iOS / Swift 4.2.1
- os: osx
env: TYPE=tvos NIMBLE_RUNTIME_TVOS_SDK_VERSION=10.0
env: TYPE=tvos
name: tvOS / Swift 4.2.1
- os: osx
env: TYPE=macos
name: macOS / Swift 4.2.1
- os: osx
env: TYPE=macos
osx_image: xcode9
osx_image: xcode10.2
name: macOS / Swift 5.0
- os: osx
env: TYPE=swiftpm
env:
- TYPE=swiftpm
- os: osx
env: TYPE=swiftpm
osx_image: xcode9
- os: linux
dist: trusty
sudo: required
env: TYPE=swiftpm
install:
- eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"
- os: linux
env:
- TYPE=swiftpm
osx_image: xcode10.2
- &linux
name: Linux / Swift 4.2.1
os: linux
dist: trusty
sudo: required
env:
- TYPE=swiftpm
- SWIFT_VERSION=4.0.2
- SWIFT_VERSION=4.2.1
install:
- eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"
- <<: *linux
name: Linux / Swift 5.0 Development
env:
- TYPE=swiftpm
- SWIFT_VERSION=5.0-DEVELOPMENT-SNAPSHOT-2019-02-28-a
install:
- if [[ "$TYPE" == "podspec" ]]; then sudo gem install bundler; bundle install; fi
- eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"
install: true
script:
- ./test $TYPE
notifications:
email: false

View file

@ -1 +1 @@
github "mattgallagher/CwlPreconditionTesting" "cb7ab89273cfd0725a7a2f865cc6fc560a9b9083"
github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5"

View file

@ -1,2 +1,2 @@
github "mattgallagher/CwlCatchException" "b14c111e9b33cd142bd4bc75c482cfd5c3490923"
github "mattgallagher/CwlPreconditionTesting" "cb7ab89273cfd0725a7a2f865cc6fc560a9b9083"
github "mattgallagher/CwlPreconditionTesting" "1e62a726d54c743f4585233f08fcaac7307319b5"

View file

@ -20,6 +20,8 @@
#import <Foundation/Foundation.h>
extern bool _swift_reportFatalErrorsToDebugger;
//! Project version number for CwlUtils.
FOUNDATION_EXPORT double CwlPreconditionTestingVersionNumber;

View file

@ -20,6 +20,8 @@
#import <Foundation/Foundation.h>
extern bool _swift_reportFatalErrorsToDebugger;
//! Project version number for CwlUtils.
FOUNDATION_EXPORT double CwlPreconditionTesting_POSIXVersionNumber;

View file

@ -1,4 +1,4 @@
# A sample Gemfile
source "https://rubygems.org"
gem 'cocoapods', '1.5.0'
gem 'cocoapods', '~> 1.6.0.rc.2'

View file

@ -2,75 +2,75 @@ GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.0)
activesupport (4.2.10)
activesupport (4.2.11)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
atomos (0.1.2)
atomos (0.1.3)
claide (1.0.2)
cocoapods (1.5.0)
cocoapods (1.6.0.rc.2)
activesupport (>= 4.0.2, < 5)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.5.0)
cocoapods-core (= 1.6.0.rc.2)
cocoapods-deintegrate (>= 1.0.2, < 2.0)
cocoapods-downloader (>= 1.2.0, < 2.0)
cocoapods-downloader (>= 1.2.2, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-stats (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.3.0, < 2.0)
cocoapods-trunk (>= 1.3.1, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (~> 2.0.1)
fourflusher (>= 2.2.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.6.5)
molinillo (~> 0.6.6)
nap (~> 1.0)
ruby-macho (~> 1.1)
xcodeproj (>= 1.5.7, < 2.0)
cocoapods-core (1.5.0)
ruby-macho (~> 1.3, >= 1.3.1)
xcodeproj (>= 1.8.0, < 2.0)
cocoapods-core (1.6.0.rc.2)
activesupport (>= 4.0.2, < 6)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.2)
cocoapods-downloader (1.2.0)
cocoapods-downloader (1.2.2)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.3.0)
cocoapods-stats (1.1.0)
cocoapods-trunk (1.3.1)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.1.0)
colored2 (3.1.2)
concurrent-ruby (1.0.5)
concurrent-ruby (1.1.4)
escape (0.0.4)
fourflusher (2.0.1)
fourflusher (2.2.0)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
minitest (5.11.3)
molinillo (0.6.5)
nanaimo (0.2.5)
molinillo (0.6.6)
nanaimo (0.2.6)
nap (1.1.0)
netrc (0.11.0)
ruby-macho (1.1.0)
ruby-macho (1.3.1)
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
xcodeproj (1.5.7)
xcodeproj (1.8.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.2)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.4)
nanaimo (~> 0.2.6)
PLATFORMS
ruby
DEPENDENCIES
cocoapods (= 1.5.0)
cocoapods (~> 1.6.0.rc.2)
BUNDLED WITH
1.16.1
1.17.2

View file

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "Nimble"
s.version = "7.1.2"
s.version = "8.0.0"
s.summary = "A Matcher Framework for Swift and Objective-C"
s.description = <<-DESC
Use Nimble to express the expected outcomes of Swift or Objective-C expressions. Inspired by Cedar.
@ -45,8 +45,11 @@ Pod::Spec.new do |s|
s.pod_target_xcconfig = {
'APPLICATION_EXTENSION_API_ONLY' => 'YES',
'ENABLE_BITCODE' => 'NO',
'OTHER_LDFLAGS' => '-weak-lswiftXCTest',
'OTHER_LDFLAGS' => '$(inherited) -weak-lswiftXCTest -Xlinker -no_application_extension',
'OTHER_SWIFT_FLAGS' => '$(inherited) -suppress-warnings',
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"',
}
s.cocoapods_version = '>= 1.4.0'
s.swift_version = '4.2'
end

View file

@ -23,8 +23,8 @@
/* Begin PBXBuildFile section */
1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; };
1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; };
1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; };
1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; };
1F0648D41963AAB2001F9C46 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; };
1F0648D51963AAB2001F9C46 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; };
1F14FB64194180C5009F2A08 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; };
1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871BD1CA89EDB00A34BF2 /* DSL.m */; };
@ -50,10 +50,10 @@
1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BC1CA89EDB00A34BF2 /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871BE1CA89EDB00A34BF2 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1871C01CA89EDB00A34BF2 /* NMBStringify.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; };
1F1871E41CA89FB600A34BF2 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* Async.swift */; };
1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; };
1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; };
1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */; };
1F1871E71CA8A18400A34BF2 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* Async.swift */; };
1F1871E81CA8A18400A34BF2 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E31CA89FB600A34BF2 /* Async.swift */; };
1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; };
1F1871EB1CA8A18800A34BF2 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */; };
1F1A742F1940169200FFFC47 /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F1A742E1940169200FFFC47 /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -143,11 +143,11 @@
1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; };
1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EA59651B551EE6002D767E /* ThrowError.swift */; };
1F5DF18B1BDCA0F500C3A531 /* Functional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD251968AB07008ED995 /* Functional.swift */; };
1F5DF18C1BDCA0F500C3A531 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; };
1F5DF18C1BDCA0F500C3A531 /* Await.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Await.swift */; };
1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD271968AB07008ED995 /* SourceLocation.swift */; };
1F5DF18E1BDCA0F500C3A531 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD281968AB07008ED995 /* Stringers.swift */; };
1F5DF1921BDCA10200C3A531 /* AsynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F925EE5195C121200ED456B /* AsynchronousTest.swift */; };
1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */; };
1F5DF1931BDCA10200C3A531 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; };
1F5DF1941BDCA10200C3A531 /* UserDescriptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */; };
1F5DF1951BDCA10200C3A531 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F14FB63194180C5009F2A08 /* utils.swift */; };
1F5DF1961BDCA10200C3A531 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; };
@ -273,8 +273,8 @@
1FD8CD5B1968AB07008ED995 /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1C1968AB07008ED995 /* Equal.swift */; };
1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; };
1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */; };
1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; };
1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Async.swift */; };
1FD8CD6A1968AB07008ED995 /* Await.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Await.swift */; };
1FD8CD6B1968AB07008ED995 /* Await.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD261968AB07008ED995 /* Await.swift */; };
1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; };
1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */; };
1FE661571E6574E30035F243 /* ExpectationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE661561E6574E20035F243 /* ExpectationMessage.swift */; };
@ -347,6 +347,13 @@
AE7ADE491C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; };
AE7ADE4A1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; };
AE7ADE4B1C80C00D00B94CD3 /* MatchErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */; };
B20058C120E92C7500C1264D /* ElementsEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C020E92C7500C1264D /* ElementsEqual.swift */; };
B20058C220E92CA900C1264D /* ElementsEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C020E92C7500C1264D /* ElementsEqual.swift */; };
B20058C320E92CA900C1264D /* ElementsEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C020E92C7500C1264D /* ElementsEqual.swift */; };
B20058C520E92CE400C1264D /* ElementsEqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C420E92CE400C1264D /* ElementsEqualTest.swift */; };
B20058C620E92CE400C1264D /* ElementsEqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C420E92CE400C1264D /* ElementsEqualTest.swift */; };
B20058C720E92CE400C1264D /* ElementsEqualTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20058C420E92CE400C1264D /* ElementsEqualTest.swift */; };
CD037213207DCC580047AF28 /* XCTestManifests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD037212207DCC580047AF28 /* XCTestManifests.swift */; };
CD79C99E1D2CC832004B6F9A /* ObjCAsyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56651A3B305F009E1637 /* ObjCAsyncTest.m */; };
CD79C99F1D2CC835004B6F9A /* ObjCSyncTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F8A37AF1B7C5042001C8357 /* ObjCSyncTest.m */; };
CD79C9A01D2CC839004B6F9A /* ObjCBeAnInstanceOfTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4A56691A3B3108009E1637 /* ObjCBeAnInstanceOfTest.m */; };
@ -487,7 +494,7 @@
/* Begin PBXFileReference section */
1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = "<group>"; };
1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTests.swift; sourceTree = "<group>"; };
1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTest.swift; sourceTree = "<group>"; };
1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = "<group>"; };
1F1871BC1CA89EDB00A34BF2 /* DSL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DSL.h; sourceTree = "<group>"; };
1F1871BD1CA89EDB00A34BF2 /* DSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DSL.m; sourceTree = "<group>"; };
@ -498,7 +505,7 @@
1F1871C21CA89EDB00A34BF2 /* NMBExpectation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBExpectation.swift; sourceTree = "<group>"; };
1F1871C31CA89EDB00A34BF2 /* NMBObjCMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NMBObjCMatcher.swift; sourceTree = "<group>"; };
1F1871CD1CA89EE000A34BF2 /* ExceptionCapture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExceptionCapture.swift; sourceTree = "<group>"; };
1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncMatcherWrapper.swift; sourceTree = "<group>"; };
1F1871E31CA89FB600A34BF2 /* Async.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Async.swift; sourceTree = "<group>"; };
1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherFunc.swift; sourceTree = "<group>"; };
1F1A74291940169200FFFC47 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1F1A742D1940169200FFFC47 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -582,7 +589,7 @@
1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherProtocols.swift; sourceTree = "<group>"; };
1FD8CD1E1968AB07008ED995 /* RaisesException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RaisesException.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
1FD8CD251968AB07008ED995 /* Functional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functional.swift; sourceTree = "<group>"; };
1FD8CD261968AB07008ED995 /* Async.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Async.swift; sourceTree = "<group>"; };
1FD8CD261968AB07008ED995 /* Await.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Await.swift; sourceTree = "<group>"; };
1FD8CD271968AB07008ED995 /* SourceLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceLocation.swift; sourceTree = "<group>"; };
1FD8CD281968AB07008ED995 /* Stringers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stringers.swift; sourceTree = "<group>"; };
1FDBD8661AF8A4FF0089F27B /* AssertionDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssertionDispatcher.swift; sourceTree = "<group>"; };
@ -612,6 +619,9 @@
AE4BA9AC1C88DDB500B73906 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
AE7ADE441C80BF8000B94CD3 /* MatchError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchError.swift; sourceTree = "<group>"; };
AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatchErrorTest.swift; sourceTree = "<group>"; };
B20058C020E92C7500C1264D /* ElementsEqual.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementsEqual.swift; sourceTree = "<group>"; };
B20058C420E92CE400C1264D /* ElementsEqualTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementsEqualTest.swift; sourceTree = "<group>"; };
CD037212207DCC580047AF28 /* XCTestManifests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XCTestManifests.swift; sourceTree = "<group>"; };
CDFB6A1E1F7E07C600AD8CC7 /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = "<group>"; };
CDFB6A201F7E07C600AD8CC7 /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = "<group>"; };
CDFB6A221F7E07C600AD8CC7 /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; sourceTree = "<group>"; };
@ -768,9 +778,10 @@
isa = PBXGroup;
children = (
1F925EE5195C121200ED456B /* AsynchronousTest.swift */,
1F0648D31963AAB2001F9C46 /* SynchronousTests.swift */,
1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */,
965B0D0B1B62C06D0005AE66 /* UserDescriptionTest.swift */,
6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */,
CD037212207DCC580047AF28 /* XCTestManifests.swift */,
1FFD729A1963FC8200CD29A2 /* objc */,
1F14FB61194180A7009F2A08 /* Helpers */,
1F925EE3195C11B000ED456B /* Matchers */,
@ -810,6 +821,7 @@
1F925F01195C189500ED456B /* ContainTest.swift */,
1F925EFE195C187600ED456B /* EndWithTest.swift */,
1F925F04195C18B700ED456B /* EqualTest.swift */,
B20058C420E92CE400C1264D /* ElementsEqualTest.swift */,
472FD1361B9E094B00C7B8DA /* HaveCountTest.swift */,
DDB4D5EF19FE442800E9D9FE /* MatchTest.swift */,
1F925EEB195C12C800ED456B /* RaisesExceptionTest.swift */,
@ -843,7 +855,7 @@
isa = PBXGroup;
children = (
DDB1BC781A92235600F743C3 /* AllPass.swift */,
1F1871E31CA89FB600A34BF2 /* AsyncMatcherWrapper.swift */,
1F1871E31CA89FB600A34BF2 /* Async.swift */,
1FD8CD0E1968AB07008ED995 /* BeAKindOf.swift */,
1FD8CD0D1968AB07008ED995 /* BeAnInstanceOf.swift */,
1FD8CD0F1968AB07008ED995 /* BeCloseTo.swift */,
@ -861,6 +873,7 @@
7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */,
1FD8CD1B1968AB07008ED995 /* EndWith.swift */,
1FD8CD1C1968AB07008ED995 /* Equal.swift */,
B20058C020E92C7500C1264D /* ElementsEqual.swift */,
472FD1341B9E085700C7B8DA /* HaveCount.swift */,
DDB4D5EC19FE43C200E9D9FE /* Match.swift */,
1F1871E51CA89FCD00A34BF2 /* MatcherFunc.swift */,
@ -882,7 +895,7 @@
isa = PBXGroup;
children = (
1FD8CD251968AB07008ED995 /* Functional.swift */,
1FD8CD261968AB07008ED995 /* Async.swift */,
1FD8CD261968AB07008ED995 /* Await.swift */,
1FD8CD271968AB07008ED995 /* SourceLocation.swift */,
1FD8CD281968AB07008ED995 /* Stringers.swift */,
AE4BA9AC1C88DDB500B73906 /* Errors.swift */,
@ -1081,9 +1094,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 1F1A743F1940169200FFFC47 /* Build configuration list for PBXNativeTarget "Nimble-iOS" */;
buildPhases = (
1F1A74261940169200FFFC47 /* Headers */,
1F1A74241940169200FFFC47 /* Sources */,
1F1A74251940169200FFFC47 /* Frameworks */,
1F1A74261940169200FFFC47 /* Headers */,
1F1A74271940169200FFFC47 /* Resources */,
);
buildRules = (
@ -1120,9 +1133,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 1F5DF16A1BDCA0CE00C3A531 /* Build configuration list for PBXNativeTarget "Nimble-tvOS" */;
buildPhases = (
1F5DF1521BDCA0CE00C3A531 /* Headers */,
1F5DF1501BDCA0CE00C3A531 /* Sources */,
1F5DF1511BDCA0CE00C3A531 /* Frameworks */,
1F5DF1521BDCA0CE00C3A531 /* Headers */,
1F5DF1531BDCA0CE00C3A531 /* Resources */,
);
buildRules = (
@ -1156,9 +1169,9 @@
isa = PBXNativeTarget;
buildConfigurationList = 1F925EC0195C0D6300ED456B /* Build configuration list for PBXNativeTarget "Nimble-macOS" */;
buildPhases = (
1F925EAA195C0D6300ED456B /* Headers */,
1F925EA8195C0D6300ED456B /* Sources */,
1F925EA9195C0D6300ED456B /* Frameworks */,
1F925EAA195C0D6300ED456B /* Headers */,
1F925EAB195C0D6300ED456B /* Resources */,
);
buildRules = (
@ -1343,6 +1356,7 @@
DDB4D5ED19FE43C200E9D9FE /* Match.swift in Sources */,
1F91DD311C74BF61002C309F /* BeVoid.swift in Sources */,
7B13BA0B1DD361D200C9098C /* ContainElementSatisfying.swift in Sources */,
B20058C220E92CA900C1264D /* ElementsEqual.swift in Sources */,
1FCF91531C61C8A400B15DCB /* PostNotification.swift in Sources */,
1FD8CD2E1968AB07008ED995 /* AssertionRecorder.swift in Sources */,
29EA59661B551EE6002D767E /* ThrowError.swift in Sources */,
@ -1366,11 +1380,11 @@
1FE661581E6574E30035F243 /* ExpectationMessage.swift in Sources */,
1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */,
1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */,
1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */,
1F1871E41CA89FB600A34BF2 /* Async.swift in Sources */,
1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */,
A8A3B6EB2071487E00E25A08 /* SatisfyAllOf.swift in Sources */,
1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */,
1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */,
1FD8CD6A1968AB07008ED995 /* Await.swift in Sources */,
CDFB6A241F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */,
1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */,
1FD8CD341968AB07008ED995 /* DSL.swift in Sources */,
@ -1427,6 +1441,7 @@
1F4A56911A3B344A009E1637 /* ObjCBeNilTest.m in Sources */,
1F8A37B01B7C5042001C8357 /* ObjCSyncTest.m in Sources */,
1F4A56941A3B346F009E1637 /* ObjCContainTest.m in Sources */,
B20058C620E92CE400C1264D /* ElementsEqualTest.swift in Sources */,
1F299EAB19627B2D002641AF /* BeEmptyTest.swift in Sources */,
7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfyingTest.m in Sources */,
1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */,
@ -1441,7 +1456,7 @@
1F4A56851A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */,
DD9A9A8F19CF439B00706F49 /* BeIdenticalToObjectTest.swift in Sources */,
1F4BB8B71DACA0E40048464B /* ThrowAssertionTest.swift in Sources */,
1F0648D41963AAB2001F9C46 /* SynchronousTests.swift in Sources */,
1F0648D41963AAB2001F9C46 /* SynchronousTest.swift in Sources */,
347155CA1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */,
4793854D1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */,
1F925F08195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */,
@ -1470,7 +1485,7 @@
1F5DF1751BDCA0F500C3A531 /* FailureMessage.swift in Sources */,
A8A3B6EC2071487F00E25A08 /* SatisfyAllOf.swift in Sources */,
1F5DF1801BDCA0F500C3A531 /* BeLessThanOrEqual.swift in Sources */,
1F1871E81CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */,
1F1871E81CA8A18400A34BF2 /* Async.swift in Sources */,
1F5DF18A1BDCA0F500C3A531 /* ThrowError.swift in Sources */,
1F5DF1891BDCA0F500C3A531 /* RaisesException.swift in Sources */,
1F5DF1761BDCA0F500C3A531 /* AllPass.swift in Sources */,
@ -1504,12 +1519,13 @@
1F1871E91CA8A18700A34BF2 /* MatcherFunc.swift in Sources */,
1F5DF17A1BDCA0F500C3A531 /* BeEmpty.swift in Sources */,
CDFB6A511F7E087500AD8CC7 /* CwlCatchBadInstructionPosix.swift in Sources */,
1F5DF18C1BDCA0F500C3A531 /* Async.swift in Sources */,
1F5DF18C1BDCA0F500C3A531 /* Await.swift in Sources */,
1F1871D81CA89EEF00A34BF2 /* NMBStringify.m in Sources */,
1F5DF1821BDCA0F500C3A531 /* BeNil.swift in Sources */,
1F5DF16F1BDCA0F500C3A531 /* AssertionDispatcher.swift in Sources */,
964CFEFF1C4FF48900513336 /* ThrowAssertion.swift in Sources */,
1F5DF1841BDCA0F500C3A531 /* EndWith.swift in Sources */,
B20058C320E92CA900C1264D /* ElementsEqual.swift in Sources */,
1F5DF18D1BDCA0F500C3A531 /* SourceLocation.swift in Sources */,
1F5DF1701BDCA0F500C3A531 /* DSL.swift in Sources */,
CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */,
@ -1562,11 +1578,12 @@
1F5DF19C1BDCA10200C3A531 /* BeginWithTest.swift in Sources */,
1F5DF1A01BDCA10200C3A531 /* BeIdenticalToTest.swift in Sources */,
1F5DF19A1BDCA10200C3A531 /* BeCloseToTest.swift in Sources */,
B20058C720E92CE400C1264D /* ElementsEqualTest.swift in Sources */,
1F5DF1A61BDCA10200C3A531 /* EndWithTest.swift in Sources */,
CD79C9A31D2CC841004B6F9A /* ObjCBeFalseTest.m in Sources */,
1F5DF1A71BDCA10200C3A531 /* EqualTest.swift in Sources */,
CD79C9AA1D2CC848004B6F9A /* ObjCBeLessThanOrEqualToTest.m in Sources */,
1F5DF1931BDCA10200C3A531 /* SynchronousTests.swift in Sources */,
1F5DF1931BDCA10200C3A531 /* SynchronousTest.swift in Sources */,
CD79C9A11D2CC83B004B6F9A /* ObjCBeCloseToTest.m in Sources */,
1F5DF19D1BDCA10200C3A531 /* BeGreaterThanOrEqualToTest.swift in Sources */,
A8A3B6F7207329DE00E25A08 /* SatisfyAllOfTest.swift in Sources */,
@ -1605,7 +1622,7 @@
1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */,
1F43728C1A1B343C00EB80F8 /* SourceLocation.swift in Sources */,
1FD8CD4F1968AB07008ED995 /* BeLessThanOrEqual.swift in Sources */,
1F1871E71CA8A18400A34BF2 /* AsyncMatcherWrapper.swift in Sources */,
1F1871E71CA8A18400A34BF2 /* Async.swift in Sources */,
1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */,
1F43728B1A1B343900EB80F8 /* Functional.swift in Sources */,
AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */,
@ -1618,6 +1635,7 @@
1FD8CD2F1968AB07008ED995 /* AssertionRecorder.swift in Sources */,
7B13BA061DD360AA00C9098C /* ContainElementSatisfying.swift in Sources */,
1F91DD321C74BF61002C309F /* BeVoid.swift in Sources */,
B20058C120E92C7500C1264D /* ElementsEqual.swift in Sources */,
1FCF91541C61C8A400B15DCB /* PostNotification.swift in Sources */,
DDB4D5EE19FE43C200E9D9FE /* Match.swift in Sources */,
29EA59671B551EE6002D767E /* ThrowError.swift in Sources */,
@ -1645,7 +1663,7 @@
1F1871D41CA89EEE00A34BF2 /* NMBStringify.m in Sources */,
A8F6B5BD2070186D00FCB5ED /* SatisfyAllOf.swift in Sources */,
1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */,
1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */,
1FD8CD6B1968AB07008ED995 /* Await.swift in Sources */,
CDFB6A231F7E07C700AD8CC7 /* CwlCatchException.swift in Sources */,
964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */,
1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */,
@ -1676,10 +1694,12 @@
DDB4D5F119FE442800E9D9FE /* MatchTest.swift in Sources */,
1F4A56741A3B3210009E1637 /* ObjCBeginWithTest.m in Sources */,
1F4A56831A3B336F009E1637 /* ObjCBeLessThanOrEqualToTest.m in Sources */,
CD037213207DCC580047AF28 /* XCTestManifests.swift in Sources */,
7B13BA0D1DD361DE00C9098C /* ContainElementSatisfyingTest.swift in Sources */,
1F925F03195C189500ED456B /* ContainTest.swift in Sources */,
A8A3B6FD2073644700E25A08 /* ObjcStringersTest.m in Sources */,
1F4A56891A3B33CB009E1637 /* ObjCBeFalsyTest.m in Sources */,
B20058C520E92CE400C1264D /* ElementsEqualTest.swift in Sources */,
1F4A568F1A3B342B009E1637 /* ObjCBeFalseTest.m in Sources */,
1F925F12195C190B00ED456B /* BeGreaterThanOrEqualToTest.swift in Sources */,
1F925EF0195C136500ED456B /* BeLogicalTest.swift in Sources */,
@ -1716,7 +1736,7 @@
1F4A56861A3B33A0009E1637 /* ObjCBeTruthyTest.m in Sources */,
DD9A9A9019CF43AD00706F49 /* BeIdenticalToObjectTest.swift in Sources */,
1F4BB8B61DACA0E30048464B /* ThrowAssertionTest.swift in Sources */,
1F0648D51963AAB2001F9C46 /* SynchronousTests.swift in Sources */,
1F0648D51963AAB2001F9C46 /* SynchronousTest.swift in Sources */,
347155CB1C337C8900549F03 /* XCTestCaseProvider.swift in Sources */,
4793854E1BA0BB2500296F85 /* ObjCHaveCountTest.m in Sources */,
1F925F09195C18CF00ED456B /* BeGreaterThanTest.swift in Sources */,
@ -1836,13 +1856,13 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.10;
METAL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
@ -1895,12 +1915,12 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.10;
METAL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 9.0;
VALIDATE_PRODUCT = YES;
@ -1933,9 +1953,12 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
"-weak_framework",
XCTest,
"-weak-lswiftXCTest",
"-Xlinker",
"-no_application_extension",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_MODULE_NAME = Nimble;
@ -1967,9 +1990,12 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
"-weak_framework",
XCTest,
"-weak-lswiftXCTest",
"-Xlinker",
"-no_application_extension",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_MODULE_NAME = Nimble;
@ -2043,9 +2069,12 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = YES;
OTHER_LDFLAGS = (
"$(inherited)",
"-weak_framework",
XCTest,
"-weak-lswiftXCTest",
"-Xlinker",
"-no_application_extension",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_MODULE_NAME = Nimble;
@ -2080,9 +2109,12 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = (
"$(inherited)",
"-weak_framework",
XCTest,
"-weak-lswiftXCTest",
"-Xlinker",
"-no_application_extension",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_MODULE_NAME = Nimble;
@ -2160,9 +2192,12 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
METAL_ENABLE_DEBUG_INFO = YES;
OTHER_LDFLAGS = (
"$(inherited)",
"-weak_framework",
XCTest,
"-weak-lswiftXCTest",
"-Xlinker",
"-no_application_extension",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_MODULE_NAME = Nimble;
@ -2197,9 +2232,12 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
METAL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = (
"$(inherited)",
"-weak_framework",
XCTest,
"-weak-lswiftXCTest",
"-Xlinker",
"-no_application_extension",
);
PRODUCT_BUNDLE_IDENTIFIER = "net.jeffhui.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_MODULE_NAME = Nimble;

View file

@ -2,7 +2,7 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
<key>BuildSystemType</key>
<string>Latest</string>
</dict>
</plist>

View file

@ -1,11 +1,21 @@
// swift-tools-version:3.0
// swift-tools-version:4.2
import PackageDescription
let package = Package(
name: "Nimble",
exclude: [
"Sources/NimbleObjectiveC",
"Tests/NimbleTests/objc",
]
products: [
.library(name: "Nimble", targets: ["Nimble"]),
],
targets: [
.target(
name: "Nimble",
dependencies: []
),
.testTarget(
name: "NimbleTests",
dependencies: ["Nimble"],
exclude: ["objc"]
),
],
swiftLanguageVersions: [.v4_2]
)

View file

@ -1,22 +0,0 @@
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "Nimble",
products: [
.library(name: "Nimble", targets: ["Nimble"]),
],
targets: [
.target(
name: "Nimble",
dependencies: []
),
.testTarget(
name: "NimbleTests",
dependencies: ["Nimble"],
exclude: ["objc"]
),
],
swiftLanguageVersions: [4]
)

View file

@ -4,6 +4,7 @@
[![CocoaPods](https://img.shields.io/cocoapods/v/Nimble.svg)](https://cocoapods.org/pods/Nimble)
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Platforms](https://img.shields.io/cocoapods/p/Nimble.svg)](https://cocoapods.org/pods/Nimble)
[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
Use Nimble to express the expected outcomes of Swift
or Objective-C expressions. Inspired by
@ -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
@ -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
@ -1277,7 +1262,7 @@ public func equal<T: Equatable>(expectedValue: T?) -> Predicate<T> {
// Predicate { actual in ... }
//
// But shown with types here for clarity.
return Predicate { (actual: Expression<T>) throws -> PredicateResult in
return Predicate { (actualExpression: Expression<T>) throws -> PredicateResult in
let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>")
if let actualValue = try actualExpression.evaluate() {
return PredicateResult(
@ -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

View file

@ -13,5 +13,6 @@ public protocol AssertionHandler {
///
/// @see AssertionHandler
public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in
// swiftlint:disable:previous identifier_name
return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler()
}()

View file

@ -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

View file

@ -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,11 +32,13 @@ internal struct ObjCMatcherWrapper: Matcher {
// Equivalent to Expectation, but for Nimble's Objective-C interface
public class NMBExpectation: 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) {
self._actualBlock = actualBlock

View file

@ -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)
}))
}
@ -57,9 +59,14 @@ public class NMBObjCMatcher: NSObject, NMBMatcher {
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 {
@ -69,9 +76,14 @@ public class NMBObjCMatcher: NSObject, NMBMatcher {
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 {

View file

@ -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()
}
}

View file

@ -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

View file

@ -1,6 +1,6 @@
import Foundation
#if !(os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
#if !canImport(Darwin)
// swift-corelibs-foundation doesn't provide NSException at all, so provide a dummy
class NSException {}
#endif

View file

@ -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

View file

@ -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
}

View file

@ -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,7 +71,14 @@ 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)
let (pass, msg) = execute(
expression,
.toMatch,
matcher.predicate,
to: "to",
description: description,
captureExceptions: false
)
verify(pass, msg)
}
@ -127,6 +120,6 @@ public struct Expectation<T> {
}
// see:
// - AsyncMatcherWrapper for extension
// - `async` for extension
// - NMBExpectation for Objective-C interface
}

View file

@ -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

View file

@ -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

View file

@ -28,6 +28,7 @@ public class FailureMessage: NSObject {
}
}
// swiftlint:disable:next identifier_name
internal var _stringValueOverride: String?
internal var hasOverriddenStringValue: Bool {
return _stringValueOverride != nil

View file

@ -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()
}
}
}

View file

@ -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
)

View file

@ -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()
}
}
}

View file

@ -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()
}
}
}

View file

@ -1,5 +1,6 @@
import Foundation
// swiftlint:disable:next identifier_name
public let DefaultDelta = 0.0001
internal func isCloseTo(_ actualValue: NMBDoubleConvertible?,
@ -34,10 +35,12 @@ 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
@ -49,7 +52,13 @@ public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher {
})
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 {
@ -58,7 +67,13 @@ public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher {
})
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)
}

View file

@ -13,6 +13,17 @@ public func beEmpty<S: Sequence>() -> Predicate<S> {
}
}
/// 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() -> Predicate<String> {
@ -61,19 +72,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)"

View file

@ -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()
}
}
}

View file

@ -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 .fail
}
return false
}.requireNonNil
}
/// 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()
}
}
}

View file

@ -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()
}
}
}

View file

@ -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 .fail
}
return false
}.requireNonNil
}
/// 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()
}
}
}

View file

@ -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 .fail
}
return false
}.requireNonNil
}
/// 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()
}
}
}

View file

@ -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()
}
}
}

View file

@ -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()
}
}
}

View file

@ -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: ()) {
extension Expectation where T == () {
public static func == (lhs: Expectation<()>, rhs: ()) {
lhs.to(beVoid())
}
public func != (lhs: Expectation<()>, rhs: ()) {
public static func != (lhs: Expectation<()>, rhs: ()) {
lhs.toNot(beVoid())
}
}

View file

@ -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()
}
}
}

View file

@ -1,22 +1,43 @@
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
}
return false
}.requireNonNil
}
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
@ -25,16 +46,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 .fail
}
return false
}.requireNonNil
}
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
@ -43,13 +64,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 .fail
}
return false
}.requireNonNil
}
/// A Nimble matcher that succeeds when the actual collection contains the expected object.
@ -58,37 +79,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
}
return PredicateStatus(bool: matches)
}
}.requireNonNil
}
#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())
}
}
}

View file

@ -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)
}
}
}

View file

@ -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)
}
}
}

View file

@ -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 .fail
}
return false
}.requireNonNil
}
/// 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 .fail
}
return false
}.requireNonNil
}
#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()
}
}
}

View file

@ -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,8 +55,20 @@ 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() {
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))>"
@ -156,17 +95,6 @@ private func equal<T>(_ expectedValue: Set<T>?, stringify: @escaping (Set<T>?) -
message: errorMessage
)
}
return PredicateResult(
status: .fail,
message: errorMessage.appendedBeNilHint()
)
} else {
return PredicateResult(
status: .fail,
message: errorMessage.appendedBeNilHint()
)
}
}
}
public func ==<T: Equatable>(lhs: Expectation<T>, rhs: T?) {
@ -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()
}
}
}

View file

@ -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())
}
}
}

View file

@ -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()
}
}
}

View file

@ -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())
}
}

View file

@ -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,7 +28,7 @@ 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
@ -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)
}
}

View file

@ -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())
}
}

View file

@ -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,9 +252,13 @@ 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()
}
}
}
@ -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 {

View file

@ -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
@ -133,12 +140,17 @@ public class NMBObjCRaiseExceptionMatcher: NSObject, NMBMatcher {
let block: () -> Any? = ({ _ = actualBlock(); return nil })
let expr = Expression(expression: block, location: location)
return try! raiseException(
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 {

View file

@ -4,33 +4,11 @@ import Foundation
/// 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)
}
/// Deprecated. Please use `satisfyAnyOf<T>(_) -> Predicate<T>` instead.
internal func satisfyAllOf<T, U>(_ matchers: [U]) -> Predicate<T>
where U: Matcher, U.ValueType == T {
return NonNilMatcherFunc<T> { actualExpression, failureMessage in
let postfixMessages = NSMutableArray()
var matches = true
for matcher in matchers {
if try matcher.doesNotMatch(actualExpression, failureMessage: failureMessage) {
matches = false
}
postfixMessages.add(NSString(string: "{\(failureMessage.postfixMessage)}"))
}
failureMessage.postfixMessage = "match all of: " + postfixMessages.componentsJoined(by: ", and ")
if let actualValue = try actualExpression.evaluate() {
failureMessage.actualValue = "\(actualValue)"
}
return matches
}.predicate
return satisfyAllOf(matchers.map { $0.predicate })
}
internal func satisfyAllOf<T>(_ predicates: [Predicate<T>]) -> Predicate<T> {
return Predicate { actualExpression in
return Predicate.define { actualExpression in
var postfixMessages = [String]()
var matches = true
for predicate in predicates {
@ -53,18 +31,15 @@ internal func satisfyAllOf<T>(_ predicates: [Predicate<T>]) -> Predicate<T> {
)
}
return PredicateResult(
bool: matches,
message: msg
)
}.requireNonNil
return PredicateResult(bool: matches, message: msg)
}
}
public func && <T>(left: Predicate<T>, right: Predicate<T>) -> Predicate<T> {
return satisfyAllOf(left, right)
}
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
#if canImport(Darwin)
extension NMBObjCMatcher {
@objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate {
return NMBPredicate { actualExpression in
@ -82,11 +57,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())
}
}
@ -94,7 +73,7 @@ extension NMBObjCMatcher {
elementEvaluators.append(elementEvaluator)
}
return try! satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC()
return try satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC()
}
}
}

View file

@ -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()
}
}
}

View file

@ -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
}
}

View file

@ -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())
}
}

View file

@ -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() {

View file

@ -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

View file

@ -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
@ -158,7 +159,7 @@ public func stringify<T>(_ value: T?) -> String {
return String(describing: value)
}
#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)

View file

@ -1,37 +1,8 @@
import XCTest
@testable import NimbleTests
// This is the entry point for NimbleTests on Linux
import NimbleTests
XCTMain([
testCase(AsyncTest.allTests),
testCase(SynchronousTest.allTests),
testCase(UserDescriptionTest.allTests),
var tests = [XCTestCaseEntry]()
tests += NimbleTests.__allTests()
// Matchers
testCase(AllPassTest.allTests),
testCase(BeAKindOfSwiftTest.allTests),
testCase(BeAnInstanceOfTest.allTests),
testCase(BeCloseToTest.allTests),
testCase(BeginWithTest.allTests),
testCase(BeGreaterThanOrEqualToTest.allTests),
testCase(BeGreaterThanTest.allTests),
testCase(BeIdenticalToObjectTest.allTests),
testCase(BeIdenticalToTest.allTests),
testCase(BeLessThanOrEqualToTest.allTests),
testCase(BeLessThanTest.allTests),
testCase(BeTruthyTest.allTests),
testCase(BeTrueTest.allTests),
testCase(BeFalsyTest.allTests),
testCase(BeFalseTest.allTests),
testCase(BeNilTest.allTests),
testCase(ContainTest.allTests),
testCase(EndWithTest.allTests),
testCase(EqualTest.allTests),
testCase(HaveCountTest.allTests),
testCase(MatchTest.allTests),
// testCase(RaisesExceptionTest.allTests),
testCase(ThrowErrorTest.allTests),
testCase(SatisfyAnyOfTest.allTests),
testCase(PostNotificationTest.allTests),
])
XCTMain(tests)

View file

@ -4,25 +4,6 @@ import XCTest
import Nimble
final class AsyncTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (AsyncTest) -> () throws -> Void)] {
return [
("testToEventuallyPositiveMatches", testToEventuallyPositiveMatches),
("testToEventuallyNegativeMatches", testToEventuallyNegativeMatches),
("testWaitUntilWithCustomDefaultsTimeout", testWaitUntilWithCustomDefaultsTimeout),
("testWaitUntilPositiveMatches", testWaitUntilPositiveMatches),
("testToEventuallyWithCustomDefaultTimeout", testToEventuallyWithCustomDefaultTimeout),
("testWaitUntilTimesOutIfNotCalled", testWaitUntilTimesOutIfNotCalled),
("testWaitUntilTimesOutWhenExceedingItsTime", testWaitUntilTimesOutWhenExceedingItsTime),
("testWaitUntilNegativeMatches", testWaitUntilNegativeMatches),
("testWaitUntilDetectsStalledMainThreadActivity", testWaitUntilDetectsStalledMainThreadActivity),
("testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed", testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed),
("testWaitUntilErrorsIfDoneIsCalledMultipleTimes", testWaitUntilErrorsIfDoneIsCalledMultipleTimes),
("testWaitUntilMustBeInMainThread", testWaitUntilMustBeInMainThread),
("testToEventuallyMustBeInMainThread", testToEventuallyMustBeInMainThread),
("testSubjectUnderTestIsReleasedFromMemory", testSubjectUnderTestIsReleasedFromMemory),
]
}
class Error: Swift.Error {}
let errorToThrow = Error()
@ -70,20 +51,12 @@ final class AsyncTest: XCTestCase, XCTestCaseProvider {
var asyncOperation: () -> Void = { sleepThenSetValueTo(1) }
if #available(OSX 10.10, *) {
DispatchQueue.global().async(execute: asyncOperation)
} else {
DispatchQueue.global(priority: .default).async(execute: asyncOperation)
}
expect { value }.toEventually(equal(1))
asyncOperation = { sleepThenSetValueTo(0) }
if #available(OSX 10.10, *) {
DispatchQueue.global().async(execute: asyncOperation)
} else {
DispatchQueue.global(priority: .default).async(execute: asyncOperation)
}
expect { value }.toEventuallyNot(equal(1))
}
@ -124,11 +97,7 @@ final class AsyncTest: XCTestCase, XCTestCaseProvider {
done()
waiting = false
}
if #available(OSX 10.10, *) {
DispatchQueue.global().async(execute: asyncOperation)
} else {
DispatchQueue.global(priority: .default).async(execute: asyncOperation)
}
}
}
@ -161,15 +130,16 @@ final class AsyncTest: XCTestCase, XCTestCaseProvider {
func testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed() {
// Currently we are unable to catch Objective-C exceptions when built by the Swift Package Manager
#if !SWIFT_PACKAGE
let referenceLine = #line + 9
var msg = "Unexpected exception raised: Nested async expectations are not allowed "
msg += "to avoid creating flaky tests."
msg += "\n\n"
msg += "The call to\n\t"
msg += "expect(...).toEventually(...) at \(#file):\(referenceLine + 7)\n"
msg += "triggered this exception because\n\t"
msg += "waitUntil(...) at \(#file):\(referenceLine + 1)\n"
msg += "is currently managing the main run loop."
let referenceLine = #line + 10
let msg = """
Unexpected exception raised: Nested async expectations are not allowed to avoid creating flaky tests.
The call to
\texpect(...).toEventually(...) at \(#file):\(referenceLine + 7)
triggered this exception because
\twaitUntil(...) at \(#file):\(referenceLine + 1)
is currently managing the main run loop.
"""
failsWithErrorMessage(msg) { // reference line
waitUntil(timeout: 2.0) { done in
var protected: Int = 0
@ -204,11 +174,7 @@ final class AsyncTest: XCTestCase, XCTestCaseProvider {
}.to(raiseException(named: "InvalidNimbleAPIUsage"))
executedAsyncBlock = true
}
if #available(OSX 10.10, *) {
DispatchQueue.global().async(execute: asyncOperation)
} else {
DispatchQueue.global(priority: .default).async(execute: asyncOperation)
}
expect(executedAsyncBlock).toEventually(beTruthy())
#endif
}
@ -222,11 +188,7 @@ final class AsyncTest: XCTestCase, XCTestCaseProvider {
}.to(raiseException(named: "InvalidNimbleAPIUsage"))
executedAsyncBlock = true
}
if #available(OSX 10.10, *) {
DispatchQueue.global().async(execute: asyncOperation)
} else {
DispatchQueue.global(priority: .default).async(execute: asyncOperation)
}
expect(executedAsyncBlock).toEventually(beTruthy())
#endif
}

View file

@ -4,7 +4,7 @@ import XCTest
// XCTestCaseProvider should be adopted by all XCTestCase subclasses. It provides a
// mechanism for us to fail tests in Xcode which haven't been included in the `allTests`
// list for swift-corelibs-xctest which is unable to dynamically discover tests. Note
// that only `static var allTests` needs to be explicitly implemented, as `allTestNames`
// that only `static var __allTests` needs to be explicitly implemented, as `allTestNames`
// has a default implementation provided by a protocol extension.
// Implementation note: This is broken down into two separate protocols because we need a
@ -12,7 +12,7 @@ import XCTest
public protocol XCTestCaseProviderStatic {
// This should be explicitly implemented by XCTestCase subclasses
static var allTests: [(String, (Self) -> () throws -> Void)] { get }
static var __allTests: [(String, (Self) -> () -> ())] { get }
}
public protocol XCTestCaseNameProvider {
@ -20,17 +20,21 @@ public protocol XCTestCaseNameProvider {
var allTestNames: [String] { get }
}
#if os(macOS)
public protocol XCTestCaseProvider: XCTestCaseProviderStatic, XCTestCaseNameProvider {}
extension XCTestCaseProvider {
var allTestNames: [String] {
return type(of: self).allTests.map({ name, _ in
return type(of: self).__allTests.map({ name, _ in
return name
})
}
}
#else
public protocol XCTestCaseProvider {}
#endif
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
#if os(macOS)
extension XCTestCase {
override open func tearDown() {
@ -45,7 +49,13 @@ extension XCTestCase {
extension XCTestCaseNameProvider {
fileprivate func assertContainsTest(_ name: String) {
let contains = self.allTestNames.contains(name)
XCTAssert(contains, "Test '\(name)' is missing from the allTests array")
XCTAssert(
contains,
"""
Test '\(name)' is missing from the __allTests array.
Please run `$ swift test --generate-linuxmain` to update the manifests.
"""
)
}
}

View file

@ -3,12 +3,12 @@ import Foundation
@testable import Nimble
import XCTest
func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () throws -> Void) {
func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: () throws -> Void) {
var filePath = file
var lineNumber = line
let recorder = AssertionRecorder()
withAssertionHandler(recorder, closure: closure)
withAssertionHandler(recorder, file: file, line: line, closure: closure)
for msg in messages {
var lastFailure: AssertionRecord?
@ -37,7 +37,12 @@ func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line:
} else {
let knownFailures = recorder.assertions.filter { !$0.success }.map { $0.message.stringValue }
let knownFailuresJoined = knownFailures.joined(separator: ", ")
message = "Expected error message (\(msg)), got (\(knownFailuresJoined))\n\nAssertions Received:\n\(recorder.assertions)"
message = """
Expected error message (\(msg)), got (\(knownFailuresJoined))
Assertions Received:
\(recorder.assertions)
"""
}
NimbleAssertionHandler.assert(false,
message: FailureMessage(stringValue: message),
@ -45,7 +50,7 @@ func failsWithErrorMessage(_ messages: [String], file: FileString = #file, line:
}
}
func failsWithErrorMessage(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) {
func failsWithErrorMessage(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: () -> Void) {
return failsWithErrorMessage(
[message],
file: file,
@ -55,7 +60,7 @@ func failsWithErrorMessage(_ message: String, file: FileString = #file, line: UI
)
}
func failsWithErrorMessageForNil(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: @escaping () -> Void) {
func failsWithErrorMessageForNil(_ message: String, file: FileString = #file, line: UInt = #line, preferOriginalSourceLocation: Bool = false, closure: () -> Void) {
failsWithErrorMessage("\(message) (use beNil() to match nils)", file: file, line: line, preferOriginalSourceLocation: preferOriginalSourceLocation, closure: closure)
}
@ -68,15 +73,15 @@ func deferToMainQueue(action: @escaping () -> Void) {
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
public class NimbleHelper: NSObject {
@objc public class func expectFailureMessage(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) {
@objc public class func expectFailureMessage(_ message: NSString, block: () -> Void, file: FileString, line: UInt) {
failsWithErrorMessage(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block)
}
@objc public class func expectFailureMessages(_ messages: [NSString], block: @escaping () -> Void, file: FileString, line: UInt) {
@objc public class func expectFailureMessages(_ messages: [NSString], block: () -> Void, file: FileString, line: UInt) {
failsWithErrorMessage(messages.map({String(describing: $0)}), file: file, line: line, preferOriginalSourceLocation: true, closure: block)
}
@objc public class func expectFailureMessageForNil(_ message: NSString, block: @escaping () -> Void, file: FileString, line: UInt) {
@objc public class func expectFailureMessageForNil(_ message: NSString, block: () -> Void, file: FileString, line: UInt) {
failsWithErrorMessageForNil(String(describing: message), file: file, line: line, preferOriginalSourceLocation: true, closure: block)
}
}

View file

@ -43,17 +43,6 @@ extension Optional where Wrapped: Comparable {
}
final class AllPassTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (AllPassTest) -> () throws -> Void)] {
return [
("testAllPassArray", testAllPassArray),
("testAllPassMatcher", testAllPassMatcher),
("testAllPassCollectionsWithOptionalsDontWork", testAllPassCollectionsWithOptionalsDontWork),
("testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer", testAllPassCollectionsWithOptionalsUnwrappingOneOptionalLayer),
("testAllPassSet", testAllPassSet),
("testAllPassWithNilAsExpectedValue", testAllPassWithNilAsExpectedValue),
]
}
func testAllPassArray() {
expect([1, 2, 3, 4]).to(allPass({$0 < 5}))
expect([1, 2, 3, 4]).toNot(allPass({$0 > 5}))

View file

@ -8,13 +8,6 @@ private class TestClassConformingToProtocol: TestProtocol {}
private struct TestStructConformingToProtocol: TestProtocol {}
final class BeAKindOfSwiftTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeAKindOfSwiftTest) -> () throws -> Void)] {
return [
("testPositiveMatch", testPositiveMatch),
("testFailureMessages", testFailureMessages),
]
}
enum TestEnum {
case one, two
}
@ -54,23 +47,17 @@ final class BeAKindOfSwiftTest: XCTestCase, XCTestCaseProvider {
}
}
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
final class BeAKindOfObjCTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeAKindOfObjCTest) -> () throws -> Void)] {
return [
("testPositiveMatch", testPositiveMatch),
("testFailureMessages", testFailureMessages),
]
}
func testPositiveMatch() {
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
expect(TestNull()).to(beAKindOf(NSNull.self))
expect(NSObject()).to(beAKindOf(NSObject.self))
expect(NSNumber(value: 1)).toNot(beAKindOf(NSDate.self))
#endif
}
func testFailureMessages() {
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
failsWithErrorMessageForNil("expected to not be a kind of NSNull, got <nil>") {
expect(nil as NSNull?).toNot(beAKindOf(NSNull.self))
}
@ -83,7 +70,6 @@ final class BeAKindOfObjCTest: XCTestCase, XCTestCaseProvider {
failsWithErrorMessage("expected to not be a kind of NSNumber, got <__NSCFNumber instance>") {
expect(NSNumber(value: 1)).toNot(beAKindOf(NSNumber.self))
}
}
}
#endif
}
}

View file

@ -7,15 +7,6 @@ private class TestClassConformingToProtocol: TestProtocol {}
private struct TestStructConformingToProtocol: TestProtocol {}
final class BeAnInstanceOfTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeAnInstanceOfTest) -> () throws -> Void)] {
return [
("testPositiveMatch", testPositiveMatch),
("testPositiveMatchSwiftTypes", testPositiveMatchSwiftTypes),
("testFailureMessages", testFailureMessages),
("testFailureMessagesSwiftTypes", testFailureMessagesSwiftTypes),
]
}
func testPositiveMatch() {
expect(NSNull()).to(beAnInstanceOf(NSNull.self))
expect(NSNumber(value: 1)).toNot(beAnInstanceOf(NSDate.self))

View file

@ -3,24 +3,6 @@ import XCTest
import Nimble
final class BeCloseToTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeCloseToTest) -> () throws -> Void)] {
return [
("testBeCloseTo", testBeCloseTo),
("testBeCloseToWithin", testBeCloseToWithin),
("testBeCloseToWithNSNumber", testBeCloseToWithNSNumber),
("testBeCloseToWithDate", testBeCloseToWithDate),
("testBeCloseToWithNSDate", testBeCloseToWithNSDate),
("testBeCloseToOperator", testBeCloseToOperator),
("testBeCloseToWithinOperator", testBeCloseToWithinOperator),
("testPlusMinusOperator", testPlusMinusOperator),
("testBeCloseToOperatorWithDate", testBeCloseToOperatorWithDate),
("testBeCloseToWithinOperatorWithDate", testBeCloseToWithinOperatorWithDate),
("testPlusMinusOperatorWithDate", testPlusMinusOperatorWithDate),
("testBeCloseToArray", testBeCloseToArray),
("testBeCloseToWithCGFloat", testBeCloseToWithCGFloat),
]
}
func testBeCloseTo() {
expect(1.2).to(beCloseTo(1.2001))
expect(1.2 as CDouble).to(beCloseTo(1.2001))
@ -34,8 +16,8 @@ final class BeCloseToTest: XCTestCase, XCTestCaseProvider {
func testBeCloseToWithin() {
expect(1.2).to(beCloseTo(9.300, within: 10))
failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") {
expect(1.2).toNot(beCloseTo(1.2001, within: 1.0))
failsWithErrorMessage("expected to not be close to <1.2001> (within 1.1), got <1.2>") {
expect(1.2).toNot(beCloseTo(1.2001, within: 1.1))
}
}
@ -44,8 +26,8 @@ final class BeCloseToTest: XCTestCase, XCTestCaseProvider {
expect(NSNumber(value: 1.2)).to(beCloseTo(NSNumber(value: 9.300), within: 10))
expect(1.2).to(beCloseTo(NSNumber(value: 9.300), within: 10))
failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") {
expect(NSNumber(value: 1.2)).toNot(beCloseTo(1.2001, within: 1.0))
failsWithErrorMessage("expected to not be close to <1.2001> (within 1.1), got <1.2>") {
expect(NSNumber(value: 1.2)).toNot(beCloseTo(1.2001, within: 1.1))
}
}
@ -53,8 +35,8 @@ final class BeCloseToTest: XCTestCase, XCTestCaseProvider {
expect(CGFloat(1.2)).to(beCloseTo(1.2001))
expect(CGFloat(1.2)).to(beCloseTo(CGFloat(1.2001)))
failsWithErrorMessage("expected to not be close to <1.2001> (within 1), got <1.2>") {
expect(CGFloat(1.2)).toNot(beCloseTo(1.2001, within: 1.0))
failsWithErrorMessage("expected to not be close to <1.2001> (within 1.1), got <1.2>") {
expect(CGFloat(1.2)).toNot(beCloseTo(1.2001, within: 1.1))
}
}
@ -89,11 +71,11 @@ final class BeCloseToTest: XCTestCase, XCTestCaseProvider {
expect(1.2) (9.300, 10)
expect(1.2) == (9.300, 10)
failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") {
expect(1.2) (1.0, 0.1)
failsWithErrorMessage("expected to be close to <1.1> (within 0.1), got <1.3>") {
expect(1.3) (1.1, 0.1)
}
failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") {
expect(1.2) == (1.0, 0.1)
failsWithErrorMessage("expected to be close to <1.1> (within 0.1), got <1.3>") {
expect(1.3) == (1.1, 0.1)
}
}
@ -101,11 +83,11 @@ final class BeCloseToTest: XCTestCase, XCTestCaseProvider {
expect(1.2) 9.300 ± 10
expect(1.2) == 9.300 ± 10
failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") {
expect(1.2) 1.0 ± 0.1
failsWithErrorMessage("expected to be close to <1.1> (within 0.1), got <1.3>") {
expect(1.3) 1.1 ± 0.1
}
failsWithErrorMessage("expected to be close to <1> (within 0.1), got <1.2>") {
expect(1.2) == 1.0 ± 0.1
failsWithErrorMessage("expected to be close to <1.1> (within 0.1), got <1.3>") {
expect(1.3) == 1.1 ± 0.1
}
}
@ -150,11 +132,11 @@ final class BeCloseToTest: XCTestCase, XCTestCaseProvider {
expect([0.0, 1.1, 2.2]) [0.0001, 1.1001, 2.2001]
expect([0.0, 1.1, 2.2]).to(beCloseTo([0.1, 1.2, 2.3], within: 0.1))
failsWithErrorMessage("expected to be close to <[0, 1]> (each within 0.0001), got <[0, 1.1]>") {
expect([0.0, 1.1]) [0.0, 1.0]
failsWithErrorMessage("expected to be close to <[0.1, 1.1]> (each within 0.0001), got <[0.1, 1.2]>") {
expect([0.1, 1.2]) [0.1, 1.1]
}
failsWithErrorMessage("expected to be close to <[0.2, 1.2]> (each within 0.1), got <[0, 1.1]>") {
expect([0.0, 1.1]).to(beCloseTo([0.2, 1.2], within: 0.1))
failsWithErrorMessage("expected to be close to <[0.3, 1.3]> (each within 0.1), got <[0.1, 1.2]>") {
expect([0.1, 1.2]).to(beCloseTo([0.3, 1.3], within: 0.1))
}
}
}

View file

@ -3,13 +3,6 @@ import XCTest
import Nimble
final class BeEmptyTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeEmptyTest) -> () throws -> Void)] {
return [
("testBeEmptyPositive", testBeEmptyPositive),
("testBeEmptyNegative", testBeEmptyNegative),
]
}
func testBeEmptyPositive() {
expect([] as [Int]).to(beEmpty())
expect([1]).toNot(beEmpty())
@ -41,16 +34,12 @@ final class BeEmptyTest: XCTestCase, XCTestCaseProvider {
expect("").to(beEmpty())
expect("foo").toNot(beEmpty())
expect([] as TestOptionSet).to(beEmpty())
expect(TestOptionSet.one).toNot(beEmpty())
}
func testBeEmptyNegative() {
failsWithErrorMessageForNil("expected to be empty, got <nil>") {
expect(nil as NSString?).to(beEmpty())
}
failsWithErrorMessageForNil("expected to not be empty, got <nil>") {
expect(nil as [CInt]?).toNot(beEmpty())
}
failsWithErrorMessage("expected to not be empty, got <()>") {
expect(NSArray()).toNot(beEmpty())
}
@ -58,12 +47,14 @@ final class BeEmptyTest: XCTestCase, XCTestCaseProvider {
expect([1]).to(beEmpty())
}
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
failsWithErrorMessage("expected to not be empty, got <{()}>") {
expect(NSSet()).toNot(beEmpty())
}
failsWithErrorMessage("expected to be empty, got <{(1)}>") {
expect(NSSet(object: NSNumber(value: 1))).to(beEmpty())
}
#endif
failsWithErrorMessage("expected to not be empty, got <()>") {
expect(NSIndexSet()).toNot(beEmpty())
@ -78,5 +69,49 @@ final class BeEmptyTest: XCTestCase, XCTestCaseProvider {
failsWithErrorMessage("expected to be empty, got <foo>") {
expect("foo").to(beEmpty())
}
failsWithErrorMessage("expected to not be empty, got <TestOptionSet(rawValue: 0)>") {
expect([] as TestOptionSet).toNot(beEmpty())
}
failsWithErrorMessage("expected to be empty, got <TestOptionSet(rawValue: 1)>") {
expect(TestOptionSet.one).to(beEmpty())
}
}
func testNilMatches() {
failsWithErrorMessageForNil("expected to be empty, got <nil>") {
expect(nil as NSString?).to(beEmpty())
}
failsWithErrorMessageForNil("expected to not be empty, got <nil>") {
expect(nil as NSString?).toNot(beEmpty())
}
failsWithErrorMessageForNil("expected to be empty, got <nil>") {
expect(nil as [CInt]?).to(beEmpty())
}
failsWithErrorMessageForNil("expected to not be empty, got <nil>") {
expect(nil as [CInt]?).toNot(beEmpty())
}
failsWithErrorMessageForNil("expected to be empty, got <nil>") {
expect(nil as TestOptionSet?).to(beEmpty())
}
failsWithErrorMessageForNil("expected to not be empty, got <nil>") {
expect(nil as TestOptionSet?).toNot(beEmpty())
}
}
}
private struct TestOptionSet: OptionSet, CustomStringConvertible {
let rawValue: Int
static let one = TestOptionSet(rawValue: 1 << 0)
init(rawValue: Int) {
self.rawValue = rawValue
}
var description: String {
return "TestOptionSet(rawValue: \(rawValue))"
}
}

View file

@ -3,13 +3,6 @@ import XCTest
import Nimble
final class BeGreaterThanOrEqualToTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeGreaterThanOrEqualToTest) -> () throws -> Void)] {
return [
("testGreaterThanOrEqualTo", testGreaterThanOrEqualTo),
("testGreaterThanOrEqualToOperator", testGreaterThanOrEqualToOperator),
]
}
func testGreaterThanOrEqualTo() {
expect(10).to(beGreaterThanOrEqualTo(10))
expect(10).to(beGreaterThanOrEqualTo(2))

View file

@ -3,13 +3,6 @@ import XCTest
import Nimble
final class BeGreaterThanTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeGreaterThanTest) -> () throws -> Void)] {
return [
("testGreaterThan", testGreaterThan),
("testGreaterThanOperator", testGreaterThanOperator),
]
}
func testGreaterThan() {
expect(10).to(beGreaterThan(2))
expect(1).toNot(beGreaterThan(2))

View file

@ -3,17 +3,6 @@ import XCTest
import Nimble
final class BeIdenticalToObjectTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeIdenticalToObjectTest) -> () throws -> Void)] {
return [
("testBeIdenticalToPositive", testBeIdenticalToPositive),
("testBeIdenticalToNegative", testBeIdenticalToNegative),
("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage),
("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage),
("testFailsOnNils", testFailsOnNils),
("testOperators", testOperators),
]
}
private class BeIdenticalToObjectTester {}
private let testObjectA = BeIdenticalToObjectTester()
private let testObjectB = BeIdenticalToObjectTester()

View file

@ -3,17 +3,6 @@ import XCTest
@testable import Nimble
final class BeIdenticalToTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeIdenticalToTest) -> () throws -> Void)] {
return [
("testBeIdenticalToPositive", testBeIdenticalToPositive),
("testBeIdenticalToNegative", testBeIdenticalToNegative),
("testBeIdenticalToPositiveMessage", testBeIdenticalToPositiveMessage),
("testBeIdenticalToNegativeMessage", testBeIdenticalToNegativeMessage),
("testOperators", testOperators),
("testBeAlias", testBeAlias),
]
}
func testBeIdenticalToPositive() {
let value = NSDate()
expect(value).to(beIdenticalTo(value))

View file

@ -3,13 +3,6 @@ import XCTest
import Nimble
final class BeLessThanOrEqualToTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeLessThanOrEqualToTest) -> () throws -> Void)] {
return [
("testLessThanOrEqualTo", testLessThanOrEqualTo),
("testLessThanOrEqualToOperator", testLessThanOrEqualToOperator),
]
}
func testLessThanOrEqualTo() {
expect(10).to(beLessThanOrEqualTo(10))
expect(2).to(beLessThanOrEqualTo(10))

View file

@ -3,13 +3,6 @@ import XCTest
import Nimble
final class BeLessThanTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeLessThanTest) -> () throws -> Void)] {
return [
("testLessThan", testLessThan),
("testLessThanOperator", testLessThanOperator),
]
}
func testLessThan() {
expect(2).to(beLessThan(10))
expect(2).toNot(beLessThan(1))

View file

@ -30,18 +30,6 @@ enum ConvertsToBool: ExpressibleByBooleanLiteral, CustomStringConvertible {
}
final class BeTruthyTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeTruthyTest) -> () throws -> Void)] {
return [
("testShouldMatchNonNilTypes", testShouldMatchNonNilTypes),
("testShouldMatchTrue", testShouldMatchTrue),
("testShouldNotMatchNilTypes", testShouldNotMatchNilTypes),
("testShouldNotMatchFalse", testShouldNotMatchFalse),
("testShouldNotMatchNilBools", testShouldNotMatchNilBools),
("testShouldMatchBoolConvertibleTypesThatConvertToTrue", testShouldMatchBoolConvertibleTypesThatConvertToTrue),
("testShouldNotMatchBoolConvertibleTypesThatConvertToFalse", testShouldNotMatchBoolConvertibleTypesThatConvertToFalse),
]
}
func testShouldMatchNonNilTypes() {
expect(true as Bool?).to(beTruthy())
@ -123,14 +111,6 @@ final class BeTruthyTest: XCTestCase, XCTestCaseProvider {
}
final class BeTrueTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeTrueTest) -> () throws -> Void)] {
return [
("testShouldMatchTrue", testShouldMatchTrue),
("testShouldNotMatchFalse", testShouldNotMatchFalse),
("testShouldNotMatchNilBools", testShouldNotMatchNilBools),
]
}
func testShouldMatchTrue() {
expect(true).to(beTrue())
@ -159,16 +139,6 @@ final class BeTrueTest: XCTestCase, XCTestCaseProvider {
}
final class BeFalsyTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeFalsyTest) -> () throws -> Void)] {
return [
("testShouldMatchNilTypes", testShouldMatchNilTypes),
("testShouldNotMatchTrue", testShouldNotMatchTrue),
("testShouldNotMatchNonNilTypes", testShouldNotMatchNonNilTypes),
("testShouldMatchFalse", testShouldMatchFalse),
("testShouldMatchNilBools", testShouldMatchNilBools),
]
}
func testShouldMatchNilTypes() {
expect(false as Bool?).to(beFalsy())
@ -234,14 +204,6 @@ final class BeFalsyTest: XCTestCase, XCTestCaseProvider {
}
final class BeFalseTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeFalseTest) -> () throws -> Void)] {
return [
("testShouldNotMatchTrue", testShouldNotMatchTrue),
("testShouldMatchFalse", testShouldMatchFalse),
("testShouldNotMatchNilBools", testShouldNotMatchNilBools),
]
}
func testShouldNotMatchTrue() {
expect(true).toNot(beFalse())

View file

@ -2,12 +2,6 @@ import XCTest
import Nimble
final class BeNilTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeNilTest) -> () throws -> Void)] {
return [
("testBeNil", testBeNil),
]
}
func producesNil() -> [Int]? {
return nil
}

View file

@ -2,12 +2,6 @@ import XCTest
import Nimble
final class BeVoidTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeVoidTest) -> () throws -> Void)] {
return [
("testBeVoid", testBeVoid),
]
}
func testBeVoid() {
expect(()).to(beVoid())
expect(() as ()?).to(beVoid())

View file

@ -3,13 +3,6 @@ import XCTest
import Nimble
final class BeginWithTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (BeginWithTest) -> () throws -> Void)] {
return [
("testPositiveMatches", testPositiveMatches),
("testNegativeMatches", testNegativeMatches),
]
}
func testPositiveMatches() {
expect([1, 2, 3]).to(beginWith(1))
expect([1, 2, 3]).toNot(beginWith(2))

View file

@ -3,20 +3,6 @@ import XCTest
import Nimble
final class ContainElementSatisfyingTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (ContainElementSatisfyingTest) -> () throws -> Void)] {
return [
("testContainElementSatisfying", testContainElementSatisfying),
("testContainElementSatisfyingDefaultErrorMessage", testContainElementSatisfyingDefaultErrorMessage),
("testContainElementSatisfyingSpecificErrorMessage", testContainElementSatisfyingSpecificErrorMessage),
("testContainElementSatisfyingNegativeCase",
testContainElementSatisfyingNegativeCase),
("testContainElementSatisfyingNegativeCaseDefaultErrorMessage",
testContainElementSatisfyingNegativeCaseDefaultErrorMessage),
("testContainElementSatisfyingNegativeCaseSpecificErrorMessage",
testContainElementSatisfyingNegativeCaseSpecificErrorMessage),
]
}
func testContainElementSatisfying() {
var orderIndifferentArray = [1, 2, 3]
expect(orderIndifferentArray).to(containElementSatisfying({ number in

View file

@ -3,22 +3,12 @@ import XCTest
import Nimble
final class ContainTest: XCTestCase, XCTestCaseProvider {
static var allTests: [(String, (ContainTest) -> () throws -> Void)] {
return [
("testContain", testContain),
("testContainSubstring", testContainSubstring),
("testContainObjCSubstring", testContainObjCSubstring),
("testVariadicArguments", testVariadicArguments),
("testCollectionArguments", testCollectionArguments),
]
}
func testContain() {
func testContainSequence() {
expect([1, 2, 3]).to(contain(1))
expect([1, 2, 3]).toNot(contain(4))
expect([1, 2, 3] as [CInt]).to(contain(1 as CInt))
expect([1, 2, 3] as [CInt]).toNot(contain(4 as CInt))
expect(["foo", "bar", "baz"]).to(contain("baz"))
expect([1, 2, 3]).toNot(contain(4))
expect(["foo", "bar", "baz"]).toNot(contain("ba"))
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
expect(NSArray(array: ["a"])).to(contain(NSString(string: "a")))
@ -41,6 +31,25 @@ final class ContainTest: XCTestCase, XCTestCaseProvider {
}
}
func testContainSetAlgebra() {
expect([.a, .b, .c] as TestOptionSet).to(contain(.a))
expect([.a, .b, .c] as TestOptionSet).toNot(contain(.d))
failsWithErrorMessage("expected to contain <8>, got <7>") {
expect([.a, .b, .c] as TestOptionSet).to(contain(.d))
}
failsWithErrorMessage("expected to not contain <2>, got <7>") {
expect([.a, .b, .c] as TestOptionSet).toNot(contain(.b))
}
failsWithErrorMessageForNil("expected to contain <1>, got <nil>") {
expect(nil as TestOptionSet?).to(contain(.a))
}
failsWithErrorMessageForNil("expected to not contain <1>, got <nil>") {
expect(nil as TestOptionSet?).toNot(contain(.a))
}
}
func testContainSubstring() {
expect("foo").to(contain("o"))
expect("foo").to(contain("oo"))
@ -93,3 +102,23 @@ final class ContainTest: XCTestCase, XCTestCaseProvider {
}
}
}
private struct TestOptionSet: OptionSet, CustomStringConvertible {
let rawValue: Int
// swiftlint:disable identifier_name
static let a = TestOptionSet(rawValue: 1 << 0)
static let b = TestOptionSet(rawValue: 1 << 1)
static let c = TestOptionSet(rawValue: 1 << 2)
static let d = TestOptionSet(rawValue: 1 << 3)
static let e = TestOptionSet(rawValue: 1 << 4)
// swiftlint:enable identifier_name
init(rawValue: Int) {
self.rawValue = rawValue
}
var description: String {
return "\(rawValue)"
}
}

Some files were not shown because too many files have changed in this diff Show more